]> git.madduck.net Git - etc/vim.git/commitdiff

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Version 0.5
authorAndy Wokula <anwoku@yahoo.de>
Sat, 9 Mar 2013 00:00:00 +0000 (00:00 +0000)
committerAble Scraper <scraper@vim-scripts.org>
Sun, 24 Mar 2013 03:50:35 +0000 (22:50 -0500)
Bug fixes (accept more patterns): `\z(', `\z1', ..., `[foo'; added cases where `^', `*', `$' become literal; `[=a=]` in collections, a few more.

autoload/explainpat.vim
autoload/nwo/magic.vim
doc/explainpat.txt
plugin/explainpat.vim

index c0545eae682c3fd62c5a7faec3ff0cbc782e6ddf..a45fa5805689498c865344272bc1e85bbc184b48 100644 (file)
@@ -1,24 +1,19 @@
 " File:         explainpat.vim
 " Created:      2011 Nov 02
-" Last Change:  2012 Dec 19
-" Rev Days:     3
+" Last Change:  2013 Mar 09
+" Rev Days:     8
 " Author:      Andy Wokula <anwoku@yahoo.de>
 " License:     Vim License, see :h license
-" Version:     0.2
+" Version:     0.5
 
 " Implements :ExplainPattern [pattern]
 
 " TODO {{{
 " - more testing, completeness check
-" - detailed collections
-" - \z
+" ? detailed collections
 " ? literal string: also print the unescaped magic items
 " ? literal string: show leading/trailing spaces
-" + start of "first" capturing group, start of 2nd ...
-" + `\|' should get less indent than the branches, do we need to create an
-"   AST?       ! no, keep it straight forward
-" + \%[...]
-" + \{, \{-
+"
 "}}}
 
 " Init Folklore {{{
@@ -27,7 +22,9 @@ set cpo&vim
 let g:explainpat#loaded = 1
 "}}}
 
-func! explainpat#ExplainPattern(cmd_arg) "{{{
+func! explainpat#ExplainPattern(cmd_arg, ...) "{{{
+    " {a:1}    alternative help printer object (caution, no sanity check)
+    "          (for test running)
     if a:cmd_arg == ""
        " let pattern_str = nwo#vis#Get()
        echo "(usage) :ExplainPattern [{register} | {pattern}]"
@@ -45,11 +42,15 @@ func! explainpat#ExplainPattern(cmd_arg) "{{{
        echo printf('Magic Pattern: %s', magicpat)
     endif
 
-    " hmm, we need state for \%[ ... ]
+    " we need state:
+    " set flag when in `\%[ ... ]' (optionally matched atoms):
     let s:in_opt_atoms = 0
+    " counter for `\(':
     let s:capture_group_nr = 0
+    " >=1 at pos 0 or after '\|', '\&', '\(', '\%(' or '\n'; else 0 or less:
+    let s:at_begin_of_pat = 1
 
-    let hulit = s:NewHelpPrinter()
+    let hulit = a:0>=1 && type(a:1)==s:DICT ? a:1 : s:NewHelpPrinter()
     call hulit.AddIndent('  ')
     let bull = s:NewTokenBiter(magicpat, '')
     while !bull.AtEnd()
@@ -62,7 +63,10 @@ func! explainpat#ExplainPattern(cmd_arg) "{{{
                call hulit.Print(item, Doc)
            elseif type(Doc) == s:FUNCREF
                call call(Doc, [bull, hulit, item])
+           elseif type(Doc) == s:LIST
+               call call(Doc[0], [bull, hulit, item, Doc[1]])
            endif
+           let s:at_begin_of_pat -= 1
        else
            echoerr printf('ExplainPattern: cannot parse "%s"', bull.Rest())
            break
@@ -76,9 +80,10 @@ endfunc "}}}
 let s:STRING = type("")
 let s:DICT   = type({})
 let s:FUNCREF = type(function("tr"))
+let s:LIST = type([])
 " }}}
 
