neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

matchit.txt (20830B)


      1 *matchit.txt* Extended |%| matching  Last change: 2026 Jan 06
      2 
      3 	VIM REFERENCE MANUAL    by Benji Fisher et al
      4 
      5 
      6 *matchit* *matchit.vim*
      7 
      8 1. Extended matching with "%"				|matchit-intro|
      9 2. Activation						|matchit-activate|
     10 3. Configuration					|matchit-configure|
     11 4. Supporting a New Language				|matchit-newlang|
     12 5. Known Bugs and Limitations				|matchit-bugs|
     13 
     14 The functionality mentioned here is a plugin, see |add-plugin|.
     15 You can avoid loading this plugin by setting the "loaded_matchit" variable
     16 in your |vimrc| file: >
     17 :let loaded_matchit = 1
     18 
     19 ==============================================================================
     20 1. Extended matching with "%"				*matchit-intro*
     21 
     22 						*matchit-%*
     23 %	Cycle forward through matching groups, such as "if", "else", "endif",
     24 as specified by |b:match_words|.
     25 
     26 						*g%* *v_g%* *o_g%*
     27 g%	Cycle backwards through matching groups, as specified by
     28 |b:match_words|.  For example, go from "if" to "endif" to "else".
     29 
     30 						*[%* *v_[%* *o_[%*
     31 [%	Go to [count] previous unmatched group, as specified by
     32 |b:match_words|.  Similar to |[{|.
     33 
     34 						*]%* *v_]%* *o_]%*
     35 ]%	Go to [count] next unmatched group, as specified by
     36 |b:match_words|.  Similar to |]}|.
     37 
     38 						*v_a%*
     39 a%	In Visual mode, select the matching group, as specified by
     40 |b:match_words|, containing the cursor.  Similar to |v_a[|.
     41 A [count] is ignored, and only the first character of the closing
     42 pattern is selected.
     43 
     44 In Vim, as in plain vi, the percent key, |%|, jumps the cursor from a brace,
     45 bracket, or paren to its match.  This can be configured with the 'matchpairs'
     46 option.  The matchit plugin extends this in several ways:
     47 
     48     You can match whole words, such as "if" and "endif", not just
     49 single characters.  You can also specify a |regular-expression|.
     50     You can define groups with more than two words, such as "if",
     51 "else", "endif".  Banging on the "%" key will cycle from the "if" to
     52 the first "else", the next "else", ..., the closing "endif", and back
     53 to the opening "if".  Nested structures are skipped.  Using |g%| goes
     54 in the reverse direction.
     55     By default, words inside comments and strings are ignored, unless
     56 the cursor is inside a comment or string when you type "%".  If the
     57 only thing you want to do is modify the behavior of "%" so that it
     58 behaves this way, you do not have to define |b:match_words|, since the
     59 script uses the 'matchpairs' option as well as this variable.
     60 
     61 See |matchit-details| for details on what the script does, and |b:match_words|
     62 for how to specify matching patterns.
     63 
     64 MODES:			*matchit-modes* *matchit-v_%* *matchit-o_%*
     65 
     66 Mostly, % and related motions (|g%| and |[%| and |]%|) should just work like built-in
     67 |motion| commands in |Operator-pending| and |Visual| modes (as of 8.1.648)
     68 
     69 LANGUAGES:					*matchit-languages*
     70 
     71 Currently, the following languages are supported:  Ada, ASP with VBS, Csh,
     72 DTD, Entity, Essbase, Fortran, HTML, JSP (same as HTML), LaTeX, Lua, Pascal,
     73 SGML, Shell, Tcsh, Vim, XML.  Other languages may already have support via
     74 the default |filetype-plugin|s in the standard vim distribution.
     75 
     76 To support a new language, see |matchit-newlang| below.
     77 
     78 DETAILS:				*matchit-details* *matchit-parse*
     79 
     80 Here is an outline of what matchit.vim does each time you hit the "%" key.  If
     81 there are |backref|s in |b:match_words| then the first step is to produce a
     82 version in which these back references have been eliminated; if there are no
     83 |backref|s then this step is skipped.  This step is called parsing.  For
     84 example, "\(foo\|bar\):end\1" is parsed to yield
     85 "\(foo\|bar\):end\(foo\|bar\)".  This can get tricky, especially if there are
     86 nested groups.  If debugging is turned on, the parsed version is saved as
     87 |b:match_pat|.
     88 
     89 						*matchit-choose*
     90 Next, the script looks for a word on the current line that matches the pattern
     91 just constructed.  It includes the patterns from the 'matchpairs' option.
     92 The goal is to do what you expect, which turns out to be a little complicated.
     93 The script follows these rules:
     94 
     95 Insist on a match that ends on or after the cursor.
     96 Prefer a match that includes the cursor position (that is, one that
     97 	starts on or before the cursor).
     98 Prefer a match that starts as close to the cursor as possible.
     99 If more than one pattern in |b:match_words| matches, choose the one
    100 	that is listed first.
    101 
    102 Examples:
    103 
    104 Suppose you >
    105 	:let b:match_words = '<:>,<tag>:</tag>'
    106 <	and hit "%" with the cursor on or before the "<" in "a <tag> is born".
    107 The pattern '<' comes first, so it is preferred over '<tag>', which
    108 also matches.  If the cursor is on the "t", however, then '<tag>' is
    109 preferred, because this matches a bit of text containing the cursor.
    110 If the two groups of patterns were reversed then '<' would never be
    111 preferred.
    112 
    113 Suppose you >
    114 	:let b:match_words = 'if:end if'
    115 <	(Note the space!) and hit "%" with the cursor at the end of "end if".
    116 Then "if" matches, which is probably not what you want, but if the
    117 cursor starts on the "end " then "end if" is chosen.  (You can avoid
    118 this problem by using a more complicated pattern.)
    119 
    120 If there is no match, the cursor does not move.  (Before version 1.13 of the
    121 script, it would fall back on the usual behavior of |%|).  If debugging is
    122 turned on, the matched bit of text is saved as |b:match_match| and the cursor
    123 column of the start of the match is saved as |b:match_col|.
    124 
    125 Next, the script looks through |b:match_words| (original and parsed versions)
    126 for the group and pattern that match.  If debugging is turned on, the group is
    127 saved as |b:match_ini| (the first pattern) and |b:match_tail| (the rest).  If
    128 there are |backref|s then, in addition, the matching pattern is saved as
    129 |b:match_word| and a table of translations is saved as |b:match_table|.  If
    130 there are |backref|s, these are determined from the matching pattern and
    131 |b:match_match| and substituted into each pattern in the matching group.
    132 
    133 The script decides whether to search forwards or backwards and chooses
    134 arguments for the |searchpair()| function.  Then, the cursor is moved to the
    135 start of the match, and |searchpair()| is called.  By default, matching
    136 structures inside strings and comments are ignored.  This can be changed by
    137 setting |b:match_skip|.
    138 
    139 ==============================================================================
    140 2. Activation						*matchit-activate*
    141 
    142 To use the matchit plugin add this line to your |vimrc|: >
    143 packadd! matchit
    144 
    145 The script should start working the next time you start Vim.
    146 
    147 To use the matchit plugin after Vim has started, execute this command: >
    148 packadd matchit
    149 
    150 (Earlier versions of the script did nothing unless a |buffer-variable| named
    151 |b:match_words| was defined.  Even earlier versions contained autocommands
    152 that set this variable for various file types.  Now, |b:match_words| is
    153 defined in many of the default |filetype-plugin|s instead.)
    154 
    155 For a new language, you can add autocommands to the script or to your vimrc
    156 file, but the recommended method is to add a line such as >
    157 let b:match_words = '\<foo\>:\<bar\>'
    158 to the |filetype-plugin| for your language.  See |b:match_words| below for how
    159 this variable is interpreted.
    160 
    161 TROUBLESHOOTING					*matchit-troubleshoot*
    162 
    163 The script should work in most installations of Vim.  It may not work if Vim
    164 was compiled with a minimal feature set, for example if the |+syntax| option
    165 was not enabled.  If your Vim has support for syntax compiled in, but you do
    166 not have |syntax| highlighting turned on, matchit.vim should work, but it may
    167 fail to skip matching groups in comments and strings.  If the |filetype|
    168 mechanism is turned off, the |b:match_words| variable will probably not be
    169 defined automatically.
    170 
    171 2.1 Temporarily disable the matchit plugin	*matchit-disable* *:MatchDisable*
    172 
    173 To temporarily disable the matchit plugin, after it has been loaded,
    174 execute this command: >
    175 :MatchDisable
    176 
    177 This will delete all the defined key mappings to the Vim default.
    178 Now the "%" command will work like before loading the plugin |%|
    179 
    180 2.2 Re-enable the matchit plugin		*:MatchEnable*
    181 
    182 To re-enable the plugin, after it was disabled, use the following command: >
    183 :MatchEnable
    184 
    185 This will resetup the key mappings.
    186 
    187 ==============================================================================
    188 3. Configuration					*matchit-configure*
    189 
    190 There are several variables that govern the behavior of matchit.vim.  Note
    191 that these are variables local to the buffer, not options, so use |:let| to
    192 define them, not |:set|.  Some of these variables have values that matter; for
    193 others, it only matters whether the variable has been defined.  All of these
    194 can be defined in the |filetype-plugin| or autocommand that defines
    195 |b:match_words| or "on the fly."
    196 
    197 The main variable is |b:match_words|.  It is described in the section below on
    198 supporting a new language.
    199 
    200 			*MatchError* *matchit-hl* *matchit-highlight*
    201 MatchError is the highlight group for error messages from the script.  By
    202 default, it is linked to WarningMsg.  If you do not want to be bothered by
    203 error messages, you can define this to be something invisible.  For example,
    204 if you use the GUI version of Vim and your command line is normally white, you
    205 can do >
    206 :hi MatchError guifg=white guibg=white
    207 <
    208 					*b:match_ignorecase*
    209 If you >
    210 :let b:match_ignorecase = 1
    211 then matchit.vim acts as if 'ignorecase' is set: for example, "end" and "END"
    212 are equivalent.  If you >
    213 :let b:match_ignorecase = 0
    214 then matchit.vim treats "end" and "END" differently.  (There will be no
    215 b:match_infercase option unless someone requests it.)
    216 
    217 					*b:match_debug*
    218 Define b:match_debug if you want debugging information to be saved.  See
    219 |matchit-debug|, below.
    220 
    221 					*b:match_skip*
    222 If b:match_skip is defined, it is passed as the skip argument to
    223 |searchpair()|.  This controls when matching structures are skipped, or
    224 ignored.  By default, they are ignored inside comments and strings, as
    225 determined by the |syntax| mechanism.  (If syntax highlighting is turned off,
    226 nothing is skipped.)  You can set b:match_skip to a string, which evaluates to
    227 a non-zero, numerical value if the match is to be skipped or zero if the match
    228 should not be skipped.  In addition, the following special values are
    229 supported by matchit.vim:
    230 s:foo becomes (current syntax item) =~ foo
    231 S:foo becomes (current syntax item) !~ foo
    232 r:foo becomes (line before cursor) =~ foo
    233 R:foo becomes (line before cursor) !~ foo
    234 t:foo becomes (current treesitter captures) =~ foo
    235 T:foo becomes (current treesitter captures) !~ foo
    236 (The "s" is meant to suggest "syntax", and the "r" is meant to suggest
    237 "regular expression".)
    238 
    239 Examples:
    240 
    241 You can get the default behavior with >
    242 	:let b:match_skip = 's:comment\|string'
    243 <
    244 If you want to skip matching structures unless they are at the start
    245 of the line (ignoring whitespace) then you can >
    246 	:let b:match_skip = 'R:^\s*'
    247 <	Do not do this if strings or comments can span several lines, since
    248 the normal syntax checking will not be done if you set b:match_skip.
    249 
    250 In LaTeX, since "%" is used as the comment character, you can >
    251 	:let b:match_skip = 'r:%'
    252 <	Unfortunately, this will skip anything after "\%", an escaped "%".  To
    253 allow for this, and also "\\%" (an escaped backslash followed by the
    254 comment character) you can >
    255 	:let b:match_skip = 'r:\(^\|[^\\]\)\(\\\\\)*%'
    256 <
    257 See the $VIMRUNTIME/ftplugin/vim.vim for an example that uses both
    258 syntax and a regular expression.
    259 
    260 					*b:match_function*
    261 If b:match_function is defined, matchit.vim will first call this function to
    262 perform matching.  This is useful for languages with an indentation-based block
    263 structure (such as Python) or other complex matching requirements that cannot
    264 be expressed with regular expression patterns.
    265 
    266 The function should accept one argument:
    267 forward - 1 for forward search (% command)
    268           0 for backward search (g% command)
    269 
    270 The function should return a list with one of these values:
    271 [line, col]  - Match found at the specified position
    272 []           - No match found; fall through to regular matching
    273                (|b:match_words|, matchpairs, etc.)
    274 
    275 The cursor position is not changed by the function; matchit handles cursor
    276 movement based on the returned position.
    277 
    278 If the function throws an error, matchit gives up and doesn't continue.
    279 Enable |b:match_debug| to see error messages from custom match functions.
    280 
    281 Python example (simplified): >
    282 let s:keywords = {'if': 'elif\|else', 'elif': 'elif\|else'}
    283 
    284 function! s:PythonMatch(forward) abort
    285   let keyword = matchstr(getline('.'), '^\s*\zs\w\+')
    286   let pattern = get(s:keywords, keyword, '')
    287   if empty(pattern) | return [] | endif
    288 
    289   " Forward-only. Backwards left as an exercise for the reader.
    290   let [lnum, col] = searchpos('^\s*\%(' . pattern . '\)\>', 'nW' 0, 0,
    291   \                            'indent(".") != ' . indent('.'))
    292   return lnum > 0 ? [lnum, col] : []
    293 endfunction
    294 
    295 let b:match_function = function('s:PythonMatch')
    296 <
    297 See |matchit-newlang| below for more details on supporting new languages.
    298 
    299 ==============================================================================
    300 4. Supporting a New Language				*matchit-newlang*
    301 						*b:match_words*
    302 In order for matchit.vim to support a new language, you must define a suitable
    303 pattern for |b:match_words|.  You may also want to set some of the
    304 |matchit-configure| variables, as described above.  If your language has a
    305 complicated syntax, or many keywords, you will need to know something about
    306 Vim's |regular-expression|s.
    307 
    308 The format for |b:match_words| is similar to that of the 'matchpairs' option:
    309 it is a comma (,)-separated list of groups; each group is a colon(:)-separated
    310 list of patterns (regular expressions).  Commas and colons that are part of a
    311 pattern should be escaped with backslashes ('\:' and '\,').  It is OK to have
    312 only one group; the effect is undefined if a group has only one pattern.
    313 A simple example is >
    314 :let b:match_words = '\<if\>:\<endif\>,'
    315 	\ . '\<while\>:\<continue\>:\<break\>:\<endwhile\>'
    316 (In Vim regular expressions, |\<| and |\>| denote word boundaries.  Thus "if"
    317 matches the end of "endif" but "\<if\>" does not.)  Then banging on the "%"
    318 key will bounce the cursor between "if" and the matching "endif"; and from
    319 "while" to any matching "continue" or "break", then to the matching "endwhile"
    320 and back to the "while".  It is almost always easier to use |literal-string|s
    321 (single quotes) as above:  '\<if\>' rather than "\\<if\\>" and so on.
    322 
    323 Exception:  If the ":" character does not appear in b:match_words, then it is
    324 treated as an expression to be evaluated.  For example, >
    325 :let b:match_words = 'GetMatchWords()'
    326 allows you to define a function.  This can return a different string depending
    327 on the current syntax, for example.
    328 
    329 Once you have defined the appropriate value of |b:match_words|, you will
    330 probably want to have this set automatically each time you edit the
    331 appropriate file type.  The recommended way to do this is by adding the
    332 definition to a |filetype-plugin| file.
    333 
    334 Tips: Be careful that your initial pattern does not match your final pattern.
    335 See the example above for the use of word-boundary expressions.  It is usually
    336 better to use ".\{-}" (as many as necessary) instead of ".*" (as many as
    337 possible).  See |\{-|.  For example, in the string "<tag>label</tag>", "<.*>"
    338 matches the whole string whereas "<.\{-}>" and "<[^>]*>" match "<tag>" and
    339 "</tag>".
    340 
    341 			*matchit-spaces* *matchit-s:notend*
    342 If "if" is to be paired with "end if" (Note the space!) then word boundaries
    343 are not enough.  Instead, define a regular expression s:notend that will match
    344 anything but "end" and use it as follows: >
    345 :let s:notend = '\%(\<end\s\+\)\@<!'
    346 :let b:match_words = s:notend . '\<if\>:\<end\s\+if\>'
    347 <							*matchit-s:sol*
    348 This is a simplified version of what is done for Ada.  The s:notend is a
    349 |script-variable|.  Similarly, you may want to define a start-of-line regular
    350 expression >
    351 :let s:sol = '\%(^\|;\)\s*'
    352 if keywords are only recognized after the start of a line or after a
    353 semicolon (;), with optional white space.
    354 
    355 					*matchit-backref*
    356 In any group, the expressions |\1|, |\2|, ..., |\9| refer to parts of the
    357 INITIAL pattern enclosed in |\(|escaped parentheses|\)|.  These are referred
    358 to as back references, or backrefs.  For example, >
    359 :let b:match_words = '\<b\(o\+\)\>:\(h\)\1\>'
    360 means that "bo" pairs with "ho" and "boo" pairs with "hoo" and so on.  Note
    361 that "\1" does not refer to the "\(h\)" in this example.  If you have
    362 "\(nested \(parentheses\)\) then "\d" refers to the d-th "\(" and everything
    363 up to and including the matching "\)":  in "\(nested\(parentheses\)\)", "\1"
    364 refers to everything and "\2" refers to "\(parentheses\)".  If you use a
    365 variable such as |s:notend| or |s:sol| in the previous paragraph then remember
    366 to count any "\(" patterns in this variable.  You do not have to count groups
    367 defined by |\%(\)|.
    368 
    369 It should be possible to resolve back references from any pattern in the
    370 group.  For example, >
    371 :let b:match_words = '\(foo\)\(bar\):more\1:and\2:end\1\2'
    372 would not work because "\2" cannot be determined from "morefoo" and "\1"
    373 cannot be determined from "andbar".  On the other hand, >
    374 :let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1'
    375 should work (and have the same effect as "foobar:barfoo:endfoobar"), although
    376 this has not been thoroughly tested.
    377 
    378 You can use |zero-width| patterns such as |\@<=| and |\zs|.  (The latter has
    379 not been thoroughly tested in matchit.vim.)  For example, if the keyword "if"
    380 must occur at the start of the line, with optional white space, you might use
    381 the pattern "\(^\s*\)\@<=if" so that the cursor will end on the "i" instead of
    382 at the start of the line.  For another example, if HTML had only one tag then
    383 one could >
    384 :let b:match_words = '<:>,<\@<=tag>:<\@<=/tag>'
    385 so that "%" can bounce between matching "<" and ">" pairs or (starting on
    386 "tag" or "/tag") between matching tags.  Without the |\@<=|, the script would
    387 bounce from "tag" to the "<" in "</tag>", and another "%" would not take you
    388 back to where you started.
    389 
    390 DEBUGGING				*matchit-debug* *:MatchDebug*
    391 
    392 If you are having trouble figuring out the appropriate definition of
    393 |b:match_words| then you can take advantage of the same information I use when
    394 debugging the script.  This is especially true if you are not sure whether
    395 your patterns or my script are at fault!  To make this more convenient, I have
    396 made the command :MatchDebug, which defines the variable |b:match_debug| and
    397 creates a Matchit menu.  This menu makes it convenient to check the values of
    398 the variables described below.  You will probably also want to read
    399 |matchit-details| above.
    400 
    401 Defining the variable |b:match_debug| causes the script to set the following
    402 variables, each time you hit the "%" key.  Several of these are only defined
    403 if |b:match_words| includes |backref|s.
    404 
    405 						*b:match_pat*
    406 The b:match_pat variable is set to |b:match_words| with |backref|s parsed.
    407 						*b:match_match*
    408 The b:match_match variable is set to the bit of text that is recognized as a
    409 match.
    410 						*b:match_col*
    411 The b:match_col variable is set to the cursor column of the start of the
    412 matching text.
    413 						*b:match_wholeBR*
    414 The b:match_wholeBR variable is set to the comma-separated group of patterns
    415 that matches, with |backref|s unparsed.
    416 						*b:match_iniBR*
    417 The b:match_iniBR variable is set to the first pattern in |b:match_wholeBR|.
    418 						*b:match_ini*
    419 The b:match_ini variable is set to the first pattern in |b:match_wholeBR|,
    420 with |backref|s resolved from |b:match_match|.
    421 						*b:match_tail*
    422 The b:match_tail variable is set to the remaining patterns in
    423 |b:match_wholeBR|, with |backref|s resolved from |b:match_match|.
    424 						*b:match_word*
    425 The b:match_word variable is set to the pattern from |b:match_wholeBR| that
    426 matches |b:match_match|.
    427 						*b:match_table*
    428 The back reference '\'.d refers to the same thing as '\'.b:match_table[d] in
    429 |b:match_word|.
    430 
    431 ==============================================================================
    432 5. Known Bugs and Limitations				*matchit-bugs*
    433 
    434 Repository: https://github.com/chrisbra/matchit/
    435 Bugs can be reported at the repository and the latest development snapshot can
    436 also be downloaded there.
    437 
    438 Just because I know about a bug does not mean that it is on my todo list.  I
    439 try to respond to reports of bugs that cause real problems.  If it does not
    440 cause serious problems, or if there is a work-around, a bug may sit there for
    441 a while.  Moral:  if a bug (known or not) bothers you, let me know.
    442 
    443 It would be nice if "\0" were recognized as the entire pattern.  That is, it
    444 would be nice if "foo:\end\0" had the same effect as "\(foo\):\end\1".  I may
    445 try to implement this in a future version.  (This is not so easy to arrange as
    446 you might think!)
    447 
    448 ==============================================================================
    449 vim:tw=78:ts=8:fo=tcq2:ft=help: