From 1f1ec255b080e74de602667e8b6285a638efb5ec Mon Sep 17 00:00:00 2001 From: Andy Wokula Date: Sun, 6 Aug 2017 19:41:53 +0200 Subject: [PATCH] updated to v0.7 (2013) --- autoload/explainpat.vim | 97 ++++++++++++++++++++++++++++++----------- doc/explainpat.txt | 36 +++++++++++---- 2 files changed, 99 insertions(+), 34 deletions(-) diff --git a/autoload/explainpat.vim b/autoload/explainpat.vim index a45fa58..6c65567 100644 --- a/autoload/explainpat.vim +++ b/autoload/explainpat.vim @@ -1,14 +1,31 @@ " File: explainpat.vim " Created: 2011 Nov 02 -" Last Change: 2013 Mar 09 -" Rev Days: 8 +" Last Change: 2013 Dec 30 +" Rev Days: 12 " Author: Andy Wokula " License: Vim License, see :h license -" Version: 0.5 +" Version: 0.7 " 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 @@ -52,7 +69,7 @@ func! explainpat#ExplainPattern(cmd_arg, ...) "{{{ 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 != '' @@ -83,7 +100,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 +109,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 +121,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') @@ -160,7 +177,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 +186,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['\@<='] = "(assertion) require match for preceding atom to the left" -let s:doc['\@= 1 @@ -211,7 +239,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 +254,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 +288,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 +307,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 +326,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 +395,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 "}}} @@ -484,8 +531,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 +569,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 "}}} diff --git a/doc/explainpat.txt b/doc/explainpat.txt index f4500fa..86cab16 100644 --- a/doc/explainpat.txt +++ b/doc/explainpat.txt @@ -1,11 +1,12 @@ *explainpat.txt* Give detailed help on a regexp pattern. - For Vim version 7.0. Last change: 2013 Mar 09 + For Vim version 7.0. Last change: 2013 Jun 29 By Andy Wokula *explainpat* *explainpat.vim* ExplainPat is a plugin to inspect a Vim regexp pattern and show a line of help -for each found regexp item. +for each found regexp item. Purpose is to get a better view on somebody +else's complex regexp string. It may also help with spotting mistakes. If you find that it explains something wrong, please drop me an email. @@ -22,6 +23,7 @@ URL http://vim.sourceforge.net/scripts/script.php?script_id=4364 / explain the last search pattern * explain pattern from the clipboard a explain pattern from register a + etc. Notes: The pattern is first converted into a purely |magic| pattern using @@ -33,12 +35,30 @@ specifiers are effectively removed from the explanation. Pattern: \) \) end of group +============================================================================== +TODO: + +Ideas: +- If the user already knows regular expressions but of a different kind, + explain items in that different language. + Other regexp idioms: + Perl, Python, Emacs, Java, C#, Sed, Grep; + Vim ... very magic, nomagic, very nomagic + Possible config var name: + g:explainpat_user_knows = "Perl" + g:explainpat_background = "Perl" + g:explainpat_in_terms_of = "Perl" + g:explainpat_language = "Perl" + ============================================================================== History: +v0.6 ++ BF `[]` is a literal string (not a collection) + v0.5 + BF `$\n^` -+ wording: `\|' is not an "OR branch" (it separates or branches) ++ 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.) @@ -46,8 +66,8 @@ v0.5 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', ... + (sometimes these become literal); special cases: `^**`, `^^`, `\c^^`, `$$`, + `a\|^b`, `a\&*b`, `[ab`, `\_[ab`, ... v0.3 + BF accept `\z(...\)` and `\z[N]` @@ -61,10 +81,10 @@ v0.2 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 ++ `\|` 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: -- 2.39.2