-let s:magic_item_pattern = '\C^\%(\\\%(@<.\|%[dxouU[(^$V#<>]\=\|z[1-9se(]\|{\|@[>=!]\|_[[^$.]\=\|.\)\|.\)'
+let s:magic_item_pattern = '\C^\%(\\\%(@<.\|%[dxouU[(^$V#<>]\=\|z[1-9se(]\|@[>=!]\|_[[^$.]\=\|.\)\|.\)'
 
 let s:doc = {} " {{{
 " this is all the help data ...
@@ -87,23 +92,33 @@ let s:doc = {} " {{{
 
 func! s:DocOrBranch(bull, hulit, item) "{{{
     call a:hulit.RemIndent()
-    call a:hulit.Print(a:item, "OR branch")
+    call a:hulit.Print(a:item, "OR (separate alternatives)")
     call a:hulit.AddIndent('  ')
+    let s:at_begin_of_pat = 2
 endfunc "}}}
 
 let s:doc['\|'] = function("s:DocOrBranch")
-let s:doc['\&'] = "AND branch"
+
+func! s:DocBeginOfPat(bull, hulit, item, msg) "{{{
+    call a:hulit.Print(a:item, a:msg)
+    let s:at_begin_of_pat = 2
+endfunc "}}}
+
+let s:doc['\&'] = [function("s:DocBeginOfPat"), "AND (separate concats, all must match)"]
 
 let s:ord = split('n first second third fourth fifth sixth seventh eighth ninth')
 
 func! s:DocGroupStart(bull, hulit, item) "{{{
     if a:item == '\%('
        call a:hulit.Print(a:item, "start of non-capturing group")
-    else " a:item == '\('
+    elseif a:item == '\('
        let s:capture_group_nr += 1
        call a:hulit.Print(a:item, printf("start of %s capturing group", get(s:ord, s:capture_group_nr, '(invalid)')))
+    else " a:item == '\z('
+       call a:hulit.Print(a:item, 'start of "external" group (only usable in :syn-region)')
     endif
     call a:hulit.AddIndent('| ', '  ')
+    let s:at_begin_of_pat = 2
 endfunc "}}}
 func! s:DocGroupEnd(bull, hulit, item) "{{{
     call a:hulit.RemIndent(2)
@@ -113,9 +128,21 @@ endfunc "}}}
 let s:doc['\('] = function("s:DocGroupStart")
 let s:doc['\%('] = function("s:DocGroupStart")
 let s:doc['\)'] =  function("s:DocGroupEnd")
+" let s:doc['\z('] = "only in syntax scripts"
+let s:doc['\z('] = function("s:DocGroupStart")
+
+func! s:DocStar(bull, hulit, item) "{{{
+    if s:at_begin_of_pat >= 1
+       " call a:hulit.Print(a:item, "(at begin of pattern) literal `*'")
+       call a:hulit.AddLiteral(a:item)
+    else
+       call a:hulit.Print(a:item, "(multi) zero or more of the preceding atom")
+    endif
+endfunc "}}}
+
+" let s:doc['*'] = "(multi) zero or more of the preceding atom"
+let s:doc['*'] = function("s:DocStar")
 
-let s:doc['\z('] = "only in syntax scripts"
-let s:doc['*'] = "(multi) zero or more of the preceding atom"
 let s:doc['\+'] = "(multi) one or more of the preceding atom"
 let s:doc['\='] = "(multi) zero or one of the preceding atom"
 let s:doc['\?'] = "(multi) zero or one of the preceding atom"
@@ -144,9 +171,36 @@ let s:doc['\@='] = "(assertion) require match for preceding atom"
 let s:doc['\@!'] = "(assertion) forbid match for preceding atom"
 let s:doc['\@<='] = "(assertion) require match for preceding atom to the left"
 let s:doc['\@<!'] = "(assertion) forbid match for preceding atom to the left"
-let s:doc['^'] = "(assertion) require match at start of line"
+
+func! s:DocCircumFlex(bull, hulit, item) "{{{
+    if s:at_begin_of_pat >= 1
+       call a:hulit.Print(a:item, "(assertion) require match at start of line")
+       " after `^' is not at begin of pattern ... handle special case `^*' here:
+       if a:bull.Bite('^\*') == "*"
+           call a:hulit.AddLiteral("*")
+       endif
+    else
+       " call a:hulit.Print(a:item, "(not at begin of pattern) literal `^'")
+       call a:hulit.AddLiteral(a:item)
+    endif
+endfunc "}}}
+
+" let s:doc['^'] = "(assertion) require match at start of line"
+let s:doc['^'] = function("s:DocCircumFlex")
+
 let s:doc['\_^'] = "(assertion) like `^', allowed anywhere in the pattern"
-let s:doc['$'] = "(assertion) require match at end of line"
+
+func! s:DocDollar(bull, hulit, item) "{{{
+    if a:bull.Rest() =~ '^$\|^\\[&|)n]'
+       call a:hulit.Print(a:item, "(assertion) require match at end of line")
+    else
+       call a:hulit.AddLiteral(a:item)
+    endif
+endfunc "}}}
+
+" let s:doc['$'] = "(assertion) require match at end of line"
+let s:doc['$'] = function("s:DocDollar")
+
 let s:doc['\_$'] = "(assertion) like `$', allowed anywhere in the pattern"
 let s:doc['.'] = "match any character"
 let s:doc['\_.'] = "match any character or newline"
@@ -266,7 +320,7 @@ let s:doc['\e'] = "match <Esc>"
 let s:doc['\t'] = "match <Tab>"
 let s:doc['\r'] = "match <CR>"
 let s:doc['\b'] = "match CTRL-H"
-let s:doc['\n'] = "match a newline"
+let s:doc['\n'] = [function("s:DocBeginOfPat"), "match a newline"]
 let s:doc['~'] = "match the last given substitute string"
 let s:doc['\1'] = "match first captured string"
 let s:doc['\2'] = "match second captured string"
@@ -278,21 +332,31 @@ let s:doc['\7'] = "match seventh captured string"
 let s:doc['\8'] = "match eighth captured string"
 let s:doc['\9'] = "match ninth captured string"
 
-" \z1
-" \z2
-" \z9
+let s:doc['\z1'] = 'match same string matched by first "external" group'
+let s:doc['\z2'] = 'match same string matched by second "external" group'
+let s:doc['\z3'] = 'match same string matched by third "external" group'
+let s:doc['\z4'] = 'match same string matched by fourth "external" group '
+let s:doc['\z5'] = 'match same string matched by fifth "external" group'
+let s:doc['\z6'] = 'match same string matched by sixth "external" group'
+let s:doc['\z7'] = 'match same string matched by seventh "external" group'
+let s:doc['\z8'] = 'match same string matched by eighth "external" group'
+let s:doc['\z9'] = 'match same string matched by ninth "external" group'
 
 " from MakeMagic()
 " skip the rest of a collection
-let s:coll_skip_pat = '^\^\=]\=\%(\%(\\[\^\]\-\\bertn]\|\[:\w\+:]\|[^\]]\)\@>\)*]'
+let s:coll_skip_pat = '^\^\=]\=\%(\%(\\[\^\]\-\\bertn]\|\[:\w\+:]\|\[=.=]\|\[\..\.]\|[^\]]\)\@>\)*]'
 
 func! s:DocCollection(bull, hulit, item) "{{{
     let collstr = a:bull.Bite(s:coll_skip_pat)
-    let inverse = collstr =~ '^\^'
-    let with_nl = a:item == '\_['
-    let descr = inverse ? printf('collection not matching [%s', collstr[1:]) : 'collection'
-    let descr_nl = printf("%s%s", (inverse && with_nl ? ', but' : ''), (with_nl ? ' with end-of-line added' : ''))
-    call a:hulit.Print(a:item. collstr, descr. descr_nl)
+    if collstr != ""
+       let inverse = collstr =~ '^\^'
+       let with_nl = a:item == '\_['
+       let descr = inverse ? printf('collection not matching [%s', collstr[1:]) : 'collection'
+       let descr_nl = printf("%s%s", (inverse && with_nl ? ', but' : ''), (with_nl ? ' with end-of-line added' : ''))
+       call a:hulit.Print(a:item. collstr, descr. descr_nl)
+    else
+       call a:hulit.AddLiteral('[')
+    endif
 endfunc "}}}
 
 let s:doc['['] = function("s:DocCollection")
