tomkersten-vixploder 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +105 -0
- data/PostInstall.txt +21 -0
- data/README.rdoc +131 -0
- data/Rakefile +21 -0
- data/bin/256colors2.pl +63 -0
- data/bin/colortest +365 -0
- data/bin/vixplode +10 -0
- data/lib/dotfiles/aliases +30 -0
- data/lib/dotfiles/gvimrc +20 -0
- data/lib/dotfiles/vim/.VimballRecord +2 -0
- data/lib/dotfiles/vim/after/ftplugin/actionscript_snippets.vim +9 -0
- data/lib/dotfiles/vim/after/ftplugin/aspvbs_snippets.vim +17 -0
- data/lib/dotfiles/vim/after/ftplugin/c_snippets.vim +58 -0
- data/lib/dotfiles/vim/after/ftplugin/css_snippets.vim +30 -0
- data/lib/dotfiles/vim/after/ftplugin/django_model_snippets.vim +61 -0
- data/lib/dotfiles/vim/after/ftplugin/django_template_snippets.vim +32 -0
- data/lib/dotfiles/vim/after/ftplugin/f-script_snippets.vim +14 -0
- data/lib/dotfiles/vim/after/ftplugin/haskell_snippets.vim +9 -0
- data/lib/dotfiles/vim/after/ftplugin/html_snippets.vim +57 -0
- data/lib/dotfiles/vim/after/ftplugin/java_snippets.vim +52 -0
- data/lib/dotfiles/vim/after/ftplugin/javascript_snippets.vim +10 -0
- data/lib/dotfiles/vim/after/ftplugin/latex_snippets.vim +13 -0
- data/lib/dotfiles/vim/after/ftplugin/logo_snippets.vim +9 -0
- data/lib/dotfiles/vim/after/ftplugin/markdown_snippets.vim +10 -0
- data/lib/dotfiles/vim/after/ftplugin/movable_type_snippets.vim +14 -0
- data/lib/dotfiles/vim/after/ftplugin/objc_snippets.vim +53 -0
- data/lib/dotfiles/vim/after/ftplugin/ocaml_snippets.vim +26 -0
- data/lib/dotfiles/vim/after/ftplugin/perl_snippets.vim +23 -0
- data/lib/dotfiles/vim/after/ftplugin/php_snippets.vim +30 -0
- data/lib/dotfiles/vim/after/ftplugin/phpdoc_snippets.vim +19 -0
- data/lib/dotfiles/vim/after/ftplugin/propel_snippets.vim +14 -0
- data/lib/dotfiles/vim/after/ftplugin/python_snippets.vim +202 -0
- data/lib/dotfiles/vim/after/ftplugin/rails_snippets.vim +54 -0
- data/lib/dotfiles/vim/after/ftplugin/ruby_snippets.vim +32 -0
- data/lib/dotfiles/vim/after/ftplugin/sh_snippets.vim +12 -0
- data/lib/dotfiles/vim/after/ftplugin/slate_snippets.vim +19 -0
- data/lib/dotfiles/vim/after/ftplugin/smarty_snippets.vim +35 -0
- data/lib/dotfiles/vim/after/ftplugin/symfony_snippets.vim +21 -0
- data/lib/dotfiles/vim/after/ftplugin/tcl_snippets.vim +14 -0
- data/lib/dotfiles/vim/after/ftplugin/template_toolkit_snippets.vim +13 -0
- data/lib/dotfiles/vim/after/ftplugin/tex_snippets.vim +13 -0
- data/lib/dotfiles/vim/after/ftplugin/xhtml_snippets.vim +48 -0
- data/lib/dotfiles/vim/autoload/fakeclip.vim +253 -0
- data/lib/dotfiles/vim/autoload/rails.vim +4377 -0
- data/lib/dotfiles/vim/autoload/rubycomplete.vim +802 -0
- data/lib/dotfiles/vim/colors/inkpot.vim +212 -0
- data/lib/dotfiles/vim/colors/ir_black.vim +212 -0
- data/lib/dotfiles/vim/colors/ir_black_mod.vim +213 -0
- data/lib/dotfiles/vim/colors/railscasts.vim +100 -0
- data/lib/dotfiles/vim/colors/rubyblue.vim +74 -0
- data/lib/dotfiles/vim/colors/twilight.vim +75 -0
- data/lib/dotfiles/vim/colors/twilight2.vim +74 -0
- data/lib/dotfiles/vim/colors/wombat256.vim +302 -0
- data/lib/dotfiles/vim/compiler/eruby.vim +41 -0
- data/lib/dotfiles/vim/compiler/ruby.vim +68 -0
- data/lib/dotfiles/vim/compiler/rubyunit.vim +35 -0
- data/lib/dotfiles/vim/doc/NERD_tree.txt +1235 -0
- data/lib/dotfiles/vim/doc/fakeclip.txt +190 -0
- data/lib/dotfiles/vim/doc/matchit.txt +406 -0
- data/lib/dotfiles/vim/doc/project.txt +710 -0
- data/lib/dotfiles/vim/doc/rails.txt +1123 -0
- data/lib/dotfiles/vim/doc/snippets_emu.txt +354 -0
- data/lib/dotfiles/vim/doc/surround.txt +218 -0
- data/lib/dotfiles/vim/doc/tags +433 -0
- data/lib/dotfiles/vim/filetype.vim +13 -0
- data/lib/dotfiles/vim/ftdetect/gist.vim +3 -0
- data/lib/dotfiles/vim/ftdetect/ruby.vim +14 -0
- data/lib/dotfiles/vim/ftplugin/eruby.vim +101 -0
- data/lib/dotfiles/vim/ftplugin/ruby.vim +230 -0
- data/lib/dotfiles/vim/indent/eruby.vim +73 -0
- data/lib/dotfiles/vim/indent/ruby.vim +373 -0
- data/lib/dotfiles/vim/plugin/NERD_tree.vim +3536 -0
- data/lib/dotfiles/vim/plugin/comments.vim +321 -0
- data/lib/dotfiles/vim/plugin/fakeclip.vim +174 -0
- data/lib/dotfiles/vim/plugin/fuzzyfinder.vim +1676 -0
- data/lib/dotfiles/vim/plugin/fuzzyfinder_textmate.vim +150 -0
- data/lib/dotfiles/vim/plugin/gist.vim +241 -0
- data/lib/dotfiles/vim/plugin/gitdiff.vim +141 -0
- data/lib/dotfiles/vim/plugin/matchit.vim +812 -0
- data/lib/dotfiles/vim/plugin/mru.vim +787 -0
- data/lib/dotfiles/vim/plugin/rails.vim +310 -0
- data/lib/dotfiles/vim/plugin/rspec.vim +12 -0
- data/lib/dotfiles/vim/plugin/snippets.vim +17 -0
- data/lib/dotfiles/vim/plugin/snippetsEmu.vim +973 -0
- data/lib/dotfiles/vim/plugin/supertab.vim +531 -0
- data/lib/dotfiles/vim/plugin/surround.vim +632 -0
- data/lib/dotfiles/vim/ref_vimrc +80 -0
- data/lib/dotfiles/vim/ruby/fuzzy_file_finder.rb +353 -0
- data/lib/dotfiles/vim/syntax/eruby.vim +85 -0
- data/lib/dotfiles/vim/syntax/haml.vim +113 -0
- data/lib/dotfiles/vim/syntax/mkd.vim +86 -0
- data/lib/dotfiles/vim/syntax/ruby.vim +324 -0
- data/lib/dotfiles/vim/syntax/sass.vim +93 -0
- data/lib/dotfiles/vimrc +269 -0
- data/lib/vixplode/cli.rb +73 -0
- data/lib/vixploder.rb +6 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/vixplode_cli_spec.rb +15 -0
- data/spec/vixploder_spec.rb +7 -0
- data/tasks/rspec.rake +21 -0
- metadata +202 -8
@@ -0,0 +1,812 @@
|
|
1
|
+
" matchit.vim: (global plugin) Extended "%" matching
|
2
|
+
" Last Change: Fri Jan 25 10:00 AM 2008 EST
|
3
|
+
" Maintainer: Benji Fisher PhD <benji@member.AMS.org>
|
4
|
+
" Version: 1.13.2, for Vim 6.3+
|
5
|
+
" URL: http://www.vim.org/script.php?script_id=39
|
6
|
+
|
7
|
+
" Documentation:
|
8
|
+
" The documentation is in a separate file, matchit.txt .
|
9
|
+
|
10
|
+
" Credits:
|
11
|
+
" Vim editor by Bram Moolenaar (Thanks, Bram!)
|
12
|
+
" Original script and design by Raul Segura Acevedo
|
13
|
+
" Support for comments by Douglas Potts
|
14
|
+
" Support for back references and other improvements by Benji Fisher
|
15
|
+
" Support for many languages by Johannes Zellner
|
16
|
+
" Suggestions for improvement, bug reports, and support for additional
|
17
|
+
" languages by Jordi-Albert Batalla, Neil Bird, Servatius Brandt, Mark
|
18
|
+
" Collett, Stephen Wall, Dany St-Amant, Yuheng Xie, and Johannes Zellner.
|
19
|
+
|
20
|
+
" Debugging:
|
21
|
+
" If you'd like to try the built-in debugging commands...
|
22
|
+
" :MatchDebug to activate debugging for the current buffer
|
23
|
+
" This saves the values of several key script variables as buffer-local
|
24
|
+
" variables. See the MatchDebug() function, below, for details.
|
25
|
+
|
26
|
+
" TODO: I should think about multi-line patterns for b:match_words.
|
27
|
+
" This would require an option: how many lines to scan (default 1).
|
28
|
+
" This would be useful for Python, maybe also for *ML.
|
29
|
+
" TODO: Maybe I should add a menu so that people will actually use some of
|
30
|
+
" the features that I have implemented.
|
31
|
+
" TODO: Eliminate the MultiMatch function. Add yet another argument to
|
32
|
+
" Match_wrapper() instead.
|
33
|
+
" TODO: Allow :let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1'
|
34
|
+
" TODO: Make backrefs safer by using '\V' (very no-magic).
|
35
|
+
" TODO: Add a level of indirection, so that custom % scripts can use my
|
36
|
+
" work but extend it.
|
37
|
+
|
38
|
+
" allow user to prevent loading
|
39
|
+
" and prevent duplicate loading
|
40
|
+
if exists("loaded_matchit") || &cp
|
41
|
+
finish
|
42
|
+
endif
|
43
|
+
let loaded_matchit = 1
|
44
|
+
let s:last_mps = ""
|
45
|
+
let s:last_words = ":"
|
46
|
+
|
47
|
+
let s:save_cpo = &cpo
|
48
|
+
set cpo&vim
|
49
|
+
|
50
|
+
nnoremap <silent> % :<C-U>call <SID>Match_wrapper('',1,'n') <CR>
|
51
|
+
nnoremap <silent> g% :<C-U>call <SID>Match_wrapper('',0,'n') <CR>
|
52
|
+
vnoremap <silent> % :<C-U>call <SID>Match_wrapper('',1,'v') <CR>m'gv``
|
53
|
+
vnoremap <silent> g% :<C-U>call <SID>Match_wrapper('',0,'v') <CR>m'gv``
|
54
|
+
onoremap <silent> % v:<C-U>call <SID>Match_wrapper('',1,'o') <CR>
|
55
|
+
onoremap <silent> g% v:<C-U>call <SID>Match_wrapper('',0,'o') <CR>
|
56
|
+
|
57
|
+
" Analogues of [{ and ]} using matching patterns:
|
58
|
+
nnoremap <silent> [% :<C-U>call <SID>MultiMatch("bW", "n") <CR>
|
59
|
+
nnoremap <silent> ]% :<C-U>call <SID>MultiMatch("W", "n") <CR>
|
60
|
+
vmap [% <Esc>[%m'gv``
|
61
|
+
vmap ]% <Esc>]%m'gv``
|
62
|
+
" vnoremap <silent> [% :<C-U>call <SID>MultiMatch("bW", "v") <CR>m'gv``
|
63
|
+
" vnoremap <silent> ]% :<C-U>call <SID>MultiMatch("W", "v") <CR>m'gv``
|
64
|
+
onoremap <silent> [% v:<C-U>call <SID>MultiMatch("bW", "o") <CR>
|
65
|
+
onoremap <silent> ]% v:<C-U>call <SID>MultiMatch("W", "o") <CR>
|
66
|
+
|
67
|
+
" text object:
|
68
|
+
vmap a% <Esc>[%v]%
|
69
|
+
|
70
|
+
" Auto-complete mappings: (not yet "ready for prime time")
|
71
|
+
" TODO Read :help write-plugin for the "right" way to let the user
|
72
|
+
" specify a key binding.
|
73
|
+
" let g:match_auto = '<C-]>'
|
74
|
+
" let g:match_autoCR = '<C-CR>'
|
75
|
+
" if exists("g:match_auto")
|
76
|
+
" execute "inoremap " . g:match_auto . ' x<Esc>"=<SID>Autocomplete()<CR>Pls'
|
77
|
+
" endif
|
78
|
+
" if exists("g:match_autoCR")
|
79
|
+
" execute "inoremap " . g:match_autoCR . ' <CR><C-R>=<SID>Autocomplete()<CR>'
|
80
|
+
" endif
|
81
|
+
" if exists("g:match_gthhoh")
|
82
|
+
" execute "inoremap " . g:match_gthhoh . ' <C-O>:call <SID>Gthhoh()<CR>'
|
83
|
+
" endif " gthhoh = "Get the heck out of here!"
|
84
|
+
|
85
|
+
let s:notslash = '\\\@<!\%(\\\\\)*'
|
86
|
+
|
87
|
+
function! s:Match_wrapper(word, forward, mode) range
|
88
|
+
" In s:CleanUp(), :execute "set" restore_options .
|
89
|
+
let restore_options = (&ic ? " " : " no") . "ignorecase"
|
90
|
+
if exists("b:match_ignorecase")
|
91
|
+
let &ignorecase = b:match_ignorecase
|
92
|
+
endif
|
93
|
+
let restore_options = " ve=" . &ve . restore_options
|
94
|
+
set ve=
|
95
|
+
" If this function was called from Visual mode, make sure that the cursor
|
96
|
+
" is at the correct end of the Visual range:
|
97
|
+
if a:mode == "v"
|
98
|
+
execute "normal! gv\<Esc>"
|
99
|
+
endif
|
100
|
+
" In s:CleanUp(), we may need to check whether the cursor moved forward.
|
101
|
+
let startline = line(".")
|
102
|
+
let startcol = col(".")
|
103
|
+
" Use default behavior if called with a count.
|
104
|
+
if v:count
|
105
|
+
exe "normal! " . v:count . "%"
|
106
|
+
return s:CleanUp(restore_options, a:mode, startline, startcol)
|
107
|
+
end
|
108
|
+
|
109
|
+
" First step: if not already done, set the script variables
|
110
|
+
" s:do_BR flag for whether there are backrefs
|
111
|
+
" s:pat parsed version of b:match_words
|
112
|
+
" s:all regexp based on s:pat and the default groups
|
113
|
+
"
|
114
|
+
if !exists("b:match_words") || b:match_words == ""
|
115
|
+
let match_words = ""
|
116
|
+
" Allow b:match_words = "GetVimMatchWords()" .
|
117
|
+
elseif b:match_words =~ ":"
|
118
|
+
let match_words = b:match_words
|
119
|
+
else
|
120
|
+
execute "let match_words =" b:match_words
|
121
|
+
endif
|
122
|
+
" Thanks to Preben "Peppe" Guldberg and Bram Moolenaar for this suggestion!
|
123
|
+
if (match_words != s:last_words) || (&mps != s:last_mps) ||
|
124
|
+
\ exists("b:match_debug")
|
125
|
+
let s:last_words = match_words
|
126
|
+
let s:last_mps = &mps
|
127
|
+
" The next several lines were here before
|
128
|
+
" BF started messing with this script.
|
129
|
+
" quote the special chars in 'matchpairs', replace [,:] with \| and then
|
130
|
+
" append the builtin pairs (/*, */, #if, #ifdef, #else, #elif, #endif)
|
131
|
+
" let default = substitute(escape(&mps, '[$^.*~\\/?]'), '[,:]\+',
|
132
|
+
" \ '\\|', 'g').'\|\/\*\|\*\/\|#if\>\|#ifdef\>\|#else\>\|#elif\>\|#endif\>'
|
133
|
+
let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") .
|
134
|
+
\ '\/\*:\*\/,#if\%(def\)\=:#else\>:#elif\>:#endif\>'
|
135
|
+
" s:all = pattern with all the keywords
|
136
|
+
let match_words = match_words . (strlen(match_words) ? "," : "") . default
|
137
|
+
if match_words !~ s:notslash . '\\\d'
|
138
|
+
let s:do_BR = 0
|
139
|
+
let s:pat = match_words
|
140
|
+
else
|
141
|
+
let s:do_BR = 1
|
142
|
+
let s:pat = s:ParseWords(match_words)
|
143
|
+
endif
|
144
|
+
let s:all = substitute(s:pat, s:notslash . '\zs[,:]\+', '\\|', 'g')
|
145
|
+
let s:all = '\%(' . s:all . '\)'
|
146
|
+
" let s:all = '\%(' . substitute(s:all, '\\\ze[,:]', '', 'g') . '\)'
|
147
|
+
if exists("b:match_debug")
|
148
|
+
let b:match_pat = s:pat
|
149
|
+
endif
|
150
|
+
endif
|
151
|
+
|
152
|
+
" Second step: set the following local variables:
|
153
|
+
" matchline = line on which the cursor started
|
154
|
+
" curcol = number of characters before match
|
155
|
+
" prefix = regexp for start of line to start of match
|
156
|
+
" suffix = regexp for end of match to end of line
|
157
|
+
" Require match to end on or after the cursor and prefer it to
|
158
|
+
" start on or before the cursor.
|
159
|
+
let matchline = getline(startline)
|
160
|
+
if a:word != ''
|
161
|
+
" word given
|
162
|
+
if a:word !~ s:all
|
163
|
+
echohl WarningMsg|echo 'Missing rule for word:"'.a:word.'"'|echohl NONE
|
164
|
+
return s:CleanUp(restore_options, a:mode, startline, startcol)
|
165
|
+
endif
|
166
|
+
let matchline = a:word
|
167
|
+
let curcol = 0
|
168
|
+
let prefix = '^\%('
|
169
|
+
let suffix = '\)$'
|
170
|
+
" Now the case when "word" is not given
|
171
|
+
else " Find the match that ends on or after the cursor and set curcol.
|
172
|
+
let regexp = s:Wholematch(matchline, s:all, startcol-1)
|
173
|
+
let curcol = match(matchline, regexp)
|
174
|
+
" If there is no match, give up.
|
175
|
+
if curcol == -1
|
176
|
+
return s:CleanUp(restore_options, a:mode, startline, startcol)
|
177
|
+
endif
|
178
|
+
let endcol = matchend(matchline, regexp)
|
179
|
+
let suf = strlen(matchline) - endcol
|
180
|
+
let prefix = (curcol ? '^.*\%' . (curcol + 1) . 'c\%(' : '^\%(')
|
181
|
+
let suffix = (suf ? '\)\%' . (endcol + 1) . 'c.*$' : '\)$')
|
182
|
+
endif
|
183
|
+
if exists("b:match_debug")
|
184
|
+
let b:match_match = matchstr(matchline, regexp)
|
185
|
+
let b:match_col = curcol+1
|
186
|
+
endif
|
187
|
+
|
188
|
+
" Third step: Find the group and single word that match, and the original
|
189
|
+
" (backref) versions of these. Then, resolve the backrefs.
|
190
|
+
" Set the following local variable:
|
191
|
+
" group = colon-separated list of patterns, one of which matches
|
192
|
+
" = ini:mid:fin or ini:fin
|
193
|
+
"
|
194
|
+
" Reconstruct the version with unresolved backrefs.
|
195
|
+
let patBR = substitute(match_words.',',
|
196
|
+
\ s:notslash.'\zs[,:]*,[,:]*', ',', 'g')
|
197
|
+
let patBR = substitute(patBR, s:notslash.'\zs:\{2,}', ':', 'g')
|
198
|
+
" Now, set group and groupBR to the matching group: 'if:endif' or
|
199
|
+
" 'while:endwhile' or whatever. A bit of a kluge: s:Choose() returns
|
200
|
+
" group . "," . groupBR, and we pick it apart.
|
201
|
+
let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR)
|
202
|
+
let i = matchend(group, s:notslash . ",")
|
203
|
+
let groupBR = strpart(group, i)
|
204
|
+
let group = strpart(group, 0, i-1)
|
205
|
+
" Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix
|
206
|
+
if s:do_BR " Do the hard part: resolve those backrefs!
|
207
|
+
let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline)
|
208
|
+
endif
|
209
|
+
if exists("b:match_debug")
|
210
|
+
let b:match_wholeBR = groupBR
|
211
|
+
let i = matchend(groupBR, s:notslash . ":")
|
212
|
+
let b:match_iniBR = strpart(groupBR, 0, i-1)
|
213
|
+
endif
|
214
|
+
|
215
|
+
" Fourth step: Set the arguments for searchpair().
|
216
|
+
let i = matchend(group, s:notslash . ":")
|
217
|
+
let j = matchend(group, '.*' . s:notslash . ":")
|
218
|
+
let ini = strpart(group, 0, i-1)
|
219
|
+
let mid = substitute(strpart(group, i,j-i-1), s:notslash.'\zs:', '\\|', 'g')
|
220
|
+
let fin = strpart(group, j)
|
221
|
+
"Un-escape the remaining , and : characters.
|
222
|
+
let ini = substitute(ini, s:notslash . '\zs\\\(:\|,\)', '\1', 'g')
|
223
|
+
let mid = substitute(mid, s:notslash . '\zs\\\(:\|,\)', '\1', 'g')
|
224
|
+
let fin = substitute(fin, s:notslash . '\zs\\\(:\|,\)', '\1', 'g')
|
225
|
+
" searchpair() requires that these patterns avoid \(\) groups.
|
226
|
+
let ini = substitute(ini, s:notslash . '\zs\\(', '\\%(', 'g')
|
227
|
+
let mid = substitute(mid, s:notslash . '\zs\\(', '\\%(', 'g')
|
228
|
+
let fin = substitute(fin, s:notslash . '\zs\\(', '\\%(', 'g')
|
229
|
+
" Set mid. This is optimized for readability, not micro-efficiency!
|
230
|
+
if a:forward && matchline =~ prefix . fin . suffix
|
231
|
+
\ || !a:forward && matchline =~ prefix . ini . suffix
|
232
|
+
let mid = ""
|
233
|
+
endif
|
234
|
+
" Set flag. This is optimized for readability, not micro-efficiency!
|
235
|
+
if a:forward && matchline =~ prefix . fin . suffix
|
236
|
+
\ || !a:forward && matchline !~ prefix . ini . suffix
|
237
|
+
let flag = "bW"
|
238
|
+
else
|
239
|
+
let flag = "W"
|
240
|
+
endif
|
241
|
+
" Set skip.
|
242
|
+
if exists("b:match_skip")
|
243
|
+
let skip = b:match_skip
|
244
|
+
elseif exists("b:match_comment") " backwards compatibility and testing!
|
245
|
+
let skip = "r:" . b:match_comment
|
246
|
+
else
|
247
|
+
let skip = 's:comment\|string'
|
248
|
+
endif
|
249
|
+
let skip = s:ParseSkip(skip)
|
250
|
+
if exists("b:match_debug")
|
251
|
+
let b:match_ini = ini
|
252
|
+
let b:match_tail = (strlen(mid) ? mid.'\|' : '') . fin
|
253
|
+
endif
|
254
|
+
|
255
|
+
" Fifth step: actually start moving the cursor and call searchpair().
|
256
|
+
" Later, :execute restore_cursor to get to the original screen.
|
257
|
+
let restore_cursor = virtcol(".") . "|"
|
258
|
+
normal! g0
|
259
|
+
let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor
|
260
|
+
normal! H
|
261
|
+
let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
|
262
|
+
execute restore_cursor
|
263
|
+
call cursor(0, curcol + 1)
|
264
|
+
" normal! 0
|
265
|
+
" if curcol
|
266
|
+
" execute "normal!" . curcol . "l"
|
267
|
+
" endif
|
268
|
+
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
|
269
|
+
let skip = "0"
|
270
|
+
else
|
271
|
+
execute "if " . skip . "| let skip = '0' | endif"
|
272
|
+
endif
|
273
|
+
let sp_return = searchpair(ini, mid, fin, flag, skip)
|
274
|
+
let final_position = "call cursor(" . line(".") . "," . col(".") . ")"
|
275
|
+
" Restore cursor position and original screen.
|
276
|
+
execute restore_cursor
|
277
|
+
normal! m'
|
278
|
+
if sp_return > 0
|
279
|
+
execute final_position
|
280
|
+
endif
|
281
|
+
return s:CleanUp(restore_options, a:mode, startline, startcol, mid.'\|'.fin)
|
282
|
+
endfun
|
283
|
+
|
284
|
+
" Restore options and do some special handling for Operator-pending mode.
|
285
|
+
" The optional argument is the tail of the matching group.
|
286
|
+
fun! s:CleanUp(options, mode, startline, startcol, ...)
|
287
|
+
execute "set" a:options
|
288
|
+
" Open folds, if appropriate.
|
289
|
+
if a:mode != "o"
|
290
|
+
if &foldopen =~ "percent"
|
291
|
+
normal! zv
|
292
|
+
endif
|
293
|
+
" In Operator-pending mode, we want to include the whole match
|
294
|
+
" (for example, d%).
|
295
|
+
" This is only a problem if we end up moving in the forward direction.
|
296
|
+
elseif (a:startline < line(".")) ||
|
297
|
+
\ (a:startline == line(".") && a:startcol < col("."))
|
298
|
+
if a:0
|
299
|
+
" Check whether the match is a single character. If not, move to the
|
300
|
+
" end of the match.
|
301
|
+
let matchline = getline(".")
|
302
|
+
let currcol = col(".")
|
303
|
+
let regexp = s:Wholematch(matchline, a:1, currcol-1)
|
304
|
+
let endcol = matchend(matchline, regexp)
|
305
|
+
if endcol > currcol " This is NOT off by one!
|
306
|
+
execute "normal!" . (endcol - currcol) . "l"
|
307
|
+
endif
|
308
|
+
endif " a:0
|
309
|
+
endif " a:mode != "o" && etc.
|
310
|
+
return 0
|
311
|
+
endfun
|
312
|
+
|
313
|
+
" Example (simplified HTML patterns): if
|
314
|
+
" a:groupBR = '<\(\k\+\)>:</\1>'
|
315
|
+
" a:prefix = '^.\{3}\('
|
316
|
+
" a:group = '<\(\k\+\)>:</\(\k\+\)>'
|
317
|
+
" a:suffix = '\).\{2}$'
|
318
|
+
" a:matchline = "123<tag>12" or "123</tag>12"
|
319
|
+
" then extract "tag" from a:matchline and return "<tag>:</tag>" .
|
320
|
+
fun! s:InsertRefs(groupBR, prefix, group, suffix, matchline)
|
321
|
+
if a:matchline !~ a:prefix .
|
322
|
+
\ substitute(a:group, s:notslash . '\zs:', '\\|', 'g') . a:suffix
|
323
|
+
return a:group
|
324
|
+
endif
|
325
|
+
let i = matchend(a:groupBR, s:notslash . ':')
|
326
|
+
let ini = strpart(a:groupBR, 0, i-1)
|
327
|
+
let tailBR = strpart(a:groupBR, i)
|
328
|
+
let word = s:Choose(a:group, a:matchline, ":", "", a:prefix, a:suffix,
|
329
|
+
\ a:groupBR)
|
330
|
+
let i = matchend(word, s:notslash . ":")
|
331
|
+
let wordBR = strpart(word, i)
|
332
|
+
let word = strpart(word, 0, i-1)
|
333
|
+
" Now, a:matchline =~ a:prefix . word . a:suffix
|
334
|
+
if wordBR != ini
|
335
|
+
let table = s:Resolve(ini, wordBR, "table")
|
336
|
+
else
|
337
|
+
" let table = "----------"
|
338
|
+
let table = ""
|
339
|
+
let d = 0
|
340
|
+
while d < 10
|
341
|
+
if tailBR =~ s:notslash . '\\' . d
|
342
|
+
" let table[d] = d
|
343
|
+
let table = table . d
|
344
|
+
else
|
345
|
+
let table = table . "-"
|
346
|
+
endif
|
347
|
+
let d = d + 1
|
348
|
+
endwhile
|
349
|
+
endif
|
350
|
+
let d = 9
|
351
|
+
while d
|
352
|
+
if table[d] != "-"
|
353
|
+
let backref = substitute(a:matchline, a:prefix.word.a:suffix,
|
354
|
+
\ '\'.table[d], "")
|
355
|
+
" Are there any other characters that should be escaped?
|
356
|
+
let backref = escape(backref, '*,:')
|
357
|
+
execute s:Ref(ini, d, "start", "len")
|
358
|
+
let ini = strpart(ini, 0, start) . backref . strpart(ini, start+len)
|
359
|
+
let tailBR = substitute(tailBR, s:notslash . '\zs\\' . d,
|
360
|
+
\ escape(backref, '\\'), 'g')
|
361
|
+
endif
|
362
|
+
let d = d-1
|
363
|
+
endwhile
|
364
|
+
if exists("b:match_debug")
|
365
|
+
if s:do_BR
|
366
|
+
let b:match_table = table
|
367
|
+
let b:match_word = word
|
368
|
+
else
|
369
|
+
let b:match_table = ""
|
370
|
+
let b:match_word = ""
|
371
|
+
endif
|
372
|
+
endif
|
373
|
+
return ini . ":" . tailBR
|
374
|
+
endfun
|
375
|
+
|
376
|
+
" Input a comma-separated list of groups with backrefs, such as
|
377
|
+
" a:groups = '\(foo\):end\1,\(bar\):end\1'
|
378
|
+
" and return a comma-separated list of groups with backrefs replaced:
|
379
|
+
" return '\(foo\):end\(foo\),\(bar\):end\(bar\)'
|
380
|
+
fun! s:ParseWords(groups)
|
381
|
+
let groups = substitute(a:groups.",", s:notslash.'\zs[,:]*,[,:]*', ',', 'g')
|
382
|
+
let groups = substitute(groups, s:notslash . '\zs:\{2,}', ':', 'g')
|
383
|
+
let parsed = ""
|
384
|
+
while groups =~ '[^,:]'
|
385
|
+
let i = matchend(groups, s:notslash . ':')
|
386
|
+
let j = matchend(groups, s:notslash . ',')
|
387
|
+
let ini = strpart(groups, 0, i-1)
|
388
|
+
let tail = strpart(groups, i, j-i-1) . ":"
|
389
|
+
let groups = strpart(groups, j)
|
390
|
+
let parsed = parsed . ini
|
391
|
+
let i = matchend(tail, s:notslash . ':')
|
392
|
+
while i != -1
|
393
|
+
" In 'if:else:endif', ini='if' and word='else' and then word='endif'.
|
394
|
+
let word = strpart(tail, 0, i-1)
|
395
|
+
let tail = strpart(tail, i)
|
396
|
+
let i = matchend(tail, s:notslash . ':')
|
397
|
+
let parsed = parsed . ":" . s:Resolve(ini, word, "word")
|
398
|
+
endwhile " Now, tail has been used up.
|
399
|
+
let parsed = parsed . ","
|
400
|
+
endwhile " groups =~ '[^,:]'
|
401
|
+
let parsed = substitute(parsed, ',$', '', '')
|
402
|
+
return parsed
|
403
|
+
endfun
|
404
|
+
|
405
|
+
" TODO I think this can be simplified and/or made more efficient.
|
406
|
+
" TODO What should I do if a:start is out of range?
|
407
|
+
" Return a regexp that matches all of a:string, such that
|
408
|
+
" matchstr(a:string, regexp) represents the match for a:pat that starts
|
409
|
+
" as close to a:start as possible, before being preferred to after, and
|
410
|
+
" ends after a:start .
|
411
|
+
" Usage:
|
412
|
+
" let regexp = s:Wholematch(getline("."), 'foo\|bar', col(".")-1)
|
413
|
+
" let i = match(getline("."), regexp)
|
414
|
+
" let j = matchend(getline("."), regexp)
|
415
|
+
" let match = matchstr(getline("."), regexp)
|
416
|
+
fun! s:Wholematch(string, pat, start)
|
417
|
+
let group = '\%(' . a:pat . '\)'
|
418
|
+
let prefix = (a:start ? '\(^.*\%<' . (a:start + 2) . 'c\)\zs' : '^')
|
419
|
+
let len = strlen(a:string)
|
420
|
+
let suffix = (a:start+1 < len ? '\(\%>'.(a:start+1).'c.*$\)\@=' : '$')
|
421
|
+
if a:string !~ prefix . group . suffix
|
422
|
+
let prefix = ''
|
423
|
+
endif
|
424
|
+
return prefix . group . suffix
|
425
|
+
endfun
|
426
|
+
|
427
|
+
" No extra arguments: s:Ref(string, d) will
|
428
|
+
" find the d'th occurrence of '\(' and return it, along with everything up
|
429
|
+
" to and including the matching '\)'.
|
430
|
+
" One argument: s:Ref(string, d, "start") returns the index of the start
|
431
|
+
" of the d'th '\(' and any other argument returns the length of the group.
|
432
|
+
" Two arguments: s:Ref(string, d, "foo", "bar") returns a string to be
|
433
|
+
" executed, having the effect of
|
434
|
+
" :let foo = s:Ref(string, d, "start")
|
435
|
+
" :let bar = s:Ref(string, d, "len")
|
436
|
+
fun! s:Ref(string, d, ...)
|
437
|
+
let len = strlen(a:string)
|
438
|
+
if a:d == 0
|
439
|
+
let start = 0
|
440
|
+
else
|
441
|
+
let cnt = a:d
|
442
|
+
let match = a:string
|
443
|
+
while cnt
|
444
|
+
let cnt = cnt - 1
|
445
|
+
let index = matchend(match, s:notslash . '\\(')
|
446
|
+
if index == -1
|
447
|
+
return ""
|
448
|
+
endif
|
449
|
+
let match = strpart(match, index)
|
450
|
+
endwhile
|
451
|
+
let start = len - strlen(match)
|
452
|
+
if a:0 == 1 && a:1 == "start"
|
453
|
+
return start - 2
|
454
|
+
endif
|
455
|
+
let cnt = 1
|
456
|
+
while cnt
|
457
|
+
let index = matchend(match, s:notslash . '\\(\|\\)') - 1
|
458
|
+
if index == -2
|
459
|
+
return ""
|
460
|
+
endif
|
461
|
+
" Increment if an open, decrement if a ')':
|
462
|
+
let cnt = cnt + (match[index]=="(" ? 1 : -1) " ')'
|
463
|
+
" let cnt = stridx('0(', match[index]) + cnt
|
464
|
+
let match = strpart(match, index+1)
|
465
|
+
endwhile
|
466
|
+
let start = start - 2
|
467
|
+
let len = len - start - strlen(match)
|
468
|
+
endif
|
469
|
+
if a:0 == 1
|
470
|
+
return len
|
471
|
+
elseif a:0 == 2
|
472
|
+
return "let " . a:1 . "=" . start . "| let " . a:2 . "=" . len
|
473
|
+
else
|
474
|
+
return strpart(a:string, start, len)
|
475
|
+
endif
|
476
|
+
endfun
|
477
|
+
|
478
|
+
" Count the number of disjoint copies of pattern in string.
|
479
|
+
" If the pattern is a literal string and contains no '0' or '1' characters
|
480
|
+
" then s:Count(string, pattern, '0', '1') should be faster than
|
481
|
+
" s:Count(string, pattern).
|
482
|
+
fun! s:Count(string, pattern, ...)
|
483
|
+
let pat = escape(a:pattern, '\\')
|
484
|
+
if a:0 > 1
|
485
|
+
let foo = substitute(a:string, '[^'.a:pattern.']', "a:1", "g")
|
486
|
+
let foo = substitute(a:string, pat, a:2, "g")
|
487
|
+
let foo = substitute(foo, '[^' . a:2 . ']', "", "g")
|
488
|
+
return strlen(foo)
|
489
|
+
endif
|
490
|
+
let result = 0
|
491
|
+
let foo = a:string
|
492
|
+
let index = matchend(foo, pat)
|
493
|
+
while index != -1
|
494
|
+
let result = result + 1
|
495
|
+
let foo = strpart(foo, index)
|
496
|
+
let index = matchend(foo, pat)
|
497
|
+
endwhile
|
498
|
+
return result
|
499
|
+
endfun
|
500
|
+
|
501
|
+
" s:Resolve('\(a\)\(b\)', '\(c\)\2\1\1\2') should return table.word, where
|
502
|
+
" word = '\(c\)\(b\)\(a\)\3\2' and table = '-32-------'. That is, the first
|
503
|
+
" '\1' in target is replaced by '\(a\)' in word, table[1] = 3, and this
|
504
|
+
" indicates that all other instances of '\1' in target are to be replaced
|
505
|
+
" by '\3'. The hard part is dealing with nesting...
|
506
|
+
" Note that ":" is an illegal character for source and target,
|
507
|
+
" unless it is preceded by "\".
|
508
|
+
fun! s:Resolve(source, target, output)
|
509
|
+
let word = a:target
|
510
|
+
let i = matchend(word, s:notslash . '\\\d') - 1
|
511
|
+
let table = "----------"
|
512
|
+
while i != -2 " There are back references to be replaced.
|
513
|
+
let d = word[i]
|
514
|
+
let backref = s:Ref(a:source, d)
|
515
|
+
" The idea is to replace '\d' with backref. Before we do this,
|
516
|
+
" replace any \(\) groups in backref with :1, :2, ... if they
|
517
|
+
" correspond to the first, second, ... group already inserted
|
518
|
+
" into backref. Later, replace :1 with \1 and so on. The group
|
519
|
+
" number w+b within backref corresponds to the group number
|
520
|
+
" s within a:source.
|
521
|
+
" w = number of '\(' in word before the current one
|
522
|
+
let w = s:Count(
|
523
|
+
\ substitute(strpart(word, 0, i-1), '\\\\', '', 'g'), '\(', '1')
|
524
|
+
let b = 1 " number of the current '\(' in backref
|
525
|
+
let s = d " number of the current '\(' in a:source
|
526
|
+
while b <= s:Count(substitute(backref, '\\\\', '', 'g'), '\(', '1')
|
527
|
+
\ && s < 10
|
528
|
+
if table[s] == "-"
|
529
|
+
if w + b < 10
|
530
|
+
" let table[s] = w + b
|
531
|
+
let table = strpart(table, 0, s) . (w+b) . strpart(table, s+1)
|
532
|
+
endif
|
533
|
+
let b = b + 1
|
534
|
+
let s = s + 1
|
535
|
+
else
|
536
|
+
execute s:Ref(backref, b, "start", "len")
|
537
|
+
let ref = strpart(backref, start, len)
|
538
|
+
let backref = strpart(backref, 0, start) . ":". table[s]
|
539
|
+
\ . strpart(backref, start+len)
|
540
|
+
let s = s + s:Count(substitute(ref, '\\\\', '', 'g'), '\(', '1')
|
541
|
+
endif
|
542
|
+
endwhile
|
543
|
+
let word = strpart(word, 0, i-1) . backref . strpart(word, i+1)
|
544
|
+
let i = matchend(word, s:notslash . '\\\d') - 1
|
545
|
+
endwhile
|
546
|
+
let word = substitute(word, s:notslash . '\zs:', '\\', 'g')
|
547
|
+
if a:output == "table"
|
548
|
+
return table
|
549
|
+
elseif a:output == "word"
|
550
|
+
return word
|
551
|
+
else
|
552
|
+
return table . word
|
553
|
+
endif
|
554
|
+
endfun
|
555
|
+
|
556
|
+
" Assume a:comma = ",". Then the format for a:patterns and a:1 is
|
557
|
+
" a:patterns = "<pat1>,<pat2>,..."
|
558
|
+
" a:1 = "<alt1>,<alt2>,..."
|
559
|
+
" If <patn> is the first pattern that matches a:string then return <patn>
|
560
|
+
" if no optional arguments are given; return <patn>,<altn> if a:1 is given.
|
561
|
+
fun! s:Choose(patterns, string, comma, branch, prefix, suffix, ...)
|
562
|
+
let tail = (a:patterns =~ a:comma."$" ? a:patterns : a:patterns . a:comma)
|
563
|
+
let i = matchend(tail, s:notslash . a:comma)
|
564
|
+
if a:0
|
565
|
+
let alttail = (a:1 =~ a:comma."$" ? a:1 : a:1 . a:comma)
|
566
|
+
let j = matchend(alttail, s:notslash . a:comma)
|
567
|
+
endif
|
568
|
+
let current = strpart(tail, 0, i-1)
|
569
|
+
if a:branch == ""
|
570
|
+
let currpat = current
|
571
|
+
else
|
572
|
+
let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g')
|
573
|
+
endif
|
574
|
+
while a:string !~ a:prefix . currpat . a:suffix
|
575
|
+
let tail = strpart(tail, i)
|
576
|
+
let i = matchend(tail, s:notslash . a:comma)
|
577
|
+
if i == -1
|
578
|
+
return -1
|
579
|
+
endif
|
580
|
+
let current = strpart(tail, 0, i-1)
|
581
|
+
if a:branch == ""
|
582
|
+
let currpat = current
|
583
|
+
else
|
584
|
+
let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g')
|
585
|
+
endif
|
586
|
+
if a:0
|
587
|
+
let alttail = strpart(alttail, j)
|
588
|
+
let j = matchend(alttail, s:notslash . a:comma)
|
589
|
+
endif
|
590
|
+
endwhile
|
591
|
+
if a:0
|
592
|
+
let current = current . a:comma . strpart(alttail, 0, j-1)
|
593
|
+
endif
|
594
|
+
return current
|
595
|
+
endfun
|
596
|
+
|
597
|
+
" Call this function to turn on debugging information. Every time the main
|
598
|
+
" script is run, buffer variables will be saved. These can be used directly
|
599
|
+
" or viewed using the menu items below.
|
600
|
+
if !exists(":MatchDebug")
|
601
|
+
command! -nargs=0 MatchDebug call s:Match_debug()
|
602
|
+
endif
|
603
|
+
|
604
|
+
fun! s:Match_debug()
|
605
|
+
let b:match_debug = 1 " Save debugging information.
|
606
|
+
" pat = all of b:match_words with backrefs parsed
|
607
|
+
amenu &Matchit.&pat :echo b:match_pat<CR>
|
608
|
+
" match = bit of text that is recognized as a match
|
609
|
+
amenu &Matchit.&match :echo b:match_match<CR>
|
610
|
+
" curcol = cursor column of the start of the matching text
|
611
|
+
amenu &Matchit.&curcol :echo b:match_col<CR>
|
612
|
+
" wholeBR = matching group, original version
|
613
|
+
amenu &Matchit.wh&oleBR :echo b:match_wholeBR<CR>
|
614
|
+
" iniBR = 'if' piece, original version
|
615
|
+
amenu &Matchit.ini&BR :echo b:match_iniBR<CR>
|
616
|
+
" ini = 'if' piece, with all backrefs resolved from match
|
617
|
+
amenu &Matchit.&ini :echo b:match_ini<CR>
|
618
|
+
" tail = 'else\|endif' piece, with all backrefs resolved from match
|
619
|
+
amenu &Matchit.&tail :echo b:match_tail<CR>
|
620
|
+
" fin = 'endif' piece, with all backrefs resolved from match
|
621
|
+
amenu &Matchit.&word :echo b:match_word<CR>
|
622
|
+
" '\'.d in ini refers to the same thing as '\'.table[d] in word.
|
623
|
+
amenu &Matchit.t&able :echo '0:' . b:match_table . ':9'<CR>
|
624
|
+
endfun
|
625
|
+
|
626
|
+
" Jump to the nearest unmatched "(" or "if" or "<tag>" if a:spflag == "bW"
|
627
|
+
" or the nearest unmatched "</tag>" or "endif" or ")" if a:spflag == "W".
|
628
|
+
" Return a "mark" for the original position, so that
|
629
|
+
" let m = MultiMatch("bW", "n") ... execute m
|
630
|
+
" will return to the original position. If there is a problem, do not
|
631
|
+
" move the cursor and return "", unless a count is given, in which case
|
632
|
+
" go up or down as many levels as possible and again return "".
|
633
|
+
" TODO This relies on the same patterns as % matching. It might be a good
|
634
|
+
" idea to give it its own matching patterns.
|
635
|
+
fun! s:MultiMatch(spflag, mode)
|
636
|
+
if !exists("b:match_words") || b:match_words == ""
|
637
|
+
return ""
|
638
|
+
end
|
639
|
+
let restore_options = (&ic ? "" : "no") . "ignorecase"
|
640
|
+
if exists("b:match_ignorecase")
|
641
|
+
let &ignorecase = b:match_ignorecase
|
642
|
+
endif
|
643
|
+
let startline = line(".")
|
644
|
+
let startcol = col(".")
|
645
|
+
|
646
|
+
" First step: if not already done, set the script variables
|
647
|
+
" s:do_BR flag for whether there are backrefs
|
648
|
+
" s:pat parsed version of b:match_words
|
649
|
+
" s:all regexp based on s:pat and the default groups
|
650
|
+
" This part is copied and slightly modified from s:Match_wrapper().
|
651
|
+
let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") .
|
652
|
+
\ '\/\*:\*\/,#if\%(def\)\=:#else\>:#elif\>:#endif\>'
|
653
|
+
" Allow b:match_words = "GetVimMatchWords()" .
|
654
|
+
if b:match_words =~ ":"
|
655
|
+
let match_words = b:match_words
|
656
|
+
else
|
657
|
+
execute "let match_words =" b:match_words
|
658
|
+
endif
|
659
|
+
if (match_words != s:last_words) || (&mps != s:last_mps) ||
|
660
|
+
\ exists("b:match_debug")
|
661
|
+
let s:last_words = match_words
|
662
|
+
let s:last_mps = &mps
|
663
|
+
if match_words !~ s:notslash . '\\\d'
|
664
|
+
let s:do_BR = 0
|
665
|
+
let s:pat = match_words
|
666
|
+
else
|
667
|
+
let s:do_BR = 1
|
668
|
+
let s:pat = s:ParseWords(match_words)
|
669
|
+
endif
|
670
|
+
let s:all = '\%(' . substitute(s:pat . (strlen(s:pat)?",":"") . default,
|
671
|
+
\ '[,:]\+','\\|','g') . '\)'
|
672
|
+
if exists("b:match_debug")
|
673
|
+
let b:match_pat = s:pat
|
674
|
+
endif
|
675
|
+
endif
|
676
|
+
|
677
|
+
" Second step: figure out the patterns for searchpair()
|
678
|
+
" and save the screen, cursor position, and 'ignorecase'.
|
679
|
+
" - TODO: A lot of this is copied from s:Match_wrapper().
|
680
|
+
" - maybe even more functionality should be split off
|
681
|
+
" - into separate functions!
|
682
|
+
let cdefault = (s:pat =~ '[^,]$' ? "," : "") . default
|
683
|
+
let open = substitute(s:pat . cdefault,
|
684
|
+
\ s:notslash . '\zs:.\{-}' . s:notslash . ',', '\\),\\(', 'g')
|
685
|
+
let open = '\(' . substitute(open, s:notslash . '\zs:.*$', '\\)', '')
|
686
|
+
let close = substitute(s:pat . cdefault,
|
687
|
+
\ s:notslash . '\zs,.\{-}' . s:notslash . ':', '\\),\\(', 'g')
|
688
|
+
let close = substitute(close, '^.\{-}' . s:notslash . ':', '\\(', '') . '\)'
|
689
|
+
if exists("b:match_skip")
|
690
|
+
let skip = b:match_skip
|
691
|
+
elseif exists("b:match_comment") " backwards compatibility and testing!
|
692
|
+
let skip = "r:" . b:match_comment
|
693
|
+
else
|
694
|
+
let skip = 's:comment\|string'
|
695
|
+
endif
|
696
|
+
let skip = s:ParseSkip(skip)
|
697
|
+
" let restore_cursor = line(".") . "G" . virtcol(".") . "|"
|
698
|
+
" normal! H
|
699
|
+
" let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
|
700
|
+
let restore_cursor = virtcol(".") . "|"
|
701
|
+
normal! g0
|
702
|
+
let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor
|
703
|
+
normal! H
|
704
|
+
let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
|
705
|
+
execute restore_cursor
|
706
|
+
|
707
|
+
" Third step: call searchpair().
|
708
|
+
" Replace '\('--but not '\\('--with '\%(' and ',' with '\|'.
|
709
|
+
let openpat = substitute(open, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g')
|
710
|
+
let openpat = substitute(openpat, ',', '\\|', 'g')
|
711
|
+
let closepat = substitute(close, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g')
|
712
|
+
let closepat = substitute(closepat, ',', '\\|', 'g')
|
713
|
+
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
|
714
|
+
let skip = '0'
|
715
|
+
else
|
716
|
+
execute "if " . skip . "| let skip = '0' | endif"
|
717
|
+
endif
|
718
|
+
mark '
|
719
|
+
let level = v:count1
|
720
|
+
while level
|
721
|
+
if searchpair(openpat, '', closepat, a:spflag, skip) < 1
|
722
|
+
call s:CleanUp(restore_options, a:mode, startline, startcol)
|
723
|
+
return ""
|
724
|
+
endif
|
725
|
+
let level = level - 1
|
726
|
+
endwhile
|
727
|
+
|
728
|
+
" Restore options and return a string to restore the original position.
|
729
|
+
call s:CleanUp(restore_options, a:mode, startline, startcol)
|
730
|
+
return restore_cursor
|
731
|
+
endfun
|
732
|
+
|
733
|
+
" Search backwards for "if" or "while" or "<tag>" or ...
|
734
|
+
" and return "endif" or "endwhile" or "</tag>" or ... .
|
735
|
+
" For now, this uses b:match_words and the same script variables
|
736
|
+
" as s:Match_wrapper() . Later, it may get its own patterns,
|
737
|
+
" either from a buffer variable or passed as arguments.
|
738
|
+
" fun! s:Autocomplete()
|
739
|
+
" echo "autocomplete not yet implemented :-("
|
740
|
+
" if !exists("b:match_words") || b:match_words == ""
|
741
|
+
" return ""
|
742
|
+
" end
|
743
|
+
" let startpos = s:MultiMatch("bW")
|
744
|
+
"
|
745
|
+
" if startpos == ""
|
746
|
+
" return ""
|
747
|
+
" endif
|
748
|
+
" " - TODO: figure out whether 'if' or '<tag>' matched, and construct
|
749
|
+
" " - the appropriate closing.
|
750
|
+
" let matchline = getline(".")
|
751
|
+
" let curcol = col(".") - 1
|
752
|
+
" " - TODO: Change the s:all argument if there is a new set of match pats.
|
753
|
+
" let regexp = s:Wholematch(matchline, s:all, curcol)
|
754
|
+
" let suf = strlen(matchline) - matchend(matchline, regexp)
|
755
|
+
" let prefix = (curcol ? '^.\{' . curcol . '}\%(' : '^\%(')
|
756
|
+
" let suffix = (suf ? '\).\{' . suf . '}$' : '\)$')
|
757
|
+
" " Reconstruct the version with unresolved backrefs.
|
758
|
+
" let patBR = substitute(b:match_words.',', '[,:]*,[,:]*', ',', 'g')
|
759
|
+
" let patBR = substitute(patBR, ':\{2,}', ':', "g")
|
760
|
+
" " Now, set group and groupBR to the matching group: 'if:endif' or
|
761
|
+
" " 'while:endwhile' or whatever.
|
762
|
+
" let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR)
|
763
|
+
" let i = matchend(group, s:notslash . ",")
|
764
|
+
" let groupBR = strpart(group, i)
|
765
|
+
" let group = strpart(group, 0, i-1)
|
766
|
+
" " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix
|
767
|
+
" if s:do_BR
|
768
|
+
" let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline)
|
769
|
+
" endif
|
770
|
+
" " let g:group = group
|
771
|
+
"
|
772
|
+
" " - TODO: Construct the closing from group.
|
773
|
+
" let fake = "end" . expand("<cword>")
|
774
|
+
" execute startpos
|
775
|
+
" return fake
|
776
|
+
" endfun
|
777
|
+
|
778
|
+
" Close all open structures. "Get the heck out of here!"
|
779
|
+
" fun! s:Gthhoh()
|
780
|
+
" let close = s:Autocomplete()
|
781
|
+
" while strlen(close)
|
782
|
+
" put=close
|
783
|
+
" let close = s:Autocomplete()
|
784
|
+
" endwhile
|
785
|
+
" endfun
|
786
|
+
|
787
|
+
" Parse special strings as typical skip arguments for searchpair():
|
788
|
+
" s:foo becomes (current syntax item) =~ foo
|
789
|
+
" S:foo becomes (current syntax item) !~ foo
|
790
|
+
" r:foo becomes (line before cursor) =~ foo
|
791
|
+
" R:foo becomes (line before cursor) !~ foo
|
792
|
+
fun! s:ParseSkip(str)
|
793
|
+
let skip = a:str
|
794
|
+
if skip[1] == ":"
|
795
|
+
if skip[0] == "s"
|
796
|
+
let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" .
|
797
|
+
\ strpart(skip,2) . "'"
|
798
|
+
elseif skip[0] == "S"
|
799
|
+
let skip = "synIDattr(synID(line('.'),col('.'),1),'name') !~? '" .
|
800
|
+
\ strpart(skip,2) . "'"
|
801
|
+
elseif skip[0] == "r"
|
802
|
+
let skip = "strpart(getline('.'),0,col('.'))=~'" . strpart(skip,2). "'"
|
803
|
+
elseif skip[0] == "R"
|
804
|
+
let skip = "strpart(getline('.'),0,col('.'))!~'" . strpart(skip,2). "'"
|
805
|
+
endif
|
806
|
+
endif
|
807
|
+
return skip
|
808
|
+
endfun
|
809
|
+
|
810
|
+
let &cpo = s:save_cpo
|
811
|
+
|
812
|
+
" vim:sts=2:sw=2:
|