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: