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.
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: