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