Movatterモバイル変換


[0]ホーム

URL:


Quick links:help overview ·quick reference ·user manual toc ·reference manual toc·faq
Go to keyword (shortcut:k)
Site search (shortcut:s)
matchit.txt Extended "%" matching  Last change: 2026 Jan 06VIM REFERENCE MANUAL    by Benji Fisher et almatchitmatchit.vim1. Extended matching with "%"matchit-intro2. Activationmatchit-activate3. Configurationmatchit-configure4. Supportinga New Languagematchit-newlang5. Known Bugs and Limitationsmatchit-bugsThe functionality mentioned hereisa plugin, seeadd-plugin.Thispluginis only available if'compatible'is not set.==============================================================================1. Extended matching with "%"matchit-intromatchit-%%Cycle forward through matching groups, suchas "if", "else", "endif",as specified byb:match_words.g%v_g%o_g%g%Cycle backwards through matching groups,as specified byb:match_words.  For example,go from "if" to "endif" to "else".[%v_[%o_[%[%Go to[count] previous unmatched group,as specified byb:match_words.  Similar to[{.]%v_]%o_]%]%Go to[count] next unmatched group,as specified byb:match_words.  Similar to]}.v_a%a%InVisual mode, select the matching group,as specified byb:match_words, containing the cursor.  Similar tov_a[.A[count]is ignored, and only the first character of the closingpatternis selected.In Vim,as in plain vi, the percent key,%, jumps the cursor froma brace,bracket, or paren to its match.  This can be configured with the'matchpairs'option.  Thematchitpluginextends this in several ways:    You can match whole words, suchas "if" and "endif", not justsingle characters.  You can also specifyaregular-expression.    You can define groups with more than two words, suchas "if","else", "endif".  Banging on the "%" key will cycle from the "if" tothe first "else", the next "else", ..., the closing "endif", and backto the opening "if".  Nested structures are skipped.  Usingg% goesin the reverse direction.    By default, words inside comments and strings are ignored, unlessthe cursoris insidea comment orstring when you type "%".  If theonly thing you want todois modify the behavior of "%" so thatitbehaves this way, youdo not have to defineb:match_words, since thescript uses the'matchpairs' optionas wellas this variable.Seematchit-details for details on what thescript does, andb:match_wordsfor how to specify matching patterns.MODES:matchit-modesmatchit-v_%matchit-o_%Mostly,% and related motions(g% and[% and]%) should just work like built-inmotion commands inOperator-pending andVisual modes (as of 8.1.648)LANGUAGES:matchit-languagesCurrently, the following languages are supported:  Ada, ASP with VBS, Csh,DTD, Entity, Essbase, Fortran, HTML, JSP (sameas HTML), LaTeX, Lua, Pascal,SGML, Shell, Tcsh, Vim, XML.  Other languages may already have support viathe defaultfiletype-plugins in the standard vim distribution.To supporta new language, seematchit-newlang below.DETAILS:matchit-detailsmatchit-parseHereis an outline of whatmatchit.vim does each time you hit the "%" key.  Ifthere arebackrefs inb:match_words then the first stepis to produceaversion in which these back references have been eliminated; if there are nobackrefs then this stepis skipped.  This stepis called parsing.  Forexample, "\(foo\|bar\):end\1"is parsed to yield"\(foo\|bar\):end\(foo\|bar\)".  This can get tricky, especially if there arenested groups.  If debuggingis turned on, the parsed versionis savedasb:match_pat.matchit-chooseNext, thescript looks foraword on the current line that matches thepatternjust constructed.  It includes the patterns from the'matchpairs' option.The goalis todo what you expect, which turns out to bea little complicated.Thescript follows these rules:Insist ona match that ends on or after the cursor.Prefera match that includes the cursor position (that is, one thatstarts on or before the cursor).Prefera match that startsas close to the cursoras possible.If more than onepattern inb:match_words matches, choose the onethatis listed first.Examples:Suppose you:let b:match_words = '<:>,<tag>:</tag>'and hit "%" with the cursor on or before the "<" in "a<tag>is born".Thepattern '<' comes first, soitis preferred over '<tag>', whichalso matches.  If the cursoris on the "t", however, then '<tag>'ispreferred, because this matchesa bit of text containing the cursor.If the two groups of patterns were reversed then '<' would never bepreferred.Suppose you:let b:match_words = 'if:end if'(Note the space!) and hit "%" with the cursorat theend of "end if".Then "if" matches, whichis probably not what you want, but if thecursor starts on the "end " then "end if"is chosen.  (You can avoidthis problem by usinga more complicated pattern.)If thereis no match, the cursor does not move.  (Before version 1.13 of thescript,it would fall back on the usual behavior of%).  If debuggingisturned on, the matched bit of textis savedasb:match_match and the cursorcolumn of the start of the matchis savedasb:match_col.Next, thescript looks throughb:match_words (original and parsed versions)for the group andpattern that match.  If debuggingis turned on, the groupissavedasb:match_ini (the first pattern) andb:match_tail (the rest).  Ifthere arebackrefs then, in addition, the matchingpatternis savedasb:match_word anda table of translationsis savedasb:match_table.  Ifthere arebackrefs, these are determined from the matchingpattern andb:match_match and substituted into eachpattern in the matching group.Thescript decides whether to search forwards or backwards and choosesarguments for thesearchpair() function.  Then, the cursoris moved to thestart of the match, andsearchpair()is called.  By default, matchingstructures inside strings and comments are ignored.  This can be changed bysettingb:match_skip.==============================================================================2. Activationmatchit-activateTo use thematchitplugin add this line to yourvimrc:packadd! matchitThescript should start working the next time you start Vim.To use thematchitplugin after Vim has started, execute this command:       packadd matchit(Earlier versions of thescript did nothing unlessabuffer-variable namedb:match_words was defined.  Even earlier versions containedautocommandsthat set this variable forvarious file types.  Now,b:match_wordsisdefined in many of the defaultfiletype-plugins instead.)Fora new language, you can addautocommands to thescript or to yourvimrcfile, but the recommendedmethodis to adda line suchaslet b:match_words = '\<foo\>:\<bar\>'to thefiletype-plugin for your language.  Seeb:match_words below for howthis variableis interpreted.TROUBLESHOOTINGmatchit-troubleshootThescript should work in most installations of Vim.  It may not work if Vimwas compiled witha minimal feature set, for example if the+syntax optionwas not enabled.  If your Vim has support forsyntax compiled in, but youdonot havesyntax highlighting turned on,matchit.vim should work, butit mayfail to skip matching groups in comments and strings.  If thefiletypemechanismis turned off, theb:match_words variable will probably not bedefined automatically.2.1 Temporarily disable thematchitpluginmatchit-disable:MatchDisableTo temporarily disable thematchit plugin, afterit has been loaded,execute this command::MatchDisableThis will delete all the defined key mappings to the Vim default.Now the "%" command will work like before loading theplugin%2.2 Re-enable thematchitplugin:MatchEnableTo re-enable the plugin, afterit was disabled, use the following command::MatchEnableThis will resetup the key mappings.==============================================================================3. Configurationmatchit-configureThere are severalvariables that govern the behavior of matchit.vim.Notethat these arevariables local to the buffer, not options, so use:let todefine them, not:set.  Some of thesevariables have values that matter; forothers,it only matters whether the variable has been defined.  All of thesecan be defined in thefiletype-plugin orautocommand that definesb:match_words or "on the fly."The main variableisb:match_words.  Itis described in thesection below onsupportinga new language.MatchErrormatchit-hlmatchit-highlightMatchErroris the highlight group for errormessages from the script.  Bydefault,itis linked to WarningMsg.  If youdo not want to be bothered byerror messages, you can define this to be something invisible.  For example,if you use theGUI version of Vim and your command lineis normally white, youcando:hi MatchError guifg=white guibg=whiteb:match_ignorecaseIf you:let b:match_ignorecase = 1thenmatchit.vim actsas if'ignorecase'is set: for example, "end" and "END"are equivalent.  If you:let b:match_ignorecase = 0thenmatchit.vim treats "end" and "END" differently.  (There will be nob:match_infercase option unless someone requests it.)b:match_debugDefineb:match_debug if you want debugging information to be saved.  Seematchit-debug, below.b:match_skipIfb:match_skipis defined,itis passedas the skip argument tosearchpair().  This controls when matching structures are skipped, orignored.  By default, they are ignored inside comments and strings,asdetermined by thesyntax mechanism.  (Ifsyntax highlightingis turned off,nothingis skipped.)  You can setb:match_skip toa string, which evaluates toa non-zero, numerical value if the matchis to be skipped or zero if the matchshould not be skipped.  In addition, the following special values aresupported by matchit.vim:s:foo becomes (currentsyntax item) =~ fooS:foo becomes (currentsyntax item) !~ foor:foo becomes (line before cursor) =~ fooR:foo becomes (line before cursor) !~ foo(The "s"is meant to suggest "syntax", and the "r"is meant to suggest"regularexpression".)Examples:You can get the default behavior with:let b:match_skip = 's:comment\|string'If you want to skip matching structures unless they areat the startof the line (ignoring whitespace) then you can:let b:match_skip = 'R:^\s*'Do notdo this if strings or comments can span several lines, sincethe normalsyntax checking will not be done if you set b:match_skip.In LaTeX, since "%"is usedas the comment character, you can:let b:match_skip = 'r:%'Unfortunately, this will skip anything after "\%", an escaped "%".  Toallow for this, and also "\\%" (an escapedbackslash followed by thecomment character) you can:let b:match_skip = 'r:\(^\|[^\\]\)\(\\\\\)*%'See the $VIMRUNTIME/ftplugin/vim.vim for an example that uses bothsyntax anda regular expression.b:match_functionIfb:match_functionis defined,matchit.vim will first call this function toperform matching.  Thisis useful for languages with an indentation-based blockstructure (suchas Python) or other complex matching requirements that cannotbe expressed with regularexpression patterns.The function should accept one argument:forward- 1 for forward search (% command)0 for backward search (g% command)The function should returnalist with one of these values:[line, col]- Match foundat the specified position[]- No match found; fall through to regular matching(b:match_words, matchpairs, etc.)The cursor positionis not changed by the function;matchit handles cursormovement based on the returned position.If the function throws an error,matchit gives up and doesn't continue.Enableb:match_debug to see errormessages from custom match functions.Python example (simplified):let s:keywords = {'if': 'elif\|else', 'elif': 'elif\|else'}function! s:PythonMatch(forward) abort  let keyword = matchstr(getline('.'), '^\s*\zs\w\+')  let pattern = get(s:keywords, keyword, '')  if empty(pattern) | return [] | endif  " Forward-only. Backwards left as an exercise for the reader.  let [lnum, col] = searchpos('^\s*\%(' . pattern . '\)\>', 'nW' 0, 0,  \                            'indent(".") != ' . indent('.'))  return lnum > 0 ? [lnum, col] : []endfunctionlet b:match_function = function('s:PythonMatch')Seematchit-newlang below for more details on supporting new languages.==============================================================================4. Supportinga New Languagematchit-newlangb:match_wordsIn order formatchit.vim to supporta new language, youmust definea suitablepattern forb:match_words.  You may also want to set some of thematchit-configure variables,as described above.  If your language hasacomplicated syntax, or many keywords, you will need to know something aboutVim'sregular-expressions.The format forb:match_wordsis similar to that of the'matchpairs' option:itisa comma (,)-separatedlist of groups; each groupisa colon(:)-separatedlist of patterns (regular expressions).  Commas and colons that are part ofapattern should be escaped with backslashes ('\:' and '\,').  Itis OK to haveonly one group; the effectis undefined ifa group has only one pattern.A simple exampleis:let b:match_words = '\<if\>:\<endif\>,'\ . '\<while\>:\<continue\>:\<break\>:\<endwhile\>'(In Vim regular expressions,\< and\> denoteword boundaries.  Thus "if"matches theend of "endif" but "\<if\>" does not.)  Then banging on the "%"key will bounce the cursor between "if" and the matching "endif"; and from"while" to any matching "continue" or "break", then to the matching "endwhile"and back to the "while".  Itis almost always easier to useliteral-strings(single quotes)as above:  '\<if\>' rather than "\\<if\\>" and so on.Exception:  If the ":" character does not appear in b:match_words, thenitistreatedas anexpression to be evaluated.  For example,:let b:match_words = 'GetMatchWords()'allows you to definea function.  This can returna differentstring dependingon the current syntax, for example.Once you have defined the appropriate value ofb:match_words, you willprobably want to have this set automatically each time you edit theappropriate file type.  The recommended way todo thisis by adding thedefinition toafiletype-plugin file.Tips: Be careful that your initialpattern does not match your final pattern.See the example above for the use of word-boundary expressions.  Itis usuallybetter to use ".\{-}" (as manyas necessary) instead of ".*" (as manyaspossible).  See\{-.  For example, in thestring "<tag>label</tag>", "<.*>"matches the wholestring whereas "<.\{-}>" and "<[^>]*>" match "<tag>" and"</tag>".matchit-spacesmatchit-s:notendIf "if"is to be paired with "end if" (Note the space!) thenword boundariesare not enough.  Instead, definea regularexpression s:notend that will matchanything but "end" and useitas follows::let s:notend = '\%(\<end\s\+\)\@<!':let b:match_words = s:notend . '\<if\>:\<end\s\+if\>'matchit-s:solThisisa simplified version of whatis done for Ada.  The s:notendisascript-variable.  Similarly, you may want to definea start-of-line regularexpression:let s:sol = '\%(^\|;\)\s*'if keywords are only recognized after the start ofa line or afterasemicolon (;), with optional white space.matchit-backrefIn any group, the expressions\1,\2, ...,\9 refer to parts of theINITIALpattern enclosed in\(escaped parentheses\).  These are referredtoas back references, or backrefs.  For example,:let b:match_words = '\<b\(o\+\)\>:\(h\)\1\>'means that "bo" pairs with "ho" and "boo" pairs with "hoo" and so on.Notethat "\1" does not refer to the "\(h\)" in this example.  If you have"\(nested \(parentheses\)\) then "\d" refers to the d-th "\(" and everythingup to and including the matching "\)":  in "\(nested\(parentheses\)\)", "\1"refers to everything and "\2" refers to "\(parentheses\)".  If you useavariable suchass:notend ors:sol in the previousparagraph then remembertocount any "\(" patterns in this variable.  Youdo not have tocount groupsdefined by\%(\).It should be possible to resolve back references from anypattern in thegroup.  For example,:let b:match_words = '\(foo\)\(bar\):more\1:and\2:end\1\2'would not work because "\2" cannot be determined from "morefoo" and "\1"cannot be determined from "andbar".  On the other hand,:let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1'should work (and have the same effectas "foobar:barfoo:endfoobar"), althoughthis has not been thoroughly tested.You can usezero-width patterns suchas\@<= and\zs.  (The latter hasnot been thoroughly tested in matchit.vim.)  For example, if the keyword "if"must occurat the start of the line, with optional white space, you might usethepattern "\(^\s*\)\@<=if" so that the cursor willend on the "i" instead ofat the start of the line.  For another example, if HTML had only onetag thenone could:let b:match_words = '<:>,<\@<=tag>:<\@<=/tag>'so that "%" can bounce between matching "<" and ">" pairs or (starting on"tag" or "/tag") between matching tags.  Without the\@<=, thescript wouldbounce from "tag" to the "<" in "</tag>", and another "%" would not take youback to where you started.DEBUGGINGmatchit-debug:MatchDebugIf you are having trouble figuring out the appropriate definition ofb:match_words then you can take advantage of the same informationI use whendebugging the script.  Thisis especiallytrue if you are not sure whetheryour patterns or myscript areat fault!  To make this more convenient,I havemade the command :MatchDebug, which defines the variableb:match_debug andcreatesa Matchit menu.  This menu makesit convenient to check the values ofthevariables described below.  You will probably also want to readmatchit-details above.Defining the variableb:match_debug causes thescript to set the followingvariables, each time you hit the "%" key.  Several of these are only definedifb:match_words includesbackrefs.b:match_patTheb:match_pat variableis set tob:match_words withbackrefs parsed.b:match_matchTheb:match_match variableis set to the bit of text thatis recognizedasamatch.b:match_colTheb:match_col variableis set to the cursor column of the start of thematching text.b:match_wholeBRTheb:match_wholeBR variableis set to the comma-separated group of patternsthat matches, withbackrefs unparsed.b:match_iniBRTheb:match_iniBR variableis set to the firstpattern inb:match_wholeBR.b:match_iniTheb:match_ini variableis set to the firstpattern inb:match_wholeBR,withbackrefs resolved fromb:match_match.b:match_tailTheb:match_tail variableis set to the remaining patterns inb:match_wholeBR, withbackrefs resolved fromb:match_match.b:match_wordTheb:match_word variableis set to thepattern fromb:match_wholeBR thatmatchesb:match_match.b:match_tableThe backreference '\'.d refers to the same thingas '\'.b:match_table[d] inb:match_word.==============================================================================5. Known Bugs and Limitationsmatchit-bugsRepository:https://github.com/chrisbra/matchit/Bugs can be reportedat the repository and the latestdevelopment snapshot canalso be downloaded there.Just becauseI know abouta bug does not mean thatitis on mytodo list.Itry to respond to reports ofbugs that cause real problems.  Ifit does notcause serious problems, or if thereisa work-around,a bug may sit there fora while.  Moral:  ifa bug (known or not) bothers you, let me know.It would be nice if "\0" were recognizedas the entire pattern.  That is,itwould be nice if "foo:\end\0" had the same effectas "\(foo\):\end\1".I maytry to implement this ina future version.  (Thisis not soeasy to arrangeasyou might think!)==============================================================================vim:tw=78:ts=8:fo=tcq2:ft=help:

Quick links:help overview ·quick reference ·user manual toc ·reference manual toc·faq


[8]ページ先頭

©2009-2026 Movatter.jp