@@ -318,9 +382,15 @@ endfunc "}}}
 let s:doc['\%['] = function("s:DocOptAtoms")
 let s:doc[']'] = function("s:DocOptAtoms")
 
-let s:doc['\c'] = "ignore case while matching the pattern"
-let s:doc['\C'] = "match case while matching the pattern"
-let s:doc['\Z'] = "ignore composing characters in the pattern"
+func! s:DocAnywhere(bull, hulit, item, msg) "{{{
+    call a:hulit.Print(a:item, a:msg)
+    " keep state:
+    let s:at_begin_of_pat += 1
+endfunc "}}}
+
+let s:doc['\c'] = [function("s:DocAnywhere"), "ignore case while matching the pattern"]
+let s:doc['\C'] = [function("s:DocAnywhere"), "match case while matching the pattern"]
+let s:doc['\Z'] = [function("s:DocAnywhere"), "ignore composing characters in the pattern"]
 
 " \%d 123
 " \%x 2a
@@ -466,7 +536,7 @@ func! s:NewTokenBiter(str, ...) "{{{
        return bite
     endfunc "}}}
 
-    " get the unparsed rest of input
+    " get the unparsed rest of input (not consuming)
     func! obj.Rest() "{{{
        return self.str
     endfunc "}}}
index 3342102e0a58c9ba321275592e8e374cd56dd839..557af8246f6e5c53646d098eaa0a13f5a13974cd 100644 (file)
@@ -1,10 +1,10 @@
 " File:         makemagic.vim
 " Created:      2011 Apr 18
-" Last Change:  2012 Dec 19
-" Rev Days:     4
+" Last Change:  2013 Mar 06
+" Rev Days:     6
 " Author:      Andy Wokula <anwoku@yahoo.de>
 " License:     Vim License, see :h license
