tomkersten-vixploder 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +105 -0
  3. data/PostInstall.txt +21 -0
  4. data/README.rdoc +131 -0
  5. data/Rakefile +21 -0
  6. data/bin/256colors2.pl +63 -0
  7. data/bin/colortest +365 -0
  8. data/bin/vixplode +10 -0
  9. data/lib/dotfiles/aliases +30 -0
  10. data/lib/dotfiles/gvimrc +20 -0
  11. data/lib/dotfiles/vim/.VimballRecord +2 -0
  12. data/lib/dotfiles/vim/after/ftplugin/actionscript_snippets.vim +9 -0
  13. data/lib/dotfiles/vim/after/ftplugin/aspvbs_snippets.vim +17 -0
  14. data/lib/dotfiles/vim/after/ftplugin/c_snippets.vim +58 -0
  15. data/lib/dotfiles/vim/after/ftplugin/css_snippets.vim +30 -0
  16. data/lib/dotfiles/vim/after/ftplugin/django_model_snippets.vim +61 -0
  17. data/lib/dotfiles/vim/after/ftplugin/django_template_snippets.vim +32 -0
  18. data/lib/dotfiles/vim/after/ftplugin/f-script_snippets.vim +14 -0
  19. data/lib/dotfiles/vim/after/ftplugin/haskell_snippets.vim +9 -0
  20. data/lib/dotfiles/vim/after/ftplugin/html_snippets.vim +57 -0
  21. data/lib/dotfiles/vim/after/ftplugin/java_snippets.vim +52 -0
  22. data/lib/dotfiles/vim/after/ftplugin/javascript_snippets.vim +10 -0
  23. data/lib/dotfiles/vim/after/ftplugin/latex_snippets.vim +13 -0
  24. data/lib/dotfiles/vim/after/ftplugin/logo_snippets.vim +9 -0
  25. data/lib/dotfiles/vim/after/ftplugin/markdown_snippets.vim +10 -0
  26. data/lib/dotfiles/vim/after/ftplugin/movable_type_snippets.vim +14 -0
  27. data/lib/dotfiles/vim/after/ftplugin/objc_snippets.vim +53 -0
  28. data/lib/dotfiles/vim/after/ftplugin/ocaml_snippets.vim +26 -0
  29. data/lib/dotfiles/vim/after/ftplugin/perl_snippets.vim +23 -0
  30. data/lib/dotfiles/vim/after/ftplugin/php_snippets.vim +30 -0
  31. data/lib/dotfiles/vim/after/ftplugin/phpdoc_snippets.vim +19 -0
  32. data/lib/dotfiles/vim/after/ftplugin/propel_snippets.vim +14 -0
  33. data/lib/dotfiles/vim/after/ftplugin/python_snippets.vim +202 -0
  34. data/lib/dotfiles/vim/after/ftplugin/rails_snippets.vim +54 -0
  35. data/lib/dotfiles/vim/after/ftplugin/ruby_snippets.vim +32 -0
  36. data/lib/dotfiles/vim/after/ftplugin/sh_snippets.vim +12 -0
  37. data/lib/dotfiles/vim/after/ftplugin/slate_snippets.vim +19 -0
  38. data/lib/dotfiles/vim/after/ftplugin/smarty_snippets.vim +35 -0
  39. data/lib/dotfiles/vim/after/ftplugin/symfony_snippets.vim +21 -0
  40. data/lib/dotfiles/vim/after/ftplugin/tcl_snippets.vim +14 -0
  41. data/lib/dotfiles/vim/after/ftplugin/template_toolkit_snippets.vim +13 -0
  42. data/lib/dotfiles/vim/after/ftplugin/tex_snippets.vim +13 -0
  43. data/lib/dotfiles/vim/after/ftplugin/xhtml_snippets.vim +48 -0
  44. data/lib/dotfiles/vim/autoload/fakeclip.vim +253 -0
  45. data/lib/dotfiles/vim/autoload/rails.vim +4377 -0
  46. data/lib/dotfiles/vim/autoload/rubycomplete.vim +802 -0
  47. data/lib/dotfiles/vim/colors/inkpot.vim +212 -0
  48. data/lib/dotfiles/vim/colors/ir_black.vim +212 -0
  49. data/lib/dotfiles/vim/colors/ir_black_mod.vim +213 -0
  50. data/lib/dotfiles/vim/colors/railscasts.vim +100 -0
  51. data/lib/dotfiles/vim/colors/rubyblue.vim +74 -0
  52. data/lib/dotfiles/vim/colors/twilight.vim +75 -0
  53. data/lib/dotfiles/vim/colors/twilight2.vim +74 -0
  54. data/lib/dotfiles/vim/colors/wombat256.vim +302 -0
  55. data/lib/dotfiles/vim/compiler/eruby.vim +41 -0
  56. data/lib/dotfiles/vim/compiler/ruby.vim +68 -0
  57. data/lib/dotfiles/vim/compiler/rubyunit.vim +35 -0
  58. data/lib/dotfiles/vim/doc/NERD_tree.txt +1235 -0
  59. data/lib/dotfiles/vim/doc/fakeclip.txt +190 -0
  60. data/lib/dotfiles/vim/doc/matchit.txt +406 -0
  61. data/lib/dotfiles/vim/doc/project.txt +710 -0
  62. data/lib/dotfiles/vim/doc/rails.txt +1123 -0
  63. data/lib/dotfiles/vim/doc/snippets_emu.txt +354 -0
  64. data/lib/dotfiles/vim/doc/surround.txt +218 -0
  65. data/lib/dotfiles/vim/doc/tags +433 -0
  66. data/lib/dotfiles/vim/filetype.vim +13 -0
  67. data/lib/dotfiles/vim/ftdetect/gist.vim +3 -0
  68. data/lib/dotfiles/vim/ftdetect/ruby.vim +14 -0
  69. data/lib/dotfiles/vim/ftplugin/eruby.vim +101 -0
  70. data/lib/dotfiles/vim/ftplugin/ruby.vim +230 -0
  71. data/lib/dotfiles/vim/indent/eruby.vim +73 -0
  72. data/lib/dotfiles/vim/indent/ruby.vim +373 -0
  73. data/lib/dotfiles/vim/plugin/NERD_tree.vim +3536 -0
  74. data/lib/dotfiles/vim/plugin/comments.vim +321 -0
  75. data/lib/dotfiles/vim/plugin/fakeclip.vim +174 -0
  76. data/lib/dotfiles/vim/plugin/fuzzyfinder.vim +1676 -0
  77. data/lib/dotfiles/vim/plugin/fuzzyfinder_textmate.vim +150 -0
  78. data/lib/dotfiles/vim/plugin/gist.vim +241 -0
  79. data/lib/dotfiles/vim/plugin/gitdiff.vim +141 -0
  80. data/lib/dotfiles/vim/plugin/matchit.vim +812 -0
  81. data/lib/dotfiles/vim/plugin/mru.vim +787 -0
  82. data/lib/dotfiles/vim/plugin/rails.vim +310 -0
  83. data/lib/dotfiles/vim/plugin/rspec.vim +12 -0
  84. data/lib/dotfiles/vim/plugin/snippets.vim +17 -0
  85. data/lib/dotfiles/vim/plugin/snippetsEmu.vim +973 -0
  86. data/lib/dotfiles/vim/plugin/supertab.vim +531 -0
  87. data/lib/dotfiles/vim/plugin/surround.vim +632 -0
  88. data/lib/dotfiles/vim/ref_vimrc +80 -0
  89. data/lib/dotfiles/vim/ruby/fuzzy_file_finder.rb +353 -0
  90. data/lib/dotfiles/vim/syntax/eruby.vim +85 -0
  91. data/lib/dotfiles/vim/syntax/haml.vim +113 -0
  92. data/lib/dotfiles/vim/syntax/mkd.vim +86 -0
  93. data/lib/dotfiles/vim/syntax/ruby.vim +324 -0
  94. data/lib/dotfiles/vim/syntax/sass.vim +93 -0
  95. data/lib/dotfiles/vimrc +269 -0
  96. data/lib/vixplode/cli.rb +73 -0
  97. data/lib/vixploder.rb +6 -0
  98. data/script/console +10 -0
  99. data/script/destroy +14 -0
  100. data/script/generate +14 -0
  101. data/spec/spec.opts +1 -0
  102. data/spec/spec_helper.rb +10 -0
  103. data/spec/vixplode_cli_spec.rb +15 -0
  104. data/spec/vixploder_spec.rb +7 -0
  105. data/tasks/rspec.rake +21 -0
  106. 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: