This mapping has 3 multi-map groups: several pairings are equally correct there. The code view shows one arbitrary valid pairing, not the only one.

Before

1" matchit.vim: (global plugin) Extended "%" matching
2" autload script of matchit plugin, see ../plugin/matchit.vim
3" Last Change: May 20, 2024
4
5" Neovim does not support scriptversion
6if has("vimscript-4")
7 scriptversion 4
8endif
9
…lines 10–64 unchanged (55 lines)
65 " If this function was called from Visual mode, make sure that the cursor
66 " is at the correct end of the Visual range:
67 elseif a:mode == "v"
68 execute "normal! gv\<Esc>"
69 let startpos = [line("."), col(".")]
70 endif
71
72 " First step: if not already done, set the script variables
73 " s:do_BR flag for whether there are backrefs
74 " s:pat parsed version of b:match_words
75 " s:all regexp based on s:pat and the default groups
76 if !exists("b:match_words") || b:match_words == ""
77 let match_words = ""
…lines 78–87 unchanged (10 lines)
88 " quote the special chars in 'matchpairs', replace [,:] with \| and then
89 " append the builtin pairs (/*, */, #if, #ifdef, #ifndef, #else, #elif,
90 " #elifdef, #elifndef, #endif)
91 let default = escape(&mps, '[$^.*~\\/?]') .. (strlen(&mps) ? "," : "") ..
92 \ '\/\*:\*\/,#\s*if\%(n\=def\)\=:#\s*else\>:#\s*elif\%(n\=def\)\=\>:#\s*endif\>'
93 " s:all = pattern with all the keywords
94 let match_words = match_words .. (strlen(match_words) ? "," : "") .. default
95 let s:last_words = match_words
96 if match_words !~ s:notslash .. '\\\d'
97 let s:do_BR = 0
98 let s:pat = match_words
99 else
100 let s:do_BR = 1
101 let s:pat = s:ParseWords(match_words)
102 endif
103 let s:all = substitute(s:pat, s:notslash .. '\zs[,:]\+', '\\|', 'g')
104 " un-escape \, to ,
105 let s:all = substitute(s:all, '\\,', ',', 'g')
106 " Just in case there are too many '\(...)' groups inside the pattern, make
107 " sure to use \%(...) groups, so that error E872 can be avoided
108 let s:all = substitute(s:all, '\\(', '\\%(', 'g')
109 let s:all = '\%(' .. s:all .. '\)'
110 if exists("b:match_debug")
111 let b:match_pat = s:pat
…lines 112–337 unchanged (226 lines)
338 let b:match_table = ""
339 let b:match_word = ""
340 endif
341 endif
342 return ini .. ":" .. tailBR
343endfun
344
345" Input a comma-separated list of groups with backrefs, such as
346" a:groups = '\(foo\):end\1,\(bar\):end\1'
347" and return a comma-separated list of groups with backrefs replaced:
348" return '\(foo\):end\(foo\),\(bar\):end\(bar\)'
349fun! s:ParseWords(groups)
350 let groups = substitute(a:groups .. ",", s:notslash .. '\zs[,:]*,[,:]*', ',', 'g')
…lines 351–535 unchanged (185 lines)
536 let current = strpart(tail, 0, i-1)
537 if a:branch == ""
538 let currpat = current
539 else
540 let currpat = substitute(current, s:notslash .. a:branch, '\\|', 'g')
541 endif
542 " un-escape \, to ,
543 let currpat = substitute(currpat, '\\,', ',', 'g')
544 while a:string !~ a:prefix .. currpat .. a:suffix
545 let tail = strpart(tail, i)
546 let i = matchend(tail, s:notslash .. a:comma)
547 if i == -1
548 return -1
549 endif
550 let current = strpart(tail, 0, i-1)
551 if a:branch == ""
552 let currpat = current
553 else
554 let currpat = substitute(current, s:notslash .. a:branch, '\\|', 'g')
555 endif
556 if a:0
557 let alttail = strpart(alttail, j)
558 let j = matchend(alttail, s:notslash .. a:comma)
559 endif
560 endwhile
561 if a:0
562 let current = current .. a:comma .. strpart(alttail, 0, j-1)
…lines 563–618 unchanged (56 lines)
619 endif
620 if (match_words != s:last_words) || (&mps != s:last_mps) ||
621 \ exists("b:match_debug")
622 let default = escape(&mps, '[$^.*~\\/?]') .. (strlen(&mps) ? "," : "") ..
623 \ '\/\*:\*\/,#\s*if\%(n\=def\)\=:#\s*else\>:#\s*elif\>:#\s*endif\>'
624 let s:last_mps = &mps
625 let match_words = match_words .. (strlen(match_words) ? "," : "") .. default
626 let s:last_words = match_words
627 if match_words !~ s:notslash .. '\\\d'
628 let s:do_BR = 0
629 let s:pat = match_words
630 else
631 let s:do_BR = 1
…lines 632–793 unchanged (162 lines)

After

1" matchit.vim: (global plugin) Extended "%" matching
2" autload script of matchit plugin, see ../plugin/matchit.vim
3" Last Change: Jan 06, 2025
4
5" Neovim does not support scriptversion
6if has("vimscript-4")
7 scriptversion 4
8endif
9
…lines 10–65 unchanged (56 lines)
66 " is at the correct end of the Visual range:
67 elseif a:mode == "v"
68 execute "normal! gv\<Esc>"
69 let startpos = [line("."), col(".")]
70 endif
71
72 " Check for custom match function hook
73 if exists("b:match_function")
74 let MatchFunc = b:match_function
75 try
76 let result = call(MatchFunc, [a:forward])
77 if !empty(result)
78 call cursor(result)
79 return s:CleanUp(restore_options, a:mode, startpos)
80 endif
81 catch /.*/
82 if exists("b:match_debug")
83 echohl WarningMsg
84 echom 'matchit: b:match_function error: ' .. v:exception
85 echohl NONE
86 endif
87 return s:CleanUp(restore_options, a:mode, startpos)
88 endtry
89 " Empty result: fall through to regular matching
90 endif
91
92 " First step: if not already done, set the script variables
93 " s:do_BR flag for whether there are backrefs
94 " s:pat parsed version of b:match_words
95 " s:all regexp based on s:pat and the default groups
96 if !exists("b:match_words") || b:match_words == ""
…lines 97–107 unchanged (11 lines)
108 " quote the special chars in 'matchpairs', replace [,:] with \| and then
109 " append the builtin pairs (/*, */, #if, #ifdef, #ifndef, #else, #elif,
110 " #elifdef, #elifndef, #endif)
111 let default = escape(&mps, '[$^.*~\\/?]') .. (strlen(&mps) ? "," : "") ..
112 \ '\/\*:\*\/,#\s*if\%(n\=def\)\=:#\s*else\>:#\s*elif\%(n\=def\)\=\>:#\s*endif\>'
113 " s:all = pattern with all the keywords
114 let match_words = s:Append(match_words, default)
115 let s:last_words = match_words
116 if match_words !~ s:notslash .. '\\\d'
117 let s:do_BR = 0
118 let s:pat = match_words
119 else
120 let s:do_BR = 1
121 let s:pat = s:ParseWords(match_words)
122 endif
123 let s:all = substitute(s:pat, s:notslash .. '\zs[,:]\+', '\\|', 'g')
124 " un-escape \, and \: to , and :
125 let s:all = substitute(s:all, s:notslash .. '\zs\\\(:\|,\)', '\1', 'g')
126 " Just in case there are too many '\(...)' groups inside the pattern, make
127 " sure to use \%(...) groups, so that error E872 can be avoided
128 let s:all = substitute(s:all, '\\(', '\\%(', 'g')
129 let s:all = '\%(' .. s:all .. '\)'
130 if exists("b:match_debug")
131 let b:match_pat = s:pat
…lines 132–358 unchanged (227 lines)
359 let b:match_word = ""
360 endif
361 endif
362 return ini .. ":" .. tailBR
363endfun
364
365" String append item2 to item and add ',' in between items
366fun! s:Append(item, item2)
367 if a:item == ''
368 return a:item2
369 endif
370 " there is already a trailing comma, don't add another one
371 if a:item[-1:] == ','
372 return a:item .. a:item2
373 endif
374 return a:item .. ',' .. a:item2
375endfun
376
377" Input a comma-separated list of groups with backrefs, such as
378" a:groups = '\(foo\):end\1,\(bar\):end\1'
379" and return a comma-separated list of groups with backrefs replaced:
380" return '\(foo\):end\(foo\),\(bar\):end\(bar\)'
381fun! s:ParseWords(groups)
…lines 382–567 unchanged (186 lines)
568 let current = strpart(tail, 0, i-1)
569 if a:branch == ""
570 let currpat = current
571 else
572 let currpat = substitute(current, s:notslash .. a:branch, '\\|', 'g')
573 endif
574 " un-escape \, and \: to , and :
575 let currpat = substitute(currpat, s:notslash .. '\zs\\\(:\|,\)', '\1', 'g')
576 while a:string !~ a:prefix .. currpat .. a:suffix
577 let tail = strpart(tail, i)
578 let i = matchend(tail, s:notslash .. a:comma)
579 if i == -1
580 return -1
581 endif
582 let current = strpart(tail, 0, i-1)
583 if a:branch == ""
584 let currpat = current
585 else
586 let currpat = substitute(current, s:notslash .. a:branch, '\\|', 'g')
587 endif
588 " un-escape \, and \: to , and :
589 let currpat = substitute(currpat, s:notslash .. '\zs\\\(:\|,\)', '\1', 'g')
590 if a:0
591 let alttail = strpart(alttail, j)
592 let j = matchend(alttail, s:notslash .. a:comma)
593 endif
594 endwhile
595 if a:0
…lines 596–652 unchanged (57 lines)
653 endif
654 if (match_words != s:last_words) || (&mps != s:last_mps) ||
655 \ exists("b:match_debug")
656 let default = escape(&mps, '[$^.*~\\/?]') .. (strlen(&mps) ? "," : "") ..
657 \ '\/\*:\*\/,#\s*if\%(n\=def\)\=:#\s*else\>:#\s*elif\>:#\s*endif\>'
658 let s:last_mps = &mps
659 let match_words = s:Append(match_words, default)
660 let s:last_words = match_words
661 if match_words !~ s:notslash .. '\\\d'
662 let s:do_BR = 0
663 let s:pat = match_words
664 else
665 let s:do_BR = 1
…lines 666–827 unchanged (162 lines)