-" Version:     0.1
+" Version:     0.3
 
 "" Comments {{{
 
@@ -18,6 +18,7 @@
 " TODO
 " - recognize [#-\\]], with spaces: [ #-\ \] ]
 "   (collection ends at second ']')
+" + \v\z( => \z(
 
 " 2011 Nov 01  copied from asneeded\makemagic.vim
 "              now asneeded\nwo\makemagic.vim (comments there!)
@@ -108,7 +109,7 @@ endfunc "}}}
 " s:variables {{{
 
 " pattern to match very magic items:
-let s:vmagic_items_pat = '\\.\|%\%([#$(UV[\^cdlouvx]\|''.\|[<>]\%(''.\|[clv]\)\)\|[&()+<=>?|]\|@\%([!=>]\|<[!=]\)\|{'
+let s:vmagic_items_pat = '\C\\\%(z(\|.\)\|%\%([#$(UV[\^cdlouvx]\|[<>]\=\%(''.\|\d\+[clv]\)\)\|[&()+<=>?|]\|@\%([!=>]\|<[!=]\)\|{'
 
 " not escaped - require an even number of '\' (zero or more) to the left:
 let s:not_escaped  = '\%(\%(^\|[^\\]\)\%(\\\\\)*\)\@<='
@@ -129,7 +130,7 @@ let s:switchpat = {
 
 " skip over a collection (starting at '[' (same for all magic modes) or
 " starting at '\_[' (same for all modes))
-let s:collection_skip_pat = '^\%(\\_\)\=\[\^\=]\=\%(\%(\\[\^\]\-\\bertn]\|\[:\w\+:]\|[^\]]\)\@>\)*]'
+let s:collection_skip_pat = '^\%(\\_\)\=\[\^\=]\=\%(\%(\\[\^\]\-\\bertn]\|\[:\w\+:]\|\[=.=]\|\[\..\.]\|[^\]]\)\@>\)*]'
 
 " }}}
 
index e38bc62631975f3be794d0f2f1e1a5c87e4c40ed..f4500fa416eb7dd354b46ed7c66fca2e6fd70737 100644 (file)
@@ -1,20 +1,21 @@
 *explainpat.txt*    Give detailed help on a regexp pattern.
 
-                   For Vim version 7.0.  Last change: 2012 Dec 19
+                   For Vim version 7.0.  Last change: 2013 Mar 09
                    By Andy Wokula <anwoku@yahoo.de>
 
                                                *explainpat* *explainpat.vim*
-When you want to inspect a given Vim regexp pattern, this script might save
-you lots of help lookups.  And it will make the structure of a regexp visible.
-And it helps spotting mistakes.
+ExplainPat is a plugin to inspect a Vim regexp pattern and show a line of help
+for each found regexp item.
 
-If you find that it explains something wrong, drop me an email.
+If you find that it explains something wrong, please drop me an email.
 
+URL http://vim.sourceforge.net/scripts/script.php?script_id=4364
 ==============================================================================
                                                *:ExplainPattern*
-:ExplainPattern [{pattern} | {register}]
-                       parse the given Vim {pattern} and print a line of help
-                       (with color) for each found pattern item.  Nested
+:ExplainPattern {pattern}
+:ExplainPattern {register}
+                       inspect the given Vim {pattern} and print a line of
+                       help (with color) for each found pattern item.  Nested
                        items get extra indent.
 
                        A single-char argument is used as {register} argument:
@@ -23,8 +24,8 @@ If you find that it explains something wrong, drop me an email.
                                a       explain pattern from register a
 
 Notes:
-The pattern is first converted into a purely magic pattern using
-|nwo#magic#MakeMagic()|.  This means that embedded |\V| |\M| |\m| |\V|
+The pattern is first converted into a purely |magic| pattern using
+|nwo#magic#MakeMagic()|.  This means that embedded |/\V| |/\M| |/\m| |/\v|
 specifiers are effectively removed from the explanation.
 
 :ExplainPattern also accepts some invalid patterns: >
@@ -32,5 +33,38 @@ specifiers are effectively removed from the explanation.
        Pattern: \)
        \)         end of group
 
+==============================================================================
+History:
+
+v0.5
++ BF `$\n^`
++ wording: `\|' is not an "OR branch" (it separates or branches)
++ NF added tests (not part of release)
++ NF accept custom help printer (for testing purpose, could also be used to
+  export HTML etc.)
+
+v0.4
++ BF `[foo` is a literal string
++ BF for |/star|, |/^| and |/$|, distinguish position in the pattern
+  (sometimes these become literal); special cases: `^**', `^^', `\c^^', `$$',
+  `a\|^b', `a\&*b', `[ab', `\_[ab', ...
+
+v0.3
++ BF accept `\z(...\)` and `\z[N]`
++ BF accept `[=a=]` and `[.a.]` in collections
+
+v0.2
++ include vim_use suggestions [2012 Dec 19]
+  * for collections [^...], add "not matching [...]"
+  * fix `\%>'a1`
+  * more detailed `\%x31`
+
+v0.1 (initial version)
++ start of "first" capturing group, start of 2nd ...
++ `\|' should get less indent than the branches, do we need to create an
+  AST? ! no, keep it straight forward
++ \%[...]
++ \{, \{-
+
 ==============================================================================
 vim:tw=78:fo=tcq2:sts=0:ts=8:sw=8:fdm=marker:fmr=^_\^,^\^:ft=help:
index ebe9fb12475cf6c97398d15f8a58782b64fd7abe..18dd5740e983d6a02c2fae95a332bdf4dcbf3d09 100644 (file)
@@ -1,10 +1,10 @@
 " File:         explainpat.vim
 " Created:      2011 Nov 02
-" Last Change:  2012 Dec 19
-" Rev Days:     3
+" Last Change:  2013 Mar 08
+" Rev Days:     7
 " Author:      Andy Wokula <anwoku@yahoo.de>
 " License:     Vim License, see :h license
-" Version:     0.2
+" Version:     0.5
 
 " :ExplainPattern [pattern]
 "