]> git.madduck.net Git - etc/vim.git/blobdiff - autoload/explainpat.vim

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:

added \{...\}
[etc/vim.git] / autoload / explainpat.vim
index a45fa5805689498c865344272bc1e85bbc184b48..566273266fc981d00b81d37c22cb182946766377 100644 (file)
@@ -1,14 +1,30 @@
 " File:         explainpat.vim
 " Created:      2011 Nov 02
 " File:         explainpat.vim
 " Created:      2011 Nov 02
-" Last Change:  2013 Mar 09
-" Rev Days:     8
+" Last Change:  2017 Oct 20
+" Version:     0.7
 " Author:      Andy Wokula <anwoku@yahoo.de>
 " License:     Vim License, see :h license
 " Author:      Andy Wokula <anwoku@yahoo.de>
 " License:     Vim License, see :h license
-" Version:     0.5
 
 " Implements :ExplainPattern [pattern]
 
 
 " Implements :ExplainPattern [pattern]
 
+" History: "{{{
+" 2013 Jun 21  AND/OR text is confusing, removed
+" 2013 Apr 20  ...
+"}}}
+
 " TODO {{{
 " TODO {{{
+" - add something like "(empty) ... match everywhere" ... example: '\v(&&|str)'
+"   Pattern: \v(&&|str)
+"   Magic Pattern: \(\&\&\|str\)
+"     \(         start of first capturing group
+"     |                  (empty) match everywhere
+"     |   \&         AND
+"     |                  (empty) match everywhere
+"     |   \&         AND
+"     |                  (empty) match everywhere
+"     | \|         OR
+"     |   str        literal string (3 atom(s))
+"     \)         end of group
 " - more testing, completeness check
 " ? detailed collections
 " ? literal string: also print the unescaped magic items
 " - more testing, completeness check
 " ? detailed collections
 " ? literal string: also print the unescaped magic items
@@ -52,7 +68,7 @@ func! explainpat#ExplainPattern(cmd_arg, ...) "{{{
 
     let hulit = a:0>=1 && type(a:1)==s:DICT ? a:1 : s:NewHelpPrinter()
     call hulit.AddIndent('  ')
 
     let hulit = a:0>=1 && type(a:1)==s:DICT ? a:1 : s:NewHelpPrinter()
     call hulit.AddIndent('  ')
-    let bull = s:NewTokenBiter(magicpat, '')
+    let bull = s:NewTokenBiter(magicpat)
     while !bull.AtEnd()
        let item = bull.Bite(s:magic_item_pattern)
        if item != ''
     while !bull.AtEnd()
        let item = bull.Bite(s:magic_item_pattern)
        if item != ''
@@ -83,7 +99,7 @@ let s:FUNCREF = type(function("tr"))
 let s:LIST = type([])
 " }}}
 
 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 ...
 
 let s:doc = {} " {{{
 " this is all the help data ...
@@ -92,7 +108,7 @@ let s:doc = {} " {{{
 
 func! s:DocOrBranch(bull, hulit, item) "{{{
     call a:hulit.RemIndent()
 
 func! s:DocOrBranch(bull, hulit, item) "{{{
     call a:hulit.RemIndent()
-    call a:hulit.Print(a:item, "OR (separate alternatives)")
+    call a:hulit.Print(a:item, "OR")
     call a:hulit.AddIndent('  ')
     let s:at_begin_of_pat = 2
 endfunc "}}}
     call a:hulit.AddIndent('  ')
     let s:at_begin_of_pat = 2
 endfunc "}}}
@@ -104,7 +120,7 @@ func! s:DocBeginOfPat(bull, hulit, item, msg) "{{{
     let s:at_begin_of_pat = 2
 endfunc "}}}
 
     let s:at_begin_of_pat = 2
 endfunc "}}}
 
-let s:doc['\&'] = [function("s:DocBeginOfPat"), "AND (separate concats, all must match)"]
+let s:doc['\&'] = [function("s:DocBeginOfPat"), "AND"]
 
 let s:ord = split('n first second third fourth fifth sixth seventh eighth ninth')
 
 
 let s:ord = split('n first second third fourth fifth sixth seventh eighth ninth')
 
@@ -150,7 +166,7 @@ let s:doc['\?'] = "(multi) zero or one of the preceding atom"
 " let s:doc['\{-'] = "(multi) N to M, non-greedy"
 
 func! s:DocBraceMulti(bull, hulit, item) "{{{
 " let s:doc['\{-'] = "(multi) N to M, non-greedy"
 
 func! s:DocBraceMulti(bull, hulit, item) "{{{
-    let rest = a:bull.Bite('^-\=\d*\%(,\d*\)\=}')
+    let rest = a:bull.Bite('^-\=\d*\%(,\d*\)\=\\\=}')
     if rest != ""
        if rest == '-}'
            call a:hulit.Print(a:item. rest, "non-greedy version of `*'")
     if rest != ""
        if rest == '-}'
            call a:hulit.Print(a:item. rest, "non-greedy version of `*'")
@@ -160,7 +176,7 @@ func! s:DocBraceMulti(bull, hulit, item) "{{{
            call a:hulit.Print(a:item. rest, "(multi) N to M, greedy")
        endif
     else
            call a:hulit.Print(a:item. rest, "(multi) N to M, greedy")
        endif
     else
-       echoerr printf('ExplainPattern: cannot parse %s', a:item. a:bull.Rest())
+       call a:hulit.Print(a:item, "(invalid) incomplete `\\{...}' item")
     endif
 endfunc "}}}
 
     endif
 endfunc "}}}
 
@@ -169,8 +185,19 @@ let s:doc['\{'] = function("s:DocBraceMulti")
 let s:doc['\@>'] = "(multi) match preceding atom like a full pattern"
 let s:doc['\@='] = "(assertion) require match for preceding atom"
 let s:doc['\@!'] = "(assertion) forbid match for preceding atom"
 let s:doc['\@>'] = "(multi) match preceding atom like a full pattern"
 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"
+
+func! s:DocBefore(bull, hulit, item) "{{{
+    let rest = a:bull.Bite('^[=!]')
+    if rest == "="
+       call a:hulit.Print(a:item.rest, "(assertion) require match for preceding atom to the left")
+    elseif rest == "!"
+       call a:hulit.Print(a:item.rest, "(assertion) forbid match for preceding atom to the left")
+    else
+       call a:hulit.Print(a:item.rest, "(invalid) `\\@<' must be followed by `=' or `!'")
+    endif
+endfunc "}}}
+
+let s:doc['\@<'] = function("s:DocBefore")
 
 func! s:DocCircumFlex(bull, hulit, item) "{{{
     if s:at_begin_of_pat >= 1
 
 func! s:DocCircumFlex(bull, hulit, item) "{{{
     if s:at_begin_of_pat >= 1
@@ -211,7 +238,8 @@ func! s:DocUnderscore(bull, hulit, item) "{{{
        let cclass_doc = get(s:doc, '\'. cclass, '(invalid character class)')
        call a:hulit.Print(a:item. cclass, printf('%s or end-of-line', cclass_doc))
     else
        let cclass_doc = get(s:doc, '\'. cclass, '(invalid character class)')
        call a:hulit.Print(a:item. cclass, printf('%s or end-of-line', cclass_doc))
     else
-       echoerr printf('ExplainPattern: cannot parse %s', a:item. matchstr(a:bull.Rest(), '.'))
+       call a:hulit.Print(a:item, "(invalid) `\\_' should be followed by a letter or `[...]'")
+       " echoerr printf('ExplainPattern: cannot parse %s', a:item. matchstr(a:bull.Rest(), '.'))
     endif
 endfunc "}}}
 
     endif
 endfunc "}}}
 
@@ -225,6 +253,21 @@ let s:doc['\%$'] = "(assertion) match at end of buffer"
 let s:doc['\%V'] = "(assertion) match within the Visual area"
 let s:doc['\%#'] = "(assertion) match with cursor position"
 
 let s:doc['\%V'] = "(assertion) match within the Visual area"
 let s:doc['\%#'] = "(assertion) match with cursor position"
 
+func! s:DocRegexEngine(bull, hulit, item) "{{{
+    let engine = a:bull.Bite('^[012]')
+    if engine == "0"
+       call a:hulit.Print(a:item.engine, 'Force automatic selection of the regexp engine (since v7.3.970).')
+    elseif engine == "1" 
+       call a:hulit.Print(a:item.engine, 'Force using the old engine (since v7.3.970).')
+    elseif engine == "2"
+       call a:hulit.Print(a:item.engine, 'Force using the NFA engine (since v7.3.970).')
+    else
+       call a:hulit.Print(a:item, '(invalid) \%#= can only be followed by 0, 1, or 2')
+    endif
+endfunc "}}}
+
+let s:doc['\%#='] = function("s:DocRegexEngine")
+
 " \%'m   \%<'m   \%>'m
 " \%23l  \%<23l  \%>23l
 " \%23c  \%<23c  \%>23c
 " \%'m   \%<'m   \%>'m
 " \%23l  \%<23l  \%>23l
 " \%23c  \%<23c  \%>23c
@@ -244,7 +287,8 @@ func! s:DocBspercAt(bull, hulit, item) "{{{
        elseif type ==# "v"
            call a:hulit.Print(a:item.rest, "match in virtual column ". number)
        else
        elseif type ==# "v"
            call a:hulit.Print(a:item.rest, "match in virtual column ". number)
        else
-           echoerr printf('ExplainPattern: incomplete item %s', a:item. rest)
+           call a:hulit.Print(a:item.rest, "(invalid) incomplete `\\%' item")
+           " echoerr printf('ExplainPattern: incomplete item %s', a:item. rest)
        endif
     endif
 endfunc "}}}
        endif
     endif
 endfunc "}}}
@@ -262,7 +306,8 @@ func! s:DocBspercBefore(bull, hulit, item) "{{{
        elseif type ==# "v"
            call a:hulit.Print(a:item.rest, "match before virtual column ". number)
        else
        elseif type ==# "v"
            call a:hulit.Print(a:item.rest, "match before virtual column ". number)
        else
-           echoerr printf('ExplainPattern: incomplete item %s', a:item. rest)
+           call a:hulit.Print(a:item.rest, "(invalid) incomplete `\\%<' item")
+           " echoerr printf('ExplainPattern: incomplete item %s', a:item. rest)
        endif
     endif
 endfunc "}}}
        endif
     endif
 endfunc "}}}
@@ -280,7 +325,8 @@ func! s:DocBspercAfter(bull, hulit, item) "{{{
        elseif type ==# "v"
            call a:hulit.Print(a:item.rest, "match after virtual column ". number)
        else
        elseif type ==# "v"
            call a:hulit.Print(a:item.rest, "match after virtual column ". number)
        else
-           echoerr printf('ExplainPattern: incomplete item %s', a:item. rest)
+           call a:hulit.Print(a:item.rest, "(invalid) incomplete `\\%>' item")
+           " echoerr printf('ExplainPattern: incomplete item %s', a:item. rest)
        endif
     endif
 endfunc "}}}
        endif
     endif
 endfunc "}}}
@@ -348,14 +394,14 @@ let s:coll_skip_pat = '^\^\=]\=\%(\%(\\[\^\]\-\\bertn]\|\[:\w\+:]\|\[=.=]\|\[\..
 
 func! s:DocCollection(bull, hulit, item) "{{{
     let collstr = a:bull.Bite(s:coll_skip_pat)
 
 func! s:DocCollection(bull, hulit, item) "{{{
     let collstr = a:bull.Bite(s:coll_skip_pat)
-    if collstr != ""
+    if collstr == "" || collstr == "]"
+       call a:hulit.AddLiteral('['. collstr)
+    else
        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)
        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 "}}}
 
     endif
 endfunc "}}}
 
@@ -484,8 +530,9 @@ func! s:NewHelpPrinter() "{{{
            if self.literals =~ '\\'
                let self.literals = substitute(self.literals, '\\\(.\)', '\1', 'g')
            endif
            if self.literals =~ '\\'
                let self.literals = substitute(self.literals, '\\\(.\)', '\1', 'g')
            endif
-           let so = self.literals =~ '[^ ]' ? '' : ', spaces only'
-           echon " (". strchars(self.literals). " atom(s)". so.")"
+           let spconly = self.literals =~ '[^ ]' ? '' : ', spaces only'
+           let nlit = strchars(self.literals)
+           echon " (". nlit. (nlit==1 ? " atom" : " atoms"). spconly.")"
        endif
        echohl None
        let self.literals = ''
        endif
        echohl None
        let self.literals = ''
@@ -521,18 +568,15 @@ func! s:NewHelpPrinter() "{{{
     return obj
 endfunc "}}}
 
     return obj
 endfunc "}}}
 
-func! s:NewTokenBiter(str, ...) "{{{
+func! s:NewTokenBiter(str) "{{{
     " {str}    string to eat pieces from
     " {str}    string to eat pieces from
-    " {a:1}    pattern to skip separators
-    let whitepat = a:0>=1 ? a:1 : '^\s*'
-    let obj = {'str': a:str, 'whitepat': whitepat}
+    let obj = {'str': a:str}
 
     " consume piece from start of input matching {pat}
     func! obj.Bite(pat) "{{{
        " {pat}     should start with '^'
 
     " consume piece from start of input matching {pat}
     func! obj.Bite(pat) "{{{
        " {pat}     should start with '^'
-       let skip = matchend(self.str, self.whitepat)
-       let bite = matchstr(self.str, a:pat, skip)
-       let self.str = strpart(self.str, matchend(self.str, self.whitepat, skip + strlen(bite)))
+       let bite = matchstr(self.str, a:pat)
+       let self.str = strpart(self.str, strlen(bite))
        return bite
     endfunc "}}}
 
        return bite
     endfunc "}}}