whoami7 - Manager
:
/
home
/
creaupfw
/
www
/
wp-includes
/
assets
/
Upload File:
files >> /home/creaupfw/www/wp-includes/assets/vim80.zip
PK ��ZU�� � indent.vimnu �[��� " Vim support file to switch on loading indent files for file types " " Maintainer: Bram Moolenaar <Bram@vim.org> " Last Change: 2008 Feb 22 if exists("did_indent_on") finish endif let did_indent_on = 1 augroup filetypeindent au FileType * call s:LoadIndent() func! s:LoadIndent() if exists("b:undo_indent") exe b:undo_indent unlet! b:undo_indent b:did_indent endif let s = expand("<amatch>") if s != "" if exists("b:did_indent") unlet b:did_indent endif " When there is a dot it is used to separate filetype names. Thus for " "aaa.bbb" load "indent/aaa.vim" and then "indent/bbb.vim". for name in split(s, '\.') exe 'runtime! indent/' . name . '.vim' endfor endif endfunc augroup END PK ��ZdѠ�# �# ( pack/dist/opt/justify/plugin/justify.vimnu �[��� " Function to left and right align text. " " Written by: Preben "Peppe" Guldberg <c928400@student.dtu.dk> " Created: 980806 14:13 (or around that time anyway) " Revised: 001103 00:36 (See "Revisions" below) " function Justify( [ textwidth [, maxspaces [, indent] ] ] ) " " Justify() will left and right align a line by filling in an " appropriate amount of spaces. Extra spaces are added to existing " spaces starting from the right side of the line. As an example, the " following documentation has been justified. " " The function takes the following arguments: " textwidth argument " ------------------ " If not specified, the value of the 'textwidth' option is used. If " 'textwidth' is zero a value of 80 is used. " " Additionally the arguments 'tw' and '' are accepted. The value of " 'textwidth' will be used. These are handy, if you just want to specify " the maxspaces argument. " maxspaces argument " ------------------ " If specified, alignment will only be done, if the longest space run " after alignment is no longer than maxspaces. " " An argument of '' is accepted, should the user like to specify all " arguments. " " To aid user defined commands, negative values are accepted aswell. " Using a negative value specifies the default behaviour: any length of " space runs will be used to justify the text. " indent argument " --------------- " This argument specifies how a line should be indented. The default is " to keep the current indentation. " " Negative values: Keep current amount of leading whitespace. " Positive values: Indent all lines with leading whitespace using this " amount of whitespace. " " Note that the value 0, needs to be quoted as a string. This value " leads to a left flushed text. " " Additionally units of 'shiftwidth'/'sw' and 'tabstop'/'ts' may be " added. In this case, if the value of indent is positive, the amount of " whitespace to be added will be multiplied by the value of the " 'shiftwidth' and 'tabstop' settings. If these units are used, the " argument must be given as a string, eg. Justify('','','2sw'). " " If the values of 'sw' or 'tw' are negative, they are treated as if " they were 0, which means that the text is flushed left. There is no " check if a negative number prefix is used to change the sign of a " negative 'sw' or 'ts' value. " " As with the other arguments, '' may be used to get the default " behaviour. " Notes: " " If the line, adjusted for space runs and leading/trailing whitespace, " is wider than the used textwidth, the line will be left untouched (no " whitespace removed). This should be equivalent to the behaviour of " :left, :right and :center. " " If the resulting line is shorter than the used textwidth it is left " untouched. " " All space runs in the line are truncated before the alignment is " carried out. " " If you have set 'noexpandtab', :retab! is used to replace space runs " with whitespace using the value of 'tabstop'. This should be " conformant with :left, :right and :center. " " If joinspaces is set, an extra space is added after '.', '?' and '!'. " If 'cpooptions' include 'j', extra space is only added after '.'. " (This may on occasion conflict with maxspaces.) " Related mappings: " " Mappings that will align text using the current text width, using at " most four spaces in a space run and keeping current indentation. nmap _j :%call Justify('tw',4)<CR> vmap _j :call Justify('tw',4)<CR> " " Mappings that will remove space runs and format lines (might be useful " prior to aligning the text). nmap ,gq :%s/\s\+/ /g<CR>gq1G vmap ,gq :s/\s\+/ /g<CR>gvgq " User defined command: " " The following is an ex command that works as a shortcut to the Justify " function. Arguments to Justify() can be added after the command. com! -range -nargs=* Justify <line1>,<line2>call Justify(<f-args>) " " The following commands are all equivalent: " " 1. Simplest use of Justify(): " :call Justify() " :Justify " " 2. The _j mapping above via the ex command: " :%Justify tw 4 " " 3. Justify visualised text at 72nd column while indenting all " previously indented text two shiftwidths " :'<,'>call Justify(72,'','2sw') " :'<,'>Justify 72 -1 2sw " " This documentation has been justified using the following command: ":se et|kz|1;/^" function Justify(/+,'z-g/^" /s/^" //|call Justify(70,3)|s/^/" / " Revisions: " 001103: If 'joinspaces' was set, calculations could be wrong. " Tabs at start of line could also lead to errors. " Use setline() instead of "exec 's/foo/bar/' - safer. " Cleaned up the code a bit. " " Todo: Convert maps to the new script specific form " Error function function! Justify_error(message) echohl Error echo "Justify([tw, [maxspaces [, indent]]]): " . a:message echohl None endfunction " Now for the real thing function! Justify(...) range if a:0 > 3 call Justify_error("Too many arguments (max 3)") return 1 endif " Set textwidth (accept 'tw' and '' as arguments) if a:0 >= 1 if a:1 =~ '^\(tw\)\=$' let tw = &tw elseif a:1 =~ '^\d\+$' let tw = a:1 else call Justify_error("tw must be a number (>0), '' or 'tw'") return 2 endif else let tw = &tw endif if tw == 0 let tw = 80 endif " Set maximum number of spaces between WORDs if a:0 >= 2 if a:2 == '' let maxspaces = tw elseif a:2 =~ '^-\d\+$' let maxspaces = tw elseif a:2 =~ '^\d\+$' let maxspaces = a:2 else call Justify_error("maxspaces must be a number or ''") return 3 endif else let maxspaces = tw endif if maxspaces <= 1 call Justify_error("maxspaces should be larger than 1") return 4 endif " Set the indentation style (accept sw and ts units) let indent_fix = '' if a:0 >= 3 if (a:3 == '') || a:3 =~ '^-[1-9]\d*\(shiftwidth\|sw\|tabstop\|ts\)\=$' let indent = -1 elseif a:3 =~ '^-\=0\(shiftwidth\|sw\|tabstop\|ts\)\=$' let indent = 0 elseif a:3 =~ '^\d\+\(shiftwidth\|sw\|tabstop\|ts\)\=$' let indent = substitute(a:3, '\D', '', 'g') elseif a:3 =~ '^\(shiftwidth\|sw\|tabstop\|ts\)$' let indent = 1 else call Justify_error("indent: a number with 'sw'/'ts' unit") return 5 endif if indent >= 0 while indent > 0 let indent_fix = indent_fix . ' ' let indent = indent - 1 endwhile let indent_sw = 0 if a:3 =~ '\(shiftwidth\|sw\)' let indent_sw = &sw elseif a:3 =~ '\(tabstop\|ts\)' let indent_sw = &ts endif let indent_fix2 = '' while indent_sw > 0 let indent_fix2 = indent_fix2 . indent_fix let indent_sw = indent_sw - 1 endwhile let indent_fix = indent_fix2 endif else let indent = -1 endif " Avoid substitution reports let save_report = &report set report=1000000 " Check 'joinspaces' and 'cpo' if &js == 1 if &cpo =~ 'j' let join_str = '\(\. \)' else let join_str = '\([.!?!] \)' endif endif let cur = a:firstline while cur <= a:lastline let str_orig = getline(cur) let save_et = &et set et exec cur . "retab" let &et = save_et let str = getline(cur) let indent_str = indent_fix let indent_n = strlen(indent_str) " Shall we remember the current indentation if indent < 0 let indent_orig = matchstr(str_orig, '^\s*') if strlen(indent_orig) > 0 let indent_str = indent_orig let indent_n = strlen(matchstr(str, '^\s*')) endif endif " Trim trailing, leading and running whitespace let str = substitute(str, '\s\+$', '', '') let str = substitute(str, '^\s\+', '', '') let str = substitute(str, '\s\+', ' ', 'g') let str_n = strdisplaywidth(str) " Possible addition of space after punctuation if exists("join_str") let str = substitute(str, join_str, '\1 ', 'g') endif let join_n = strdisplaywidth(str) - str_n " Can extraspaces be added? " Note that str_n may be less than strlen(str) [joinspaces above] if strdisplaywidth(str) <= tw - indent_n && str_n > 0 " How many spaces should be added let s_add = tw - str_n - indent_n - join_n let s_nr = strlen(substitute(str, '\S', '', 'g') ) - join_n let s_dup = s_add / s_nr let s_mod = s_add % s_nr " Test if the changed line fits with tw if 0 <= (str_n + (maxspaces - 1)*s_nr + indent_n) - tw " Duplicate spaces while s_dup > 0 let str = substitute(str, '\( \+\)', ' \1', 'g') let s_dup = s_dup - 1 endwhile " Add extra spaces from the end while s_mod > 0 let str = substitute(str, '\(\(\s\+\S\+\)\{' . s_mod . '}\)$', ' \1', '') let s_mod = s_mod - 1 endwhile " Indent the line if indent_n > 0 let str = substitute(str, '^', indent_str, '' ) endif " Replace the line call setline(cur, str) " Convert to whitespace if &et == 0 exec cur . 'retab!' endif endif " Change of line endif " Possible change let cur = cur + 1 endwhile norm ^ let &report = save_report endfunction " EOF vim: tw=78 ts=8 sw=4 sts=4 noet ai PK ��Z"<� � � 2 pack/dist/opt/editexisting/plugin/editexisting.vimnu �[��� " Vim Plugin: Edit the file with an existing Vim if possible " Maintainer: Bram Moolenaar " Last Change: 2016 Mar 28 " To use add ":packadd! editexisting" in your vimrc file. " This plugin serves two purposes: " 1. On startup, if we were invoked with one file name argument and the file " is not modified then try to find another Vim instance that is editing " this file. If there is one then bring it to the foreground and exit. " 2. When a file is edited and a swap file exists for it, try finding that " other Vim and bring it to the foreground. Requires Vim 7, because it " uses the SwapExists autocommand event. " Function that finds the Vim instance that is editing "filename" and brings " it to the foreground. func s:EditElsewhere(filename) let fname_esc = substitute(a:filename, "'", "''", "g") let servers = serverlist() while servers != '' " Get next server name in "servername"; remove it from "servers". let i = match(servers, "\n") if i == -1 let servername = servers let servers = '' else let servername = strpart(servers, 0, i) let servers = strpart(servers, i + 1) endif " Skip ourselves. if servername ==? v:servername continue endif " Check if this server is editing our file. if remote_expr(servername, "bufloaded('" . fname_esc . "')") " Yes, bring it to the foreground. if has("win32") call remote_foreground(servername) endif call remote_expr(servername, "foreground()") if remote_expr(servername, "exists('*EditExisting')") " Make sure the file is visible in a window (not hidden). " If v:swapcommand exists and is set, send it to the server. if exists("v:swapcommand") let c = substitute(v:swapcommand, "'", "''", "g") call remote_expr(servername, "EditExisting('" . fname_esc . "', '" . c . "')") else call remote_expr(servername, "EditExisting('" . fname_esc . "', '')") endif endif if !(has('vim_starting') && has('gui_running') && has('gui_win32')) " Tell the user what is happening. Not when the GUI is starting " though, it would result in a message box. echomsg "File is being edited by " . servername sleep 2 endif return 'q' endif endwhile return '' endfunc " When the plugin is loaded and there is one file name argument: Find another " Vim server that is editing this file right now. if argc() == 1 && !&modified if s:EditElsewhere(expand("%:p")) == 'q' quit endif endif " Setup for handling the situation that an existing swap file is found. try au! SwapExists * let v:swapchoice = s:EditElsewhere(expand("<afile>:p")) catch " Without SwapExists we don't do anything for ":edit" commands endtry " Function used on the server to make the file visible and possibly execute a " command. func! EditExisting(fname, command) " Get the window number of the file in the current tab page. let winnr = bufwinnr(a:fname) if winnr <= 0 " Not found, look in other tab pages. let bufnr = bufnr(a:fname) for i in range(tabpagenr('$')) if index(tabpagebuflist(i + 1), bufnr) >= 0 " Make this tab page the current one and find the window number. exe 'tabnext ' . (i + 1) let winnr = bufwinnr(a:fname) break endif endfor endif if winnr > 0 exe winnr . "wincmd w" elseif exists('*fnameescape') exe "split " . fnameescape(a:fname) else exe "split " . escape(a:fname, " \t\n*?[{`$\\%#'\"|!<") endif if a:command != '' exe "normal! " . a:command endif redraw endfunc PK ��Z/��lR R , pack/dist/opt/shellmenu/plugin/shellmenu.vimnu �[��� " When you're writing shell scripts and you are in doubt which test to use, " which shell environment variables are defined, what the syntax of the case " statement is, and you need to invoke 'man sh'? " " Your problems are over now! " " Attached is a Vim script file for turning gvim into a shell script editor. " It may also be used as an example how to use menus in Vim. " " Written by: Lennart Schultz <les@dmi.min.dk> imenu Stmts.for for in do doneki kk0elli imenu Stmts.case case in ) ;; esacbki k0elli imenu Stmts.if if then fiki kk0elli imenu Stmts.if-else if then else fiki kki kk0elli imenu Stmts.elif elif then ki kk0elli imenu Stmts.while while do doneki kk0elli imenu Stmts.break break imenu Stmts.continue continue imenu Stmts.function () { }ki k0i imenu Stmts.return return imenu Stmts.return-true return 0 imenu Stmts.return-false return 1 imenu Stmts.exit exit imenu Stmts.shift shift imenu Stmts.trap trap imenu Test.existence [ -e ]hi imenu Test.existence - file [ -f ]hi imenu Test.existence - file (not empty) [ -s ]hi imenu Test.existence - directory [ -d ]hi imenu Test.existence - executable [ -x ]hi imenu Test.existence - readable [ -r ]hi imenu Test.existence - writable [ -w ]hi imenu Test.String is empty [ x = "x$" ]hhi imenu Test.String is not empty [ x != "x$" ]hhi imenu Test.Strings is equal [ "" = "" ]hhhhhhhi imenu Test.Strings is not equal [ "" != "" ]hhhhhhhhi imenu Test.Values is greater than [ -gt ]hhhhhhi imenu Test.Values is greater equal [ -ge ]hhhhhhi imenu Test.Values is equal [ -eq ]hhhhhhi imenu Test.Values is not equal [ -ne ]hhhhhhi imenu Test.Values is less than [ -lt ]hhhhhhi imenu Test.Values is less equal [ -le ]hhhhhhi imenu ParmSub.Substitute word if parm not set ${:-}hhi imenu ParmSub.Set parm to word if not set ${:=}hhi imenu ParmSub.Substitute word if parm set else nothing ${:+}hhi imenu ParmSub.If parm not set print word and exit ${:?}hhi imenu SpShVars.Number of positional parameters ${#} imenu SpShVars.All positional parameters (quoted spaces) ${*} imenu SpShVars.All positional parameters (unquoted spaces) ${@} imenu SpShVars.Flags set ${-} imenu SpShVars.Return code of last command ${?} imenu SpShVars.Process number of this shell ${$} imenu SpShVars.Process number of last background command ${!} imenu Environ.HOME ${HOME} imenu Environ.PATH ${PATH} imenu Environ.CDPATH ${CDPATH} imenu Environ.MAIL ${MAIL} imenu Environ.MAILCHECK ${MAILCHECK} imenu Environ.PS1 ${PS1} imenu Environ.PS2 ${PS2} imenu Environ.IFS ${IFS} imenu Environ.SHACCT ${SHACCT} imenu Environ.SHELL ${SHELL} imenu Environ.LC_CTYPE ${LC_CTYPE} imenu Environ.LC_MESSAGES ${LC_MESSAGES} imenu Builtins.cd cd imenu Builtins.echo echo imenu Builtins.eval eval imenu Builtins.exec exec imenu Builtins.export export imenu Builtins.getopts getopts imenu Builtins.hash hash imenu Builtins.newgrp newgrp imenu Builtins.pwd pwd imenu Builtins.read read imenu Builtins.readonly readonly imenu Builtins.return return imenu Builtins.times times imenu Builtins.type type imenu Builtins.umask umask imenu Builtins.wait wait imenu Set.set set imenu Set.unset unset imenu Set.mark modified or modified variables set -a imenu Set.exit when command returns non-zero exit code set -e imenu Set.Disable file name generation set -f imenu Set.remember function commands set -h imenu Set.All keyword arguments are placed in the environment set -k imenu Set.Read commands but do not execute them set -n imenu Set.Exit after reading and executing one command set -t imenu Set.Treat unset variables as an error when substituting set -u imenu Set.Print shell input lines as they are read set -v imenu Set.Print commands and their arguments as they are executed set -x PK ��Z�3�X X , pack/dist/opt/swapmouse/plugin/swapmouse.vimnu �[��� " These macros swap the left and right mouse buttons (for left handed) " Don't forget to do ":set mouse=a" or the mouse won't work at all noremap <LeftMouse> <RightMouse> noremap <2-LeftMouse> <2-RightMouse> noremap <3-LeftMouse> <3-RightMouse> noremap <4-LeftMouse> <4-RightMouse> noremap <LeftDrag> <RightDrag> noremap <LeftRelease> <RightRelease> noremap <RightMouse> <LeftMouse> noremap <2-RightMouse> <2-LeftMouse> noremap <3-RightMouse> <3-LeftMouse> noremap <4-RightMouse> <4-LeftMouse> noremap <RightDrag> <LeftDrag> noremap <RightRelease> <LeftRelease> noremap g<LeftMouse> <C-RightMouse> noremap g<RightMouse> <C-LeftMouse> noremap! <LeftMouse> <RightMouse> noremap! <LeftDrag> <RightDrag> noremap! <LeftRelease> <RightRelease> noremap! <RightMouse> <LeftMouse> noremap! <RightDrag> <LeftDrag> noremap! <RightRelease> <LeftRelease> PK ��Z+� � � pack/dist/opt/matchit/doc/tagsnu �[��� :MatchDebug matchit.txt /*:MatchDebug* MatchError matchit.txt /*MatchError* [% matchit.txt /*[%* ]% matchit.txt /*]%* b:match_col matchit.txt /*b:match_col* b:match_debug matchit.txt /*b:match_debug* b:match_ignorecase matchit.txt /*b:match_ignorecase* b:match_ini matchit.txt /*b:match_ini* b:match_iniBR matchit.txt /*b:match_iniBR* b:match_match matchit.txt /*b:match_match* b:match_pat matchit.txt /*b:match_pat* b:match_skip matchit.txt /*b:match_skip* b:match_table matchit.txt /*b:match_table* b:match_tail matchit.txt /*b:match_tail* b:match_wholeBR matchit.txt /*b:match_wholeBR* b:match_word matchit.txt /*b:match_word* b:match_words matchit.txt /*b:match_words* g% matchit.txt /*g%* matchit matchit.txt /*matchit* matchit-% matchit.txt /*matchit-%* matchit-\1 matchit.txt /*matchit-\\1* matchit-activate matchit.txt /*matchit-activate* matchit-backref matchit.txt /*matchit-backref* matchit-bugs matchit.txt /*matchit-bugs* matchit-choose matchit.txt /*matchit-choose* matchit-configure matchit.txt /*matchit-configure* matchit-debug matchit.txt /*matchit-debug* matchit-details matchit.txt /*matchit-details* matchit-highlight matchit.txt /*matchit-highlight* matchit-hl matchit.txt /*matchit-hl* matchit-intro matchit.txt /*matchit-intro* matchit-languages matchit.txt /*matchit-languages* matchit-modes matchit.txt /*matchit-modes* matchit-newlang matchit.txt /*matchit-newlang* matchit-o_% matchit.txt /*matchit-o_%* matchit-parse matchit.txt /*matchit-parse* matchit-s:notend matchit.txt /*matchit-s:notend* matchit-s:sol matchit.txt /*matchit-s:sol* matchit-spaces matchit.txt /*matchit-spaces* matchit-troubleshoot matchit.txt /*matchit-troubleshoot* matchit-v_% matchit.txt /*matchit-v_%* matchit.txt matchit.txt /*matchit.txt* matchit.vim matchit.txt /*matchit.vim* o_[% matchit.txt /*o_[%* o_]% matchit.txt /*o_]%* o_g% matchit.txt /*o_g%* v_[% matchit.txt /*v_[%* v_]% matchit.txt /*v_]%* v_a% matchit.txt /*v_a%* v_g% matchit.txt /*v_g%* PK ��Znx��K K % pack/dist/opt/matchit/doc/matchit.txtnu �[��� *matchit.txt* Extended "%" matching For instructions on installing this file, type :help matchit-install inside Vim. For Vim version 6.3. Last change: 2017 May 14 VIM REFERENCE MANUAL by Benji Fisher *matchit* *matchit.vim* 1. Extended matching with "%" |matchit-intro| 2. Activation |matchit-activate| 3. Configuration |matchit-configure| 4. Supporting a New Language |matchit-newlang| 5. Known Bugs and Limitations |matchit-bugs| The functionality mentioned here is a plugin, see |add-plugin|. This plugin is only available if 'compatible' is not set. You can avoid loading this plugin by setting the "loaded_matchit" variable in your |vimrc| file: > :let loaded_matchit = 1 {Vi does not have any of this} ============================================================================== 1. Extended matching with "%" *matchit-intro* *matchit-%* % Cycle forward through matching groups, such as "if", "else", "endif", as specified by |b:match_words|. *g%* *v_g%* *o_g%* g% Cycle backwards through matching groups, as specified by |b:match_words|. For example, go from "if" to "endif" to "else". *[%* *v_[%* *o_[%* [% Go to [count] previous unmatched group, as specified by |b:match_words|. Similar to |[{|. *]%* *v_]%* *o_]%* ]% Go to [count] next unmatched group, as specified by |b:match_words|. Similar to |]}|. *v_a%* a% In Visual mode, select the matching group, as specified by |b:match_words|, containing the cursor. Similar to |v_a[|. A [count] is ignored, and only the first character of the closing pattern is selected. In Vim, as in plain vi, the percent key, |%|, jumps the cursor from a brace, bracket, or paren to its match. This can be configured with the 'matchpairs' option. The matchit plugin extends this in several ways: You can match whole words, such as "if" and "endif", not just single characters. You can also specify a |regular-expression|. You can define groups with more than two words, such as "if", "else", "endif". Banging on the "%" key will cycle from the "if" to the first "else", the next "else", ..., the closing "endif", and back to the opening "if". Nested structures are skipped. Using |g%| goes in the reverse direction. By default, words inside comments and strings are ignored, unless the cursor is inside a comment or string when you type "%". If the only thing you want to do is modify the behavior of "%" so that it behaves this way, you do not have to define |b:match_words|, since the script uses the 'matchpairs' option as well as this variable. See |matchit-details| for details on what the script does, and |b:match_words| for how to specify matching patterns. MODES: *matchit-modes* *matchit-v_%* *matchit-o_%* Mostly, % and related motions (|g%| and |[%| and |]%|) work just like built-in |motion| commands in |Operator-pending| and |Visual| modes. However, you cannot make these motions |linewise| or |characterwise|, since the |:omap|s that define them start with "v" in order to make the default behavior inclusive. (See |o_v|.) In other words, "dV%" will not work. The work-around is to go through Visual mode: "V%d" will work. LANGUAGES: *matchit-languages* Currently, the following languages are supported: Ada, ASP with VBS, Csh, DTD, Entity, Essbase, Fortran, HTML, JSP (same as HTML), LaTeX, Lua, Pascal, SGML, Shell, Tcsh, Vim, XML. Other languages may already have support via the default |filetype-plugin|s in the standard vim distribution. To support a new language, see |matchit-newlang| below. DETAILS: *matchit-details* *matchit-parse* Here is an outline of what matchit.vim does each time you hit the "%" key. If there are |backref|s in |b:match_words| then the first step is to produce a version in which these back references have been eliminated; if there are no |backref|s then this step is skipped. This step is called parsing. For example, "\(foo\|bar\):end\1" is parsed to yield "\(foo\|bar\):end\(foo\|bar\)". This can get tricky, especially if there are nested groups. If debugging is turned on, the parsed version is saved as |b:match_pat|. *matchit-choose* Next, the script looks for a word on the current line that matches the pattern just constructed. It includes the patterns from the 'matchpairs' option. The goal is to do what you expect, which turns out to be a little complicated. The script follows these rules: Insist on a match that ends on or after the cursor. Prefer a match that includes the cursor position (that is, one that starts on or before the cursor). Prefer a match that starts as close to the cursor as possible. If more than one pattern in |b:match_words| matches, choose the one that is 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". The pattern '<' comes first, so it is preferred over '<tag>', which also matches. If the cursor is on the "t", however, then '<tag>' is preferred, because this matches a bit of text containing the cursor. If the two groups of patterns were reversed then '<' would never be preferred. Suppose you > :let b:match_words = 'if:end if' < (Note the space!) and hit "%" with the cursor at the end of "end if". Then "if" matches, which is probably not what you want, but if the cursor starts on the "end " then "end if" is chosen. (You can avoid this problem by using a more complicated pattern.) If there is no match, the cursor does not move. (Before version 1.13 of the script, it would fall back on the usual behavior of |%|). If debugging is turned on, the matched bit of text is saved as |b:match_match| and the cursor column of the start of the match is saved as |b:match_col|. Next, the script looks through |b:match_words| (original and parsed versions) for the group and pattern that match. If debugging is turned on, the group is saved as |b:match_ini| (the first pattern) and |b:match_tail| (the rest). If there are |backref|s then, in addition, the matching pattern is saved as |b:match_word| and a table of translations is saved as |b:match_table|. If there are |backref|s, these are determined from the matching pattern and |b:match_match| and substituted into each pattern in the matching group. The script decides whether to search forwards or backwards and chooses arguments for the |searchpair()| function. Then, the cursor is moved to the start of the match, and |searchpair()| is called. By default, matching structures inside strings and comments are ignored. This can be changed by setting |b:match_skip|. ============================================================================== 2. Activation *matchit-activate* To use the matchit plugin add this line to your |vimrc|: > packadd! matchit The script should start working the next time you start Vim. (Earlier versions of the script did nothing unless a |buffer-variable| named |b:match_words| was defined. Even earlier versions contained autocommands that set this variable for various file types. Now, |b:match_words| is defined in many of the default |filetype-plugin|s instead.) For a new language, you can add autocommands to the script or to your vimrc file, but the recommended method is to add a line such as > let b:match_words = '\<foo\>:\<bar\>' to the |filetype-plugin| for your language. See |b:match_words| below for how this variable is interpreted. TROUBLESHOOTING *matchit-troubleshoot* The script should work in most installations of Vim. It may not work if Vim was compiled with a minimal feature set, for example if the |+syntax| option was not enabled. If your Vim has support for syntax compiled in, but you do not have |syntax| highlighting turned on, matchit.vim should work, but it may fail to skip matching groups in comments and strings. If the |filetype| mechanism is turned off, the |b:match_words| variable will probably not be defined automatically. ============================================================================== 3. Configuration *matchit-configure* There are several variables that govern the behavior of matchit.vim. Note that these are variables local to the buffer, not options, so use |:let| to define them, not |:set|. Some of these variables have values that matter; for others, it only matters whether the variable has been defined. All of these can be defined in the |filetype-plugin| or autocommand that defines |b:match_words| or "on the fly." The main variable is |b:match_words|. It is described in the section below on supporting a new language. *MatchError* *matchit-hl* *matchit-highlight* MatchError is the highlight group for error messages from the script. By default, it is linked to WarningMsg. If you do not want to be bothered by error messages, you can define this to be something invisible. For example, if you use the GUI version of Vim and your command line is normally white, you can do > :hi MatchError guifg=white guibg=white < *b:match_ignorecase* If you > :let b:match_ignorecase = 1 then matchit.vim acts as if 'ignorecase' is set: for example, "end" and "END" are equivalent. If you > :let b:match_ignorecase = 0 then matchit.vim treats "end" and "END" differently. (There will be no b:match_infercase option unless someone requests it.) *b:match_debug* Define b:match_debug if you want debugging information to be saved. See |matchit-debug|, below. *b:match_skip* If b:match_skip is defined, it is passed as the skip argument to |searchpair()|. This controls when matching structures are skipped, or ignored. By default, they are ignored inside comments and strings, as determined by the |syntax| mechanism. (If syntax highlighting is turned off, nothing is skipped.) You can set b:match_skip to a string, which evaluates to a non-zero, numerical value if the match is to be skipped or zero if the match should not be skipped. In addition, the following special values are supported by matchit.vim: s:foo becomes (current syntax item) =~ foo S:foo becomes (current syntax item) !~ foo r:foo becomes (line before cursor) =~ foo R:foo becomes (line before cursor) !~ foo (The "s" is meant to suggest "syntax", and the "r" is meant to suggest "regular expression".) Examples: You can get the default behavior with > :let b:match_skip = 's:comment\|string' < If you want to skip matching structures unless they are at the start of the line (ignoring whitespace) then you can > :let b:match_skip = 'R:^\s*' < Do not do this if strings or comments can span several lines, since the normal syntax checking will not be done if you set b:match_skip. In LaTeX, since "%" is used as the comment character, you can > :let b:match_skip = 'r:%' < Unfortunately, this will skip anything after "\%", an escaped "%". To allow for this, and also "\\%" (an escaped backslash followed by the comment character) you can > :let b:match_skip = 'r:\(^\|[^\\]\)\(\\\\\)*%' < See the $VIMRUNTIME/ftplugin/vim.vim for an example that uses both syntax and a regular expression. ============================================================================== 4. Supporting a New Language *matchit-newlang* *b:match_words* In order for matchit.vim to support a new language, you must define a suitable pattern for |b:match_words|. You may also want to set some of the |matchit-configure| variables, as described above. If your language has a complicated syntax, or many keywords, you will need to know something about Vim's |regular-expression|s. The format for |b:match_words| is similar to that of the 'matchpairs' option: it is a comma (,)-separated list of groups; each group is a colon(:)-separated list of patterns (regular expressions). Commas and backslashes that are part of a pattern should be escaped with backslashes ('\:' and '\,'). It is OK to have only one group; the effect is undefined if a group has only one pattern. A simple example is > :let b:match_words = '\<if\>:\<endif\>,' \ . '\<while\>:\<continue\>:\<break\>:\<endwhile\>' (In Vim regular expressions, |\<| and |\>| denote word boundaries. Thus "if" matches the end 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". It is almost always easier to use |literal-string|s (single quotes) as above: '\<if\>' rather than "\\<if\\>" and so on. Exception: If the ":" character does not appear in b:match_words, then it is treated as an expression to be evaluated. For example, > :let b:match_words = 'GetMatchWords()' allows you to define a function. This can return a different string depending on the current syntax, for example. Once you have defined the appropriate value of |b:match_words|, you will probably want to have this set automatically each time you edit the appropriate file type. The recommended way to do this is by adding the definition to a |filetype-plugin| file. Tips: Be careful that your initial pattern does not match your final pattern. See the example above for the use of word-boundary expressions. It is usually better to use ".\{-}" (as many as necessary) instead of ".*" (as many as possible). See |\{-|. For example, in the string "<tag>label</tag>", "<.*>" matches the whole string whereas "<.\{-}>" and "<[^>]*>" match "<tag>" and "</tag>". *matchit-spaces* *matchit-s:notend* If "if" is to be paired with "end if" (Note the space!) then word boundaries are not enough. Instead, define a regular expression s:notend that will match anything but "end" and use it as follows: > :let s:notend = '\%(\<end\s\+\)\@<!' :let b:match_words = s:notend . '\<if\>:\<end\s\+if\>' < *matchit-s:sol* This is a simplified version of what is done for Ada. The s:notend is a |script-variable|. Similarly, you may want to define a start-of-line regular expression > :let s:sol = '\%(^\|;\)\s*' if keywords are only recognized after the start of a line or after a semicolon (;), with optional white space. *matchit-backref* *matchit-\1* In any group, the expressions |\1|, |\2|, ..., |\9| refer to parts of the INITIAL pattern enclosed in |\(|escaped parentheses|\)|. These are referred to as 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. Note that "\1" does not refer to the "\(h\)" in this example. If you have "\(nested \(parentheses\)\) then "\d" refers to the d-th "\(" and everything up to and including the matching "\)": in "\(nested\(parentheses\)\)", "\1" refers to everything and "\2" refers to "\(parentheses\)". If you use a variable such as |s:notend| or |s:sol| in the previous paragraph then remember to count any "\(" patterns in this variable. You do not have to count groups defined by |\%(\)|. It should be possible to resolve back references from any pattern in the group. 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 effect as "foobar:barfoo:endfoobar"), although this has not been thoroughly tested. You can use |zero-width| patterns such as |\@<=| and |\zs|. (The latter has not been thouroughly tested in matchit.vim.) For example, if the keyword "if" must occur at the start of the line, with optional white space, you might use the pattern "\(^\s*\)\@<=if" so that the cursor will end on the "i" instead of at the start of the line. For another example, if HTML had only one tag then one 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 |\@<=|, the script would bounce from "tag" to the "<" in "</tag>", and another "%" would not take you back to where you started. DEBUGGING *matchit-debug* *:MatchDebug* If you are having trouble figuring out the appropriate definition of |b:match_words| then you can take advantage of the same information I use when debugging the script. This is especially true if you are not sure whether your patterns or my script are at fault! To make this more convenient, I have made the command :MatchDebug, which defines the variable |b:match_debug| and creates a Matchit menu. This menu makes it convenient to check the values of the variables described below. You will probably also want to read |matchit-details| above. Defining the variable |b:match_debug| causes the script to set the following variables, each time you hit the "%" key. Several of these are only defined if |b:match_words| includes |backref|s. *b:match_pat* The b:match_pat variable is set to |b:match_words| with |backref|s parsed. *b:match_match* The b:match_match variable is set to the bit of text that is recognized as a match. *b:match_col* The b:match_col variable is set to the cursor column of the start of the matching text. *b:match_wholeBR* The b:match_wholeBR variable is set to the comma-separated group of patterns that matches, with |backref|s unparsed. *b:match_iniBR* The b:match_iniBR variable is set to the first pattern in |b:match_wholeBR|. *b:match_ini* The b:match_ini variable is set to the first pattern in |b:match_wholeBR|, with |backref|s resolved from |b:match_match|. *b:match_tail* The b:match_tail variable is set to the remaining patterns in |b:match_wholeBR|, with |backref|s resolved from |b:match_match|. *b:match_word* The b:match_word variable is set to the pattern from |b:match_wholeBR| that matches |b:match_match|. *b:match_table* The back reference '\'.d refers to the same thing as '\'.b:match_table[d] in |b:match_word|. ============================================================================== 5. Known Bugs and Limitations *matchit-bugs* Just because I know about a bug does not mean that it is on my todo list. I try to respond to reports of bugs that cause real problems. If it does not cause serious problems, or if there is a work-around, a bug may sit there for a while. Moral: if a bug (known or not) bothers you, let me know. The various |:vmap|s defined in the script (%, |g%|, |[%|, |]%|, |a%|) may have undesired effects in Select mode |Select-mode-mapping|. At least, if you want to replace the selection with any character in "ag%[]" there will be a pause of |'updatetime'| first. E.g., "yV%" would normally work linewise, but the plugin mapping makes it characterwise. It would be nice if "\0" were recognized as the entire pattern. That is, it would be nice if "foo:\end\0" had the same effect as "\(foo\):\end\1". I may try to implement this in a future version. (This is not so easy to arrange as you might think!) ============================================================================== vim:tw=78:fo=tcq2: PK ��Z�oR�*y *y ( pack/dist/opt/matchit/plugin/matchit.vimnu �[��� " matchit.vim: (global plugin) Extended "%" matching " Last Change: 2017 Sep 15 " Maintainer: Benji Fisher PhD <benji@member.AMS.org> " Version: 1.13.3, for Vim 6.3+ " Fix from Fernando Torres included. " Improvement from Ken Takata included. " URL: http://www.vim.org/script.php?script_id=39 " Documentation: " The documentation is in a separate file, matchit.txt . " Credits: " Vim editor by Bram Moolenaar (Thanks, Bram!) " Original script and design by Raul Segura Acevedo " Support for comments by Douglas Potts " Support for back references and other improvements by Benji Fisher " Support for many languages by Johannes Zellner " Suggestions for improvement, bug reports, and support for additional " languages by Jordi-Albert Batalla, Neil Bird, Servatius Brandt, Mark " Collett, Stephen Wall, Dany St-Amant, Yuheng Xie, and Johannes Zellner. " Debugging: " If you'd like to try the built-in debugging commands... " :MatchDebug to activate debugging for the current buffer " This saves the values of several key script variables as buffer-local " variables. See the MatchDebug() function, below, for details. " TODO: I should think about multi-line patterns for b:match_words. " This would require an option: how many lines to scan (default 1). " This would be useful for Python, maybe also for *ML. " TODO: Maybe I should add a menu so that people will actually use some of " the features that I have implemented. " TODO: Eliminate the MultiMatch function. Add yet another argument to " Match_wrapper() instead. " TODO: Allow :let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1' " TODO: Make backrefs safer by using '\V' (very no-magic). " TODO: Add a level of indirection, so that custom % scripts can use my " work but extend it. " allow user to prevent loading " and prevent duplicate loading if exists("loaded_matchit") || &cp finish endif let loaded_matchit = 1 let s:last_mps = "" let s:last_words = ":" let s:patBR = "" let s:save_cpo = &cpo set cpo&vim nnoremap <silent> % :<C-U>call <SID>Match_wrapper('',1,'n') <CR> nnoremap <silent> g% :<C-U>call <SID>Match_wrapper('',0,'n') <CR> vnoremap <silent> % :<C-U>call <SID>Match_wrapper('',1,'v') <CR>m'gv`` vnoremap <silent> g% :<C-U>call <SID>Match_wrapper('',0,'v') <CR>m'gv`` onoremap <silent> % v:<C-U>call <SID>Match_wrapper('',1,'o') <CR> onoremap <silent> g% v:<C-U>call <SID>Match_wrapper('',0,'o') <CR> " Analogues of [{ and ]} using matching patterns: nnoremap <silent> [% :<C-U>call <SID>MultiMatch("bW", "n") <CR> nnoremap <silent> ]% :<C-U>call <SID>MultiMatch("W", "n") <CR> vmap [% <Esc>[%m'gv`` vmap ]% <Esc>]%m'gv`` " vnoremap <silent> [% :<C-U>call <SID>MultiMatch("bW", "v") <CR>m'gv`` " vnoremap <silent> ]% :<C-U>call <SID>MultiMatch("W", "v") <CR>m'gv`` onoremap <silent> [% v:<C-U>call <SID>MultiMatch("bW", "o") <CR> onoremap <silent> ]% v:<C-U>call <SID>MultiMatch("W", "o") <CR> " text object: vmap a% <Esc>[%v]% " Auto-complete mappings: (not yet "ready for prime time") " TODO Read :help write-plugin for the "right" way to let the user " specify a key binding. " let g:match_auto = '<C-]>' " let g:match_autoCR = '<C-CR>' " if exists("g:match_auto") " execute "inoremap " . g:match_auto . ' x<Esc>"=<SID>Autocomplete()<CR>Pls' " endif " if exists("g:match_autoCR") " execute "inoremap " . g:match_autoCR . ' <CR><C-R>=<SID>Autocomplete()<CR>' " endif " if exists("g:match_gthhoh") " execute "inoremap " . g:match_gthhoh . ' <C-O>:call <SID>Gthhoh()<CR>' " endif " gthhoh = "Get the heck out of here!" let s:notslash = '\\\@<!\%(\\\\\)*' function! s:Match_wrapper(word, forward, mode) range " In s:CleanUp(), :execute "set" restore_options . let restore_options = "" if exists("b:match_ignorecase") && b:match_ignorecase != &ic let restore_options .= (&ic ? " " : " no") . "ignorecase" let &ignorecase = b:match_ignorecase endif if &ve != '' let restore_options = " ve=" . &ve . restore_options set ve= endif " If this function was called from Visual mode, make sure that the cursor " is at the correct end of the Visual range: if a:mode == "v" execute "normal! gv\<Esc>" endif " In s:CleanUp(), we may need to check whether the cursor moved forward. let startline = line(".") let startcol = col(".") " Use default behavior if called with a count. if v:count exe "normal! " . v:count . "%" return s:CleanUp(restore_options, a:mode, startline, startcol) end " First step: if not already done, set the script variables " s:do_BR flag for whether there are backrefs " s:pat parsed version of b:match_words " s:all regexp based on s:pat and the default groups " if !exists("b:match_words") || b:match_words == "" let match_words = "" " Allow b:match_words = "GetVimMatchWords()" . elseif b:match_words =~ ":" let match_words = b:match_words else execute "let match_words =" b:match_words endif " Thanks to Preben "Peppe" Guldberg and Bram Moolenaar for this suggestion! if (match_words != s:last_words) || (&mps != s:last_mps) \ || exists("b:match_debug") let s:last_mps = &mps " The next several lines were here before " BF started messing with this script. " quote the special chars in 'matchpairs', replace [,:] with \| and then " append the builtin pairs (/*, */, #if, #ifdef, #else, #elif, #endif) " let default = substitute(escape(&mps, '[$^.*~\\/?]'), '[,:]\+', " \ '\\|', 'g').'\|\/\*\|\*\/\|#if\>\|#ifdef\>\|#else\>\|#elif\>\|#endif\>' let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") . \ '\/\*:\*\/,#\s*if\%(def\)\=:#\s*else\>:#\s*elif\>:#\s*endif\>' " s:all = pattern with all the keywords let match_words = match_words . (strlen(match_words) ? "," : "") . default let s:last_words = match_words if match_words !~ s:notslash . '\\\d' let s:do_BR = 0 let s:pat = match_words else let s:do_BR = 1 let s:pat = s:ParseWords(match_words) endif let s:all = substitute(s:pat, s:notslash . '\zs[,:]\+', '\\|', 'g') let s:all = '\%(' . s:all . '\)' " let s:all = '\%(' . substitute(s:all, '\\\ze[,:]', '', 'g') . '\)' if exists("b:match_debug") let b:match_pat = s:pat endif " Reconstruct the version with unresolved backrefs. let s:patBR = substitute(match_words.',', \ s:notslash.'\zs[,:]*,[,:]*', ',', 'g') let s:patBR = substitute(s:patBR, s:notslash.'\zs:\{2,}', ':', 'g') endif " Second step: set the following local variables: " matchline = line on which the cursor started " curcol = number of characters before match " prefix = regexp for start of line to start of match " suffix = regexp for end of match to end of line " Require match to end on or after the cursor and prefer it to " start on or before the cursor. let matchline = getline(startline) if a:word != '' " word given if a:word !~ s:all echohl WarningMsg|echo 'Missing rule for word:"'.a:word.'"'|echohl NONE return s:CleanUp(restore_options, a:mode, startline, startcol) endif let matchline = a:word let curcol = 0 let prefix = '^\%(' let suffix = '\)$' " Now the case when "word" is not given else " Find the match that ends on or after the cursor and set curcol. let regexp = s:Wholematch(matchline, s:all, startcol-1) let curcol = match(matchline, regexp) " If there is no match, give up. if curcol == -1 return s:CleanUp(restore_options, a:mode, startline, startcol) endif let endcol = matchend(matchline, regexp) let suf = strlen(matchline) - endcol let prefix = (curcol ? '^.*\%' . (curcol + 1) . 'c\%(' : '^\%(') let suffix = (suf ? '\)\%' . (endcol + 1) . 'c.*$' : '\)$') endif if exists("b:match_debug") let b:match_match = matchstr(matchline, regexp) let b:match_col = curcol+1 endif " Third step: Find the group and single word that match, and the original " (backref) versions of these. Then, resolve the backrefs. " Set the following local variable: " group = colon-separated list of patterns, one of which matches " = ini:mid:fin or ini:fin " " Now, set group and groupBR to the matching group: 'if:endif' or " 'while:endwhile' or whatever. A bit of a kluge: s:Choose() returns " group . "," . groupBR, and we pick it apart. let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, s:patBR) let i = matchend(group, s:notslash . ",") let groupBR = strpart(group, i) let group = strpart(group, 0, i-1) " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix if s:do_BR " Do the hard part: resolve those backrefs! let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline) endif if exists("b:match_debug") let b:match_wholeBR = groupBR let i = matchend(groupBR, s:notslash . ":") let b:match_iniBR = strpart(groupBR, 0, i-1) endif " Fourth step: Set the arguments for searchpair(). let i = matchend(group, s:notslash . ":") let j = matchend(group, '.*' . s:notslash . ":") let ini = strpart(group, 0, i-1) let mid = substitute(strpart(group, i,j-i-1), s:notslash.'\zs:', '\\|', 'g') let fin = strpart(group, j) "Un-escape the remaining , and : characters. let ini = substitute(ini, s:notslash . '\zs\\\(:\|,\)', '\1', 'g') let mid = substitute(mid, s:notslash . '\zs\\\(:\|,\)', '\1', 'g') let fin = substitute(fin, s:notslash . '\zs\\\(:\|,\)', '\1', 'g') " searchpair() requires that these patterns avoid \(\) groups. let ini = substitute(ini, s:notslash . '\zs\\(', '\\%(', 'g') let mid = substitute(mid, s:notslash . '\zs\\(', '\\%(', 'g') let fin = substitute(fin, s:notslash . '\zs\\(', '\\%(', 'g') " Set mid. This is optimized for readability, not micro-efficiency! if a:forward && matchline =~ prefix . fin . suffix \ || !a:forward && matchline =~ prefix . ini . suffix let mid = "" endif " Set flag. This is optimized for readability, not micro-efficiency! if a:forward && matchline =~ prefix . fin . suffix \ || !a:forward && matchline !~ prefix . ini . suffix let flag = "bW" else let flag = "W" endif " Set skip. if exists("b:match_skip") let skip = b:match_skip elseif exists("b:match_comment") " backwards compatibility and testing! let skip = "r:" . b:match_comment else let skip = 's:comment\|string' endif let skip = s:ParseSkip(skip) if exists("b:match_debug") let b:match_ini = ini let b:match_tail = (strlen(mid) ? mid.'\|' : '') . fin endif " Fifth step: actually start moving the cursor and call searchpair(). " Later, :execute restore_cursor to get to the original screen. let restore_cursor = virtcol(".") . "|" normal! g0 let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor normal! H let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor execute restore_cursor call cursor(0, curcol + 1) " normal! 0 " if curcol " execute "normal!" . curcol . "l" " endif if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on")) let skip = "0" else execute "if " . skip . "| let skip = '0' | endif" endif let sp_return = searchpair(ini, mid, fin, flag, skip) let final_position = "call cursor(" . line(".") . "," . col(".") . ")" " Restore cursor position and original screen. execute restore_cursor normal! m' if sp_return > 0 execute final_position endif return s:CleanUp(restore_options, a:mode, startline, startcol, mid.'\|'.fin) endfun " Restore options and do some special handling for Operator-pending mode. " The optional argument is the tail of the matching group. fun! s:CleanUp(options, mode, startline, startcol, ...) if strlen(a:options) execute "set" a:options endif " Open folds, if appropriate. if a:mode != "o" if &foldopen =~ "percent" normal! zv endif " In Operator-pending mode, we want to include the whole match " (for example, d%). " This is only a problem if we end up moving in the forward direction. elseif (a:startline < line(".")) || \ (a:startline == line(".") && a:startcol < col(".")) if a:0 " Check whether the match is a single character. If not, move to the " end of the match. let matchline = getline(".") let currcol = col(".") let regexp = s:Wholematch(matchline, a:1, currcol-1) let endcol = matchend(matchline, regexp) if endcol > currcol " This is NOT off by one! call cursor(0, endcol) endif endif " a:0 endif " a:mode != "o" && etc. return 0 endfun " Example (simplified HTML patterns): if " a:groupBR = '<\(\k\+\)>:</\1>' " a:prefix = '^.\{3}\(' " a:group = '<\(\k\+\)>:</\(\k\+\)>' " a:suffix = '\).\{2}$' " a:matchline = "123<tag>12" or "123</tag>12" " then extract "tag" from a:matchline and return "<tag>:</tag>" . fun! s:InsertRefs(groupBR, prefix, group, suffix, matchline) if a:matchline !~ a:prefix . \ substitute(a:group, s:notslash . '\zs:', '\\|', 'g') . a:suffix return a:group endif let i = matchend(a:groupBR, s:notslash . ':') let ini = strpart(a:groupBR, 0, i-1) let tailBR = strpart(a:groupBR, i) let word = s:Choose(a:group, a:matchline, ":", "", a:prefix, a:suffix, \ a:groupBR) let i = matchend(word, s:notslash . ":") let wordBR = strpart(word, i) let word = strpart(word, 0, i-1) " Now, a:matchline =~ a:prefix . word . a:suffix if wordBR != ini let table = s:Resolve(ini, wordBR, "table") else " let table = "----------" let table = "" let d = 0 while d < 10 if tailBR =~ s:notslash . '\\' . d " let table[d] = d let table = table . d else let table = table . "-" endif let d = d + 1 endwhile endif let d = 9 while d if table[d] != "-" let backref = substitute(a:matchline, a:prefix.word.a:suffix, \ '\'.table[d], "") " Are there any other characters that should be escaped? let backref = escape(backref, '*,:') execute s:Ref(ini, d, "start", "len") let ini = strpart(ini, 0, start) . backref . strpart(ini, start+len) let tailBR = substitute(tailBR, s:notslash . '\zs\\' . d, \ escape(backref, '\\&'), 'g') endif let d = d-1 endwhile if exists("b:match_debug") if s:do_BR let b:match_table = table let b:match_word = word else let b:match_table = "" let b:match_word = "" endif endif return ini . ":" . tailBR endfun " Input a comma-separated list of groups with backrefs, such as " a:groups = '\(foo\):end\1,\(bar\):end\1' " and return a comma-separated list of groups with backrefs replaced: " return '\(foo\):end\(foo\),\(bar\):end\(bar\)' fun! s:ParseWords(groups) let groups = substitute(a:groups.",", s:notslash.'\zs[,:]*,[,:]*', ',', 'g') let groups = substitute(groups, s:notslash . '\zs:\{2,}', ':', 'g') let parsed = "" while groups =~ '[^,:]' let i = matchend(groups, s:notslash . ':') let j = matchend(groups, s:notslash . ',') let ini = strpart(groups, 0, i-1) let tail = strpart(groups, i, j-i-1) . ":" let groups = strpart(groups, j) let parsed = parsed . ini let i = matchend(tail, s:notslash . ':') while i != -1 " In 'if:else:endif', ini='if' and word='else' and then word='endif'. let word = strpart(tail, 0, i-1) let tail = strpart(tail, i) let i = matchend(tail, s:notslash . ':') let parsed = parsed . ":" . s:Resolve(ini, word, "word") endwhile " Now, tail has been used up. let parsed = parsed . "," endwhile " groups =~ '[^,:]' let parsed = substitute(parsed, ',$', '', '') return parsed endfun " TODO I think this can be simplified and/or made more efficient. " TODO What should I do if a:start is out of range? " Return a regexp that matches all of a:string, such that " matchstr(a:string, regexp) represents the match for a:pat that starts " as close to a:start as possible, before being preferred to after, and " ends after a:start . " Usage: " let regexp = s:Wholematch(getline("."), 'foo\|bar', col(".")-1) " let i = match(getline("."), regexp) " let j = matchend(getline("."), regexp) " let match = matchstr(getline("."), regexp) fun! s:Wholematch(string, pat, start) let group = '\%(' . a:pat . '\)' let prefix = (a:start ? '\(^.*\%<' . (a:start + 2) . 'c\)\zs' : '^') let len = strlen(a:string) let suffix = (a:start+1 < len ? '\(\%>'.(a:start+1).'c.*$\)\@=' : '$') if a:string !~ prefix . group . suffix let prefix = '' endif return prefix . group . suffix endfun " No extra arguments: s:Ref(string, d) will " find the d'th occurrence of '\(' and return it, along with everything up " to and including the matching '\)'. " One argument: s:Ref(string, d, "start") returns the index of the start " of the d'th '\(' and any other argument returns the length of the group. " Two arguments: s:Ref(string, d, "foo", "bar") returns a string to be " executed, having the effect of " :let foo = s:Ref(string, d, "start") " :let bar = s:Ref(string, d, "len") fun! s:Ref(string, d, ...) let len = strlen(a:string) if a:d == 0 let start = 0 else let cnt = a:d let match = a:string while cnt let cnt = cnt - 1 let index = matchend(match, s:notslash . '\\(') if index == -1 return "" endif let match = strpart(match, index) endwhile let start = len - strlen(match) if a:0 == 1 && a:1 == "start" return start - 2 endif let cnt = 1 while cnt let index = matchend(match, s:notslash . '\\(\|\\)') - 1 if index == -2 return "" endif " Increment if an open, decrement if a ')': let cnt = cnt + (match[index]=="(" ? 1 : -1) " ')' " let cnt = stridx('0(', match[index]) + cnt let match = strpart(match, index+1) endwhile let start = start - 2 let len = len - start - strlen(match) endif if a:0 == 1 return len elseif a:0 == 2 return "let " . a:1 . "=" . start . "| let " . a:2 . "=" . len else return strpart(a:string, start, len) endif endfun " Count the number of disjoint copies of pattern in string. " If the pattern is a literal string and contains no '0' or '1' characters " then s:Count(string, pattern, '0', '1') should be faster than " s:Count(string, pattern). fun! s:Count(string, pattern, ...) let pat = escape(a:pattern, '\\') if a:0 > 1 let foo = substitute(a:string, '[^'.a:pattern.']', "a:1", "g") let foo = substitute(a:string, pat, a:2, "g") let foo = substitute(foo, '[^' . a:2 . ']', "", "g") return strlen(foo) endif let result = 0 let foo = a:string let index = matchend(foo, pat) while index != -1 let result = result + 1 let foo = strpart(foo, index) let index = matchend(foo, pat) endwhile return result endfun " s:Resolve('\(a\)\(b\)', '\(c\)\2\1\1\2') should return table.word, where " word = '\(c\)\(b\)\(a\)\3\2' and table = '-32-------'. That is, the first " '\1' in target is replaced by '\(a\)' in word, table[1] = 3, and this " indicates that all other instances of '\1' in target are to be replaced " by '\3'. The hard part is dealing with nesting... " Note that ":" is an illegal character for source and target, " unless it is preceded by "\". fun! s:Resolve(source, target, output) let word = a:target let i = matchend(word, s:notslash . '\\\d') - 1 let table = "----------" while i != -2 " There are back references to be replaced. let d = word[i] let backref = s:Ref(a:source, d) " The idea is to replace '\d' with backref. Before we do this, " replace any \(\) groups in backref with :1, :2, ... if they " correspond to the first, second, ... group already inserted " into backref. Later, replace :1 with \1 and so on. The group " number w+b within backref corresponds to the group number " s within a:source. " w = number of '\(' in word before the current one let w = s:Count( \ substitute(strpart(word, 0, i-1), '\\\\', '', 'g'), '\(', '1') let b = 1 " number of the current '\(' in backref let s = d " number of the current '\(' in a:source while b <= s:Count(substitute(backref, '\\\\', '', 'g'), '\(', '1') \ && s < 10 if table[s] == "-" if w + b < 10 " let table[s] = w + b let table = strpart(table, 0, s) . (w+b) . strpart(table, s+1) endif let b = b + 1 let s = s + 1 else execute s:Ref(backref, b, "start", "len") let ref = strpart(backref, start, len) let backref = strpart(backref, 0, start) . ":". table[s] \ . strpart(backref, start+len) let s = s + s:Count(substitute(ref, '\\\\', '', 'g'), '\(', '1') endif endwhile let word = strpart(word, 0, i-1) . backref . strpart(word, i+1) let i = matchend(word, s:notslash . '\\\d') - 1 endwhile let word = substitute(word, s:notslash . '\zs:', '\\', 'g') if a:output == "table" return table elseif a:output == "word" return word else return table . word endif endfun " Assume a:comma = ",". Then the format for a:patterns and a:1 is " a:patterns = "<pat1>,<pat2>,..." " a:1 = "<alt1>,<alt2>,..." " If <patn> is the first pattern that matches a:string then return <patn> " if no optional arguments are given; return <patn>,<altn> if a:1 is given. fun! s:Choose(patterns, string, comma, branch, prefix, suffix, ...) let tail = (a:patterns =~ a:comma."$" ? a:patterns : a:patterns . a:comma) let i = matchend(tail, s:notslash . a:comma) if a:0 let alttail = (a:1 =~ a:comma."$" ? a:1 : a:1 . a:comma) let j = matchend(alttail, s:notslash . a:comma) endif let current = strpart(tail, 0, i-1) if a:branch == "" let currpat = current else let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g') endif while a:string !~ a:prefix . currpat . a:suffix let tail = strpart(tail, i) let i = matchend(tail, s:notslash . a:comma) if i == -1 return -1 endif let current = strpart(tail, 0, i-1) if a:branch == "" let currpat = current else let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g') endif if a:0 let alttail = strpart(alttail, j) let j = matchend(alttail, s:notslash . a:comma) endif endwhile if a:0 let current = current . a:comma . strpart(alttail, 0, j-1) endif return current endfun " Call this function to turn on debugging information. Every time the main " script is run, buffer variables will be saved. These can be used directly " or viewed using the menu items below. if !exists(":MatchDebug") command! -nargs=0 MatchDebug call s:Match_debug() endif fun! s:Match_debug() let b:match_debug = 1 " Save debugging information. " pat = all of b:match_words with backrefs parsed amenu &Matchit.&pat :echo b:match_pat<CR> " match = bit of text that is recognized as a match amenu &Matchit.&match :echo b:match_match<CR> " curcol = cursor column of the start of the matching text amenu &Matchit.&curcol :echo b:match_col<CR> " wholeBR = matching group, original version amenu &Matchit.wh&oleBR :echo b:match_wholeBR<CR> " iniBR = 'if' piece, original version amenu &Matchit.ini&BR :echo b:match_iniBR<CR> " ini = 'if' piece, with all backrefs resolved from match amenu &Matchit.&ini :echo b:match_ini<CR> " tail = 'else\|endif' piece, with all backrefs resolved from match amenu &Matchit.&tail :echo b:match_tail<CR> " fin = 'endif' piece, with all backrefs resolved from match amenu &Matchit.&word :echo b:match_word<CR> " '\'.d in ini refers to the same thing as '\'.table[d] in word. amenu &Matchit.t&able :echo '0:' . b:match_table . ':9'<CR> endfun " Jump to the nearest unmatched "(" or "if" or "<tag>" if a:spflag == "bW" " or the nearest unmatched "</tag>" or "endif" or ")" if a:spflag == "W". " Return a "mark" for the original position, so that " let m = MultiMatch("bW", "n") ... execute m " will return to the original position. If there is a problem, do not " move the cursor and return "", unless a count is given, in which case " go up or down as many levels as possible and again return "". " TODO This relies on the same patterns as % matching. It might be a good " idea to give it its own matching patterns. fun! s:MultiMatch(spflag, mode) if !exists("b:match_words") || b:match_words == "" return "" end let restore_options = "" if exists("b:match_ignorecase") && b:match_ignorecase != &ic let restore_options .= (&ic ? " " : " no") . "ignorecase" let &ignorecase = b:match_ignorecase endif let startline = line(".") let startcol = col(".") " First step: if not already done, set the script variables " s:do_BR flag for whether there are backrefs " s:pat parsed version of b:match_words " s:all regexp based on s:pat and the default groups " This part is copied and slightly modified from s:Match_wrapper(). let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") . \ '\/\*:\*\/,#\s*if\%(def\)\=:#\s*else\>:#\s*elif\>:#\s*endif\>' " Allow b:match_words = "GetVimMatchWords()" . if b:match_words =~ ":" let match_words = b:match_words else execute "let match_words =" b:match_words endif if (match_words != s:last_words) || (&mps != s:last_mps) || \ exists("b:match_debug") let s:last_words = match_words let s:last_mps = &mps let match_words = match_words . (strlen(match_words) ? "," : "") . default if match_words !~ s:notslash . '\\\d' let s:do_BR = 0 let s:pat = match_words else let s:do_BR = 1 let s:pat = s:ParseWords(match_words) endif let s:all = '\%(' . substitute(s:pat . (strlen(s:pat) ? "," : "") . default, \ '[,:]\+', '\\|', 'g') . '\)' if exists("b:match_debug") let b:match_pat = s:pat endif endif " Second step: figure out the patterns for searchpair() " and save the screen, cursor position, and 'ignorecase'. " - TODO: A lot of this is copied from s:Match_wrapper(). " - maybe even more functionality should be split off " - into separate functions! let cdefault = (s:pat =~ '[^,]$' ? "," : "") . default let open = substitute(s:pat . cdefault, \ s:notslash . '\zs:.\{-}' . s:notslash . ',', '\\),\\(', 'g') let open = '\(' . substitute(open, s:notslash . '\zs:.*$', '\\)', '') let close = substitute(s:pat . cdefault, \ s:notslash . '\zs,.\{-}' . s:notslash . ':', '\\),\\(', 'g') let close = substitute(close, '^.\{-}' . s:notslash . ':', '\\(', '') . '\)' if exists("b:match_skip") let skip = b:match_skip elseif exists("b:match_comment") " backwards compatibility and testing! let skip = "r:" . b:match_comment else let skip = 's:comment\|string' endif let skip = s:ParseSkip(skip) " save v:count1 variable, might be reset from the restore_cursor command let level = v:count1 let restore_cursor = virtcol(".") . "|" normal! g0 let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor normal! H let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor execute restore_cursor " Third step: call searchpair(). " Replace '\('--but not '\\('--with '\%(' and ',' with '\|'. let openpat = substitute(open, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g') let openpat = substitute(openpat, ',', '\\|', 'g') let closepat = substitute(close, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g') let closepat = substitute(closepat, ',', '\\|', 'g') if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on")) let skip = '0' else execute "if " . skip . "| let skip = '0' | endif" endif mark ' while level if searchpair(openpat, '', closepat, a:spflag, skip) < 1 call s:CleanUp(restore_options, a:mode, startline, startcol) return "" endif let level = level - 1 endwhile " Restore options and return a string to restore the original position. call s:CleanUp(restore_options, a:mode, startline, startcol) return restore_cursor endfun " Search backwards for "if" or "while" or "<tag>" or ... " and return "endif" or "endwhile" or "</tag>" or ... . " For now, this uses b:match_words and the same script variables " as s:Match_wrapper() . Later, it may get its own patterns, " either from a buffer variable or passed as arguments. " fun! s:Autocomplete() " echo "autocomplete not yet implemented :-(" " if !exists("b:match_words") || b:match_words == "" " return "" " end " let startpos = s:MultiMatch("bW") " " if startpos == "" " return "" " endif " " - TODO: figure out whether 'if' or '<tag>' matched, and construct " " - the appropriate closing. " let matchline = getline(".") " let curcol = col(".") - 1 " " - TODO: Change the s:all argument if there is a new set of match pats. " let regexp = s:Wholematch(matchline, s:all, curcol) " let suf = strlen(matchline) - matchend(matchline, regexp) " let prefix = (curcol ? '^.\{' . curcol . '}\%(' : '^\%(') " let suffix = (suf ? '\).\{' . suf . '}$' : '\)$') " " Reconstruct the version with unresolved backrefs. " let patBR = substitute(b:match_words.',', '[,:]*,[,:]*', ',', 'g') " let patBR = substitute(patBR, ':\{2,}', ':', "g") " " Now, set group and groupBR to the matching group: 'if:endif' or " " 'while:endwhile' or whatever. " let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR) " let i = matchend(group, s:notslash . ",") " let groupBR = strpart(group, i) " let group = strpart(group, 0, i-1) " " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix " if s:do_BR " let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline) " endif " " let g:group = group " " " - TODO: Construct the closing from group. " let fake = "end" . expand("<cword>") " execute startpos " return fake " endfun " Close all open structures. "Get the heck out of here!" " fun! s:Gthhoh() " let close = s:Autocomplete() " while strlen(close) " put=close " let close = s:Autocomplete() " endwhile " endfun " Parse special strings as typical skip arguments for searchpair(): " s:foo becomes (current syntax item) =~ foo " S:foo becomes (current syntax item) !~ foo " r:foo becomes (line before cursor) =~ foo " R:foo becomes (line before cursor) !~ foo fun! s:ParseSkip(str) let skip = a:str if skip[1] == ":" if skip[0] == "s" let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" . \ strpart(skip,2) . "'" elseif skip[0] == "S" let skip = "synIDattr(synID(line('.'),col('.'),1),'name') !~? '" . \ strpart(skip,2) . "'" elseif skip[0] == "r" let skip = "strpart(getline('.'),0,col('.'))=~'" . strpart(skip,2). "'" elseif skip[0] == "R" let skip = "strpart(getline('.'),0,col('.'))!~'" . strpart(skip,2). "'" endif endif return skip endfun let &cpo = s:save_cpo unlet s:save_cpo " vim:sts=2:sw=2: PK ��Z�@6 &