Before

script_file
comment "\" matchit.vim: (global plugin) Extended \"%\" matching"
comment "\" autload script of matchit plugin, see ../plugin/matchit.v"...
comment "\" Last Change: May 20, 2024"
comment "\" Neovim does not support scriptversion"
if_statement
if "if"
call_expression
identifier "has"
( "("
string_literal "\"vimscript-4\""
) ")"
body
unknown_builtin_statement
unknown_command_name "scriptversion"
arguments
command_argument "4"
endif "endif"
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "last_mps"
= "="
string_literal "\"\""
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "last_words"
= "="
string_literal "\":\""
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "patBR"
= "="
string_literal "\"\""
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "save_cpo"
= "="
option
& "&"
option_name "cpo"
set_statement
set "set"
set_item
default_option
option_name "cpo"
& "&"
vim "vim"
comment "\" Auto-complete mappings: (not yet \"ready for prime time\")"
comment "\" TODO Read :help write-plugin for the \"right\" way to let th"...
comment "\" specify a key binding."
comment "\" let g:match_auto = '<C-]>'"
comment "\" let g:match_autoCR = '<C-CR>'"
comment "\" if exists(\"g:match_auto\")"
comment "\" execute \"inoremap \" . g:match_auto . ' x<Esc>\"=<SID>Auto"...
comment "\" endif"
comment "\" if exists(\"g:match_autoCR\")"
comment "\" execute \"inoremap \" . g:match_autoCR . ' <CR><C-R>=<SID>"...
comment "\" endif"
comment "\" if exists(\"g:match_gthhoh\")"
comment "\" execute \"inoremap \" . g:match_gthhoh . ' <C-O>:call <SID"...
comment "\" endif \" gthhoh = \"Get the heck out of here!\""
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "notslash"
= "="
string_literal "'\\\\\\@1<!\\%(\\\\\\\\\\)*'"
function_definition (+114 nodes collapsed)
function_definition
function "function"
function_declaration
identifier "matchit#Match_wrapper"
parameters
( "("
identifier "word"
, ","
identifier "forward"
, ","
identifier "mode"
) ")"
range "range"
body
let_statement
let "let"
identifier "restore_options"
= "="
call_expression
scoped_identifier
scope "s:"
identifier "RestoreOptions"
( "("
) ")"
comment "\" In s:CleanUp(), we may need to check whether the cursor mo"...
let_statement
let "let"
identifier "startpos"
= "="
list
[ "["
call_expression
identifier "line"
( "("
string_literal "\".\""
) ")"
, ","
call_expression
identifier "col"
( "("
string_literal "\".\""
) ")"
] "]"
comment "\" if a count has been applied, use the default [count]% mode"...
if_statement (+33 nodes collapsed)
if_statement (+83 nodes collapsed)
comment "\" First step: if not already done, set the script variables"
comment "\" s:do_BR flag for whether there are backrefs"
comment "\" s:pat parsed version of b:match_words"
comment "\" s:all regexp based on s:pat and the default groups"
if_statement (+50 nodes collapsed)
comment "\" Thanks to Preben \"Peppe\" Guldberg and Bram Moolenaar for t"...
if_statement
if "if"
binary_operation (+27 nodes collapsed)
body
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "last_mps"
= "="
option
& "&"
option_name "mps"
comment "\" quote the special chars in 'matchpairs', replace [,:] with"...
comment "\" append the builtin pairs (/*, */, #if, #ifdef, #ifndef, #e"...
comment "\" #elifdef, #elifndef, #endif)"
let_statement (+32 nodes collapsed)
comment "\" s:all = pattern with all the keywords"
let_statement
let "let"
identifier "match_words"
= "="
binary_operation
binary_operation
identifier "match_words" any 2:1
.. ".."
( "("
ternary_expression
call_expression
identifier "strlen"
( "("
identifier "match_words" any 2:1
) ")"
? "?"
string_literal "\",\""
: ":"
string_literal "\"\""
) ")"
.. ".."
identifier "default"
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "last_words"
= "="
identifier "match_words"
if_statement (+50 nodes collapsed)
let_statement (+24 nodes collapsed)
comment "\" un-escape \\, to ,"
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "all"
= "="
call_expression
identifier "substitute"
( "("
scoped_identifier
scope "s:"
identifier "all"
, ","
string_literal "'\\\\,'"
, ","
string_literal "','"
, ","
string_literal "'g'"
) ")"
comment "\" Just in case there are too many '\\(...)' groups inside the"...
comment "\" sure to use \\%(...) groups, so that error E872 can be avoi"...
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "all"
= "="
call_expression
identifier "substitute"
( "("
scoped_identifier
scope "s:"
identifier "all"
, ","
string_literal "'\\\\('"
, ","
string_literal "'\\\\%('"
, ","
string_literal "'g'"
) ")"
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "all"
= "="
binary_operation
binary_operation
string_literal "'\\%('"
.. ".."
scoped_identifier
scope "s:"
identifier "all"
.. ".."
string_literal "'\\)'"
if_statement
if "if"
call_expression
identifier "exists"
( "("
string_literal "\"b:match_debug\""
) ")"
body
let_statement
let "let"
scoped_identifier
scope "b:"
identifier "match_pat"
= "="
scoped_identifier
scope "s:"
identifier "pat"
endif "endif"
comment "\" Reconstruct the version with unresolved backrefs."
let_statement (+25 nodes collapsed)
let_statement (+24 nodes collapsed)
comment "\" un-escape \\, to ,"
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "patBR"
= "="
call_expression
identifier "substitute"
( "("
scoped_identifier
scope "s:"
identifier "patBR"
, ","
string_literal "'\\\\,'"
, ","
string_literal "','"
, ","
string_literal "'g'"
) ")"
endif "endif"
comment "\" Second step: set the following local variables:"
comment "\" matchline = line on which the cursor started"
comment "\" curcol = number of characters before match"
comment "\" prefix = regexp for start of line to start of match"
comment "\" suffix = regexp for end of match to end of line"
comment "\" Require match to end on or after the cursor and prefer it "...
comment "\" start on or before the cursor."
let_statement
let "let"
identifier "matchline"
= "="
call_expression
identifier "getline"
( "("
index_expression
identifier "startpos"
[ "["
integer_literal "0"
] "]"
) ")"
if_statement (+210 nodes collapsed)
if_statement (+32 nodes collapsed)
comment "\" Third step: Find the group and single word that match, an"...
comment "\" (backref) versions of these. Then, resolve the backrefs."
comment "\" Set the following local variable:"
comment "\" group = colon-separated list of patterns, one of which mat"...
comment "\" = ini:mid:fin or ini:fin"
comment "\""
comment "\" Now, set group and groupBR to the matching group: 'if:endi"...
comment "\" 'while:endwhile' or whatever. A bit of a kluge: s:Choose"...
comment "\" group . \",\" . groupBR, and we pick it apart."
let_statement (+27 nodes collapsed)
let_statement
let "let"
identifier "i"
= "="
call_expression
identifier "matchend"
( "("
identifier "group"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "\",\""
) ")"
let_statement
let "let"
identifier "groupBR"
= "="
call_expression
identifier "strpart"
( "("
identifier "group"
, ","
identifier "i"
) ")"
let_statement
let "let"
identifier "group"
= "="
call_expression
identifier "strpart"
( "("
identifier "group"
, ","
integer_literal "0"
, ","
binary_operation
identifier "i"
- "-"
integer_literal "1"
) ")"
comment "\" Now, matchline =~ prefix . substitute(group,':','\\|','g') "...
if_statement (+27 nodes collapsed)
if_statement (+50 nodes collapsed)
comment "\" Fourth step: Set the arguments for searchpair()."
let_statement
let "let"
identifier "i"
= "="
call_expression
identifier "matchend"
( "("
identifier "group"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "\":\""
) ")"
let_statement
let "let"
identifier "j"
= "="
call_expression
identifier "matchend"
( "("
identifier "group"
, ","
binary_operation
binary_operation
string_literal "'.*'"
.. ".."
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "\":\""
) ")"
let_statement
let "let"
identifier "ini"
= "="
call_expression
identifier "strpart"
( "("
identifier "group"
, ","
integer_literal "0"
, ","
binary_operation
identifier "i"
- "-"
integer_literal "1"
) ")"
let_statement (+34 nodes collapsed)
let_statement
let "let"
identifier "fin"
= "="
call_expression
identifier "strpart"
( "("
identifier "group"
, ","
identifier "j"
) ")"
comment "\"Un-escape the remaining , and : characters."
let_statement
let "let"
identifier "ini"
= "="
call_expression
identifier "substitute"
( "("
identifier "ini"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\\\(:\\|,\\)'"
, ","
string_literal "'\\1'"
, ","
string_literal "'g'"
) ")"
let_statement
let "let"
identifier "mid"
= "="
call_expression
identifier "substitute"
( "("
identifier "mid"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\\\(:\\|,\\)'"
, ","
string_literal "'\\1'"
, ","
string_literal "'g'"
) ")"
let_statement
let "let"
identifier "fin"
= "="
call_expression
identifier "substitute"
( "("
identifier "fin"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\\\(:\\|,\\)'"
, ","
string_literal "'\\1'"
, ","
string_literal "'g'"
) ")"
comment "\" searchpair() requires that these patterns avoid \\(\\) group"...
let_statement
let "let"
identifier "ini"
= "="
call_expression
identifier "substitute"
( "("
identifier "ini"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\('"
, ","
string_literal "'\\\\%('"
, ","
string_literal "'g'"
) ")"
let_statement
let "let"
identifier "mid"
= "="
call_expression
identifier "substitute"
( "("
identifier "mid"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\('"
, ","
string_literal "'\\\\%('"
, ","
string_literal "'g'"
) ")"
let_statement
let "let"
identifier "fin"
= "="
call_expression
identifier "substitute"
( "("
identifier "fin"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\('"
, ","
string_literal "'\\\\%('"
, ","
string_literal "'g'"
) ")"
comment "\" Set mid. This is optimized for readability, not micro-eff"...
if_statement (+43 nodes collapsed)
comment "\" Set flag. This is optimized for readability, not micro-ef"...
if_statement (+51 nodes collapsed)
comment "\" Set skip."
if_statement (+43 nodes collapsed)
let_statement
let "let"
identifier "skip"
= "="
call_expression
scoped_identifier
scope "s:"
identifier "ParseSkip"
( "("
identifier "skip"
) ")"
if_statement (+40 nodes collapsed)
comment "\" Fifth step: actually start moving the cursor and call sea"...
comment "\" Later, :execute restore_cursor to get to the original scre"...
let_statement
let "let"
identifier "view"
= "="
call_expression
identifier "winsaveview"
( "("
) ")"
call_statement
call "call"
call_expression
identifier "cursor"
( "("
integer_literal "0"
, ","
binary_operation
identifier "curcol"
+ "+"
integer_literal "1"
) ")"
if_statement (+58 nodes collapsed)
let_statement
let "let"
identifier "sp_return"
= "="
call_expression
identifier "searchpair"
( "("
identifier "ini"
, ","
identifier "mid"
, ","
identifier "fin"
, ","
identifier "flag"
, ","
identifier "skip"
) ")"
if_statement (+57 nodes collapsed)
let_statement (+25 nodes collapsed)
comment "\" Restore cursor position and original screen."
call_statement
call "call"
call_expression
identifier "winrestview"
( "("
identifier "view"
) ")"
normal_statement
normal "normal"
bang
! "!"
commands " m'"
if_statement
if "if"
binary_operation
identifier "sp_return"
> ">"
integer_literal "0"
body
execute_statement
execute "execute"
identifier "final_position"
endif "endif"
if_statement (+39 nodes collapsed)
return_statement (+23 nodes collapsed)
endfunction "endfun"
comment "\" Restore options and do some special handling for Operator-"...
comment "\" The optional argument is the tail of the matching group."
function_definition (+200 nodes collapsed)
comment "\" Example (simplified HTML patterns): if"
comment "\" a:groupBR = '<\\(\\k\\+\\)>:</\\1>'"
comment "\" a:prefix = '^.\\{3}\\('"
comment "\" a:group = '<\\(\\k\\+\\)>:</\\(\\k\\+\\)>'"
comment "\" a:suffix = '\\).\\{2}$'"
comment "\" a:matchline = \"123<tag>12\" or \"123</tag>12\""
comment "\" then extract \"tag\" from a:matchline and return \"<tag>:</ta"...
function_definition (+481 nodes collapsed)
comment "\" Input a comma-separated list of groups with backrefs, such"...
comment "\" a:groups = '\\(foo\\):end\\1,\\(bar\\):end\\1'"
comment "\" and return a comma-separated list of groups with backrefs "...
comment "\" return '\\(foo\\):end\\(foo\\),\\(bar\\):end\\(bar\\)'"
function_definition (+278 nodes collapsed)
comment "\" TODO I think this can be simplified and/or made more effic"...
comment "\" TODO What should I do if a:start is out of range?"
comment "\" Return a regexp that matches all of a:string, such that"
comment "\" matchstr(a:string, regexp) represents the match for a:pat "...
comment "\" as close to a:start as possible, before being preferred to"...
comment "\" ends after a:start ."
comment "\" Usage:"
comment "\" let regexp = s:Wholematch(getline(\".\"), 'foo\\|bar', col(\"."...
comment "\" let i = match(getline(\".\"), regexp)"
comment "\" let j = matchend(getline(\".\"), regexp)"
comment "\" let match = matchstr(getline(\".\"), regexp)"
function_definition (+132 nodes collapsed)
comment "\" No extra arguments: s:Ref(string, d) will"
comment "\" find the d'th occurrence of '\\(' and return it, along with"...
comment "\" to and including the matching '\\)'."
comment "\" One argument: s:Ref(string, d, \"start\") returns the index"...
comment "\" of the d'th '\\(' and any other argument returns the length"...
comment "\" Two arguments: s:Ref(string, d, \"foo\", \"bar\") returns a s"...
comment "\" executed, having the effect of"
comment "\" :let foo = s:Ref(string, d, \"start\")"
comment "\" :let bar = s:Ref(string, d, \"len\")"
function_definition (+315 nodes collapsed)
comment "\" Count the number of disjoint copies of pattern in string."
comment "\" If the pattern is a literal string and contains no '0' or "...
comment "\" then s:Count(string, pattern, '0', '1') should be faster t"...
comment "\" s:Count(string, pattern)."
function_definition (+179 nodes collapsed)
comment "\" s:Resolve('\\(a\\)\\(b\\)', '\\(c\\)\\2\\1\\1\\2') should return tab"...
comment "\" word = '\\(c\\)\\(b\\)\\(a\\)\\3\\2' and table = '-32-------'. Th"...
comment "\" '\\1' in target is replaced by '\\(a\\)' in word, table[1] = "...
comment "\" indicates that all other instances of '\\1' in target are t"...
comment "\" by '\\3'. The hard part is dealing with nesting..."
comment "\" Note that \":\" is an illegal character for source and targe"...
comment "\" unless it is preceded by \"\\\"."
function_definition (+442 nodes collapsed)
comment "\" Assume a:comma = \",\". Then the format for a:patterns and "...
comment "\" a:patterns = \"<pat1>,<pat2>,...\""
comment "\" a:1 = \"<alt1>,<alt2>,...\""
comment "\" If <patn> is the first pattern that matches a:string then "...
comment "\" if no optional arguments are given; return <patn>,<altn> i"...
function_definition
function "fun"
bang
! "!"
function_declaration
scoped_identifier
scope "s:"
identifier "Choose"
parameters
( "("
identifier "patterns"
, ","
identifier "string"
, ","
identifier "comma"
, ","
identifier "branch"
, ","
identifier "prefix"
, ","
identifier "suffix"
, ","
spread "..."
) ")"
body
let_statement (+31 nodes collapsed)
let_statement
let "let"
identifier "i"
= "="
call_expression
identifier "matchend"
( "("
identifier "tail"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
argument
a: "a:"
identifier "comma"
) ")"
if_statement (+56 nodes collapsed)
let_statement
let "let"
identifier "current"
= "="
call_expression
identifier "strpart"
( "("
identifier "tail"
, ","
integer_literal "0"
, ","
binary_operation
identifier "i"
- "-"
integer_literal "1"
) ")"
if_statement (+40 nodes collapsed)
comment "\" un-escape \\, to ,"
let_statement
let "let"
identifier "currpat"
= "="
call_expression
identifier "substitute"
( "("
identifier "currpat"
, ","
string_literal "'\\\\,'"
, ","
string_literal "','"
, ","
string_literal "'g'"
) ")"
while_loop
while "while"
binary_operation
argument
a: "a:"
identifier "string"
!~ "!~"
binary_operation
binary_operation
argument
a: "a:"
identifier "prefix"
.. ".."
identifier "currpat"
.. ".."
argument
a: "a:"
identifier "suffix"
body
let_statement
let "let"
identifier "tail"
= "="
call_expression
identifier "strpart"
( "("
identifier "tail"
, ","
identifier "i"
) ")"
let_statement
let "let"
identifier "i"
= "="
call_expression
identifier "matchend"
( "("
identifier "tail"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
argument
a: "a:"
identifier "comma"
) ")"
if_statement
if "if"
binary_operation
identifier "i"
== "=="
integer_literal "-1"
body
return_statement
return "return"
integer_literal "-1"
endif "endif"
let_statement
let "let"
identifier "current"
= "="
call_expression
identifier "strpart"
( "("
identifier "tail"
, ","
integer_literal "0"
, ","
binary_operation
identifier "i"
- "-"
integer_literal "1"
) ")"
if_statement (+40 nodes collapsed)
if_statement (+36 nodes collapsed)
endwhile "endwhile"
if_statement (+31 nodes collapsed)
return_statement
return "return"
identifier "current"
endfunction "endfun"
function_definition (+89 nodes collapsed)
comment "\" Jump to the nearest unmatched \"(\" or \"if\" or \"<tag>\" if a:"...
comment "\" or the nearest unmatched \"</tag>\" or \"endif\" or \")\" if a:s"...
comment "\" Return a \"mark\" for the original position, so that"
comment "\" let m = MultiMatch(\"bW\", \"n\") ... call winrestview(m)"
comment "\" will return to the original position. If there is a probl"...
comment "\" move the cursor and return {}, unless a count is given, in"...
comment "\" go up or down as many levels as possible and again return "...
comment "\" TODO This relies on the same patterns as % matching. It m"...
comment "\" idea to give it its own matching patterns."
function_definition
function "fun"
bang
! "!"
function_declaration
identifier "matchit#MultiMatch"
parameters
( "("
identifier "spflag"
, ","
identifier "mode"
) ")"
body
let_statement
let "let"
identifier "restore_options"
= "="
call_expression
scoped_identifier
scope "s:"
identifier "RestoreOptions"
( "("
) ")"
let_statement
let "let"
identifier "startpos"
= "="
list
[ "["
call_expression
identifier "line"
( "("
string_literal "\".\""
) ")"
, ","
call_expression
identifier "col"
( "("
string_literal "\".\""
) ")"
] "]"
comment "\" save v:count1 variable, might be reset from the restore_cu"...
let_statement
let "let"
identifier "level"
= "="
scoped_identifier
scope "v:"
identifier "count1"
if_statement (+25 nodes collapsed)
comment "\" First step: if not already done, set the script variables"
comment "\" s:do_BR flag for whether there are backrefs"
comment "\" s:pat parsed version of b:match_words"
comment "\" s:all regexp based on s:pat and the default groups"
comment "\" This part is copied and slightly modified from matchit#Mat"...
if_statement (+50 nodes collapsed)
if_statement
if "if"
binary_operation (+27 nodes collapsed)
body
let_statement (+32 nodes collapsed)
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "last_mps"
= "="
option
& "&"
option_name "mps"
let_statement
let "let"
identifier "match_words"
= "="
binary_operation
binary_operation
identifier "match_words" any 2:1
.. ".."
( "("
ternary_expression
call_expression
identifier "strlen"
( "("
identifier "match_words" any 2:1
) ")"
? "?"
string_literal "\",\""
: ":"
string_literal "\"\""
) ")"
.. ".."
identifier "default" any 1:1
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "last_words"
= "="
identifier "match_words"
if_statement (+50 nodes collapsed)
let_statement (+25 nodes collapsed)
if_statement
if "if"
call_expression
identifier "exists"
( "("
string_literal "\"b:match_debug\""
) ")"
body
let_statement
let "let"
scoped_identifier
scope "b:"
identifier "match_pat"
= "="
scoped_identifier
scope "s:"
identifier "pat"
endif "endif"
comment "\" Reconstruct the version with unresolved backrefs."
let_statement (+25 nodes collapsed)
let_statement (+24 nodes collapsed)
endif "endif"
comment "\" Second step: figure out the patterns for searchpair()"
comment "\" and save the screen, cursor position, and 'ignorecase'."
comment "\" - TODO: A lot of this is copied from matchit#Match_wrappe"...
comment "\" - maybe even more functionality should be split off"
comment "\" - into separate functions!"
let_statement (+29 nodes collapsed)
let_statement (+29 nodes collapsed)
call_statement (+26 nodes collapsed)
let_statement
let "let"
identifier "closelist"
= "="
list
[ "["
] "]"
let_statement
let "let"
identifier "middlelist"
= "="
list
[ "["
] "]"
call_statement (+45 nodes collapsed)
call_statement (+37 nodes collapsed)
call_statement (+37 nodes collapsed)
call_statement (+37 nodes collapsed)
let_statement
let "let"
identifier "open"
= "="
call_expression
identifier "join"
( "("
identifier "openlist"
, ","
string_literal "','"
) ")"
let_statement
let "let"
identifier "middle"
= "="
call_expression
identifier "join"
( "("
identifier "middlelist"
, ","
string_literal "','"
) ")"
let_statement
let "let"
identifier "close"
= "="
call_expression
identifier "join"
( "("
identifier "closelist"
, ","
string_literal "','"
) ")"
if_statement (+43 nodes collapsed)
let_statement
let "let"
identifier "skip"
= "="
call_expression
scoped_identifier
scope "s:"
identifier "ParseSkip"
( "("
identifier "skip"
) ")"
let_statement
let "let"
identifier "view"
= "="
call_expression
identifier "winsaveview"
( "("
) ")"
comment "\" Third step: call searchpair()."
comment "\" Replace '\\('--but not '\\\\('--with '\\%(' and ',' with '\\|'."
let_statement (+23 nodes collapsed)
let_statement
let "let"
identifier "openpat"
= "="
call_expression
identifier "substitute"
( "("
identifier "openpat"
, ","
string_literal "','"
, ","
string_literal "'\\\\|'"
, ","
string_literal "'g'"
) ")"
let_statement (+23 nodes collapsed)
let_statement
let "let"
identifier "closepat"
= "="
call_expression
identifier "substitute"
( "("
identifier "closepat"
, ","
string_literal "','"
, ","
string_literal "'\\\\|'"
, ","
string_literal "'g'"
) ")"
let_statement (+23 nodes collapsed)
let_statement
let "let"
identifier "middlepat"
= "="
call_expression
identifier "substitute"
( "("
identifier "middlepat"
, ","
string_literal "','"
, ","
string_literal "'\\\\|'"
, ","
string_literal "'g'"
) ")"
if_statement (+72 nodes collapsed)
unknown_builtin_statement
unknown_command_name "mark"
arguments
command_argument "'"
while_loop (+55 nodes collapsed)
comment "\" Restore options and return a string to restore the origina"...
call_statement
call "call"
call_expression
scoped_identifier
scope "s:"
identifier "CleanUp"
( "("
identifier "restore_options"
, ","
argument
a: "a:"
identifier "mode"
, ","
identifier "startpos"
) ")"
return_statement
return "return"
identifier "view"
endfunction "endfun"
comment "\" Search backwards for \"if\" or \"while\" or \"<tag>\" or ..."
comment "\" and return \"endif\" or \"endwhile\" or \"</tag>\" or ... ."
comment "\" For now, this uses b:match_words and the same script varia"...
comment "\" as matchit#Match_wrapper() . Later, it may get its own pa"...
comment "\" either from a buffer variable or passed as arguments."
comment "\" fun! s:Autocomplete()"
comment "\" echo \"autocomplete not yet implemented :-(\""
comment "\" if !exists(\"b:match_words\") || b:match_words == \"\""
comment "\" return \"\""
comment "\" end"
comment "\" let startpos = matchit#MultiMatch(\"bW\")"
comment "\""
comment "\" if startpos == \"\""
comment "\" return \"\""
comment "\" endif"
comment "\" \" - TODO: figure out whether 'if' or '<tag>' matched, a"...
comment "\" \" - the appropriate closing."
comment "\" let matchline = getline(\".\")"
comment "\" let curcol = col(\".\") - 1"
comment "\" \" - TODO: Change the s:all argument if there is a new s"...
comment "\" let regexp = s:Wholematch(matchline, s:all, curcol)"
comment "\" let suf = strlen(matchline) - matchend(matchline, regexp"...
comment "\" let prefix = (curcol ? '^.\\{' . curcol . '}\\%(' : '^\\%("...
comment "\" let suffix = (suf ? '\\).\\{' . suf . '}$' : '\\)$')"
comment "\" \" Reconstruct the version with unresolved backrefs."
comment "\" let patBR = substitute(b:match_words.',', '[,:]*,[,:]*',"...
comment "\" let patBR = substitute(patBR, ':\\{2,}', ':', \"g\")"
comment "\" \" Now, set group and groupBR to the matching group: 'if:"...
comment "\" \" 'while:endwhile' or whatever."
comment "\" let group = s:Choose(s:pat, matchline, \",\", \":\", prefix,"...
comment "\" let i = matchend(group, s:notslash . \",\")"
comment "\" let groupBR = strpart(group, i)"
comment "\" let group = strpart(group, 0, i-1)"
comment "\" \" Now, matchline =~ prefix . substitute(group,':','\\|','"...
comment "\" if s:do_BR"
comment "\" let group = s:InsertRefs(groupBR, prefix, group, suffi"...
comment "\" endif"
comment "\" \" let g:group = group"
comment "\""
comment "\" \" - TODO: Construct the closing from group."
comment "\" let fake = \"end\" . expand(\"<cword>\")"
comment "\" execute startpos"
comment "\" return fake"
comment "\" endfun"
comment "\" Close all open structures. \"Get the heck out of here!\""
comment "\" fun! s:Gthhoh()"
comment "\" let close = s:Autocomplete()"
comment "\" while strlen(close)"
comment "\" put=close"
comment "\" let close = s:Autocomplete()"
comment "\" endwhile"
comment "\" endfun"
comment "\" Parse special strings as typical skip arguments for search"...
comment "\" s:foo becomes (current syntax item) =~ foo"
comment "\" S:foo becomes (current syntax item) !~ foo"
comment "\" r:foo becomes (line before cursor) =~ foo"
comment "\" R:foo becomes (line before cursor) !~ foo"
comment "\" t:foo becomes (current treesitter captures) =~ foo"
comment "\" T:foo becomes (current treesitter captures) !~ foo"
function_definition (+271 nodes collapsed)
let_statement
let "let"
option
& "&"
option_name "cpo"
= "="
scoped_identifier
scope "s:"
identifier "save_cpo"
unlet_statement
unlet "unlet"
scoped_identifier
scope "s:"
identifier "save_cpo"
comment "\" vim:sts=2:sw=2:et:"

After

script_file
comment "\" matchit.vim: (global plugin) Extended \"%\" matching"
comment "\" autload script of matchit plugin, see ../plugin/matchit.v"...
comment "\" Last Change: Jan 06, 2025"
comment "\" Neovim does not support scriptversion"
if_statement
if "if"
call_expression
identifier "has"
( "("
string_literal "\"vimscript-4\""
) ")"
body
unknown_builtin_statement
unknown_command_name "scriptversion"
arguments
command_argument "4"
endif "endif"
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "last_mps"
= "="
string_literal "\"\""
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "last_words"
= "="
string_literal "\":\""
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "patBR"
= "="
string_literal "\"\""
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "save_cpo"
= "="
option
& "&"
option_name "cpo"
set_statement
set "set"
set_item
default_option
option_name "cpo"
& "&"
vim "vim"
comment "\" Auto-complete mappings: (not yet \"ready for prime time\")"
comment "\" TODO Read :help write-plugin for the \"right\" way to let th"...
comment "\" specify a key binding."
comment "\" let g:match_auto = '<C-]>'"
comment "\" let g:match_autoCR = '<C-CR>'"
comment "\" if exists(\"g:match_auto\")"
comment "\" execute \"inoremap \" . g:match_auto . ' x<Esc>\"=<SID>Auto"...
comment "\" endif"
comment "\" if exists(\"g:match_autoCR\")"
comment "\" execute \"inoremap \" . g:match_autoCR . ' <CR><C-R>=<SID>"...
comment "\" endif"
comment "\" if exists(\"g:match_gthhoh\")"
comment "\" execute \"inoremap \" . g:match_gthhoh . ' <C-O>:call <SID"...
comment "\" endif \" gthhoh = \"Get the heck out of here!\""
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "notslash"
= "="
string_literal "'\\\\\\@1<!\\%(\\\\\\\\\\)*'"
function_definition (+114 nodes collapsed)
function_definition
function "function"
function_declaration
identifier "matchit#Match_wrapper"
parameters
( "("
identifier "word"
, ","
identifier "forward"
, ","
identifier "mode"
) ")"
range "range"
body
let_statement
let "let"
identifier "restore_options"
= "="
call_expression
scoped_identifier
scope "s:"
identifier "RestoreOptions"
( "("
) ")"
comment "\" In s:CleanUp(), we may need to check whether the cursor mo"...
let_statement
let "let"
identifier "startpos"
= "="
list
[ "["
call_expression
identifier "line"
( "("
string_literal "\".\""
) ")"
, ","
call_expression
identifier "col"
( "("
string_literal "\".\""
) ")"
] "]"
comment "\" if a count has been applied, use the default [count]% mode"...
if_statement (+33 nodes collapsed)
if_statement (+83 nodes collapsed)
comment "\" Check for custom match function hook"
if_statement
if "if"
call_expression
identifier "exists"
( "("
string_literal "\"b:match_function\""
) ")"
body
let_statement
let "let"
identifier "MatchFunc"
= "="
scoped_identifier
scope "b:"
identifier "match_function"
try_statement
try "try"
body
let_statement
let "let"
identifier "result"
= "="
call_expression
identifier "call"
( "("
identifier "MatchFunc"
, ","
list
[ "["
argument
a: "a:"
identifier "forward"
] "]"
) ")"
if_statement
if "if"
unary_operation
! "!"
call_expression
identifier "empty"
( "("
identifier "result"
) ")"
body
call_statement
call "call"
call_expression
identifier "cursor"
( "("
identifier "result"
) ")"
return_statement
return "return"
call_expression
scoped_identifier
scope "s:"
identifier "CleanUp"
( "("
identifier "restore_options"
, ","
argument
a: "a:"
identifier "mode"
, ","
identifier "startpos"
) ")"
endif "endif"
catch_statement
catch "catch"
pattern "/.*/"
body
if_statement
if "if"
call_expression
identifier "exists"
( "("
string_literal "\"b:match_debug\""
) ")"
body
echohl_statement
echohl "echohl"
hl_group "WarningMsg"
echomsg_statement
echomsg "echom"
binary_operation
string_literal "'matchit: b:match_function error: '"
.. ".."
scoped_identifier
scope "v:"
identifier "exception"
echohl_statement
echohl "echohl"
hl_group "NONE"
endif "endif"
return_statement
return "return"
call_expression
scoped_identifier
scope "s:"
identifier "CleanUp"
( "("
identifier "restore_options"
, ","
argument
a: "a:"
identifier "mode"
, ","
identifier "startpos"
) ")"
endtry "endtry"
comment "\" Empty result: fall through to regular matching"
endif "endif"
comment "\" First step: if not already done, set the script variables"
comment "\" s:do_BR flag for whether there are backrefs"
comment "\" s:pat parsed version of b:match_words"
comment "\" s:all regexp based on s:pat and the default groups"
if_statement (+50 nodes collapsed)
comment "\" Thanks to Preben \"Peppe\" Guldberg and Bram Moolenaar for t"...
if_statement
if "if"
binary_operation (+27 nodes collapsed)
body
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "last_mps"
= "="
option
& "&"
option_name "mps"
comment "\" quote the special chars in 'matchpairs', replace [,:] with"...
comment "\" append the builtin pairs (/*, */, #if, #ifdef, #ifndef, #e"...
comment "\" #elifdef, #elifndef, #endif)"
let_statement (+32 nodes collapsed)
comment "\" s:all = pattern with all the keywords"
let_statement
let "let"
identifier "match_words"
= "="
call_expression
scoped_identifier
scope "s:"
identifier "Append"
( "("
identifier "match_words" any 2:1
, ","
identifier "default"
) ")"
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "last_words"
= "="
identifier "match_words"
if_statement (+50 nodes collapsed)
let_statement (+24 nodes collapsed)
comment "\" un-escape \\, and \\: to , and :"
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "all"
= "="
call_expression
identifier "substitute"
( "("
scoped_identifier
scope "s:"
identifier "all"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\\\(:\\|,\\)'"
, ","
string_literal "'\\1'"
, ","
string_literal "'g'"
) ")"
comment "\" Just in case there are too many '\\(...)' groups inside the"...
comment "\" sure to use \\%(...) groups, so that error E872 can be avoi"...
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "all"
= "="
call_expression
identifier "substitute"
( "("
scoped_identifier
scope "s:"
identifier "all"
, ","
string_literal "'\\\\('"
, ","
string_literal "'\\\\%('"
, ","
string_literal "'g'"
) ")"
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "all"
= "="
binary_operation
binary_operation
string_literal "'\\%('"
.. ".."
scoped_identifier
scope "s:"
identifier "all"
.. ".."
string_literal "'\\)'"
if_statement
if "if"
call_expression
identifier "exists"
( "("
string_literal "\"b:match_debug\""
) ")"
body
let_statement
let "let"
scoped_identifier
scope "b:"
identifier "match_pat"
= "="
scoped_identifier
scope "s:"
identifier "pat"
endif "endif"
comment "\" Reconstruct the version with unresolved backrefs."
let_statement (+25 nodes collapsed)
let_statement (+24 nodes collapsed)
comment "\" un-escape \\, to ,"
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "patBR"
= "="
call_expression
identifier "substitute"
( "("
scoped_identifier
scope "s:"
identifier "patBR"
, ","
string_literal "'\\\\,'"
, ","
string_literal "','"
, ","
string_literal "'g'"
) ")"
endif "endif"
comment "\" Second step: set the following local variables:"
comment "\" matchline = line on which the cursor started"
comment "\" curcol = number of characters before match"
comment "\" prefix = regexp for start of line to start of match"
comment "\" suffix = regexp for end of match to end of line"
comment "\" Require match to end on or after the cursor and prefer it "...
comment "\" start on or before the cursor."
let_statement
let "let"
identifier "matchline"
= "="
call_expression
identifier "getline"
( "("
index_expression
identifier "startpos"
[ "["
integer_literal "0"
] "]"
) ")"
if_statement (+210 nodes collapsed)
if_statement (+32 nodes collapsed)
comment "\" Third step: Find the group and single word that match, an"...
comment "\" (backref) versions of these. Then, resolve the backrefs."
comment "\" Set the following local variable:"
comment "\" group = colon-separated list of patterns, one of which mat"...
comment "\" = ini:mid:fin or ini:fin"
comment "\""
comment "\" Now, set group and groupBR to the matching group: 'if:endi"...
comment "\" 'while:endwhile' or whatever. A bit of a kluge: s:Choose"...
comment "\" group . \",\" . groupBR, and we pick it apart."
let_statement (+27 nodes collapsed)
let_statement
let "let"
identifier "i"
= "="
call_expression
identifier "matchend"
( "("
identifier "group"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "\",\""
) ")"
let_statement
let "let"
identifier "groupBR"
= "="
call_expression
identifier "strpart"
( "("
identifier "group"
, ","
identifier "i"
) ")"
let_statement
let "let"
identifier "group"
= "="
call_expression
identifier "strpart"
( "("
identifier "group"
, ","
integer_literal "0"
, ","
binary_operation
identifier "i"
- "-"
integer_literal "1"
) ")"
comment "\" Now, matchline =~ prefix . substitute(group,':','\\|','g') "...
if_statement (+27 nodes collapsed)
if_statement (+50 nodes collapsed)
comment "\" Fourth step: Set the arguments for searchpair()."
let_statement
let "let"
identifier "i"
= "="
call_expression
identifier "matchend"
( "("
identifier "group"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "\":\""
) ")"
let_statement
let "let"
identifier "j"
= "="
call_expression
identifier "matchend"
( "("
identifier "group"
, ","
binary_operation
binary_operation
string_literal "'.*'"
.. ".."
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "\":\""
) ")"
let_statement
let "let"
identifier "ini"
= "="
call_expression
identifier "strpart"
( "("
identifier "group"
, ","
integer_literal "0"
, ","
binary_operation
identifier "i"
- "-"
integer_literal "1"
) ")"
let_statement (+34 nodes collapsed)
let_statement
let "let"
identifier "fin"
= "="
call_expression
identifier "strpart"
( "("
identifier "group"
, ","
identifier "j"
) ")"
comment "\"Un-escape the remaining , and : characters."
let_statement
let "let"
identifier "ini"
= "="
call_expression
identifier "substitute"
( "("
identifier "ini"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\\\(:\\|,\\)'"
, ","
string_literal "'\\1'"
, ","
string_literal "'g'"
) ")"
let_statement
let "let"
identifier "mid"
= "="
call_expression
identifier "substitute"
( "("
identifier "mid"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\\\(:\\|,\\)'"
, ","
string_literal "'\\1'"
, ","
string_literal "'g'"
) ")"
let_statement
let "let"
identifier "fin"
= "="
call_expression
identifier "substitute"
( "("
identifier "fin"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\\\(:\\|,\\)'"
, ","
string_literal "'\\1'"
, ","
string_literal "'g'"
) ")"
comment "\" searchpair() requires that these patterns avoid \\(\\) group"...
let_statement
let "let"
identifier "ini"
= "="
call_expression
identifier "substitute"
( "("
identifier "ini"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\('"
, ","
string_literal "'\\\\%('"
, ","
string_literal "'g'"
) ")"
let_statement
let "let"
identifier "mid"
= "="
call_expression
identifier "substitute"
( "("
identifier "mid"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\('"
, ","
string_literal "'\\\\%('"
, ","
string_literal "'g'"
) ")"
let_statement
let "let"
identifier "fin"
= "="
call_expression
identifier "substitute"
( "("
identifier "fin"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\('"
, ","
string_literal "'\\\\%('"
, ","
string_literal "'g'"
) ")"
comment "\" Set mid. This is optimized for readability, not micro-eff"...
if_statement (+43 nodes collapsed)
comment "\" Set flag. This is optimized for readability, not micro-ef"...
if_statement (+51 nodes collapsed)
comment "\" Set skip."
if_statement (+43 nodes collapsed)
let_statement
let "let"
identifier "skip"
= "="
call_expression
scoped_identifier
scope "s:"
identifier "ParseSkip"
( "("
identifier "skip"
) ")"
if_statement (+40 nodes collapsed)
comment "\" Fifth step: actually start moving the cursor and call sea"...
comment "\" Later, :execute restore_cursor to get to the original scre"...
let_statement
let "let"
identifier "view"
= "="
call_expression
identifier "winsaveview"
( "("
) ")"
call_statement
call "call"
call_expression
identifier "cursor"
( "("
integer_literal "0"
, ","
binary_operation
identifier "curcol"
+ "+"
integer_literal "1"
) ")"
if_statement (+58 nodes collapsed)
let_statement
let "let"
identifier "sp_return"
= "="
call_expression
identifier "searchpair"
( "("
identifier "ini"
, ","
identifier "mid"
, ","
identifier "fin"
, ","
identifier "flag"
, ","
identifier "skip"
) ")"
if_statement (+57 nodes collapsed)
let_statement (+25 nodes collapsed)
comment "\" Restore cursor position and original screen."
call_statement
call "call"
call_expression
identifier "winrestview"
( "("
identifier "view"
) ")"
normal_statement
normal "normal"
bang
! "!"
commands " m'"
if_statement
if "if"
binary_operation
identifier "sp_return"
> ">"
integer_literal "0"
body
execute_statement
execute "execute"
identifier "final_position"
endif "endif"
if_statement (+39 nodes collapsed)
return_statement (+23 nodes collapsed)
endfunction "endfun"
comment "\" Restore options and do some special handling for Operator-"...
comment "\" The optional argument is the tail of the matching group."
function_definition (+200 nodes collapsed)
comment "\" Example (simplified HTML patterns): if"
comment "\" a:groupBR = '<\\(\\k\\+\\)>:</\\1>'"
comment "\" a:prefix = '^.\\{3}\\('"
comment "\" a:group = '<\\(\\k\\+\\)>:</\\(\\k\\+\\)>'"
comment "\" a:suffix = '\\).\\{2}$'"
comment "\" a:matchline = \"123<tag>12\" or \"123</tag>12\""
comment "\" then extract \"tag\" from a:matchline and return \"<tag>:</ta"...
function_definition (+481 nodes collapsed)
comment "\" String append item2 to item and add ',' in between items"
function_definition
function "fun"
bang
! "!"
function_declaration
scoped_identifier
scope "s:"
identifier "Append"
parameters
( "("
identifier "item"
, ","
identifier "item2"
) ")"
body
if_statement
if "if"
binary_operation
argument
a: "a:"
identifier "item"
== "=="
string_literal "''"
body
return_statement
return "return"
argument
a: "a:"
identifier "item2"
endif "endif"
comment "\" there is already a trailing comma, don't add another one"
if_statement
if "if"
binary_operation
slice_expression
argument
a: "a:"
identifier "item"
[ "["
integer_literal "-1"
: ":"
] "]"
== "=="
string_literal "','"
body
return_statement
return "return"
binary_operation
argument
a: "a:"
identifier "item"
.. ".."
argument
a: "a:"
identifier "item2"
endif "endif"
return_statement
return "return"
binary_operation
binary_operation
argument
a: "a:"
identifier "item"
.. ".."
string_literal "','"
.. ".."
argument
a: "a:"
identifier "item2"
endfunction "endfun"
comment "\" Input a comma-separated list of groups with backrefs, such"...
comment "\" a:groups = '\\(foo\\):end\\1,\\(bar\\):end\\1'"
comment "\" and return a comma-separated list of groups with backrefs "...
comment "\" return '\\(foo\\):end\\(foo\\),\\(bar\\):end\\(bar\\)'"
function_definition (+278 nodes collapsed)
comment "\" TODO I think this can be simplified and/or made more effic"...
comment "\" TODO What should I do if a:start is out of range?"
comment "\" Return a regexp that matches all of a:string, such that"
comment "\" matchstr(a:string, regexp) represents the match for a:pat "...
comment "\" as close to a:start as possible, before being preferred to"...
comment "\" ends after a:start ."
comment "\" Usage:"
comment "\" let regexp = s:Wholematch(getline(\".\"), 'foo\\|bar', col(\"."...
comment "\" let i = match(getline(\".\"), regexp)"
comment "\" let j = matchend(getline(\".\"), regexp)"
comment "\" let match = matchstr(getline(\".\"), regexp)"
function_definition (+132 nodes collapsed)
comment "\" No extra arguments: s:Ref(string, d) will"
comment "\" find the d'th occurrence of '\\(' and return it, along with"...
comment "\" to and including the matching '\\)'."
comment "\" One argument: s:Ref(string, d, \"start\") returns the index"...
comment "\" of the d'th '\\(' and any other argument returns the length"...
comment "\" Two arguments: s:Ref(string, d, \"foo\", \"bar\") returns a s"...
comment "\" executed, having the effect of"
comment "\" :let foo = s:Ref(string, d, \"start\")"
comment "\" :let bar = s:Ref(string, d, \"len\")"
function_definition (+315 nodes collapsed)
comment "\" Count the number of disjoint copies of pattern in string."
comment "\" If the pattern is a literal string and contains no '0' or "...
comment "\" then s:Count(string, pattern, '0', '1') should be faster t"...
comment "\" s:Count(string, pattern)."
function_definition (+179 nodes collapsed)
comment "\" s:Resolve('\\(a\\)\\(b\\)', '\\(c\\)\\2\\1\\1\\2') should return tab"...
comment "\" word = '\\(c\\)\\(b\\)\\(a\\)\\3\\2' and table = '-32-------'. Th"...
comment "\" '\\1' in target is replaced by '\\(a\\)' in word, table[1] = "...
comment "\" indicates that all other instances of '\\1' in target are t"...
comment "\" by '\\3'. The hard part is dealing with nesting..."
comment "\" Note that \":\" is an illegal character for source and targe"...
comment "\" unless it is preceded by \"\\\"."
function_definition (+442 nodes collapsed)
comment "\" Assume a:comma = \",\". Then the format for a:patterns and "...
comment "\" a:patterns = \"<pat1>,<pat2>,...\""
comment "\" a:1 = \"<alt1>,<alt2>,...\""
comment "\" If <patn> is the first pattern that matches a:string then "...
comment "\" if no optional arguments are given; return <patn>,<altn> i"...
function_definition
function "fun"
bang
! "!"
function_declaration
scoped_identifier
scope "s:"
identifier "Choose"
parameters
( "("
identifier "patterns"
, ","
identifier "string"
, ","
identifier "comma"
, ","
identifier "branch"
, ","
identifier "prefix"
, ","
identifier "suffix"
, ","
spread "..."
) ")"
body
let_statement (+31 nodes collapsed)
let_statement
let "let"
identifier "i"
= "="
call_expression
identifier "matchend"
( "("
identifier "tail"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
argument
a: "a:"
identifier "comma"
) ")"
if_statement (+56 nodes collapsed)
let_statement
let "let"
identifier "current"
= "="
call_expression
identifier "strpart"
( "("
identifier "tail"
, ","
integer_literal "0"
, ","
binary_operation
identifier "i"
- "-"
integer_literal "1"
) ")"
if_statement (+40 nodes collapsed)
comment "\" un-escape \\, and \\: to , and :"
let_statement
let "let"
identifier "currpat"
= "="
call_expression
identifier "substitute"
( "("
identifier "currpat"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\\\(:\\|,\\)'"
, ","
string_literal "'\\1'"
, ","
string_literal "'g'"
) ")"
while_loop
while "while"
binary_operation
argument
a: "a:"
identifier "string"
!~ "!~"
binary_operation
binary_operation
argument
a: "a:"
identifier "prefix"
.. ".."
identifier "currpat"
.. ".."
argument
a: "a:"
identifier "suffix"
body
let_statement
let "let"
identifier "tail"
= "="
call_expression
identifier "strpart"
( "("
identifier "tail"
, ","
identifier "i"
) ")"
let_statement
let "let"
identifier "i"
= "="
call_expression
identifier "matchend"
( "("
identifier "tail"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
argument
a: "a:"
identifier "comma"
) ")"
if_statement
if "if"
binary_operation
identifier "i"
== "=="
integer_literal "-1"
body
return_statement
return "return"
integer_literal "-1"
endif "endif"
let_statement
let "let"
identifier "current"
= "="
call_expression
identifier "strpart"
( "("
identifier "tail"
, ","
integer_literal "0"
, ","
binary_operation
identifier "i"
- "-"
integer_literal "1"
) ")"
if_statement (+40 nodes collapsed)
comment "\" un-escape \\, and \\: to , and :"
let_statement
let "let"
identifier "currpat"
= "="
call_expression
identifier "substitute"
( "("
identifier "currpat"
, ","
binary_operation
scoped_identifier
scope "s:"
identifier "notslash"
.. ".."
string_literal "'\\zs\\\\\\(:\\|,\\)'"
, ","
string_literal "'\\1'"
, ","
string_literal "'g'"
) ")"
if_statement (+36 nodes collapsed)
endwhile "endwhile"
if_statement (+31 nodes collapsed)
return_statement
return "return"
identifier "current"
endfunction "endfun"
function_definition (+89 nodes collapsed)
comment "\" Jump to the nearest unmatched \"(\" or \"if\" or \"<tag>\" if a:"...
comment "\" or the nearest unmatched \"</tag>\" or \"endif\" or \")\" if a:s"...
comment "\" Return a \"mark\" for the original position, so that"
comment "\" let m = MultiMatch(\"bW\", \"n\") ... call winrestview(m)"
comment "\" will return to the original position. If there is a probl"...
comment "\" move the cursor and return {}, unless a count is given, in"...
comment "\" go up or down as many levels as possible and again return "...
comment "\" TODO This relies on the same patterns as % matching. It m"...
comment "\" idea to give it its own matching patterns."
function_definition
function "fun"
bang
! "!"
function_declaration
identifier "matchit#MultiMatch"
parameters
( "("
identifier "spflag"
, ","
identifier "mode"
) ")"
body
let_statement
let "let"
identifier "restore_options"
= "="
call_expression
scoped_identifier
scope "s:"
identifier "RestoreOptions"
( "("
) ")"
let_statement
let "let"
identifier "startpos"
= "="
list
[ "["
call_expression
identifier "line"
( "("
string_literal "\".\""
) ")"
, ","
call_expression
identifier "col"
( "("
string_literal "\".\""
) ")"
] "]"
comment "\" save v:count1 variable, might be reset from the restore_cu"...
let_statement
let "let"
identifier "level"
= "="
scoped_identifier
scope "v:"
identifier "count1"
if_statement (+25 nodes collapsed)
comment "\" First step: if not already done, set the script variables"
comment "\" s:do_BR flag for whether there are backrefs"
comment "\" s:pat parsed version of b:match_words"
comment "\" s:all regexp based on s:pat and the default groups"
comment "\" This part is copied and slightly modified from matchit#Mat"...
if_statement (+50 nodes collapsed)
if_statement
if "if"
binary_operation (+27 nodes collapsed)
body
let_statement (+32 nodes collapsed)
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "last_mps"
= "="
option
& "&"
option_name "mps"
let_statement
let "let"
identifier "match_words"
= "="
call_expression
scoped_identifier
scope "s:"
identifier "Append"
( "("
identifier "match_words" any 2:1
, ","
identifier "default" any 1:1
) ")"
let_statement
let "let"
scoped_identifier
scope "s:"
identifier "last_words"
= "="
identifier "match_words"
if_statement (+50 nodes collapsed)
let_statement (+25 nodes collapsed)
if_statement
if "if"
call_expression
identifier "exists"
( "("
string_literal "\"b:match_debug\""
) ")"
body
let_statement
let "let"
scoped_identifier
scope "b:"
identifier "match_pat"
= "="
scoped_identifier
scope "s:"
identifier "pat"
endif "endif"
comment "\" Reconstruct the version with unresolved backrefs."
let_statement (+25 nodes collapsed)
let_statement (+24 nodes collapsed)
endif "endif"
comment "\" Second step: figure out the patterns for searchpair()"
comment "\" and save the screen, cursor position, and 'ignorecase'."
comment "\" - TODO: A lot of this is copied from matchit#Match_wrappe"...
comment "\" - maybe even more functionality should be split off"
comment "\" - into separate functions!"
let_statement (+29 nodes collapsed)
let_statement (+29 nodes collapsed)
call_statement (+26 nodes collapsed)
let_statement
let "let"
identifier "closelist"
= "="
list
[ "["
] "]"
let_statement
let "let"
identifier "middlelist"
= "="
list
[ "["
] "]"
call_statement (+45 nodes collapsed)
call_statement (+37 nodes collapsed)
call_statement (+37 nodes collapsed)
call_statement (+37 nodes collapsed)
let_statement
let "let"
identifier "open"
= "="
call_expression
identifier "join"
( "("
identifier "openlist"
, ","
string_literal "','"
) ")"
let_statement
let "let"
identifier "middle"
= "="
call_expression
identifier "join"
( "("
identifier "middlelist"
, ","
string_literal "','"
) ")"
let_statement
let "let"
identifier "close"
= "="
call_expression
identifier "join"
( "("
identifier "closelist"
, ","
string_literal "','"
) ")"
if_statement (+43 nodes collapsed)
let_statement
let "let"
identifier "skip"
= "="
call_expression
scoped_identifier
scope "s:"
identifier "ParseSkip"
( "("
identifier "skip"
) ")"
let_statement
let "let"
identifier "view"
= "="
call_expression
identifier "winsaveview"
( "("
) ")"
comment "\" Third step: call searchpair()."
comment "\" Replace '\\('--but not '\\\\('--with '\\%(' and ',' with '\\|'."
let_statement (+23 nodes collapsed)
let_statement
let "let"
identifier "openpat"
= "="
call_expression
identifier "substitute"
( "("
identifier "openpat"
, ","
string_literal "','"
, ","
string_literal "'\\\\|'"
, ","
string_literal "'g'"
) ")"
let_statement (+23 nodes collapsed)
let_statement
let "let"
identifier "closepat"
= "="
call_expression
identifier "substitute"
( "("
identifier "closepat"
, ","
string_literal "','"
, ","
string_literal "'\\\\|'"
, ","
string_literal "'g'"
) ")"
let_statement (+23 nodes collapsed)
let_statement
let "let"
identifier "middlepat"
= "="
call_expression
identifier "substitute"
( "("
identifier "middlepat"
, ","
string_literal "','"
, ","
string_literal "'\\\\|'"
, ","
string_literal "'g'"
) ")"
if_statement (+72 nodes collapsed)
unknown_builtin_statement
unknown_command_name "mark"
arguments
command_argument "'"
while_loop (+55 nodes collapsed)
comment "\" Restore options and return a string to restore the origina"...
call_statement
call "call"
call_expression
scoped_identifier
scope "s:"
identifier "CleanUp"
( "("
identifier "restore_options"
, ","
argument
a: "a:"
identifier "mode"
, ","
identifier "startpos"
) ")"
return_statement
return "return"
identifier "view"
endfunction "endfun"
comment "\" Search backwards for \"if\" or \"while\" or \"<tag>\" or ..."
comment "\" and return \"endif\" or \"endwhile\" or \"</tag>\" or ... ."
comment "\" For now, this uses b:match_words and the same script varia"...
comment "\" as matchit#Match_wrapper() . Later, it may get its own pa"...
comment "\" either from a buffer variable or passed as arguments."
comment "\" fun! s:Autocomplete()"
comment "\" echo \"autocomplete not yet implemented :-(\""
comment "\" if !exists(\"b:match_words\") || b:match_words == \"\""
comment "\" return \"\""
comment "\" end"
comment "\" let startpos = matchit#MultiMatch(\"bW\")"
comment "\""
comment "\" if startpos == \"\""
comment "\" return \"\""
comment "\" endif"
comment "\" \" - TODO: figure out whether 'if' or '<tag>' matched, a"...
comment "\" \" - the appropriate closing."
comment "\" let matchline = getline(\".\")"
comment "\" let curcol = col(\".\") - 1"
comment "\" \" - TODO: Change the s:all argument if there is a new s"...
comment "\" let regexp = s:Wholematch(matchline, s:all, curcol)"
comment "\" let suf = strlen(matchline) - matchend(matchline, regexp"...
comment "\" let prefix = (curcol ? '^.\\{' . curcol . '}\\%(' : '^\\%("...
comment "\" let suffix = (suf ? '\\).\\{' . suf . '}$' : '\\)$')"
comment "\" \" Reconstruct the version with unresolved backrefs."
comment "\" let patBR = substitute(b:match_words.',', '[,:]*,[,:]*',"...
comment "\" let patBR = substitute(patBR, ':\\{2,}', ':', \"g\")"
comment "\" \" Now, set group and groupBR to the matching group: 'if:"...
comment "\" \" 'while:endwhile' or whatever."
comment "\" let group = s:Choose(s:pat, matchline, \",\", \":\", prefix,"...
comment "\" let i = matchend(group, s:notslash . \",\")"
comment "\" let groupBR = strpart(group, i)"
comment "\" let group = strpart(group, 0, i-1)"
comment "\" \" Now, matchline =~ prefix . substitute(group,':','\\|','"...
comment "\" if s:do_BR"
comment "\" let group = s:InsertRefs(groupBR, prefix, group, suffi"...
comment "\" endif"
comment "\" \" let g:group = group"
comment "\""
comment "\" \" - TODO: Construct the closing from group."
comment "\" let fake = \"end\" . expand(\"<cword>\")"
comment "\" execute startpos"
comment "\" return fake"
comment "\" endfun"
comment "\" Close all open structures. \"Get the heck out of here!\""
comment "\" fun! s:Gthhoh()"
comment "\" let close = s:Autocomplete()"
comment "\" while strlen(close)"
comment "\" put=close"
comment "\" let close = s:Autocomplete()"
comment "\" endwhile"
comment "\" endfun"
comment "\" Parse special strings as typical skip arguments for search"...
comment "\" s:foo becomes (current syntax item) =~ foo"
comment "\" S:foo becomes (current syntax item) !~ foo"
comment "\" r:foo becomes (line before cursor) =~ foo"
comment "\" R:foo becomes (line before cursor) !~ foo"
comment "\" t:foo becomes (current treesitter captures) =~ foo"
comment "\" T:foo becomes (current treesitter captures) !~ foo"
function_definition (+271 nodes collapsed)
let_statement
let "let"
option
& "&"
option_name "cpo"
= "="
scoped_identifier
scope "s:"
identifier "save_cpo"
unlet_statement
unlet "unlet"
scoped_identifier
scope "s:"
identifier "save_cpo"
comment "\" vim:sts=2:sw=2:et:"