X-Git-Url: https://git.madduck.net/etc/vim.git/blobdiff_plain/f96996df158d8c20be551ee728adf5618802d347..8b7939ff867684ca9e31f1f0022fb91bbbdf152d:/autoload/explainpat.vim?ds=sidebyside diff --git a/autoload/explainpat.vim b/autoload/explainpat.vim index a45fa58..0fded10 100644 --- a/autoload/explainpat.vim +++ b/autoload/explainpat.vim @@ -1,14 +1,30 @@ " File: explainpat.vim " Created: 2011 Nov 02 -" Last Change: 2013 Mar 09 -" Rev Days: 8 +" Last Change: 2017 Dec 15 +" Version: 0.9 " Author: Andy Wokula " License: Vim License, see :h license -" Version: 0.5 " Implements :ExplainPattern [pattern] +" History: "{{{ +" 2013 Jun 21 AND/OR text is confusing, removed +" 2013 Apr 20 ... +"}}} + " 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 @@ -50,9 +66,9 @@ func! explainpat#ExplainPattern(cmd_arg, ...) "{{{ " >=1 at pos 0 or after '\|', '\&', '\(', '\%(' or '\n'; else 0 or less: let s:at_begin_of_pat = 1 - let hulit = a:0>=1 && type(a:1)==s:DICT ? a:1 : s:NewHelpPrinter() + let hulit = a:0>=1 && type(a:1)==s:DICT ? a:1 : explainpat#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 != '' @@ -83,7 +99,7 @@ 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 ... @@ -92,7 +108,7 @@ let s:doc = {} " {{{ 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 "}}} @@ -104,7 +120,7 @@ func! s:DocBeginOfPat(bull, hulit, item, msg) "{{{ 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') @@ -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 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 `*'") @@ -160,7 +176,7 @@ func! s:DocBraceMulti(bull, hulit, item) "{{{ 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 "}}} @@ -169,8 +185,23 @@ 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['\@<='] = "(assertion) require match for preceding atom to the left" -let s:doc['\@= 1 @@ -211,7 +242,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 - 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 "}}} @@ -225,6 +257,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" +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 @@ -244,7 +291,8 @@ func! s:DocBspercAt(bull, hulit, item) "{{{ 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 "}}} @@ -262,7 +310,8 @@ func! s:DocBspercBefore(bull, hulit, item) "{{{ 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 "}}} @@ -280,7 +329,8 @@ func! s:DocBspercAfter(bull, hulit, item) "{{{ 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 "}}} @@ -348,14 +398,14 @@ let s:coll_skip_pat = '^\^\=]\=\%(\%(\\[\^\]\-\\bertn]\|\[:\w\+:]\|\[=.=]\|\[\.. 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) - else - call a:hulit.AddLiteral('[') endif endfunc "}}} @@ -436,7 +486,13 @@ let s:doc['\%U'] = function("s:DocBspercHexEight") " 1234abcd " \V "}}} -func! s:NewHelpPrinter() "{{{ +" {{{ +func! s:SillyCheck(digits) "{{{ + return strlen(a:digits) < 10 ? a:digits : '{silly large number}' +endfunc "}}} +" }}} + +func! explainpat#NewHelpPrinter() "{{{ let obj = {} let obj.literals = '' let obj.indents = [] @@ -484,8 +540,9 @@ func! s:NewHelpPrinter() "{{{ 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 = '' @@ -521,18 +578,15 @@ func! s:NewHelpPrinter() "{{{ return obj endfunc "}}} -func! s:NewTokenBiter(str, ...) "{{{ +func! s:NewTokenBiter(str) "{{{ " {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 '^' - 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 "}}}