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