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,4377 @@
1
+ " autoload/rails.vim
2
+ " Author: Tim Pope <vimNOSPAM@tpope.info>
3
+
4
+ " Install this file as autoload/rails.vim. This file is sourced manually by
5
+ " plugin/rails.vim. It is in autoload directory to allow for future usage of
6
+ " Vim 7's autoload feature.
7
+
8
+ " ============================================================================
9
+
10
+ " Exit quickly when:
11
+ " - this plugin was already loaded (or disabled)
12
+ " - when 'compatible' is set
13
+ if &cp || exists("g:autoloaded_rails")
14
+ finish
15
+ endif
16
+ let g:autoloaded_rails = '2.1'
17
+
18
+ let s:cpo_save = &cpo
19
+ set cpo&vim
20
+
21
+ " Utility Functions {{{1
22
+
23
+ function! s:sub(str,pat,rep)
24
+ return substitute(a:str,'\v\C'.a:pat,a:rep,'')
25
+ endfunction
26
+
27
+ function! s:gsub(str,pat,rep)
28
+ return substitute(a:str,'\v\C'.a:pat,a:rep,'g')
29
+ endfunction
30
+
31
+ function! s:string(str)
32
+ if exists("*string")
33
+ return string(a:str)
34
+ else
35
+ return "'" . s:gsub(a:str,"'","'.\"'\".'") . "'"
36
+ endif
37
+ endfunction
38
+
39
+ function! s:compact(ary)
40
+ return s:sub(s:sub(s:gsub(a:ary,'\n\n+','\n'),'\n$',''),'^\n','')
41
+ endfunction
42
+
43
+ function! s:scrub(collection,item)
44
+ " Removes item from a newline separated collection
45
+ let col = "\n" . a:collection
46
+ let idx = stridx(col,"\n".a:item."\n")
47
+ let cnt = 0
48
+ while idx != -1 && cnt < 100
49
+ let col = strpart(col,0,idx).strpart(col,idx+strlen(a:item)+1)
50
+ let idx = stridx(col,"\n".a:item."\n")
51
+ let cnt = cnt + 1
52
+ endwhile
53
+ return strpart(col,1)
54
+ endfunction
55
+
56
+ function! s:escarg(p)
57
+ return s:gsub(a:p,'[ !%#]','\\&')
58
+ endfunction
59
+
60
+ function! s:esccmd(p)
61
+ return s:gsub(a:p,'[!%#]','\\&')
62
+ endfunction
63
+
64
+ function! s:ra()
65
+ " Rails root, escaped for use as single argument
66
+ return s:escarg(RailsRoot())
67
+ endfunction
68
+
69
+ function! s:rc()
70
+ " Rails root, escaped for use with a command (spaces not escaped)
71
+ return s:esccmd(RailsRoot())
72
+ endfunction
73
+
74
+ function! s:escvar(r)
75
+ let r = fnamemodify(a:r,':~')
76
+ let r = s:gsub(r,'\W','\="_".char2nr(submatch(0))."_"')
77
+ let r = s:gsub(r,'^\d','_&')
78
+ return r
79
+ endfunction
80
+
81
+ function! s:rv()
82
+ " Rails root, escaped to be a variable name
83
+ return s:escvar(RailsRoot())
84
+ endfunction
85
+
86
+ function! s:rquote(str)
87
+ " Imperfect but adequate for Ruby arguments
88
+ if a:str =~ '^[A-Za-z0-9_/.:-]\+$'
89
+ return a:str
90
+ elseif &shell =~? 'cmd'
91
+ return '"'.s:gsub(s:gsub(a:str,'\','\\'),'"','\\"').'"'
92
+ else
93
+ return "'".s:gsub(s:gsub(a:str,'\','\\'),"'","'\\\\''")."'"
94
+ endif
95
+ endfunction
96
+
97
+ function! s:sname()
98
+ return fnamemodify(s:file,':t:r')
99
+ endfunction
100
+
101
+ function! s:hasfile(file)
102
+ return filereadable(RailsRoot().'/'.a:file)
103
+ endfunction
104
+
105
+ function! s:rubyexestr(cmd)
106
+ if RailsRoot() =~ '://'
107
+ return "ruby ".a:cmd
108
+ else
109
+ return "ruby -C ".s:rquote(RailsRoot())." ".a:cmd
110
+ endif
111
+ endfunction
112
+
113
+ function! s:rubyexebg(cmd)
114
+ let cmd = s:esccmd(s:rubyexestr(a:cmd))
115
+ if has("gui_win32")
116
+ if &shellcmdflag == "-c" && ($PATH . &shell) =~? 'cygwin'
117
+ silent exe "!cygstart -d ".s:rquote(RailsRoot())." ruby ".a:cmd
118
+ else
119
+ exe "!start ".cmd
120
+ endif
121
+ elseif exists("$STY") && !has("gui_running") && s:getopt("gnu_screen","abg") && executable("screen")
122
+ silent exe "!screen -ln -fn -t ".s:sub(s:sub(a:cmd,'\s.*',''),'^%(script|-rcommand)/','rails-').' '.cmd
123
+ else
124
+ exe "!".cmd
125
+ endif
126
+ return v:shell_error
127
+ endfunction
128
+
129
+ function! s:rubyexe(cmd,...)
130
+ if a:0
131
+ call s:rubyexebg(a:cmd)
132
+ else
133
+ exe "!".s:esccmd(s:rubyexestr(a:cmd))
134
+ endif
135
+ return v:shell_error
136
+ endfunction
137
+
138
+ function! s:rubyeval(ruby,...)
139
+ if a:0 > 0
140
+ let def = a:1
141
+ else
142
+ let def = ""
143
+ endif
144
+ if !executable("ruby")
145
+ return def
146
+ endif
147
+ let cmd = s:rubyexestr('-e '.s:rquote('begin; require %{rubygems}; rescue LoadError; end; begin; require %{active_support}; rescue LoadError; end; '.a:ruby))
148
+ "let g:rails_last_ruby_command = cmd
149
+ " If the shell is messed up, this command could cause an error message
150
+ silent! let results = system(cmd)
151
+ "let g:rails_last_ruby_result = results
152
+ if v:shell_error != 0 " results =~ '-e:\d' || results =~ 'ruby:.*(fatal)'
153
+ return def
154
+ else
155
+ return results
156
+ endif
157
+ endfunction
158
+
159
+ function! s:railseval(ruby,...)
160
+ if a:0 > 0
161
+ let def = a:1
162
+ else
163
+ let def = ""
164
+ endif
165
+ if !executable("ruby")
166
+ return def
167
+ endif
168
+ let args = "-r./config/boot -r ".s:rquote(RailsRoot()."/config/environment")." -e ".s:rquote(a:ruby)
169
+ let cmd = s:rubyexestr(args)
170
+ " If the shell is messed up, this command could cause an error message
171
+ silent! let results = system(cmd)
172
+ if v:shell_error != 0 " results =~ '-e:\d' || results =~ 'ruby:.*(fatal)'
173
+ return def
174
+ else
175
+ return results
176
+ endif
177
+ endfunction
178
+
179
+ function! s:endof(lnum)
180
+ if a:lnum == 0
181
+ return 0
182
+ endif
183
+ if &ft == "yaml" || expand("%:e") == "yml"
184
+ return -1
185
+ endif
186
+ let cline = getline(a:lnum)
187
+ let spc = matchstr(cline,'^\s*')
188
+ let endpat = '\<end\>'
189
+ if matchstr(getline(a:lnum+1),'^'.spc) && !matchstr(getline(a:lnum+1),'^'.spc.endpat) && matchstr(cline,endpat)
190
+ return a:lnum
191
+ endif
192
+ let endl = a:lnum
193
+ while endl <= line('$')
194
+ let endl = endl + 1
195
+ if getline(endl) =~ '^'.spc.endpat
196
+ return endl
197
+ elseif getline(endl) =~ '^=begin\>'
198
+ while getline(endl) !~ '^=end\>' && endl <= line('$')
199
+ let endl = endl + 1
200
+ endwhile
201
+ let endl = endl + 1
202
+ elseif getline(endl) !~ '^'.spc && getline(endl) !~ '^\s*\%(#.*\)\=$'
203
+ return 0
204
+ endif
205
+ endwhile
206
+ return 0
207
+ endfunction
208
+
209
+ function! s:lastopeningline(pattern,limit,...)
210
+ let line = a:0 ? a:1 : line(".")
211
+ while line > a:limit && getline(line) !~ a:pattern
212
+ let line = line - 1
213
+ endwhile
214
+ let lend = s:endof(line)
215
+ if line > a:limit && lend >= (a:0 ? a:1 : line("."))
216
+ return line
217
+ else
218
+ return -1
219
+ endif
220
+ endfunction
221
+
222
+ function! s:lastmethodline(...)
223
+ return s:lastopeningline(&l:define,0,a:0 ? a:1 : line("."))
224
+ endfunction
225
+
226
+ function! s:lastmethod(...)
227
+ let line = s:lastmethodline(a:0 ? a:1 : line("."))
228
+ if line
229
+ return s:sub(matchstr(getline(line),'\%('.&define.'\)\zs\h\%(\k\|[:.]\)*[?!=]\='),':$','')
230
+ else
231
+ return ""
232
+ endif
233
+ endfunction
234
+
235
+ function! s:lastrespondtoline(...)
236
+ return s:lastopeningline('\C^\s*respond_to\s*\%(\<do\)\s*|\zs\h\k*\ze|',s:lastmethodline(), a:0 ? a:1 : line("."))
237
+ endfunction
238
+
239
+ function! s:lastformat()
240
+ let rline = s:lastrespondtoline()
241
+ if rline
242
+ let variable = matchstr(getline(rline),'\C^\s*respond_to\s*\%(\<do\|{\)\s*|\zs\h\k*\ze|')
243
+ let line = line('.')
244
+ while line > rline
245
+ let match = matchstr(getline(line),'\C^\s*'.variable.'\s*\.\s*\zs\h\k*')
246
+ if match != ''
247
+ return match
248
+ endif
249
+ let line = line - 1
250
+ endwhile
251
+ endif
252
+ return ""
253
+ endfunction
254
+
255
+ function! s:format(...)
256
+ if RailsFileType() =~ '^view\>'
257
+ let format = fnamemodify(RailsFilePath(),':r:e')
258
+ else
259
+ let format = s:lastformat()
260
+ endif
261
+ if format == ''
262
+ if fnamemodify(RailsFilePath(),':e') == 'rhtml'
263
+ let format = 'html'
264
+ elseif fnamemodify(RailsFilePath(),':e') == 'rxml'
265
+ let format = 'xml'
266
+ elseif fnamemodify(RailsFilePath(),':e') == 'rjs'
267
+ let format = 'js'
268
+ elseif a:0
269
+ return a:1
270
+ endif
271
+ endif
272
+ return format
273
+ endfunction
274
+
275
+ let s:view_types = 'rhtml,erb,rxml,builder,rjs,mab,liquid,haml,dryml,mn'
276
+
277
+ function! s:viewspattern()
278
+ return '\%('.s:gsub(s:view_types,',','\\|').'\)'
279
+ endfunction
280
+
281
+ function! s:controller(...)
282
+ let t = RailsFileType()
283
+ let f = RailsFilePath()
284
+ let o = s:getopt("controller","lb")
285
+ if o != ""
286
+ return o
287
+ elseif f =~ '\<app/views/layouts/'
288
+ return s:sub(f,'.*<app/views/layouts/(.{-})\..*','\1')
289
+ elseif f =~ '\<app/views/'
290
+ return s:sub(f,'.*<app/views/(.{-})/\k+\.\k+%(\.\k+)=$','\1')
291
+ elseif f =~ '\<app/helpers/.*_helper\.rb$'
292
+ return s:sub(f,'.*<app/helpers/(.{-})_helper\.rb$','\1')
293
+ elseif f =~ '\<app/controllers/.*\.rb$'
294
+ return s:sub(f,'.*<app/controllers/(.{-})%(_controller)=\.rb$','\1')
295
+ elseif f =~ '\<app/apis/.*_api\.rb$'
296
+ return s:sub(f,'.*<app/apis/(.{-})_api\.rb$','\1')
297
+ elseif f =~ '\<test/functional/.*_test\.rb$'
298
+ return s:sub(f,'.*<test/functional/(.{-})%(_controller)=_test\.rb$','\1')
299
+ elseif f =~ '\<spec/controllers/.*_spec\.rb$'
300
+ return s:sub(f,'.*<spec/controllers/(.{-})%(_controller)=_spec\.rb$','\1')
301
+ elseif f =~ '\<spec/helpers/.*_helper_spec\.rb$'
302
+ return s:sub(f,'.*<spec/helpers/(.{-})_helper_spec\.rb$','\1')
303
+ elseif f =~ '\<spec/views/.*/\w\+_view_spec\.rb$'
304
+ return s:sub(f,'.*<spec/views/(.{-})/\w+_view_spec\.rb$','\1')
305
+ elseif f =~ '\<components/.*_controller\.rb$'
306
+ return s:sub(f,'.*<components/(.{-})_controller\.rb$','\1')
307
+ elseif f =~ '\<components/.*\.'.s:viewspattern().'$'
308
+ return s:sub(f,'.*<components/(.{-})/\k+\.\k+$','\1')
309
+ elseif f =~ '\<app/models/.*\.rb$' && t =~ '^model-mailer\>'
310
+ return s:sub(f,'.*<app/models/(.{-})\.rb$','\1')
311
+ elseif f =~ '\<public/stylesheets/.*\.css$'
312
+ return s:sub(f,'.*<public/stylesheets/(.{-})\.css$','\1')
313
+ elseif a:0 && a:1
314
+ return s:pluralize(s:model())
315
+ endif
316
+ return ""
317
+ endfunction
318
+
319
+ function! s:model(...)
320
+ let f = RailsFilePath()
321
+ let o = s:getopt("model","lb")
322
+ if o != ""
323
+ return o
324
+ elseif f =~ '\<app/models/.*_observer.rb$'
325
+ return s:sub(f,'.*<app/models/(.*)_observer\.rb$','\1')
326
+ elseif f =~ '\<app/models/.*\.rb$'
327
+ return s:sub(f,'.*<app/models/(.*)\.rb$','\1')
328
+ elseif f =~ '\<test/unit/.*_observer_test\.rb$'
329
+ return s:sub(f,'.*<test/unit/(.*)_observer_test\.rb$','\1')
330
+ elseif f =~ '\<test/unit/.*_test\.rb$'
331
+ return s:sub(f,'.*<test/unit/(.*)_test\.rb$','\1')
332
+ elseif f =~ '\<spec/models/.*_spec\.rb$'
333
+ return s:sub(f,'.*<spec/models/(.*)_spec\.rb$','\1')
334
+ elseif f =~ '\<\%(test\|spec\)/fixtures/.*\.\w*\~\=$'
335
+ return s:singularize(s:sub(f,'.*<%(test|spec)/fixtures/(.*)\.\w*\~=$','\1'))
336
+ elseif f =~ '\<\%(test\|spec\)/exemplars/.*_exemplar\.rb$'
337
+ return s:sub(f,'.*<%(test|spec)/exemplars/(.*)_exemplar\.rb$','\1')
338
+ elseif a:0 && a:1
339
+ return s:singularize(s:controller())
340
+ endif
341
+ return ""
342
+ endfunction
343
+
344
+ function! s:underscore(str)
345
+ let str = s:gsub(a:str,'::','/')
346
+ let str = s:gsub(str,'(\u+)(\u\l)','\1_\2')
347
+ let str = s:gsub(str,'(\l|\d)(\u)','\1_\2')
348
+ let str = s:gsub(str,'-','_')
349
+ let str = tolower(str)
350
+ return str
351
+ endfunction
352
+
353
+ function! s:camelize(str)
354
+ let str = s:gsub(a:str,'/(.)','::\u\1')
355
+ let str = s:gsub(str,'%([_-]|<)(.)','\u\1')
356
+ return str
357
+ endfunction
358
+
359
+ function! s:singularize(word)
360
+ " Probably not worth it to be as comprehensive as Rails but we can
361
+ " still hit the common cases.
362
+ let word = a:word
363
+ if word =~? '\.js$' || word == ''
364
+ return word
365
+ endif
366
+ let word = s:sub(word,'eople$','ersons')
367
+ let word = s:sub(word,'[aeio]@<!ies$','ys')
368
+ let word = s:sub(word,'xe[ns]$','xs')
369
+ let word = s:sub(word,'ves$','fs')
370
+ let word = s:sub(word,'ss%(es)=$','sss')
371
+ let word = s:sub(word,'s$','')
372
+ return word
373
+ endfunction
374
+
375
+ function! s:pluralize(word)
376
+ let word = a:word
377
+ if word == ''
378
+ return word
379
+ endif
380
+ let word = s:sub(word,'[aeio]@<!y$','ie')
381
+ let word = s:sub(word,'%([osxz]|[cs]h)$','&e')
382
+ let word = s:sub(word,'f@<!f$','ve')
383
+ let word = word."s"
384
+ let word = s:sub(word,'ersons$','eople')
385
+ return word
386
+ endfunction
387
+
388
+ function! s:usesubversion()
389
+ if !exists("b:rails_use_subversion")
390
+ let b:rails_use_subversion = s:getopt("subversion","abg") && (RailsRoot()!="") && isdirectory(RailsRoot()."/.svn")
391
+ endif
392
+ return b:rails_use_subversion
393
+ endfunction
394
+
395
+ function! s:environment()
396
+ if exists('$RAILS_ENV')
397
+ return $RAILS_ENV
398
+ else
399
+ return "development"
400
+ endif
401
+ endfunction
402
+
403
+ function! s:environments(...)
404
+ let e = s:getopt("environment","abg")
405
+ if e == ''
406
+ return "development\ntest\nproduction"
407
+ else
408
+ return s:gsub(e,'[:;,- ]',"\n")
409
+ endif
410
+ endfunction
411
+
412
+ function! s:warn(str)
413
+ echohl WarningMsg
414
+ echomsg a:str
415
+ echohl None
416
+ " Sometimes required to flush output
417
+ echo ""
418
+ let v:warningmsg = a:str
419
+ endfunction
420
+
421
+ function! s:error(str)
422
+ echohl ErrorMsg
423
+ echomsg a:str
424
+ echohl None
425
+ let v:errmsg = a:str
426
+ endfunction
427
+
428
+ function! s:debug(str)
429
+ if g:rails_debug
430
+ echohl Debug
431
+ echomsg a:str
432
+ echohl None
433
+ endif
434
+ endfunction
435
+
436
+ " }}}1
437
+ " "Public" Interface {{{1
438
+
439
+ " RailsRoot() is the only official public function
440
+
441
+ function! RailsRevision()
442
+ return 1000*matchstr(g:autoloaded_rails,'^\d\+')+matchstr(g:autoloaded_rails,'[1-9]\d*$')
443
+ endfunction
444
+
445
+ function! RailsRoot()
446
+ if exists("b:rails_root")
447
+ return b:rails_root
448
+ else
449
+ return ""
450
+ endif
451
+ endfunction
452
+
453
+ function! RailsFilePath()
454
+ if !exists("b:rails_root")
455
+ return ""
456
+ elseif exists("b:rails_file_path")
457
+ return b:rails_file_path
458
+ endif
459
+ let f = s:gsub(expand('%:p'),'\\ @!','/')
460
+ let f = s:sub(f,'/$','')
461
+ if s:gsub(b:rails_root,'\\ @!','/') == strpart(f,0,strlen(b:rails_root))
462
+ return strpart(f,strlen(b:rails_root)+1)
463
+ else
464
+ return f
465
+ endif
466
+ endfunction
467
+
468
+ function! RailsFile()
469
+ return RailsFilePath()
470
+ endfunction
471
+
472
+ function! RailsFileType()
473
+ if !exists("b:rails_root")
474
+ return ""
475
+ elseif exists("b:rails_file_type")
476
+ return b:rails_file_type
477
+ elseif exists("b:rails_cached_file_type")
478
+ return b:rails_cached_file_type
479
+ endif
480
+ let f = RailsFilePath()
481
+ let e = fnamemodify(RailsFilePath(),':e')
482
+ let r = ""
483
+ let top = getline(1)." ".getline(2)." ".getline(3)." ".getline(4)." ".getline(5).getline(6)." ".getline(7)." ".getline(8)." ".getline(9)." ".getline(10)
484
+ if f == ""
485
+ let r = f
486
+ elseif f =~ '_controller\.rb$' || f =~ '\<app/controllers/.*\.rb$'
487
+ if top =~ '\<wsdl_service_name\>'
488
+ let r = "controller-api"
489
+ else
490
+ let r = "controller"
491
+ endif
492
+ elseif f =~ '_api\.rb'
493
+ let r = "api"
494
+ elseif f =~ '\<test/test_helper\.rb$'
495
+ let r = "test"
496
+ elseif f =~ '\<spec/spec_helper\.rb$'
497
+ let r = "spec"
498
+ elseif f =~ '_helper\.rb$'
499
+ let r = "helper"
500
+ elseif f =~ '\<app/models\>'
501
+ let class = matchstr(top,'\<Acti\w\w\u\w\+\%(::\h\w*\)\+\>')
502
+ if class == "ActiveResource::Base"
503
+ let class = "ares"
504
+ let r = "model-ares"
505
+ elseif class != ''
506
+ "let class = s:sub(class,'::Base$','')
507
+ let class = tolower(s:gsub(class,'[^A-Z]',''))
508
+ let r = "model-".s:sub(class,'^amb>','mailer')
509
+ elseif f =~ '_mailer\.rb$'
510
+ let r = "model-mailer"
511
+ elseif top =~ '\<\%(validates_\w\+_of\|set_\%(table_name\|primary_key\)\|has_one\|has_many\|belongs_to\)\>'
512
+ let r = "model-arb"
513
+ else
514
+ let r = "model"
515
+ endif
516
+ elseif f =~ '\<app/views/layouts\>.*\.'
517
+ let r = "view-layout-" . e
518
+ elseif f =~ '\<\%(app/views\|components\)/.*/_\k\+\.\k\+\%(\.\k\+\)\=$'
519
+ let r = "view-partial-" . e
520
+ elseif f =~ '\<app/views\>.*\.' || f =~ '\<components/.*/.*\.'.s:viewspattern().'$'
521
+ let r = "view-" . e
522
+ elseif f =~ '\<test/unit/.*_test\.rb$'
523
+ let r = "test-unit"
524
+ elseif f =~ '\<test/functional/.*_test\.rb$'
525
+ let r = "test-functional"
526
+ elseif f =~ '\<test/integration/.*_test\.rb$'
527
+ let r = "test-integration"
528
+ elseif f =~ '\<spec/lib/.*_spec\.rb$'
529
+ let r = 'spec-lib'
530
+ elseif f =~ '\<lib/.*\.rb$'
531
+ let r = 'lib'
532
+ elseif f =~ '\<spec/\w*s/.*_spec\.rb$'
533
+ let r = s:sub(f,'.*<spec/(\w*)s/.*','spec-\1')
534
+ elseif f =~ '\<\%(test\|spec\)/fixtures\>'
535
+ if e == "yml"
536
+ let r = "fixtures-yaml"
537
+ else
538
+ let r = "fixtures" . (e == "" ? "" : "-" . e)
539
+ endif
540
+ elseif f =~ '\<test/.*_test\.rb'
541
+ let r = "test"
542
+ elseif f =~ '\<spec/.*_spec\.rb'
543
+ let r = "spec"
544
+ elseif f =~ '\<db/migrate\>' || f=~ '\<db/schema\.rb$'
545
+ let r = "migration"
546
+ elseif f =~ '\<vendor/plugins/.*/recipes/.*\.rb$' || f =~ '\.rake$' || f =~ '\<\%(Rake\|Cap\)file$' || f =~ '\<config/deploy\.rb$'
547
+ let r = "task"
548
+ elseif f =~ '\<log/.*\.log$'
549
+ let r = "log"
550
+ elseif e == "css" || e == "js" || e == "html"
551
+ let r = e
552
+ elseif f =~ '\<config/routes\>.*\.rb$'
553
+ let r = "config-routes"
554
+ elseif f =~ '\<config/'
555
+ let r = "config"
556
+ endif
557
+ return r
558
+ endfunction
559
+
560
+ function! RailsType()
561
+ return RailsFileType()
562
+ endfunction
563
+
564
+ function! RailsEval(ruby,...)
565
+ if !exists("b:rails_root")
566
+ return a:0 ? a:1 : ""
567
+ elseif a:0
568
+ return s:railseval(a:ruby,a:1)
569
+ else
570
+ return s:railseval(a:ruby)
571
+ endif
572
+ endfunction
573
+
574
+ " }}}1
575
+ " Autocommand Functions {{{1
576
+
577
+ function! s:QuickFixCmdPre()
578
+ if exists("b:rails_root")
579
+ if strpart(getcwd(),0,strlen(RailsRoot())) != RailsRoot()
580
+ let s:last_dir = getcwd()
581
+ echo "lchdir ".s:ra()
582
+ "exe "lchdir ".s:ra()
583
+ lchdir `=RailsRoot()`
584
+ endif
585
+ endif
586
+ endfunction
587
+
588
+ function! s:QuickFixCmdPost()
589
+ if exists("s:last_dir")
590
+ "exe "lchdir ".s:escarg(s:last_dir)
591
+ lchdir `=s:last_dir`
592
+ unlet s:last_dir
593
+ endif
594
+ endfunction
595
+
596
+ " }}}1
597
+ " Commands {{{1
598
+
599
+ function! s:prephelp()
600
+ let fn = fnamemodify(s:file,':h:h').'/doc/'
601
+ if filereadable(fn.'rails.txt')
602
+ if !filereadable(fn.'tags') || getftime(fn.'tags') <= getftime(fn.'rails.txt')
603
+ silent! helptags `=fn`
604
+ endif
605
+ endif
606
+ endfunction
607
+
608
+ function! RailsHelpCommand(...)
609
+ call s:prephelp()
610
+ let topic = a:0 ? a:1 : ""
611
+ if topic == "" || topic == "-"
612
+ return "help rails"
613
+ elseif topic =~ '^g:'
614
+ return "help ".topic
615
+ elseif topic =~ '^-'
616
+ return "help rails".topic
617
+ else
618
+ return "help rails-".topic
619
+ endif
620
+ endfunction
621
+
622
+ function! s:BufCommands()
623
+ call s:BufFinderCommands() " Provides Rcommand!
624
+ call s:BufNavCommands()
625
+ call s:BufScriptWrappers()
626
+ Rcommand! -buffer -bar -nargs=? -bang -complete=custom,s:RakeComplete Rake :call s:Rake(<bang>0,<q-args>)
627
+ Rcommand! -buffer -bar -nargs=? -bang -complete=custom,s:PreviewComplete Rpreview :call s:Preview(<bang>0,<q-args>)
628
+ Rcommand! -buffer -bar -nargs=? -bang -complete=custom,s:environments Rlog :call s:Log(<bang>0,<q-args>)
629
+ Rcommand! -buffer -bar -nargs=* -bang -complete=custom,s:SetComplete Rset :call s:Set(<bang>0,<f-args>)
630
+ command! -buffer -bar -nargs=0 Rtags :call s:Tags(<bang>0)
631
+ " Embedding all this logic directly into the command makes the error
632
+ " messages more concise.
633
+ command! -buffer -bar -nargs=? -bang Rdoc :
634
+ \ if <bang>0 || <q-args> =~ "^\\([:'-]\\|g:\\)" |
635
+ \ exe RailsHelpCommand(<q-args>) |
636
+ \ else | call s:Doc(<bang>0,<q-args>) | endif
637
+ command! -buffer -bar -nargs=0 -bang Rrefresh :if <bang>0|unlet! g:autoloaded_rails|source `=s:file`|endif|call s:Refresh(<bang>0)
638
+ if exists(":Project")
639
+ command! -buffer -bar -nargs=? -bang Rproject :call s:Project(<bang>0,<q-args>)
640
+ endif
641
+ if exists("g:loaded_dbext")
642
+ Rcommand! -buffer -bar -nargs=? -bang -complete=custom,s:environments Rdbext :call s:BufDatabase(2,<q-args>,<bang>0)
643
+ endif
644
+ let ext = expand("%:e")
645
+ if ext =~ s:viewspattern()
646
+ " TODO: complete controller names with trailing slashes here
647
+ Rcommand! -buffer -bar -nargs=? -range -complete=custom,s:controllerList Rextract :<line1>,<line2>call s:Extract(<bang>0,<f-args>)
648
+ command! -buffer -bar -nargs=? -range Rpartial :call s:warn("Warning: :Rpartial has been deprecated in favor of :Rextract") | <line1>,<line2>Rextract<bang> <args>
649
+ endif
650
+ if RailsFilePath() =~ '\<db/migrate/.*\.rb$'
651
+ command! -buffer -bar Rinvert :call s:Invert(<bang>0)
652
+ endif
653
+ endfunction
654
+
655
+ function! s:Doc(bang, string)
656
+ if a:string != ""
657
+ if exists("g:rails_search_url")
658
+ let query = substitute(a:string,'[^A-Za-z0-9_.~-]','\="%".printf("%02X",char2nr(submatch(0)))','g')
659
+ let url = printf(g:rails_search_url, query)
660
+ else
661
+ return s:error("specify a g:rails_search_url with %s for a query placeholder")
662
+ endif
663
+ elseif isdirectory(RailsRoot()."/doc/api/classes")
664
+ let url = RailsRoot()."/doc/api/index.html"
665
+ elseif s:getpidfor("0.0.0.0","8808") > 0
666
+ let url = "http://localhost:8808"
667
+ else
668
+ let url = "http://api.rubyonrails.org"
669
+ endif
670
+ call s:initOpenURL()
671
+ if exists(":OpenURL")
672
+ exe "OpenURL ".s:escarg(url)
673
+ else
674
+ return s:error("No :OpenURL command found")
675
+ endif
676
+ endfunction
677
+
678
+ function! s:Log(bang,arg)
679
+ if a:arg == ""
680
+ let lf = "log/".s:environment().".log"
681
+ else
682
+ let lf = "log/".a:arg.".log"
683
+ endif
684
+ let size = getfsize(RailsRoot()."/".lf)
685
+ if size >= 1048576
686
+ call s:warn("Log file is ".((size+512)/1024)."KB. Consider :Rake log:clear")
687
+ endif
688
+ if a:bang
689
+ exe "cgetfile ".lf
690
+ clast
691
+ else
692
+ if exists(":Tail")
693
+ " TODO: check if :Tail works with `=`
694
+ exe "Tail ".s:ra().'/'.lf
695
+ else
696
+ "exe "pedit ".s:ra().'/'.lf
697
+ pedit `=RailsRoot().'/'.lf`
698
+ endif
699
+ endif
700
+ endfunction
701
+
702
+ function! RailsNewApp(bang,...)
703
+ if a:0 == 0
704
+ if a:bang
705
+ echo "rails.vim version ".g:autoloaded_rails
706
+ else
707
+ !rails
708
+ endif
709
+ return
710
+ endif
711
+ let dir = ""
712
+ if a:1 !~ '^-'
713
+ let dir = a:1
714
+ elseif a:{a:0} =~ '[\/]'
715
+ let dir = a:{a:0}
716
+ else
717
+ let dir = a:1
718
+ endif
719
+ let str = ""
720
+ let c = 1
721
+ while c <= a:0
722
+ let str = str . " " . s:rquote(expand(a:{c}))
723
+ let c = c + 1
724
+ endwhile
725
+ "let str = s:sub(str,'^ ','')
726
+ let dir = expand(dir)
727
+ if isdirectory(fnamemodify(dir,':h')."/.svn") && g:rails_subversion
728
+ let append = " -c"
729
+ else
730
+ let append = ""
731
+ endif
732
+ if g:rails_default_database != "" && str !~ '-d \|--database='
733
+ let append = append." -d ".g:rails_default_database
734
+ endif
735
+ if a:bang
736
+ let append = append." --force"
737
+ endif
738
+ exe "!rails".append.str
739
+ if filereadable(dir."/".g:rails_default_file)
740
+ "exe "edit ".s:escarg(dir)."/".g:rails_default_file
741
+ edit `=dir.'/'.g:rails_default_file`
742
+ endif
743
+ endfunction
744
+
745
+ function! s:Tags(bang)
746
+ if exists("g:Tlist_Ctags_Cmd")
747
+ let cmd = g:Tlist_Ctags_Cmd
748
+ elseif executable("exuberant-ctags")
749
+ let cmd = "exuberant-ctags"
750
+ elseif executable("ctags-exuberant")
751
+ let cmd = "ctags-exuberant"
752
+ elseif executable("ctags")
753
+ let cmd = "ctags"
754
+ elseif executable("ctags.exe")
755
+ let cmd = "ctags.exe"
756
+ else
757
+ return s:error("ctags not found")
758
+ endif
759
+ exe "!".cmd." -R ".s:ra()
760
+ endfunction
761
+
762
+ function! s:Refresh(bang)
763
+ " What else?
764
+ if a:bang
765
+ unlet! s:rails_helper_methods
766
+ endif
767
+ if exists("g:rubycomplete_rails") && g:rubycomplete_rails && has("ruby")
768
+ silent! ruby ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
769
+ silent! ruby Dependencies.clear if defined?(Dependencies)
770
+ if a:bang
771
+ silent! ruby ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
772
+ endif
773
+ endif
774
+ call s:cacheclear()
775
+ silent doautocmd User BufLeaveRails
776
+ if a:bang && s:cacheworks()
777
+ let s:cache = {}
778
+ endif
779
+ let i = 1
780
+ let max = bufnr('$')
781
+ while i <= max
782
+ let rr = getbufvar(i,"rails_root")
783
+ if rr != ""
784
+ unlet! s:user_classes_{s:escvar(rr)}
785
+ unlet! s:dbext_type_{s:escvar(rr)}
786
+ call setbufvar(i,"rails_refresh",1)
787
+ endif
788
+ let i = i + 1
789
+ endwhile
790
+ silent doautocmd User BufEnterRails
791
+ endfunction
792
+
793
+ function! s:RefreshBuffer()
794
+ if exists("b:rails_refresh") && b:rails_refresh
795
+ let oldroot = b:rails_root
796
+ unlet! b:rails_root b:rails_use_subversion
797
+ let b:rails_refresh = 0
798
+ call RailsBufInit(oldroot)
799
+ unlet! b:rails_refresh
800
+ endif
801
+ endfunction
802
+
803
+ " }}}1
804
+ " Rake {{{1
805
+
806
+ " Depends: s:rubyexestr, s:sub, s:lastmethodline, s:getopt, s;rquote, s:QuickFixCmdPre, ...
807
+
808
+ " Current directory
809
+ let s:efm='%D(in\ %f),'
810
+ " Failure and Error headers, start a multiline message
811
+ let s:efm=s:efm
812
+ \.'%A\ %\\+%\\d%\\+)\ Failure:,'
813
+ \.'%A\ %\\+%\\d%\\+)\ Error:,'
814
+ \.'%+A'."'".'%.%#'."'".'\ FAILED,'
815
+ " Exclusions
816
+ let s:efm=s:efm
817
+ \.'%C%.%#(eval)%.%#,'
818
+ \.'%C-e:%.%#,'
819
+ \.'%C%.%#/lib/gems/%\\d.%\\d/gems/%.%#,'
820
+ \.'%C%.%#/lib/ruby/%\\d.%\\d/%.%#,'
821
+ \.'%C%.%#/vendor/rails/%.%#,'
822
+ " Specific to template errors
823
+ let s:efm=s:efm
824
+ \.'%C\ %\\+On\ line\ #%l\ of\ %f,'
825
+ \.'%CActionView::TemplateError:\ compile\ error,'
826
+ " stack backtrace is in brackets. if multiple lines, it starts on a new line.
827
+ let s:efm=s:efm
828
+ \.'%Ctest_%.%#(%.%#):%#,'
829
+ \.'%C%.%#\ [%f:%l]:,'
830
+ \.'%C\ \ \ \ [%f:%l:%.%#,'
831
+ \.'%C\ \ \ \ %f:%l:%.%#,'
832
+ \.'%C\ \ \ \ \ %f:%l:%.%#]:,'
833
+ \.'%C\ \ \ \ \ %f:%l:%.%#,'
834
+ " Catch all
835
+ let s:efm=s:efm
836
+ \.'%Z%f:%l:\ %#%m,'
837
+ \.'%Z%f:%l:,'
838
+ \.'%C%m,'
839
+ " Syntax errors in the test itself
840
+ let s:efm=s:efm
841
+ \.'%.%#.rb:%\\d%\\+:in\ `load'."'".':\ %f:%l:\ syntax\ error\\\, %m,'
842
+ \.'%.%#.rb:%\\d%\\+:in\ `load'."'".':\ %f:%l:\ %m,'
843
+ " And required files
844
+ let s:efm=s:efm
845
+ \.'%.%#:in\ `require'."'".':in\ `require'."'".':\ %f:%l:\ syntax\ error\\\, %m,'
846
+ \.'%.%#:in\ `require'."'".':in\ `require'."'".':\ %f:%l:\ %m,'
847
+ " Exclusions
848
+ let s:efm=s:efm
849
+ \.'%-G%.%#/lib/gems/%\\d.%\\d/gems/%.%#,'
850
+ \.'%-G%.%#/lib/ruby/%\\d.%\\d/%.%#,'
851
+ \.'%-G%.%#/vendor/rails/%.%#,'
852
+ \.'%-G%.%#%\\d%\\d:%\\d%\\d:%\\d%\\d%.%#,'
853
+ " Final catch all for one line errors
854
+ let s:efm=s:efm
855
+ \.'%-G%\\s%#from\ %.%#,'
856
+ \.'%f:%l:\ %#%m,'
857
+ " Drop everything else
858
+ let s:efm=s:efm
859
+ \.'%-G%.%#'
860
+
861
+ let s:efm_backtrace='%D(in\ %f),'
862
+ \.'%\\s%#from\ %f:%l:%m,'
863
+ \.'%\\s#{RAILS_ROOT}/%f:%l:\ %#%m,'
864
+ \.'%\\s%#[%f:%l:\ %#%m,'
865
+ \.'%\\s%#%f:%l:\ %#%m'
866
+
867
+ function! s:makewithruby(arg,...)
868
+ if &efm == s:efm
869
+ if a:0 ? a:1 : 1
870
+ setlocal efm=\%-E-e:%.%#,\%+E%f:%l:\ parse\ error,%W%f:%l:\ warning:\ %m,%E%f:%l:in\ %*[^:]:\ %m,%E%f:%l:\ %m,%-C%\tfrom\ %f:%l:in\ %.%#,%-Z%\tfrom\ %f:%l,%-Z%p^,%-G%.%#
871
+ endif
872
+ endif
873
+ let old_make = &makeprg
874
+ let &l:makeprg = s:rubyexestr(a:arg)
875
+ make
876
+ let &l:makeprg = old_make
877
+ endfunction
878
+
879
+ function! s:Rake(bang,arg)
880
+ let oldefm = &efm
881
+ if a:bang
882
+ let &l:errorformat = s:efm_backtrace
883
+ endif
884
+ let t = RailsFileType()
885
+ let arg = a:arg
886
+ if &filetype == "ruby" && arg == '' && g:rails_modelines
887
+ let lnum = s:lastmethodline()
888
+ let str = getline(lnum)."\n".getline(lnum+1)."\n".getline(lnum+2)."\n"
889
+ let pat = '\s\+\zs.\{-\}\ze\%(\n\|\s\s\|#{\@!\|$\)'
890
+ let mat = matchstr(str,'#\s*rake'.pat)
891
+ let mat = s:sub(mat,'\s+$','')
892
+ if mat != ""
893
+ let arg = mat
894
+ endif
895
+ endif
896
+ if arg == ''
897
+ let opt = s:getopt('task','bl')
898
+ if opt != ''
899
+ let arg = opt
900
+ endif
901
+ endif
902
+ let withrubyargs = '-r ./config/boot -r '.s:rquote(RailsRoot().'/config/environment').' -e "puts \%((in \#{Dir.getwd}))" '
903
+ if arg =~# '^\%(stats\|routes\|notes\|db:\%(charset\|collation\|version\)\)\%(:\|$\)'
904
+ " So you can see the output even with an inadequate redirect
905
+ call s:QuickFixCmdPre()
906
+ exe "!".&makeprg." ".arg
907
+ call s:QuickFixCmdPost()
908
+ elseif arg =~ '^preview\>'
909
+ exe 'R'.s:gsub(arg,':','/')
910
+ elseif arg =~ '^runner:'
911
+ let arg = s:sub(arg,'^runner:','')
912
+ let root = matchstr(arg,'%\%(:\w\)*')
913
+ let file = expand(root).matchstr(arg,'%\%(:\w\)*\zs.*')
914
+ if file =~ '[@#].*$'
915
+ let extra = " -- -n ".matchstr(file,'[@#]\zs.*')
916
+ let file = s:sub(file,'[@#].*','')
917
+ else
918
+ let extra = ''
919
+ endif
920
+ if s:hasfile(file) || s:hasfile(file.'.rb')
921
+ call s:makewithruby(withrubyargs.'-r"'.file.'"'.extra,file !~# '_\%(spec\|test\)\%(\.rb\)\=$')
922
+ else
923
+ call s:makewithruby(withrubyargs.'-e '.s:esccmd(s:rquote(arg)))
924
+ endif
925
+ elseif arg == 'run' || arg == 'runner'
926
+ call s:makewithruby(withrubyargs.'-r"'.RailsFilePath().'"',RailsFilePath() !~# '_\%(spec\|test\)\%(\.rb\)\=$')
927
+ elseif arg =~ '^run:'
928
+ let arg = s:sub(arg,'^run:','')
929
+ let arg = s:sub(arg,'^%:h',expand('%:h'))
930
+ let arg = s:sub(arg,'^%(\%|$|[@#]@=)',expand('%'))
931
+ let arg = s:sub(arg,'[@#](\w+)$',' -- -n\1')
932
+ call s:makewithruby(withrubyargs.'-r'.arg,arg !~# '_\%(spec\|test\)\.rb$')
933
+ elseif arg != ''
934
+ exe 'make '.arg
935
+ elseif t =~ '^task\>'
936
+ let lnum = s:lastmethodline()
937
+ let line = getline(lnum)
938
+ " We can't grab the namespace so only run tasks at the start of the line
939
+ if line =~ '^\%(task\|file\)\>'
940
+ exe 'make '.s:lastmethod()
941
+ else
942
+ make
943
+ endif
944
+ elseif t =~ '^spec\>'
945
+ if RailsFilePath() =~# '\<spec/spec_helper\.rb$'
946
+ make spec SPEC_OPTS=
947
+ elseif search('\C^\s*\(describe\|context\)\>','bWnc') > search('\C^end\>','bWn')
948
+ exe 'make spec SPEC="%:p" SPEC_OPTS=--line='.line('.')
949
+ else
950
+ make spec SPEC="%:p" SPEC_OPTS=
951
+ endif
952
+ elseif t =~ '^test\>'
953
+ let meth = s:lastmethod()
954
+ if meth =~ '^test_'
955
+ let call = " -n".meth.""
956
+ else
957
+ let call = ""
958
+ endif
959
+ if t =~ '^test-\%(unit\|functional\|integration\)$'
960
+ exe "make ".s:sub(s:gsub(t,'-',':'),'unit$|functional$','&s')." TEST=\"%:p\"".s:sub(call,'^ ',' TESTOPTS=')
961
+ elseif RailsFilePath() =~# '\<test/test_helper\.rb$'
962
+ make test
963
+ else
964
+ call s:makewithruby('-e "puts \%((in \#{Dir.getwd}))" -r"%:p" -- '.call,0)
965
+ endif
966
+ elseif t=~ '^\%(db-\)\=migration\>' && RailsFilePath() !~# '\<db/schema\.rb$'
967
+ let ver = matchstr(RailsFilePath(),'\<db/migrate/0*\zs\d*\ze_')
968
+ if ver != ""
969
+ exe "make db:migrate VERSION=".ver
970
+ else
971
+ make db:migrate
972
+ endif
973
+ elseif t=~ '^model\>'
974
+ make test:units TEST="%:p:r:s?[\/]app[\/]models[\/]?/test/unit/?_test.rb"
975
+ elseif t=~ '^api\>'
976
+ make test:units TEST="%:p:r:s?[\/]app[\/]apis[\/]?/test/functional/?_test.rb"
977
+ elseif t=~ '^\<\%(controller\|helper\|view\)\>'
978
+ if RailsFilePath() =~ '\<app/' && s:controller() !~# '^\%(application\)\=$'
979
+ exe 'make test:functionals TEST="'.s:ra().'/test/functional/'.s:controller().'_controller_test.rb"'
980
+ else
981
+ make test:functionals
982
+ endif
983
+ else
984
+ make
985
+ endif
986
+ if oldefm != ''
987
+ let &l:errorformat = oldefm
988
+ endif
989
+ endfunction
990
+
991
+ function! s:RakeComplete(A,L,P)
992
+ return g:rails_rake_tasks
993
+ endfunction
994
+
995
+ " }}}1
996
+ " Preview {{{1
997
+
998
+ " Depends: s:getopt, s:sub, s:controller, s:lastmethod
999
+ " Provides: s:initOpenURL
1000
+
1001
+ function! s:initOpenURL()
1002
+ if !exists(":OpenURL")
1003
+ if has("gui_mac") || has("gui_macvim") || exists("$SECURITYSESSIONID")
1004
+ command -bar -nargs=1 OpenURL :!open <args>
1005
+ elseif has("gui_win32")
1006
+ command -bar -nargs=1 OpenURL :!start cmd /cstart /b <args>
1007
+ elseif executable("sensible-browser")
1008
+ command -bar -nargs=1 OpenURL :!sensible-browser <args>
1009
+ endif
1010
+ endif
1011
+ endfunction
1012
+
1013
+ " This returns the URI with a trailing newline if it is found
1014
+ function! s:scanlineforuri(lnum)
1015
+ let line = getline(a:lnum)
1016
+ let url = matchstr(line,"\\v\\C%(%(GET|PUT|POST|DELETE)\\s+|\w+:/)/[^ \n\r\t<>\"]*[^] .,;\n\r\t<>\":]")
1017
+ if url =~ '\C^\u\+\s\+'
1018
+ let method = matchstr(url,'^\u\+')
1019
+ let url = matchstr(url,'\s\+\zs.*')
1020
+ if method !=? "GET"
1021
+ if url =~ '?'
1022
+ let url = url.'&'
1023
+ else
1024
+ let url = url.'?'
1025
+ endif
1026
+ let url = url.'_method='.tolower(method)
1027
+ endif
1028
+ endif
1029
+ if url != ""
1030
+ return s:sub(url,'^/','') . "\n"
1031
+ else
1032
+ return ""
1033
+ endif
1034
+ endfunction
1035
+
1036
+ function! s:defaultpreview()
1037
+ let ret = ''
1038
+ if s:getopt('preview','l') != ''
1039
+ let uri = s:getopt('preview','l')
1040
+ elseif s:controller() != '' && s:controller() != 'application' && RailsFilePath() !~ '^public/'
1041
+ if RailsFileType() =~ '^controller\>'
1042
+ let start = s:lastmethodline() - 1
1043
+ if start + 1
1044
+ while getline(start) =~ '^\s*\%(#.*\)\=$'
1045
+ let ret = s:scanlineforuri(start).ret
1046
+ let start = start - 1
1047
+ endwhile
1048
+ let ret = ret.s:controller().'/'.s:lastmethod().'/'
1049
+ else
1050
+ let ret = ret.s:controller().'/'
1051
+ endif
1052
+ elseif s:getopt('preview','b') != ''
1053
+ let ret = s:getopt('preview','b')
1054
+ elseif RailsFileType() =~ '^view\%(-partial\|-layout\)\@!'
1055
+ let ret = ret.s:controller().'/'.expand('%:t:r:r').'/'
1056
+ endif
1057
+ elseif s:getopt('preview','b') != ''
1058
+ let uri = s:getopt('preview','b')
1059
+ elseif RailsFilePath() =~ '^public/'
1060
+ let ret = s:sub(RailsFilePath(),'^public/','')
1061
+ elseif s:getopt('preview','ag') != ''
1062
+ let ret = s:getopt('preview','ag')
1063
+ endif
1064
+ return ret
1065
+ endfunction
1066
+
1067
+ function! s:Preview(bang,arg)
1068
+ let root = s:getopt("root_url")
1069
+ if root == ''
1070
+ let root = s:getopt("url")
1071
+ endif
1072
+ let root = s:sub(root,'/$','')
1073
+ if a:arg =~ '://'
1074
+ let uri = a:arg
1075
+ elseif a:arg != ''
1076
+ let uri = root.'/'.s:sub(a:arg,'^/','')
1077
+ else
1078
+ let uri = matchstr(s:defaultpreview(),'.\{-\}\%(\n\@=\|$\)')
1079
+ let uri = root.'/'.s:sub(s:sub(uri,'^/',''),'/$','')
1080
+ endif
1081
+ call s:initOpenURL()
1082
+ if exists(':OpenURL') && !a:bang
1083
+ exe 'OpenURL '.uri
1084
+ else
1085
+ " Work around bug where URLs ending in / get handled as FTP
1086
+ let url = uri.(uri =~ '/$' ? '?' : '')
1087
+ silent exe 'pedit '.url
1088
+ wincmd w
1089
+ if &filetype == ''
1090
+ if uri =~ '\.css$'
1091
+ setlocal filetype=css
1092
+ elseif uri =~ '\.js$'
1093
+ setlocal filetype=javascript
1094
+ elseif getline(1) =~ '^\s*<'
1095
+ setlocal filetype=xhtml
1096
+ endif
1097
+ endif
1098
+ call RailsBufInit(RailsRoot())
1099
+ map <buffer> <silent> q :bwipe<CR>
1100
+ wincmd p
1101
+ if !a:bang
1102
+ call s:warn("Define a :OpenURL command to use a browser")
1103
+ endif
1104
+ endif
1105
+ endfunction
1106
+
1107
+ function! s:PreviewComplete(A,L,P)
1108
+ return s:defaultpreview()
1109
+ endfunction
1110
+
1111
+ " }}}1
1112
+ " Script Wrappers {{{1
1113
+
1114
+ " Depends: s:rquote, s:rubyexebg, s:rubyexe, s:rubyexestr, s:sub, s:getopt, s:usesubversion, s:user_classes_..., ..., s:pluginList, ...
1115
+
1116
+ function! s:BufScriptWrappers()
1117
+ Rcommand! -buffer -bar -nargs=+ -complete=custom,s:ScriptComplete Rscript :call s:Script(<bang>0,<f-args>)
1118
+ Rcommand! -buffer -bar -nargs=* -complete=custom,s:ConsoleComplete Rconsole :call s:Console(<bang>0,'console',<f-args>)
1119
+ "Rcommand! -buffer -bar -nargs=* Rbreakpointer :call s:Console(<bang>0,'breakpointer',<f-args>)
1120
+ Rcommand! -buffer -bar -nargs=* -complete=custom,s:GenerateComplete Rgenerate :call s:Generate(<bang>0,<f-args>)
1121
+ Rcommand! -buffer -bar -nargs=* -complete=custom,s:DestroyComplete Rdestroy :call s:Destroy(<bang>0,<f-args>)
1122
+ Rcommand! -buffer -bar -nargs=? -bang -complete=custom,s:ServerComplete Rserver :call s:Server(<bang>0,<q-args>)
1123
+ Rcommand! -buffer -bang -nargs=1 -range=0 -complete=custom,s:RubyComplete Rrunner :call s:Runner(<bang>0 ? -2 : (<count>==<line2>?<count>:-1),<f-args>)
1124
+ Rcommand! -buffer -nargs=1 -range=0 -complete=custom,s:RubyComplete Rp :call s:Runner(<count>==<line2>?<count>:-1,'p begin '.<f-args>.' end')
1125
+ Rcommand! -buffer -nargs=1 -range=0 -complete=custom,s:RubyComplete Rpp :call s:Runner(<count>==<line2>?<count>:-1,'require %{pp}; pp begin '.<f-args>.' end')
1126
+ Rcommand! -buffer -nargs=1 -range=0 -complete=custom,s:RubyComplete Ry :call s:Runner(<count>==<line2>?<count>:-1,'y begin '.<f-args>.' end')
1127
+ endfunction
1128
+
1129
+ function! s:Script(bang,cmd,...)
1130
+ let str = ""
1131
+ let c = 1
1132
+ while c <= a:0
1133
+ let str = str . " " . s:rquote(a:{c})
1134
+ let c = c + 1
1135
+ endwhile
1136
+ if a:bang
1137
+ call s:rubyexebg(s:rquote("script/".a:cmd).str)
1138
+ else
1139
+ call s:rubyexe(s:rquote("script/".a:cmd).str)
1140
+ endif
1141
+ endfunction
1142
+
1143
+ function! s:Runner(count,args)
1144
+ if a:count == -2
1145
+ call s:Script(a:bang,"runner",a:args)
1146
+ else
1147
+ let str = s:rubyexestr('-r./config/boot -e "require '."'commands/runner'".'" '.s:rquote(a:args))
1148
+ let res = s:sub(system(str),'\n$','')
1149
+ if a:count < 0
1150
+ echo res
1151
+ else
1152
+ exe a:count.'put =res'
1153
+ endif
1154
+ endif
1155
+ endfunction
1156
+
1157
+ function! s:Console(bang,cmd,...)
1158
+ let str = ""
1159
+ let c = 1
1160
+ while c <= a:0
1161
+ let str = str . " " . s:rquote(a:{c})
1162
+ let c = c + 1
1163
+ endwhile
1164
+ call s:rubyexebg(s:rquote("script/".a:cmd).str)
1165
+ endfunction
1166
+
1167
+ function! s:getpidfor(bind,port)
1168
+ if has("win32") || has("win64")
1169
+ let netstat = system("netstat -anop tcp")
1170
+ let pid = matchstr(netstat,'\<'.a:bind.':'.a:port.'\>.\{-\}LISTENING\s\+\zs\d\+')
1171
+ elseif executable('lsof')
1172
+ let pid = system("lsof -i 4tcp@".a:bind.':'.a:port."|grep LISTEN|awk '{print $2}'")
1173
+ let pid = s:sub(pid,'\n','')
1174
+ else
1175
+ let pid = ""
1176
+ endif
1177
+ return pid
1178
+ endfunction
1179
+
1180
+ function! s:Server(bang,arg)
1181
+ let port = matchstr(a:arg,'\%(-p\|--port=\=\)\s*\zs\d\+')
1182
+ if port == ''
1183
+ let port = "3000"
1184
+ endif
1185
+ " TODO: Extract bind argument
1186
+ let bind = "0.0.0.0"
1187
+ if a:bang && executable("ruby")
1188
+ let pid = s:getpidfor(bind,port)
1189
+ if pid =~ '^\d\+$'
1190
+ echo "Killing server with pid ".pid
1191
+ if !has("win32")
1192
+ call system("ruby -e 'Process.kill(:TERM,".pid.")'")
1193
+ sleep 100m
1194
+ endif
1195
+ call system("ruby -e 'Process.kill(9,".pid.")'")
1196
+ sleep 100m
1197
+ endif
1198
+ if a:arg == "-"
1199
+ return
1200
+ endif
1201
+ endif
1202
+ if has("win32") || has("win64") || (exists("$STY") && !has("gui_running") && s:getopt("gnu_screen","abg") && executable("screen"))
1203
+ call s:rubyexebg(s:rquote("script/server")." ".a:arg)
1204
+ else
1205
+ "--daemon would be more descriptive but lighttpd does not support it
1206
+ call s:rubyexe(s:rquote("script/server")." ".a:arg." -d")
1207
+ endif
1208
+ call s:setopt('a:root_url','http://'.(bind=='0.0.0.0'?'localhost': bind).':'.port.'/')
1209
+ endfunction
1210
+
1211
+ function! s:Destroy(bang,...)
1212
+ if a:0 == 0
1213
+ call s:rubyexe("script/destroy")
1214
+ return
1215
+ elseif a:0 == 1
1216
+ call s:rubyexe("script/destroy ".s:rquote(a:1))
1217
+ return
1218
+ endif
1219
+ let str = ""
1220
+ let c = 1
1221
+ while c <= a:0
1222
+ let str = str . " " . s:rquote(a:{c})
1223
+ let c = c + 1
1224
+ endwhile
1225
+ call s:rubyexe(s:rquote("script/destroy").str.(s:usesubversion()?' -c':''))
1226
+ unlet! s:user_classes_{s:rv()}
1227
+ endfunction
1228
+
1229
+ function! s:Generate(bang,...)
1230
+ if a:0 == 0
1231
+ call s:rubyexe("script/generate")
1232
+ return
1233
+ elseif a:0 == 1
1234
+ call s:rubyexe("script/generate ".s:rquote(a:1))
1235
+ return
1236
+ endif
1237
+ let target = s:rquote(a:1)
1238
+ let str = ""
1239
+ let c = 2
1240
+ while c <= a:0
1241
+ let str = str . " " . s:rquote(a:{c})
1242
+ let c = c + 1
1243
+ endwhile
1244
+ if str !~ '-p\>' && str !~ '--pretend\>'
1245
+ let execstr = s:rubyexestr('-r./config/boot -e "require '."'commands/generate'".'" -- '.target." -p -f".str)
1246
+ let res = system(execstr)
1247
+ let file = matchstr(res,'\s\+\%(create\|force\)\s\+\zs\f\+\.rb\ze\n')
1248
+ if file == ""
1249
+ let file = matchstr(res,'\s\+\%(exists\)\s\+\zs\f\+\.rb\ze\n')
1250
+ endif
1251
+ "echo file
1252
+ else
1253
+ let file = ""
1254
+ endif
1255
+ if !s:rubyexe("script/generate ".target.(s:usesubversion()?' -c':'').str) && file != ""
1256
+ unlet! s:user_classes_{s:rv()}
1257
+ "exe "edit ".s:ra()."/".file
1258
+ edit `=RailsRoot().'/'.file`
1259
+ endif
1260
+ endfunction
1261
+
1262
+ function! s:ScriptComplete(ArgLead,CmdLine,P)
1263
+ let cmd = s:sub(a:CmdLine,'^\u\w*\s+','')
1264
+ let P = a:P - strlen(a:CmdLine)+strlen(cmd)
1265
+ if cmd !~ '^[ A-Za-z0-9_=-]*$'
1266
+ " You're on your own, bud
1267
+ return ""
1268
+ elseif cmd =~ '^\w*$'
1269
+ return "about\nconsole\ndestroy\ngenerate\nperformance/benchmarker\nperformance/profiler\nplugin\nproccess/reaper\nprocess/spawner\nrunner\nserver"
1270
+ elseif cmd =~ '^\%(plugin\)\s\+'.a:ArgLead.'$'
1271
+ return "discover\nlist\ninstall\nupdate\nremove\nsource\nunsource\nsources"
1272
+ elseif cmd =~ '\%(plugin\)\s\+\%(install\|remove\)\s\+'.a:ArgLead.'$' || cmd =~ '\%(generate\|destroy\)\s\+plugin\s\+'.a:ArgLead.'$'
1273
+ return s:pluginList(a:ArgLead,a:CmdLine,a:P)
1274
+ elseif cmd =~ '^\%(generate\|destroy\)\s\+'.a:ArgLead.'$'
1275
+ return g:rails_generators
1276
+ elseif cmd =~ '^\%(generate\|destroy\)\s\+\w\+\s\+'.a:ArgLead.'$'
1277
+ let target = matchstr(cmd,'^\w\+\s\+\zs\w\+\ze\s\+')
1278
+ let pattern = "" " TODO
1279
+ if target =~# '^\%(\w*_\)\=controller$'
1280
+ return s:sub(s:controllerList(pattern,"",""),'^application\n=','')
1281
+ elseif target =~# '^\%(\w*_\)\=model$' || target =~# '^scaffold\%(_resource\)\=$' || target == 'mailer'
1282
+ return s:modelList(pattern,"","")
1283
+ elseif target == 'migration' || target == 'session_migration'
1284
+ return s:migrationList(pattern,"","")
1285
+ elseif target == 'integration_test'
1286
+ return s:integrationtestList(pattern,"","")
1287
+ elseif target == 'observer'
1288
+ " script/generate observer is in Edge Rails
1289
+ let observers = s:observerList(pattern,"","")
1290
+ let models = s:modelList(pattern,"","")
1291
+ if cmd =~ '^destroy\>'
1292
+ let models = ""
1293
+ endif
1294
+ while strlen(models) > 0
1295
+ let tmp = matchstr(models."\n",'.\{-\}\ze\n')
1296
+ let models = s:sub(models,'.{-}%(\n|$)','')
1297
+ if stridx("\n".observers."\n","\n".tmp."\n") == -1 && tmp !~'_observer$'
1298
+ let observers = observers."\n".tmp
1299
+ endif
1300
+ endwhile
1301
+ return s:sub(observers,'^\n','')
1302
+ elseif target == 'web_service'
1303
+ return s:apiList(pattern,"","")
1304
+ else
1305
+ return ""
1306
+ endif
1307
+ elseif cmd =~ '^\%(generate\|destroy\)\s\+scaffold\s\+\w\+\s\+'.a:ArgLead.'$'
1308
+ return s:sub(s:controllerList("","",""),'^application\n=','')
1309
+ elseif cmd =~ '^\%(console\)\s\+\(--\=\w\+\s\+\)\='.a:ArgLead."$"
1310
+ return s:environments()."\n-s\n--sandbox"
1311
+ elseif cmd =~ '^\%(server\)\s\+.*-e\s\+'.a:ArgLead."$"
1312
+ return s:environments()
1313
+ elseif cmd =~ '^\%(server\)\s\+'
1314
+ return "-p\n-b\n-e\n-m\n-d\n-u\n-c\n-h\n--port=\n--binding=\n--environment=\n--mime-types=\n--daemon\n--debugger\n--charset=\n--help\n"
1315
+ endif
1316
+ return ""
1317
+ " return s:relglob(RailsRoot()."/script/",a:ArgLead."*")
1318
+ endfunction
1319
+
1320
+ function! s:CustomComplete(A,L,P,cmd)
1321
+ let L = "Rscript ".a:cmd." ".s:sub(a:L,'^\h\w*\s+','')
1322
+ let P = a:P - strlen(a:L) + strlen(L)
1323
+ return s:ScriptComplete(a:A,L,P)
1324
+ endfunction
1325
+
1326
+ function! s:ServerComplete(A,L,P)
1327
+ return s:CustomComplete(a:A,a:L,a:P,"server")
1328
+ endfunction
1329
+
1330
+ function! s:ConsoleComplete(A,L,P)
1331
+ return s:CustomComplete(a:A,a:L,a:P,"console")
1332
+ endfunction
1333
+
1334
+ function! s:GenerateComplete(A,L,P)
1335
+ return s:CustomComplete(a:A,a:L,a:P,"generate")
1336
+ endfunction
1337
+
1338
+ function! s:DestroyComplete(A,L,P)
1339
+ return s:CustomComplete(a:A,a:L,a:P,"destroy")
1340
+ endfunction
1341
+
1342
+ function! s:RubyComplete(A,L,R)
1343
+ return s:gsub(RailsUserClasses(),' ','\n')."\nActiveRecord::Base"
1344
+ endfunction
1345
+
1346
+ " }}}1
1347
+ " Navigation {{{1
1348
+
1349
+ function! s:BufNavCommands()
1350
+ " Vim 6.2 chokes on script local completion functions (e.g., s:FindList).
1351
+ " :Rcommand! is a thin wrapper arround :command! which works around this
1352
+ Rcommand! -buffer -bar -nargs=? -complete=custom,s:DirList Rcd :cd `=RailsRoot().'/'.<q-args>`
1353
+ Rcommand! -buffer -bar -nargs=? -complete=custom,s:DirList Rlcd :lcd `=RailsRoot().'/'.<q-args>`
1354
+ Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList Rfind :call s:Find(<bang>0,<count>,'' ,<f-args>)
1355
+ Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList REfind :call s:Find(<bang>0,<count>,'E',<f-args>)
1356
+ Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList RSfind :call s:Find(<bang>0,<count>,'S',<f-args>)
1357
+ Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList RVfind :call s:Find(<bang>0,<count>,'V',<f-args>)
1358
+ Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList RTfind :call s:Find(<bang>0,<count>,'T',<f-args>)
1359
+ Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList Rsfind :<count>RSfind<bang> <args>
1360
+ Rcommand! -buffer -bar -nargs=* -count=1 -complete=custom,s:FindList Rtabfind :<count>RTfind<bang> <args>
1361
+ Rcommand! -buffer -bar -nargs=* -bang -complete=custom,s:EditList Redit :call s:Edit(<bang>0,<count>,'' ,<f-args>)
1362
+ Rcommand! -buffer -bar -nargs=* -bang -complete=custom,s:EditList REedit :call s:Edit(<bang>0,<count>,'E',<f-args>)
1363
+ Rcommand! -buffer -bar -nargs=* -bang -complete=custom,s:EditList RSedit :call s:Edit(<bang>0,<count>,'S',<f-args>)
1364
+ Rcommand! -buffer -bar -nargs=* -bang -complete=custom,s:EditList RVedit :call s:Edit(<bang>0,<count>,'V',<f-args>)
1365
+ Rcommand! -buffer -bar -nargs=* -bang -complete=custom,s:EditList RTedit :call s:Edit(<bang>0,<count>,'T',<f-args>)
1366
+ command! -buffer -bar -nargs=0 A :call s:Alternate(<bang>0,"")
1367
+ command! -buffer -bar -nargs=0 AE :call s:Alternate(<bang>0,"E")
1368
+ command! -buffer -bar -nargs=0 AS :call s:Alternate(<bang>0,"S")
1369
+ command! -buffer -bar -nargs=0 AV :call s:Alternate(<bang>0,"V")
1370
+ command! -buffer -bar -nargs=0 AT :call s:Alternate(<bang>0,"T")
1371
+ command! -buffer -bar -nargs=0 AN :call s:Related(<bang>0,"")
1372
+ command! -buffer -bar -nargs=0 R :call s:Related(<bang>0,"")
1373
+ command! -buffer -bar -nargs=0 RE :call s:Related(<bang>0,"E")
1374
+ command! -buffer -bar -nargs=0 RS :call s:Related(<bang>0,"S")
1375
+ command! -buffer -bar -nargs=0 RV :call s:Related(<bang>0,"V")
1376
+ command! -buffer -bar -nargs=0 RT :call s:Related(<bang>0,"T")
1377
+ "command! -buffer -bar -nargs=0 RN :call s:Alternate(<bang>0,"")
1378
+ endfunction
1379
+
1380
+ function! s:djump(def)
1381
+ let def = s:sub(a:def,'^[@#]','')
1382
+ if def != ''
1383
+ let ext = matchstr(def,'\.\zs.*')
1384
+ let def = matchstr(def,'[^.]*')
1385
+ let v:errmsg = ''
1386
+ silent! exe "djump ".def
1387
+ if ext != '' && (v:errmsg == '' || v:errmsg =~ '^E387')
1388
+ let rpat = '\C^\s*respond_to\s*\%(\<do\|{\)\s*|\zs\h\k*\ze|'
1389
+ let end = s:endof(line('.'))
1390
+ let rline = search(rpat,'',end)
1391
+ if rline > 0
1392
+ "call cursor(rline,1)
1393
+ let variable = matchstr(getline(rline),rpat)
1394
+ let success = search('\C^\s*'.variable.'\s*\.\s*\zs'.ext.'\>','',end)
1395
+ if !success
1396
+ silent! exe "djump ".def
1397
+ endif
1398
+ endif
1399
+ endif
1400
+ endif
1401
+ endfunction
1402
+
1403
+ function! s:Find(bang,count,arg,...)
1404
+ let cmd = a:arg . (a:bang ? '!' : '')
1405
+ let str = ""
1406
+ if a:0
1407
+ let i = 1
1408
+ while i < a:0
1409
+ let str = str . s:escarg(a:{i}) . " "
1410
+ let i = i + 1
1411
+ endwhile
1412
+ let file = a:{i}
1413
+ let tail = matchstr(file,'[@#].*$')
1414
+ if tail != ""
1415
+ let file = s:sub(file,'[@#].*$','')
1416
+ endif
1417
+ if file != ""
1418
+ let file = s:RailsIncludefind(file)
1419
+ endif
1420
+ else
1421
+ let file = s:RailsFind()
1422
+ let tail = ""
1423
+ endif
1424
+ if file =~ '^\%(app\|config\|db\|public\|spec\|test\|vendor\)/.*\.' || !a:0 || 1
1425
+ call s:findedit((a:count==1?'' : a:count).cmd,file.tail,str)
1426
+ else
1427
+ " Old way
1428
+ let fcmd = (a:count==1?'' : a:count).s:findcmdfor(cmd)
1429
+ let fcmd = s:sub(fcmd,'(\d+)vert ','vert \1')
1430
+ if file != ""
1431
+ exe fcmd.' '.str.s:escarg(file)
1432
+ endif
1433
+ call s:djump(tail)
1434
+ endif
1435
+ endfunction
1436
+
1437
+ function! s:Edit(bang,count,arg,...)
1438
+ let cmd = a:arg . (a:bang ? '!' : '')
1439
+ if a:0
1440
+ let str = ""
1441
+ let i = 1
1442
+ while i < a:0
1443
+ "let str = str . s:escarg(a:{i}) . " "
1444
+ let str = str . "`=a:".i."` "
1445
+ let i = i + 1
1446
+ endwhile
1447
+ let file = a:{i}
1448
+ call s:findedit(s:editcmdfor(cmd),file,str)
1449
+ else
1450
+ exe s:editcmdfor(cmd)
1451
+ endif
1452
+ endfunction
1453
+
1454
+ function! s:FindList(ArgLead, CmdLine, CursorPos)
1455
+ if exists("*UserFileComplete") " genutils.vim
1456
+ return UserFileComplete(s:RailsIncludefind(a:ArgLead), a:CmdLine, a:CursorPos, 1, &path)
1457
+ else
1458
+ return ""
1459
+ endif
1460
+ endfunction
1461
+
1462
+ function! s:EditList(ArgLead, CmdLine, CursorPos)
1463
+ return s:relglob("",a:ArgLead."*[^~]")
1464
+ endfunction
1465
+
1466
+ function! s:DirList(ArgLead, CmdLine, CursorPos)
1467
+ let all = "\n".s:relglob("",a:ArgLead."*")."\n"
1468
+ let dirs = s:gsub(all,"[^\n]*[^/]\n",'')
1469
+ return s:compact(dirs)
1470
+ endfunction
1471
+
1472
+ function! RailsIncludeexpr()
1473
+ " Is this foolproof?
1474
+ if mode() =~ '[iR]' || expand("<cfile>") != v:fname
1475
+ return s:RailsIncludefind(v:fname)
1476
+ else
1477
+ return s:RailsIncludefind(v:fname,1)
1478
+ endif
1479
+ endfunction
1480
+
1481
+ function! s:linepeak()
1482
+ let line = getline(line("."))
1483
+ let line = s:sub(line,'^(.{'.col(".").'}).*','\1')
1484
+ let line = s:sub(line,'([:"'."'".']|\%[qQ]=[[({<])=\f*$','')
1485
+ return line
1486
+ endfunction
1487
+
1488
+ function! s:matchcursor(pat)
1489
+ let line = getline(".")
1490
+ let lastend = 0
1491
+ while lastend >= 0
1492
+ let beg = match(line,'\C'.a:pat,lastend)
1493
+ let end = matchend(line,'\C'.a:pat,lastend)
1494
+ if beg < col(".") && end >= col(".")
1495
+ return matchstr(line,'\C'.a:pat,lastend)
1496
+ endif
1497
+ let lastend = end
1498
+ endwhile
1499
+ return ""
1500
+ endfunction
1501
+
1502
+ function! s:findit(pat,repl)
1503
+ let res = s:matchcursor(a:pat)
1504
+ if res != ""
1505
+ return substitute(res,'\C'.a:pat,a:repl,'')
1506
+ else
1507
+ return ""
1508
+ endif
1509
+ endfunction
1510
+
1511
+ function! s:findamethod(func,repl)
1512
+ return s:findit('\s*\<\%('.a:func.'\)\s*(\=\s*[@:'."'".'"]\(\f\+\)\>.\=',a:repl)
1513
+ endfunction
1514
+
1515
+ function! s:findasymbol(sym,repl)
1516
+ return s:findit('\s*:\%('.a:sym.'\)\s*=>\s*(\=\s*[@:'."'".'"]\(\f\+\)\>.\=',a:repl)
1517
+ endfunction
1518
+
1519
+ function! s:findfromview(func,repl)
1520
+ return s:findit('\s*\%(<%\)\==\=\s*\<\%('.a:func.'\)\s*(\=\s*[@:'."'".'"]\(\f\+\)\>['."'".'"]\=\s*\%(%>\s*\)\=',a:repl)
1521
+ endfunction
1522
+
1523
+ function! s:RailsFind()
1524
+ if filereadable(expand("<cfile>"))
1525
+ return expand("<cfile>")
1526
+ endif
1527
+ " UGH
1528
+ let format = s:format('html')
1529
+ let res = s:findit('\v\s*<require\s*\(=\s*File.dirname\(__FILE__\)\s*\+\s*[:'."'".'"](\f+)>.=',expand('%:h').'/\1')
1530
+ if res != ""|return res.(fnamemodify(res,':e') == '' ? '.rb' : '')|endif
1531
+ let res = s:findit('\v<File.dirname\(__FILE__\)\s*\+\s*[:'."'".'"](\f+)>['."'".'"]=',expand('%:h').'\1')
1532
+ if res != ""|return res|endif
1533
+ let res = s:underscore(s:findit('\v\s*<%(include|extend)\(=\s*<(\f+)>','\1'))
1534
+ if res != ""|return res.".rb"|endif
1535
+ let res = s:findamethod('require','\1')
1536
+ if res != ""|return res.(fnamemodify(res,':e') == '' ? '.rb' : '')|endif
1537
+ let res = s:findamethod('belongs_to\|has_one\|composed_of\|validates_associated\|scaffold','app/models/\1.rb')
1538
+ if res != ""|return res|endif
1539
+ let res = s:singularize(s:findamethod('has_many\|has_and_belongs_to_many','app/models/\1'))
1540
+ if res != ""|return res.".rb"|endif
1541
+ let res = s:singularize(s:findamethod('create_table\|change_table\|drop_table\|add_column\|rename_column\|remove_column\|add_index','app/models/\1'))
1542
+ if res != ""|return res.".rb"|endif
1543
+ let res = s:singularize(s:findasymbol('through','app/models/\1'))
1544
+ if res != ""|return res.".rb"|endif
1545
+ let res = s:findamethod('fixtures','fixtures/\1')
1546
+ if res != ""
1547
+ return RailsFilePath() =~ '\<spec/' ? 'spec/'.res : res
1548
+ endif
1549
+ let res = s:findamethod('map\.resources','app/controllers/\1_controller.rb')
1550
+ if res != ""|return res|endif
1551
+ let res = s:findamethod('layout','\=s:findlayout(submatch(1))')
1552
+ if res != ""|return res|endif
1553
+ let res = s:findasymbol('layout','\=s:findlayout(submatch(1))')
1554
+ if res != ""|return res|endif
1555
+ let res = s:findamethod('helper','app/helpers/\1_helper.rb')
1556
+ if res != ""|return res|endif
1557
+ let res = s:findasymbol('controller','app/controllers/\1_controller.rb')
1558
+ if res != ""|return res|endif
1559
+ let res = s:findasymbol('action','\1')
1560
+ if res != ""|return res|endif
1561
+ let res = s:findasymbol('template','app/views/\1')
1562
+ if res != ""|return res|endif
1563
+ let res = s:sub(s:sub(s:findasymbol('partial','\1'),'^/',''),'\k+$','_&')
1564
+ if res != ""|return res."\n".s:findview(res)|endif
1565
+ let res = s:sub(s:sub(s:findfromview('render\s*(\=\s*:partial\s\+=>\s*','\1'),'^/',''),'\k+$','_&')
1566
+ if res != ""|return res."\n".s:findview(res)|endif
1567
+ let res = s:findamethod('render\s*:\%(template\|action\)\s\+=>\s*','\1.'.format.'\n\1')
1568
+ if res != ""|return res|endif
1569
+ let res = s:findamethod('redirect_to\s*(\=\s*:action\s\+=>\s*','\1')
1570
+ if res != ""|return res|endif
1571
+ let res = s:findfromview('stylesheet_link_tag','public/stylesheets/\1.css')
1572
+ if res != ""|return res|endif
1573
+ let res = s:sub(s:findfromview('javascript_include_tag','public/javascripts/\1.js'),'/defaults>','/application')
1574
+ if res != ""|return res|endif
1575
+ if RailsFileType() =~ '^controller\>'
1576
+ let contr = s:controller()
1577
+ let view = s:findit('\s*\<def\s\+\(\k\+\)\>(\=','/\1')
1578
+ let res = s:findview(contr.'/'.view)
1579
+ if res != ""|return res|endif
1580
+ endif
1581
+ let isf_keep = &isfname
1582
+ set isfname=@,48-57,/,-,_,: ",\",'
1583
+ " TODO: grab visual selection in visual mode
1584
+ let cfile = expand("<cfile>")
1585
+ let res = s:RailsIncludefind(cfile,1)
1586
+ let &isfname = isf_keep
1587
+ return res
1588
+ endfunction
1589
+
1590
+ function! s:initnamedroutes()
1591
+ if s:cacheneeds("named_routes")
1592
+ let exec = "ActionController::Routing::Routes.named_routes.each {|n,r| puts %{#{n} app/controllers/#{r.requirements[:controller]}_controller.rb##{r.requirements[:action]}}}"
1593
+ let string = s:railseval(exec)
1594
+ let routes = {}
1595
+ let list = split(string,"\n")
1596
+ let i = 0
1597
+ " If we use for, Vim 6.2 dumbly treats endfor like endfunction
1598
+ while i < len(list)
1599
+ let route = split(list[i]," ")
1600
+ let name = route[0]
1601
+ let routes[name] = route[1]
1602
+ let i = i + 1
1603
+ endwhile
1604
+ call s:cacheset("named_routes",routes)
1605
+ endif
1606
+ endfunction
1607
+
1608
+ function! s:namedroutefile(route)
1609
+ call s:initnamedroutes()
1610
+ if s:cachehas("named_routes") && has_key(s:cache("named_routes"),a:route)
1611
+ return s:cache("named_routes")[a:route]
1612
+ endif
1613
+ return ""
1614
+ endfunction
1615
+
1616
+ function! RailsNamedRoutes()
1617
+ call s:initnamedroutes()
1618
+ if s:cachehas("named_routes")
1619
+ return keys(s:cache("named_routes"))
1620
+ else
1621
+ " Dead code
1622
+ if s:cacheneeds("route_names")
1623
+ let lines = readfile(RailsRoot()."/config/routes.rb")
1624
+ let plurals = map(filter(copy(lines),'v:val =~# "^ map\\.resources\\s\\+:\\w"'),'matchstr(v:val,"^ map\\.resources\\=\\s\\+:\\zs\\w\\+")')
1625
+ let singulars = map(copy(plurals),'s:singularize(v:val)')
1626
+ let extras = map(copy(singulars),'"new_".v:val')+map(copy(singulars),'"edit_".v:val')
1627
+ let all = plurals + singulars + extras
1628
+ let named = map(filter(copy(lines),'v:val =~# "^ map\\.\\%(connect\\>\\|resources\\=\\>\\)\\@!\\w\\+"'),'matchstr(v:val,"^ map\\.\\zs\\w\\+")')
1629
+ call s:cacheset("route_names",named+all+map(copy(all),'"formatted_".v:val'))
1630
+ endif
1631
+ if s:cachehas("route_names")
1632
+ return s:cache("route_names")
1633
+ endif
1634
+ endif
1635
+ endfunction
1636
+
1637
+ function! s:RailsIncludefind(str,...)
1638
+ if a:str == "ApplicationController"
1639
+ return "app/controllers/application.rb"
1640
+ elseif a:str == "Test::Unit::TestCase"
1641
+ return "test/unit/testcase.rb"
1642
+ elseif a:str == "<%="
1643
+ " Probably a silly idea
1644
+ return "action_view.rb"
1645
+ endif
1646
+ let str = a:str
1647
+ if a:0 == 1
1648
+ " Get the text before the filename under the cursor.
1649
+ " We'll cheat and peak at this in a bit
1650
+ let line = s:linepeak()
1651
+ let line = s:sub(line,'([:"'."'".']|\%[qQ]=[[({<])=\f*$','')
1652
+ else
1653
+ let line = ""
1654
+ endif
1655
+ let str = s:sub(str,'^\s*','')
1656
+ let str = s:sub(str,'\s*$','')
1657
+ let str = s:sub(str,'^[:@]','')
1658
+ "let str = s:sub(str,"\\([\"']\\)\\(.*\\)\\1",'\2')
1659
+ let str = s:sub(str,':0x\x+$','') " For #<Object:0x...> style output
1660
+ let str = s:gsub(str,"[\"']",'')
1661
+ if line =~ '\<\(require\|load\)\s*(\s*$'
1662
+ return str
1663
+ endif
1664
+ let str = s:underscore(str)
1665
+ let fpat = '\(\s*\%("\f*"\|:\f*\|'."'\\f*'".'\)\s*,\s*\)*'
1666
+ if a:str =~ '\u'
1667
+ " Classes should always be in .rb files
1668
+ let str = str . '.rb'
1669
+ elseif line =~ ':partial\s*=>\s*'
1670
+ let str = s:sub(str,'([^/]+)$','_\1')
1671
+ let str = s:findview(str)
1672
+ elseif line =~ '\<layout\s*(\=\s*' || line =~ ':layout\s*=>\s*'
1673
+ let str = s:findview(s:sub(str,'^/=','layouts/'))
1674
+ elseif line =~ ':controller\s*=>\s*'
1675
+ let str = 'app/controllers/'.str.'_controller.rb'
1676
+ elseif line =~ '\<helper\s*(\=\s*'
1677
+ let str = 'app/helpers/'.str.'_helper.rb'
1678
+ elseif line =~ '\<fixtures\s*(\='.fpat
1679
+ if RailsFilePath() =~# '\<spec/'
1680
+ let str = s:sub(str,'^/@!','spec/fixtures/')
1681
+ else
1682
+ let str = s:sub(str,'^/@!','test/fixtures/')
1683
+ endif
1684
+ elseif line =~ '\<stylesheet_\(link_tag\|path\)\s*(\='.fpat
1685
+ let str = s:sub(str,'^/@!','/stylesheets/')
1686
+ let str = 'public'.s:sub(str,'^[^.]*$','&.css')
1687
+ elseif line =~ '\<javascript_\(include_tag\|path\)\s*(\='.fpat
1688
+ if str == "defaults"
1689
+ let str = "application"
1690
+ endif
1691
+ let str = s:sub(str,'^/@!','/javascripts/')
1692
+ let str = 'public'.s:sub(str,'^[^.]*$','&.js')
1693
+ elseif line =~ '\<\(has_one\|belongs_to\)\s*(\=\s*'
1694
+ let str = 'app/models/'.str.'.rb'
1695
+ elseif line =~ '\<has_\(and_belongs_to_\)\=many\s*(\=\s*'
1696
+ let str = 'app/models/'.s:singularize(str).'.rb'
1697
+ elseif line =~ '\<def\s\+' && expand("%:t") =~ '_controller\.rb'
1698
+ let str = s:sub(s:sub(RailsFilePath(),'/controllers/','/views/'),'_controller\.rb$','/'.str)
1699
+ "let str = s:sub(expand("%:p"),'.*[\/]app[\/]controllers[\/](.{-})_controller.rb','views/\1').'/'.str
1700
+ " FIXME: support nested extensions
1701
+ let vt = s:view_types.","
1702
+ while vt != ""
1703
+ let t = matchstr(vt,'[^,]*')
1704
+ let vt = s:sub(vt,'[^,]*,','')
1705
+ if filereadable(str.".".t)
1706
+ let str = str.".".t
1707
+ break
1708
+ endif
1709
+ endwhile
1710
+ elseif str =~ '_\%(path\|url\)$'
1711
+ " REST helpers
1712
+ let str = s:sub(str,'_%(path|url)$','')
1713
+ let str = s:sub(str,'^hash_for_','')
1714
+ let file = s:namedroutefile(str)
1715
+ if file == ""
1716
+ let str = s:sub(str,'^formatted_','')
1717
+ if str =~ '^\%(new\|edit\)_'
1718
+ let str = 'app/controllers/'.s:sub(s:pluralize(str),'^(new|edit)_(.*)','\2_controller.rb#\1')
1719
+ elseif str == s:singularize(str)
1720
+ " If the word can't be singularized, it's probably a link to the show
1721
+ " method. We should verify by checking for an argument, but that's
1722
+ " difficult the way things here are currently structured.
1723
+ let str = 'app/controllers/'.s:pluralize(str).'_controller.rb#show'
1724
+ else
1725
+ let str = 'app/controllers/'.str.'_controller.rb#index'
1726
+ endif
1727
+ else
1728
+ let str = file
1729
+ endif
1730
+ elseif str !~ '/'
1731
+ " If we made it this far, we'll risk making it singular.
1732
+ let str = s:singularize(str)
1733
+ let str = s:sub(str,'_id$','')
1734
+ endif
1735
+ if str =~ '^/' && !filereadable(str)
1736
+ let str = s:sub(str,'^/','')
1737
+ endif
1738
+ if str =~ '^lib/' && !filereadable(str)
1739
+ let str = s:sub(str,'^lib/','')
1740
+ endif
1741
+ return str
1742
+ endfunction
1743
+
1744
+ " }}}1
1745
+ " File Finders {{{1
1746
+
1747
+ function! s:addfilecmds(type)
1748
+ let l = s:sub(a:type,'^.','\l&')
1749
+ let cmds = 'ESVT '
1750
+ let cmd = ''
1751
+ while cmds != ''
1752
+ let cplt = " -complete=custom,".s:sid.l."List"
1753
+ exe "command! -buffer -bar -nargs=*".cplt." R".cmd.l." :call s:".l.'Edit(<bang>0,"'.cmd.'",<f-args>)'
1754
+ let cmd = strpart(cmds,0,1)
1755
+ let cmds = strpart(cmds,1)
1756
+ endwhile
1757
+ endfunction
1758
+
1759
+ function! s:BufFinderCommands()
1760
+ command! -buffer -bar -bang -nargs=+ Rcommand :call s:Command(<bang>0,<f-args>)
1761
+ call s:addfilecmds("model")
1762
+ call s:addfilecmds("view")
1763
+ call s:addfilecmds("controller")
1764
+ call s:addfilecmds("migration")
1765
+ call s:addfilecmds("observer")
1766
+ call s:addfilecmds("helper")
1767
+ call s:addfilecmds("api")
1768
+ call s:addfilecmds("layout")
1769
+ call s:addfilecmds("fixtures")
1770
+ call s:addfilecmds("unittest")
1771
+ call s:addfilecmds("functionaltest")
1772
+ call s:addfilecmds("integrationtest")
1773
+ call s:addfilecmds("stylesheet")
1774
+ call s:addfilecmds("javascript")
1775
+ call s:addfilecmds("task")
1776
+ call s:addfilecmds("lib")
1777
+ call s:addfilecmds("plugin")
1778
+ endfunction
1779
+
1780
+ function! s:autocamelize(files,test)
1781
+ if a:test =~# '^\u'
1782
+ return s:camelize(a:files)
1783
+ else
1784
+ return a:files
1785
+ endif
1786
+ endfunction
1787
+
1788
+ function! RailsUserClasses()
1789
+ if !exists("b:rails_root")
1790
+ return ""
1791
+ elseif s:getopt('classes','ab') != ''
1792
+ return s:getopt('classes','ab')
1793
+ endif
1794
+ let var = "user_classes_".s:rv()
1795
+ if !exists("s:".var)
1796
+ let s:{var} = s:sub(s:sub(s:gsub(s:camelize(
1797
+ \ s:relglob("app/models/","**/*",".rb") . "\n" .
1798
+ \ s:sub(s:relglob("app/controllers/","**/*",".rb"),'<application>','&_controller') . "\n" .
1799
+ \ s:relglob("app/helpers/","**/*",".rb") . "\n" .
1800
+ \ s:relglob("lib/","**/*",".rb") . "\n" .
1801
+ \ ""),'\n+',' '),'^\s+',''),'\s+$','')
1802
+ endif
1803
+ return s:{var}
1804
+ endfunction
1805
+
1806
+ function! s:relglob(path,glob,...)
1807
+ " How could such a simple operation be so complicated?
1808
+ if exists("+shellslash") && ! &shellslash
1809
+ let old_ss = &shellslash
1810
+ let &shellslash = 1
1811
+ endif
1812
+ if a:path =~ '[\/]$'
1813
+ let path = a:path
1814
+ else
1815
+ let path = a:path . ''
1816
+ endif
1817
+ if path !~ '^/' && path !~ '^\w:' && RailsRoot() != ''
1818
+ let path = RailsRoot() . '/' . path
1819
+ endif
1820
+ let suffix = a:0 ? a:1 : ''
1821
+ let badres = glob(path.a:glob.suffix)."\n"
1822
+ if v:version <= 602
1823
+ " Nasty Vim bug in version 6.2
1824
+ let badres = glob(path.a:glob.suffix)."\n"
1825
+ endif
1826
+ let goodres = ""
1827
+ let striplen = strlen(path)
1828
+ let stripend = strlen(suffix)
1829
+ while strlen(badres) > 0
1830
+ let idx = stridx(badres,"\n")
1831
+ "if idx == -1
1832
+ "let idx = strlen(badres)
1833
+ "endif
1834
+ let tmp = strpart(badres,0,idx)
1835
+ let badres = strpart(badres,idx+1)
1836
+ let goodres = goodres.strpart(tmp,striplen,strlen(tmp)-striplen-stripend)
1837
+ if suffix == '' && isdirectory(tmp) && goodres !~ '/$'
1838
+ let goodres = goodres."/"
1839
+ endif
1840
+ let goodres = goodres."\n"
1841
+ endwhile
1842
+ "let goodres = s:gsub("\n".goodres,'\n.{-}\~\n','\n')
1843
+ if exists("old_ss")
1844
+ let &shellslash = old_ss
1845
+ endif
1846
+ return s:compact(goodres)
1847
+ endfunction
1848
+
1849
+ if v:version <= 602
1850
+ " Yet another Vim 6.2 limitation
1851
+ let s:recurse = "*"
1852
+ else
1853
+ let s:recurse = "**/*"
1854
+ endif
1855
+
1856
+ function! s:helperList(A,L,P)
1857
+ return s:autocamelize(s:relglob("app/helpers/",s:recurse,"_helper.rb"),a:A)
1858
+ endfunction
1859
+
1860
+ function! s:controllerList(A,L,P)
1861
+ let con = s:gsub(s:relglob("app/controllers/",s:recurse,".rb"),'_controller>','')
1862
+ return s:autocamelize(con,a:A)
1863
+ endfunction
1864
+
1865
+ function! s:viewList(A,L,P)
1866
+ let c = s:controller(1)
1867
+ let top = s:relglob("app/views/",a:A."*[^~]")
1868
+ if c != ''
1869
+ let local = s:relglob("app/views/".c."/",a:A.(a:A =~ '\.' ? '' : '*.')."*[^~]")
1870
+ if local != ''
1871
+ return local."\n".top
1872
+ endif
1873
+ endif
1874
+ return top
1875
+ endfunction
1876
+
1877
+ function! s:layoutList(A,L,P)
1878
+ return s:relglob("app/views/layouts/","*")
1879
+ endfunction
1880
+
1881
+ function! s:stylesheetList(A,L,P)
1882
+ return s:relglob("public/stylesheets/",s:recurse,".css")
1883
+ endfunction
1884
+
1885
+ function! s:javascriptList(A,L,P)
1886
+ return s:relglob("public/javascripts/",s:recurse,".js")
1887
+ endfunction
1888
+
1889
+ function! s:modelList(A,L,P)
1890
+ let models = s:relglob("app/models/",s:recurse,".rb")."\n"
1891
+ " . matches everything, and no good way to exclude newline. Lame.
1892
+ let models = s:gsub(models,'[ -~]*_observer\n',"")
1893
+ let models = s:compact(models)
1894
+ return s:autocamelize(models,a:A)
1895
+ endfunction
1896
+
1897
+ function! s:observerList(A,L,P)
1898
+ return s:autocamelize(s:relglob("app/models/",s:recurse,"_observer.rb"),a:A)
1899
+ endfunction
1900
+
1901
+ function! s:fixturesList(A,L,P)
1902
+ return s:compact(s:relglob("test/fixtures/",s:recurse)."\n".s:relglob("spec/fixtures/",s:recurse))
1903
+ endfunction
1904
+
1905
+ function! s:migrationList(A,L,P)
1906
+ if a:A =~ '^\d'
1907
+ let migrations = s:relglob("db/migrate/",a:A."[0-9_]*",".rb")
1908
+ let migrations = s:gsub(migrations,'_.{-}($|\n)','\1')
1909
+ return migrations
1910
+ else
1911
+ let migrations = s:relglob("db/migrate/","[0-9]*[0-9]_".a:A."*",".rb")
1912
+ let migrations = s:gsub(migrations,'(^|\n)\d+_','\1')
1913
+ return s:autocamelize(migrations,a:A)
1914
+ endif
1915
+ endfunction
1916
+
1917
+ function! s:apiList(A,L,P)
1918
+ return s:autocamelize(s:relglob("app/apis/",s:recurse,"_api.rb"),a:A)
1919
+ endfunction
1920
+
1921
+ function! s:unittestList(A,L,P)
1922
+ return s:autocamelize(s:relglob("test/unit/",s:recurse,"_test.rb"),a:A)
1923
+ endfunction
1924
+
1925
+ function! s:functionaltestList(A,L,P)
1926
+ return s:autocamelize(s:relglob("test/functional/",s:recurse,"_test.rb"),a:A)
1927
+ endfunction
1928
+
1929
+ function! s:integrationtestList(A,L,P)
1930
+ return s:autocamelize(s:relglob("test/integration/",s:recurse,"_test.rb"),a:A)
1931
+ endfunction
1932
+
1933
+ function! s:pluginList(A,L,P)
1934
+ if a:A =~ '/'
1935
+ return s:relglob('vendor/plugins/',matchstr(a:A,'.\{-\}/').'**/*')
1936
+ else
1937
+ return s:relglob('vendor/plugins/',"*","/init.rb")
1938
+ endif
1939
+ endfunction
1940
+
1941
+ " Task files, not actual rake tasks
1942
+ function! s:taskList(A,L,P)
1943
+ let top = s:relglob("lib/tasks/",s:recurse,".rake")
1944
+ if RailsFilePath() =~ '\<vendor/plugins/.'
1945
+ let path = s:sub(RailsFilePath(),'<vendor/plugins/[^/]*/\zs.*','tasks/')
1946
+ return s:relglob(path,s:recurse,".rake") . "\n" . top
1947
+ else
1948
+ return top
1949
+ endif
1950
+ endfunction
1951
+
1952
+ function! s:libList(A,L,P)
1953
+ let all = s:relglob('lib/',s:recurse,".rb")
1954
+ if RailsFilePath() =~ '\<vendor/plugins/.'
1955
+ let path = s:sub(RailsFilePath(),'<vendor/plugins/[^/]*/\zs.*','lib/')
1956
+ let all = s:relglob(path,s:recurse,".rb") . "\n" . all
1957
+ endif
1958
+ return s:autocamelize(all,a:A)
1959
+ endfunction
1960
+
1961
+ function! s:Command(bang,...)
1962
+ if a:bang
1963
+ let str = ""
1964
+ let i = 0
1965
+ while i < a:0
1966
+ let i = i + 1
1967
+ if a:{i} =~# '^-complete=custom,s:' && v:version <= 602
1968
+ let str = str . " " . s:sub(a:{i},',s:',','.s:sid)
1969
+ else
1970
+ let str = str . " " . a:{i}
1971
+ endif
1972
+ endwhile
1973
+ exe "command!".str
1974
+ return
1975
+ endif
1976
+ let suffix = ".rb"
1977
+ let filter = "**/*"
1978
+ let prefix = ""
1979
+ let default = ""
1980
+ let name = ""
1981
+ let i = 0
1982
+ while i < a:0
1983
+ let i = i + 1
1984
+ let arg = a:{i}
1985
+ if arg =~# '^-suffix='
1986
+ let suffix = matchstr(arg,'-suffix=\zs.*')
1987
+ elseif arg =~# '^-default='
1988
+ let default = matchstr(arg,'-default=\zs.*')
1989
+ elseif arg =~# '^-\%(glob\|filter\)='
1990
+ let filter = matchstr(arg,'-\w*=\zs.*')
1991
+ elseif arg !~# '^-'
1992
+ " A literal '\n'. For evaluation below
1993
+ if name == ""
1994
+ let name = arg
1995
+ else
1996
+ let prefix = prefix."\\n".s:sub(arg,'/=$','/')
1997
+ endif
1998
+ endif
1999
+ endwhile
2000
+ let prefix = s:sub(prefix,'^\\n','')
2001
+ if name !~ '^[A-Za-z]\+$'
2002
+ return s:error("E182: Invalid command name")
2003
+ endif
2004
+ let cmds = 'ESVT '
2005
+ let cmd = ''
2006
+ while cmds != ''
2007
+ exe 'command! -buffer -bar -bang -nargs=* -complete=custom,'.s:sid.'CommandList R'.cmd.name." :call s:CommandEdit(<bang>0,'".cmd."','".name."',\"".prefix."\",".s:string(suffix).",".s:string(filter).",".s:string(default).",<f-args>)"
2008
+ let cmd = strpart(cmds,0,1)
2009
+ let cmds = strpart(cmds,1)
2010
+ endwhile
2011
+ endfunction
2012
+
2013
+ function! s:CommandList(A,L,P)
2014
+ let cmd = matchstr(a:L,'\CR[A-Z]\=\w\+')
2015
+ exe cmd." &"
2016
+ let lp = s:last_prefix . "\n"
2017
+ let res = ""
2018
+ while lp != ""
2019
+ let p = matchstr(lp,'.\{-\}\ze\n')
2020
+ let lp = s:sub(lp,'.{-}\n','')
2021
+ let res = res . s:relglob(p,s:last_filter,s:last_suffix)."\n"
2022
+ endwhile
2023
+ let res = s:compact(res)
2024
+ if s:last_camelize
2025
+ return s:autocamelize(res,a:A)
2026
+ else
2027
+ return res
2028
+ endif
2029
+ endfunction
2030
+
2031
+ function! s:CommandEdit(bang,cmd,name,prefix,suffix,filter,default,...)
2032
+ if a:0 && a:1 == "&"
2033
+ let s:last_prefix = a:prefix
2034
+ let s:last_suffix = a:suffix
2035
+ let s:last_filter = a:filter
2036
+ let s:last_camelize = (a:suffix =~# '\.rb$')
2037
+ else
2038
+ if a:default == "both()"
2039
+ if s:model() != ""
2040
+ let default = s:model()
2041
+ else
2042
+ let default = s:controller()
2043
+ endif
2044
+ elseif a:default == "model()"
2045
+ let default = s:model(1)
2046
+ elseif a:default == "controller()"
2047
+ let default = s:controller(1)
2048
+ else
2049
+ let default = a:default
2050
+ endif
2051
+ call s:EditSimpleRb(a:bang,a:cmd,a:name,a:0 ? a:1 : default,a:prefix,a:suffix)
2052
+ endif
2053
+ endfunction
2054
+
2055
+ function! s:EditSimpleRb(bang,cmd,name,target,prefix,suffix)
2056
+ let cmd = s:findcmdfor(a:cmd.(a:bang?'!':''))
2057
+ if a:target == ""
2058
+ " Good idea to emulate error numbers like this?
2059
+ return s:error("E471: Argument required") " : R',a:name)
2060
+ "else
2061
+ "let g:target = a:target
2062
+ endif
2063
+ let f = s:underscore(a:target)
2064
+ let jump = matchstr(f,'[@#].*')
2065
+ let f = s:sub(f,'[@#].*','')
2066
+ if f == '.'
2067
+ let f = s:sub(f,'\.$','')
2068
+ else
2069
+ let f = f.a:suffix.jump
2070
+ if a:suffix !~ '\.'
2071
+ "let f = f.".rb"
2072
+ endif
2073
+ endif
2074
+ let f = s:gsub(a:prefix,'\n',f.'\n').f
2075
+ return s:findedit(cmd,f)
2076
+ endfunction
2077
+
2078
+ function! s:migrationfor(file)
2079
+ let tryagain = 0
2080
+ let arg = a:file
2081
+ if arg =~ '^\d$'
2082
+ let glob = '00'.arg.'_*.rb'
2083
+ elseif arg =~ '^\d\d$'
2084
+ let glob = '0'.arg.'_*.rb'
2085
+ elseif arg =~ '^\d\d\d$'
2086
+ let glob = ''.arg.'_*.rb'
2087
+ elseif arg == ''
2088
+ if s:model(1) != ''
2089
+ let glob = '*_'.s:pluralize(s:model(1)).'.rb'
2090
+ let tryagain = 1
2091
+ else
2092
+ let glob = '*.rb'
2093
+ endif
2094
+ else
2095
+ let glob = '*'.arg.'*rb'
2096
+ endif
2097
+ let migr = s:sub(glob(RailsRoot().'/db/migrate/'.glob),'.*\n','')
2098
+ if migr == '' && tryagain
2099
+ let migr = s:sub(glob(RailsRoot().'/db/migrate/*.rb'),'.*\n','')
2100
+ endif
2101
+ if strpart(migr,0,strlen(RailsRoot())) == RailsRoot()
2102
+ let migr = strpart(migr,1+strlen(RailsRoot()))
2103
+ endif
2104
+ return migr
2105
+ endfunction
2106
+
2107
+ function! s:migrationEdit(bang,cmd,...)
2108
+ let cmd = s:findcmdfor(a:cmd.(a:bang?'!':''))
2109
+ let arg = a:0 ? a:1 : ''
2110
+ let migr = arg == "." ? "db/migrate" : s:migrationfor(arg)
2111
+ if migr != ''
2112
+ call s:findedit(cmd,migr)
2113
+ else
2114
+ return s:error("Migration not found".(arg=='' ? '' : ': '.arg))
2115
+ endif
2116
+ endfunction
2117
+
2118
+ function! s:fixturesEdit(bang,cmd,...)
2119
+ if a:0
2120
+ let c = s:underscore(a:1)
2121
+ else
2122
+ let c = s:pluralize(s:model(1))
2123
+ endif
2124
+ if c == ""
2125
+ return s:error("E471: Argument required")
2126
+ endif
2127
+ let e = fnamemodify(c,':e')
2128
+ let e = e == '' ? e : '.'.e
2129
+ let c = fnamemodify(c,':r')
2130
+ let file = 'test/fixtures/'.c.e
2131
+ if file =~ '\.\w\+$' && !s:hasfile("spec/fixtures/".c.e)
2132
+ call s:edit(a:cmd.(a:bang?'!':''),file)
2133
+ else
2134
+ call s:findedit(a:cmd.(a:bang?'!':''),file."\nspec/fixtures/".c.e)
2135
+ endif
2136
+ endfunction
2137
+
2138
+ function! s:modelEdit(bang,cmd,...)
2139
+ call s:EditSimpleRb(a:bang,a:cmd,"model",a:0? a:1 : s:model(1),"app/models/",".rb")
2140
+ endfunction
2141
+
2142
+ function! s:observerEdit(bang,cmd,...)
2143
+ call s:EditSimpleRb(a:bang,a:cmd,"observer",a:0? a:1 : s:model(1),"app/models/","_observer.rb")
2144
+ endfunction
2145
+
2146
+ function! s:viewEdit(bang,cmd,...)
2147
+ if a:0
2148
+ let view = a:1
2149
+ elseif RailsFileType() == 'controller'
2150
+ let view = s:lastmethod()
2151
+ else
2152
+ let view = ''
2153
+ endif
2154
+ if view == ''
2155
+ return s:error("No view name given")
2156
+ elseif view == '.'
2157
+ return s:edit(a:cmd.(a:bang?'!':''),'app/views')
2158
+ elseif view !~ '/' && s:controller(1) != ''
2159
+ let view = s:controller(1) . '/' . view
2160
+ endif
2161
+ if view !~ '/'
2162
+ return s:error("Cannot find view without controller")
2163
+ endif
2164
+ let file = "app/views/".view
2165
+ let found = s:findview(view)
2166
+ if found != ''
2167
+ call s:edit(a:cmd.(a:bang?'!':''),found)
2168
+ elseif file =~ '\.\w\+\.\w\+$' || file =~ '\.'.s:viewspattern().'$'
2169
+ call s:edit(a:cmd.(a:bang?'!':''),file)
2170
+ elseif file =~ '\.\w\+$'
2171
+ call s:findedit(a:cmd.(a:bang?'!':''),file)
2172
+ else
2173
+ let format = s:format('html')
2174
+ if glob(RailsRoot().'/'.file.'.'.format.'.*[^~]') != ''
2175
+ let file = file . '.' . format
2176
+ endif
2177
+ call s:findedit(a:cmd.(a:bang?'!':''),file)
2178
+ endif
2179
+ endfunction
2180
+
2181
+ function! s:findview(name)
2182
+ " TODO: full support of nested extensions
2183
+ let c = a:name
2184
+ let pre = "app/views/"
2185
+ let file = ""
2186
+ if c !~ '/'
2187
+ let controller = s:controller(1)
2188
+ if controller != ''
2189
+ let c = controller.'/'.c
2190
+ endif
2191
+ endif
2192
+ if c =~ '\.\w\+\.\w\+$' || c =~ '\.'.s:viewspattern().'$'
2193
+ return pre.c
2194
+ elseif s:hasfile(pre.c.".rhtml")
2195
+ let file = pre.c.".rhtml"
2196
+ elseif s:hasfile(pre.c.".rxml")
2197
+ let file = pre.c.".rxml"
2198
+ else
2199
+ let format = "." . s:format('html')
2200
+ let vt = s:view_types.","
2201
+ while 1
2202
+ while vt != ""
2203
+ let t = matchstr(vt,'[^,]*')
2204
+ let vt = s:sub(vt,'[^,]*,','')
2205
+ if s:hasfile(pre.c.format.".".t)
2206
+ let file = pre.c.format.".".t
2207
+ break
2208
+ endif
2209
+ endwhile
2210
+ if format == '' || file != ''
2211
+ break
2212
+ else
2213
+ let format = ''
2214
+ endif
2215
+ endwhile
2216
+ endif
2217
+ return file
2218
+ endfunction
2219
+
2220
+ function! s:findlayout(name)
2221
+ return s:findview("layouts/".(a:name == '' ? 'application' : a:name))
2222
+ endfunction
2223
+
2224
+ function! s:layoutEdit(bang,cmd,...)
2225
+ if a:0
2226
+ let c = s:underscore(a:1)
2227
+ else
2228
+ let c = s:controller(1)
2229
+ endif
2230
+ if c == ""
2231
+ let c = "application"
2232
+ endif
2233
+ let file = s:findlayout(c)
2234
+ if file == ""
2235
+ let file = s:findlayout("application")
2236
+ endif
2237
+ if file == ""
2238
+ let file = "app/views/layouts/application.html.erb"
2239
+ endif
2240
+ call s:edit(a:cmd.(a:bang?'!':''),s:sub(file,'^/',''))
2241
+ endfunction
2242
+
2243
+ function! s:controllerEdit(bang,cmd,...)
2244
+ let suffix = '.rb'
2245
+ if a:0 == 0
2246
+ let controller = s:controller(1)
2247
+ if RailsFileType() =~ '^view\%(-layout\|-partial\)\@!'
2248
+ let suffix = suffix.'#'.expand('%:t:r')
2249
+ endif
2250
+ else
2251
+ let controller = a:1
2252
+ endif
2253
+ if s:hasfile("app/controllers/".controller."_controller.rb") || !s:hasfile("app/controllers/".controller.".rb")
2254
+ let suffix = "_controller".suffix
2255
+ endif
2256
+ return s:EditSimpleRb(a:bang,a:cmd,"controller",controller,"app/controllers/",suffix)
2257
+ endfunction
2258
+
2259
+ function! s:helperEdit(bang,cmd,...)
2260
+ return s:EditSimpleRb(a:bang,a:cmd,"helper",a:0? a:1 : s:controller(1),"app/helpers/","_helper.rb")
2261
+ endfunction
2262
+
2263
+ function! s:apiEdit(bang,cmd,...)
2264
+ return s:EditSimpleRb(a:bang,a:cmd,"api",a:0 ? a:1 : s:controller(1),"app/apis/","_api.rb")
2265
+ endfunction
2266
+
2267
+ function! s:stylesheetEdit(bang,cmd,...)
2268
+ return s:EditSimpleRb(a:bang,a:cmd,"stylesheet",a:0? a:1 : s:controller(1),"public/stylesheets/",".css")
2269
+ endfunction
2270
+
2271
+ function! s:javascriptEdit(bang,cmd,...)
2272
+ return s:EditSimpleRb(a:bang,a:cmd,"javascript",a:0? a:1 : "application","public/javascripts/",".js")
2273
+ endfunction
2274
+
2275
+ function! s:unittestEdit(bang,cmd,...)
2276
+ let f = a:0 ? a:1 : s:model(1)
2277
+ if !a:0 && RailsFileType() =~ '^model-aro\>' && f != '' && f !~ '_observer$'
2278
+ if s:hasfile("test/unit/".f."_observer.rb") || !s:hasfile("test/unit/".f.".rb")
2279
+ let f = f . "_observer"
2280
+ endif
2281
+ endif
2282
+ return s:EditSimpleRb(a:bang,a:cmd,"unittest",f,"test/unit/","_test.rb")
2283
+ endfunction
2284
+
2285
+ function! s:functionaltestEdit(bang,cmd,...)
2286
+ if a:0
2287
+ let f = a:1
2288
+ else
2289
+ let f = s:controller()
2290
+ endif
2291
+ if f != '' && !s:hasfile("test/functional/".f."_test.rb")
2292
+ if s:hasfile("test/functional/".f."_controller_test.rb")
2293
+ let f = f . "_controller"
2294
+ elseif s:hasfile("test/functional/".f."_api_test.rb")
2295
+ let f = f . "_api"
2296
+ endif
2297
+ endif
2298
+ return s:EditSimpleRb(a:bang,a:cmd,"functionaltest",f,"test/functional/","_test.rb")
2299
+ endfunction
2300
+
2301
+ function! s:integrationtestEdit(bang,cmd,...)
2302
+ if a:0
2303
+ let f = a:1
2304
+ elseif s:model() != ''
2305
+ let f = s:model()
2306
+ else
2307
+ let f = s:controller()
2308
+ endif
2309
+ return s:EditSimpleRb(a:bang,a:cmd,"integrationtest",f,"test/integration/","_test.rb")
2310
+ endfunction
2311
+
2312
+ function! s:pluginEdit(bang,cmd,...)
2313
+ let cmd = s:findcmdfor(a:cmd.(a:bang?'!':''))
2314
+ let plugin = ""
2315
+ let extra = ""
2316
+ if RailsFilePath() =~ '\<vendor/plugins/.'
2317
+ let plugin = matchstr(RailsFilePath(),'\<vendor/plugins/\zs[^/]*\ze')
2318
+ let extra = "vendor/plugins/" . plugin . "/\n"
2319
+ endif
2320
+ if a:0
2321
+ if a:1 =~ '^[^/.]*/\=$' && s:hasfile("vendor/plugins/".a:1."/init.rb")
2322
+ return s:EditSimpleRb(a:bang,a:cmd,"plugin",s:sub(a:1,'/$',''),"vendor/plugins/","/init.rb")
2323
+ elseif plugin == ""
2324
+ call s:edit(cmd,"vendor/plugins/".s:sub(a:1,'\.$',''))
2325
+ elseif a:1 == "."
2326
+ call s:findedit(cmd,"vendor/plugins/".plugin)
2327
+ elseif isdirectory(RailsRoot()."/vendor/plugins/".matchstr(a:1,'^[^/]*'))
2328
+ call s:edit(cmd,"vendor/plugins/".a:1)
2329
+ else
2330
+ call s:findedit(cmd,"vendor/plugins/".a:1."\nvendor/plugins/".plugin."/".a:1)
2331
+ endif
2332
+ else
2333
+ return s:EditSimpleRb(a:bang,a:cmd,"plugin",plugin,"vendor/plugins/","/init.rb")
2334
+ endif
2335
+ endfunction
2336
+
2337
+ function! s:taskEdit(bang,cmd,...)
2338
+ let plugin = ""
2339
+ let extra = ""
2340
+ if RailsFilePath() =~ '\<vendor/plugins/.'
2341
+ let plugin = matchstr(RailsFilePath(),'\<vendor/plugins/[^/]*')
2342
+ let extra = plugin."/tasks/\n"
2343
+ endif
2344
+ if a:0
2345
+ call s:EditSimpleRb(a:bang,a:cmd,"task",a:1,extra."lib/tasks/",".rake")
2346
+ else
2347
+ call s:findedit((a:bang ? "!" : ""),(plugin != "" ? plugin."/Rakefile\n" : "")."Rakefile")
2348
+ endif
2349
+ endfunction
2350
+
2351
+ function! s:libEdit(bang,cmd,...)
2352
+ let extra = ""
2353
+ if RailsFilePath() =~ '\<vendor/plugins/.'
2354
+ let extra = s:sub(RailsFilePath(),'<vendor/plugins/[^/]*/\zs.*','lib/')."\n"
2355
+ endif
2356
+ if a:0
2357
+ call s:EditSimpleRb(a:bang,a:cmd,"task",a:0? a:1 : "",extra."lib/",".rb")
2358
+ else
2359
+ " Easter egg
2360
+ call s:EditSimpleRb(a:bang,a:cmd,"task","environment","config/",".rb")
2361
+ endif
2362
+ endfunction
2363
+
2364
+ " }}}1
2365
+ " Alternate/Related {{{1
2366
+
2367
+ function! s:findcmdfor(cmd)
2368
+ let bang = ''
2369
+ if a:cmd =~ '\!$'
2370
+ let bang = '!'
2371
+ let cmd = s:sub(a:cmd,'\!$','')
2372
+ else
2373
+ let cmd = a:cmd
2374
+ endif
2375
+ if cmd =~ '^\d'
2376
+ let num = matchstr(cmd,'^\d\+')
2377
+ let cmd = s:sub(cmd,'^\d+','')
2378
+ else
2379
+ let num = ''
2380
+ endif
2381
+ if cmd == '' || cmd == 'E' || cmd == 'F'
2382
+ return num.'find'.bang
2383
+ elseif cmd == 'S'
2384
+ return num.'sfind'.bang
2385
+ elseif cmd == 'V'
2386
+ return 'vert '.num.'sfind'.bang
2387
+ elseif cmd == 'T'
2388
+ return num.'tabfind'.bang
2389
+ else
2390
+ return num.cmd.bang
2391
+ endif
2392
+ endfunction
2393
+
2394
+ function! s:editcmdfor(cmd)
2395
+ let cmd = s:findcmdfor(a:cmd)
2396
+ let cmd = s:sub(cmd,'<sfind>','split')
2397
+ let cmd = s:sub(cmd,'find>','edit')
2398
+ return cmd
2399
+ endfunction
2400
+
2401
+ function! s:try(cmd) abort
2402
+ if !exists(":try")
2403
+ " I've seen at least one weird setup without :try
2404
+ exe a:cmd
2405
+ else
2406
+ try
2407
+ exe a:cmd
2408
+ catch
2409
+ call s:error(s:sub(v:exception,'^.{-}:\zeE',''))
2410
+ return 0
2411
+ endtry
2412
+ endif
2413
+ return 1
2414
+ endfunction
2415
+
2416
+ function! s:findedit(cmd,file,...) abort
2417
+ let cmd = s:findcmdfor(a:cmd)
2418
+ if a:file =~ '\n'
2419
+ let filelist = a:file . "\n"
2420
+ let file = ''
2421
+ while file == '' && filelist != ''
2422
+ let maybe = matchstr(filelist,'^.\{-\}\ze\n')
2423
+ let filelist = s:sub(filelist,'^.{-}\n','')
2424
+ if s:hasfile(s:sub(maybe,'[@#].*',''))
2425
+ let file = maybe
2426
+ endif
2427
+ endwhile
2428
+ if file == ''
2429
+ let file = matchstr(a:file."\n",'^.\{-\}\ze\n')
2430
+ endif
2431
+ else
2432
+ let file = a:file
2433
+ endif
2434
+ if file =~ '[@#]'
2435
+ let djump = matchstr(file,'[@#]\zs.*')
2436
+ let file = matchstr(file,'.\{-\}\ze[@#]')
2437
+ else
2438
+ let djump = ''
2439
+ endif
2440
+ if file == ''
2441
+ let testcmd = "edit"
2442
+ elseif RailsRoot() =~ '://' || cmd =~ 'edit' || cmd =~ 'split'
2443
+ if file !~ '^/' && file !~ '^\w:' && file !~ '://'
2444
+ let file = s:ra().'/'.file
2445
+ endif
2446
+ let testcmd = s:editcmdfor(cmd).' '.(a:0 ? a:1 . ' ' : '').file
2447
+ elseif isdirectory(RailsRoot().'/'.file)
2448
+ let testcmd = s:editcmdfor(cmd).' '.(a:0 ? a:1 . ' ' : '').s:ra().'/'.file
2449
+ exe testcmd
2450
+ return
2451
+ else
2452
+ let testcmd = cmd.' '.(a:0 ? a:1 . ' ' : '').file
2453
+ endif
2454
+ if s:try(testcmd)
2455
+ " Shorten the file name (I don't fully understand how Vim decides when to
2456
+ " use a relative/absolute path for the file name, so lets blindly force it
2457
+ " to be as short as possible)
2458
+ "silent! file %:~:.
2459
+ "silent! lcd .
2460
+ call s:djump(djump)
2461
+ endif
2462
+ endfunction
2463
+
2464
+ function! s:edit(cmd,file,...)
2465
+ let cmd = s:editcmdfor(a:cmd)
2466
+ let cmd = cmd.' '.(a:0 ? a:1 . ' ' : '')
2467
+ let file = a:file
2468
+ if file !~ '^/' && file !~ '^\w:' && file !~ '://'
2469
+ "let file = s:ra().'/'.file
2470
+ exe cmd."`=RailsRoot().'/'.file`"
2471
+ else
2472
+ exe cmd.file
2473
+ endif
2474
+ "exe cmd.file
2475
+ endfunction
2476
+
2477
+ function! s:Alternate(bang,cmd)
2478
+ let cmd = a:cmd.(a:bang?"!":"")
2479
+ let file = s:AlternateFile()
2480
+ if file != ""
2481
+ call s:findedit(cmd,file)
2482
+ else
2483
+ call s:warn("No alternate file is defined")
2484
+ endif
2485
+ endfunction
2486
+
2487
+ function! s:AlternateFile()
2488
+ let f = RailsFilePath()
2489
+ let t = RailsFileType()
2490
+ let altopt = s:getopt("alternate","bl")
2491
+ if altopt != ""
2492
+ return altopt
2493
+ elseif f =~ '\<config/environments/'
2494
+ return "config/environment.rb"
2495
+ elseif f == 'README'
2496
+ return "config/database.yml"
2497
+ elseif f =~ '\<config/database\.yml$' | return "config/routes.rb"
2498
+ elseif f =~ '\<config/routes\.rb$' | return "config/environment.rb"
2499
+ elseif f =~ '\<config/environment\.rb$' | return "config/database.yml"
2500
+ elseif f =~ '\<db/migrate/\d\d\d_'
2501
+ let num = matchstr(f,'\<db/migrate/0*\zs\d\+\ze_')-1
2502
+ return num ? s:migrationfor(num) : "db/schema.rb"
2503
+ elseif f =~ '\<application\.js$'
2504
+ return "app/helpers/application_helper.rb"
2505
+ elseif t =~ '^js\>'
2506
+ return "public/javascripts/application.js"
2507
+ elseif f =~ '\<db/schema\.rb$'
2508
+ return s:migrationfor("")
2509
+ elseif t =~ '^view\>'
2510
+ if t =~ '\<layout\>'
2511
+ let dest = fnamemodify(f,':r:s?/layouts\>??').'/layout.'.fnamemodify(f,':e')
2512
+ else
2513
+ let dest = f
2514
+ endif
2515
+ " Go to the (r)spec, helper, controller, or (mailer) model
2516
+ let spec = fnamemodify(dest,':r:s?\<app/?spec/?')."_spec.rb"
2517
+ let helper = fnamemodify(dest,':h:s?/views/?/helpers/?')."_helper.rb"
2518
+ let controller = fnamemodify(dest,':h:s?/views/?/controllers/?')."_controller.rb"
2519
+ let model = fnamemodify(dest,':h:s?/views/?/models/?').".rb"
2520
+ if s:hasfile(spec)
2521
+ return spec
2522
+ elseif s:hasfile(helper)
2523
+ return helper
2524
+ elseif s:hasfile(controller)
2525
+ let jumpto = expand("%:t:r")
2526
+ return controller.'#'.jumpto
2527
+ elseif s:hasfile(model)
2528
+ return model
2529
+ else
2530
+ return helper
2531
+ endif
2532
+ elseif t =~ '^controller-api\>'
2533
+ let api = s:sub(s:sub(f,'/controllers/','/apis/'),'_controller\.rb$','_api.rb')
2534
+ return api
2535
+ elseif t =~ '^helper\>'
2536
+ let controller = s:sub(s:sub(f,'/helpers/','/controllers/'),'_helper\.rb$','_controller.rb')
2537
+ let controller = s:sub(controller,'application_controller','application')
2538
+ let spec = s:sub(s:sub(f,'<app/','spec/'),'\.rb$','_spec.rb')
2539
+ if s:hasfile(spec)
2540
+ return spec
2541
+ else
2542
+ return controller
2543
+ endif
2544
+ elseif t =~ '\<fixtures\>' && f =~ '\<spec/'
2545
+ let file = s:singularize(expand("%:t:r")).'_spec.rb'
2546
+ return file
2547
+ elseif t =~ '\<fixtures\>'
2548
+ let file = s:singularize(expand("%:t:r")).'_test.rb' " .expand('%:e')
2549
+ return file
2550
+ elseif f == ''
2551
+ call s:warn("No filename present")
2552
+ elseif f =~ '\<test/unit/routing_test\.rb$'
2553
+ return 'config/routes.rb'
2554
+ elseif t=~ '^spec-view\>'
2555
+ return s:sub(s:sub(f,'<spec/','app/'),'_spec\.rb$','')
2556
+ elseif fnamemodify(f,":e") == "rb"
2557
+ let file = fnamemodify(f,":r")
2558
+ if file =~ '_\%(test\|spec\)$'
2559
+ let file = s:sub(file,'_%(test|spec)$','.rb')
2560
+ else
2561
+ let file = file.'_test.rb'
2562
+ endif
2563
+ if t =~ '^model\>'
2564
+ return s:sub(file,'app/models/','test/unit/')."\n".s:sub(s:sub(file,'_test\.rb$','_spec.rb'),'app/models/','spec/models/')
2565
+ elseif t =~ '^controller\>'
2566
+ "return s:sub(file,'app/controllers/','test/functional/')
2567
+ return s:sub(file,'<app/controllers/','test/functional/')."\n".s:sub(s:sub(file,'_test\.rb$','_spec.rb'),'app/controllers/','spec/controllers/')
2568
+ elseif t =~ '^test-unit\>'
2569
+ return s:sub(file,'test/unit/','app/models/')."\n".s:sub(file,'test/unit/','lib/')
2570
+ elseif t =~ '^test-functional\>'
2571
+ if file =~ '_api\.rb'
2572
+ return s:sub(file,'test/functional/','app/apis/')
2573
+ elseif file =~ '_controller\.rb'
2574
+ return s:sub(file,'test/functional/','app/controllers/')
2575
+ else
2576
+ return s:sub(file,'test/functional/','')
2577
+ endif
2578
+ elseif t == 'spec-lib'
2579
+ return s:sub(file,'<spec/','')
2580
+ elseif t == 'lib'
2581
+ return s:sub(f, '<lib/(.*)\.rb$', 'test/unit/\1_test\.rb')."\n".s:sub(f, '<lib/(.*)\.rb$', 'spec/lib/\1_spec\.rb')
2582
+ elseif t =~ '^spec\>'
2583
+ return s:sub(file,'<spec/','app/')
2584
+ elseif file =~ '\<vendor/.*/lib/'
2585
+ return s:sub(file,'<vendor/.{-}/\zslib/','test/')
2586
+ elseif file =~ '\<vendor/.*/test/'
2587
+ return s:sub(file,'<vendor/.{-}/\zstest/','lib/')
2588
+ else
2589
+ return fnamemodify(file,":t")
2590
+ endif
2591
+ else
2592
+ return ""
2593
+ endif
2594
+ endfunction
2595
+
2596
+ function! s:Related(bang,cmd)
2597
+ let cmd = a:cmd.(a:bang?"!":"")
2598
+ let file = s:RelatedFile()
2599
+ if file != ""
2600
+ call s:findedit(cmd,file)
2601
+ else
2602
+ call s:warn("No related file is defined")
2603
+ endif
2604
+ endfunction
2605
+
2606
+ function! s:RelatedFile()
2607
+ let f = RailsFilePath()
2608
+ let t = RailsFileType()
2609
+ let lastmethod = s:lastmethod()
2610
+ if s:getopt("related","l") != ""
2611
+ return s:getopt("related","l")
2612
+ elseif t =~ '^\%(controller\|model-mailer\)\>' && lastmethod != ""
2613
+ let root = s:sub(s:sub(s:sub(f,'/application\.rb$','/shared_controller.rb'),'/%(controllers|models)/','/views/'),'%(_controller)=\.rb$','/'.lastmethod)
2614
+ let format = s:format('html')
2615
+ if glob(RailsRoot().'/'.root.'.'.format.'.*[^~]') != ''
2616
+ return root . '.' . format
2617
+ else
2618
+ return root
2619
+ endif
2620
+ elseif s:getopt("related","b") != ""
2621
+ return s:getopt("related","b")
2622
+ elseif f =~ '\<config/environments/'
2623
+ return "config/database.yml#". expand("%:t:r")
2624
+ elseif f == 'README'
2625
+ return "config/database.yml"
2626
+ elseif f =~ '\<config/database\.yml$'
2627
+ let lm = s:lastmethod()
2628
+ if lm != ""
2629
+ return "config/environments/".lm.".rb\nconfig/environment.rb"
2630
+ else
2631
+ return "config/environment.rb"
2632
+ endif
2633
+ elseif f =~ '\<config/routes\.rb$' | return "config/database.yml"
2634
+ elseif f =~ '\<config/environment\.rb$' | return "config/routes.rb"
2635
+ elseif f =~ '\<db/migrate/\d\d\d_'
2636
+ let num = matchstr(f,'\<db/migrate/0*\zs\d\+\ze_')+1
2637
+ let migr = s:migrationfor(num)
2638
+ return migr == '' ? "db/schema.rb" : migr
2639
+ elseif t =~ '^test\>' && f =~ '\<test/\w\+/'
2640
+ let target = s:sub(f,'.*<test/\w+/','test/mocks/test/')
2641
+ let target = s:sub(target,'_test\.rb$','.rb')
2642
+ return target
2643
+ elseif f =~ '\<application\.js$'
2644
+ return "app/helpers/application_helper.rb"
2645
+ elseif t =~ '^js\>'
2646
+ return "public/javascripts/application.js"
2647
+ elseif t =~ '^view-layout\>'
2648
+ return s:sub(s:sub(s:sub(f,'/views/','/controllers/'),'/layouts/(\k+)\..*$','/\1_controller.rb'),'<application_controller\.rb$','application.rb')
2649
+ "elseif t=~ '^view-partial\>'
2650
+ "call s:warn("No related file is defined")
2651
+ elseif t =~ '^view\>'
2652
+ let controller = s:sub(s:sub(f,'/views/','/controllers/'),'/(\k+%(\.\k+)=)\..*$','_controller.rb#\1')
2653
+ let controller2 = s:sub(s:sub(f,'/views/','/controllers/'),'/(\k+%(\.\k+)=)\..*$','.rb#\1')
2654
+ let model = s:sub(s:sub(f,'/views/','/models/'),'/(\k+)\..*$','.rb#\1')
2655
+ if filereadable(s:sub(controller,'#.{-}$',''))
2656
+ return controller
2657
+ elseif filereadable(s:sub(controller2,'#.{-}$',''))
2658
+ return controller2
2659
+ elseif filereadable(s:sub(model,'#.{-}$','')) || model =~ '_mailer\.rb#'
2660
+ return model
2661
+ else
2662
+ return controller
2663
+ endif
2664
+ elseif t =~ '^controller-api\>'
2665
+ return s:sub(s:sub(f,'/controllers/','/apis/'),'_controller\.rb$','_api.rb')
2666
+ elseif t =~ '^controller\>'
2667
+ return s:sub(s:sub(f,'/controllers/','/helpers/'),'%(_controller)=\.rb$','_helper.rb')
2668
+ elseif t=~ '^helper\>'
2669
+ return s:findlayout(s:controller())
2670
+ elseif t =~ '^model-arb\>'
2671
+ "call s:migrationEdit(0,cmd,'create_'.s:pluralize(expand('%:t:r')))
2672
+ return s:migrationfor('create_'.s:pluralize(expand('%:t:r')))
2673
+ elseif t =~ '^model-aro\>'
2674
+ return s:sub(f,'_observer\.rb$','.rb')
2675
+ elseif t =~ '^api\>'
2676
+ return s:sub(s:sub(f,'/apis/','/controllers/'),'_api\.rb$','_controller.rb')
2677
+ elseif f =~ '\<db/schema\.rb$'
2678
+ return s:migrationfor(1)
2679
+ else
2680
+ "call s:warn("No related file is defined")
2681
+ return ""
2682
+ endif
2683
+ endfunction
2684
+
2685
+ " }}}1
2686
+ " Partial Extraction {{{1
2687
+
2688
+ " Depends: s:error, s:sub, s:viewspattern, s:warn
2689
+
2690
+ function! s:Extract(bang,...) range abort
2691
+ if a:0 == 0 || a:0 > 1
2692
+ return s:error("Incorrect number of arguments")
2693
+ endif
2694
+ if a:1 =~ '[^a-z0-9_/.]'
2695
+ return s:error("Invalid partial name")
2696
+ endif
2697
+ let rails_root = RailsRoot()
2698
+ let ext = expand("%:e")
2699
+ let file = a:1
2700
+ let first = a:firstline
2701
+ let last = a:lastline
2702
+ let range = first.",".last
2703
+ if RailsFileType() =~ '^view-layout\>'
2704
+ if RailsFilePath() =~ '\<app/views/layouts/application\>'
2705
+ let curdir = 'app/views/shared'
2706
+ if file !~ '/'
2707
+ let file = "shared/" .file
2708
+ endif
2709
+ else
2710
+ let curdir = s:sub(RailsFilePath(),'.*<app/views/layouts/(.*)%(\.\w*)$','app/views/\1')
2711
+ endif
2712
+ else
2713
+ let curdir = fnamemodify(RailsFilePath(),':h')
2714
+ endif
2715
+ let curdir = rails_root."/".curdir
2716
+ let dir = fnamemodify(file,":h")
2717
+ let fname = fnamemodify(file,":t")
2718
+ if fnamemodify(fname,":e") == ""
2719
+ let name = fname
2720
+ let fname = fname.".".matchstr(expand("%:t"),'\.\zs.*')
2721
+ elseif fnamemodify(fname,":e") !~ '^'.s:viewspattern().'$'
2722
+ let name = fnamemodify(fname,":r")
2723
+ let fname = fname.".".ext
2724
+ else
2725
+ let name = fnamemodify(fname,":r:r")
2726
+ endif
2727
+ let var = "@".name
2728
+ let collection = ""
2729
+ if dir =~ '^/'
2730
+ let out = (rails_root).dir."/_".fname
2731
+ elseif dir == ""
2732
+ let out = (curdir)."/_".fname
2733
+ elseif isdirectory(curdir."/".dir)
2734
+ let out = (curdir)."/".dir."/_".fname
2735
+ else
2736
+ let out = (rails_root)."/app/views/".dir."/_".fname
2737
+ endif
2738
+ if filereadable(out)
2739
+ let partial_warn = 1
2740
+ "echoerr "Partial exists"
2741
+ "return
2742
+ endif
2743
+ if bufnr(out) > 0
2744
+ if bufloaded(out)
2745
+ return s:error("Partial already open in buffer ".bufnr(out))
2746
+ else
2747
+ exe "bwipeout ".bufnr(out)
2748
+ endif
2749
+ endif
2750
+ " No tabs, they'll just complicate things
2751
+ if ext =~? '^\%(rhtml\|erb\|dryml\)$'
2752
+ let erub1 = '\<\%\s*'
2753
+ let erub2 = '\s*-=\%\>'
2754
+ else
2755
+ let erub1 = ''
2756
+ let erub2 = ''
2757
+ endif
2758
+ let spaces = matchstr(getline(first),"^ *")
2759
+ if getline(last+1) =~ '\v^\s*'.erub1.'end'.erub2.'\s*$'
2760
+ let fspaces = matchstr(getline(last+1),"^ *")
2761
+ if getline(first-1) =~ '\v^'.fspaces.erub1.'for\s+(\k+)\s+in\s+([^ %>]+)'.erub2.'\s*$'
2762
+ let collection = s:sub(getline(first-1),'^'.fspaces.erub1.'for\s+(\k+)\s+in\s+([^ >]+)'.erub2.'\s*$','\1>\2')
2763
+ elseif getline(first-1) =~ '\v^'.fspaces.erub1.'([^ %>]+)\.each\s+do\s+\|\s*(\k+)\s*\|'.erub2.'\s*$'
2764
+ let collection = s:sub(getline(first-1),'^'.fspaces.erub1.'([^ %>]+)\.each\s+do\s+\|\s*(\k+)\s*\|'.erub2.'\s*$','\2>\1')
2765
+ endif
2766
+ if collection != ''
2767
+ let var = matchstr(collection,'^\k\+')
2768
+ let collection = s:sub(collection,'^\k+\>','')
2769
+ let first = first - 1
2770
+ let last = last + 1
2771
+ endif
2772
+ else
2773
+ let fspaces = spaces
2774
+ endif
2775
+ "silent exe range."write ".out
2776
+ let renderstr = "render :partial => '".fnamemodify(file,":r:r")."'"
2777
+ if collection != ""
2778
+ let renderstr = renderstr.", :collection => ".collection
2779
+ elseif "@".name != var
2780
+ let renderstr = renderstr.", :object => ".var
2781
+ endif
2782
+ if ext =~? '^\%(rhtml\|erb\|dryml\)$'
2783
+ let renderstr = "<%= ".renderstr." %>"
2784
+ elseif ext == "rxml" || ext == "builder"
2785
+ let renderstr = "xml << ".s:sub(renderstr,"render ","render(").")"
2786
+ elseif ext == "rjs"
2787
+ let renderstr = "page << ".s:sub(renderstr,"render ","render(").")"
2788
+ elseif ext == "haml"
2789
+ let renderstr = "= ".renderstr
2790
+ elseif ext == "mn"
2791
+ let renderstr = "_".renderstr
2792
+ endif
2793
+ let buf = @@
2794
+ silent exe range."yank"
2795
+ let partial = @@
2796
+ let @@ = buf
2797
+ let ai = &ai
2798
+ let &ai = 0
2799
+ silent exe "norm! :".first.",".last."change\<CR>".fspaces.renderstr."\<CR>.\<CR>"
2800
+ let &ai = ai
2801
+ if renderstr =~ '<%'
2802
+ norm ^6w
2803
+ else
2804
+ norm ^5w
2805
+ endif
2806
+ let ft = &ft
2807
+ if &hidden
2808
+ enew
2809
+ else
2810
+ new
2811
+ endif
2812
+ let shortout = fnamemodify(out,':~:.')
2813
+ "exe "silent file ".s:escarg(shortout)
2814
+ silent file `=shortout`
2815
+ let &ft = ft
2816
+ let @@ = partial
2817
+ silent put
2818
+ 0delete
2819
+ let @@ = buf
2820
+ if spaces != ""
2821
+ silent! exe '%substitute/^'.spaces.'//'
2822
+ endif
2823
+ silent! exe '%substitute?\%(\w\|[@:"'."'".'-]\)\@<!'.var.'\>?'.name.'?g'
2824
+ 1
2825
+ call RailsBufInit(rails_root)
2826
+ if exists("l:partial_warn")
2827
+ call s:warn("Warning: partial exists!")
2828
+ endif
2829
+ endfunction
2830
+
2831
+ " }}}1
2832
+ " Migration Inversion {{{1
2833
+
2834
+ " Depends: s:sub, s:endof, s:gsub, s:error
2835
+
2836
+ function! s:mkeep(str)
2837
+ " Things to keep (like comments) from a migration statement
2838
+ return matchstr(a:str,' #[^{].*')
2839
+ endfunction
2840
+
2841
+ function! s:mextargs(str,num)
2842
+ if a:str =~ '^\s*\w\+\s*('
2843
+ return s:sub(matchstr(a:str,'^\s*\w\+\s*\zs(\%([^,)]\+[,)]\)\{,'.a:num.'\}'),',$',')')
2844
+ else
2845
+ return s:sub(s:sub(matchstr(a:str,'\w\+\>\zs\s*\%([^,){ ]*[, ]*\)\{,'.a:num.'\}'),'[, ]*$',''),'^\s+',' ')
2846
+ endif
2847
+ endfunction
2848
+
2849
+ function! s:migspc(line)
2850
+ return matchstr(a:line,'^\s*')
2851
+ endfunction
2852
+
2853
+ function! s:invertrange(beg,end)
2854
+ let str = ""
2855
+ let lnum = a:beg
2856
+ while lnum <= a:end
2857
+ let line = getline(lnum)
2858
+ let add = ""
2859
+ if line == ''
2860
+ let add = ' '
2861
+ elseif line =~ '^\s*\(#[^{].*\)\=$'
2862
+ let add = line
2863
+ elseif line =~ '\<create_table\>'
2864
+ let add = s:migspc(line)."drop_table".s:mextargs(line,1).s:mkeep(line)
2865
+ let lnum = s:endof(lnum)
2866
+ elseif line =~ '\<drop_table\>'
2867
+ let add = s:sub(line,'<drop_table>\s*\(=\s*([^,){ ]*).*','create_table \1 do |t|'."\n".matchstr(line,'^\s*').'end').s:mkeep(line)
2868
+ elseif line =~ '\<add_column\>'
2869
+ let add = s:migspc(line).'remove_column'.s:mextargs(line,2).s:mkeep(line)
2870
+ elseif line =~ '\<remove_column\>'
2871
+ let add = s:sub(line,'<remove_column>','add_column')
2872
+ elseif line =~ '\<add_index\>'
2873
+ let add = s:migspc(line).'remove_index'.s:mextargs(line,1)
2874
+ let mat = matchstr(line,':name\s*=>\s*\zs[^ ,)]*')
2875
+ if mat != ''
2876
+ let add = s:sub(add,'\)=$',', :name => '.mat.'&')
2877
+ else
2878
+ let mat = matchstr(line,'\<add_index\>[^,]*,\s*\zs\%(\[[^]]*\]\|[:"'."'".']\w*["'."'".']\=\)')
2879
+ if mat != ''
2880
+ let add = s:sub(add,'\)=$',', :column => '.mat.'&')
2881
+ endif
2882
+ endif
2883
+ let add = add.s:mkeep(line)
2884
+ elseif line =~ '\<remove_index\>'
2885
+ let add = s:sub(s:sub(line,'<remove_index','add_index'),':column\s*=>\s*','')
2886
+ elseif line =~ '\<rename_\%(table\|column\)\>'
2887
+ let add = s:sub(line,'<rename_%(table\s*\(=\s*|column\s*\(=\s*[^,]*,\s*)\zs([^,]*)(,\s*)([^,]*)','\3\2\1')
2888
+ elseif line =~ '\<change_column\>'
2889
+ let add = s:migspc(line).'change_column'.s:mextargs(line,2).s:mkeep(line)
2890
+ elseif line =~ '\<change_column_default\>'
2891
+ let add = s:migspc(line).'change_column_default'.s:mextargs(line,2).s:mkeep(line)
2892
+ elseif line =~ '\.update_all(\(["'."'".']\).*\1)$' || line =~ '\.update_all \(["'."'".']\).*\1$'
2893
+ " .update_all('a = b') => .update_all('b = a')
2894
+ let pre = matchstr(line,'^.*\.update_all[( ][}'."'".'"]')
2895
+ let post = matchstr(line,'["'."'".'])\=$')
2896
+ let mat = strpart(line,strlen(pre),strlen(line)-strlen(pre)-strlen(post))
2897
+ let mat = s:gsub(','.mat.',','%(,\s*)@<=([^ ,=]{-})(\s*\=\s*)([^,=]{-})%(\s*,)@=','\3\2\1')
2898
+ let add = pre.s:sub(s:sub(mat,'^,',''),',$','').post
2899
+ elseif line =~ '^s\*\%(if\|unless\|while\|until\|for\)\>'
2900
+ let lnum = s:endof(lnum)
2901
+ endif
2902
+ if lnum == 0
2903
+ return -1
2904
+ endif
2905
+ if add == ""
2906
+ let add = s:sub(line,'^\s*\zs.*','raise ActiveRecord::IrreversableMigration')
2907
+ elseif add == " "
2908
+ let add = ""
2909
+ endif
2910
+ let str = add."\n".str
2911
+ let lnum = lnum + 1
2912
+ endwhile
2913
+ let str = s:gsub(str,'(\s*raise ActiveRecord::IrreversableMigration\n)+','\1')
2914
+ return str
2915
+ endfunction
2916
+
2917
+ function! s:Invert(bang)
2918
+ let err = "Could not parse method"
2919
+ let src = "up"
2920
+ let dst = "down"
2921
+ let beg = search('\%('.&l:define.'\).*'.src.'\>',"w")
2922
+ let end = s:endof(beg)
2923
+ if beg + 1 == end
2924
+ let src = "down"
2925
+ let dst = "up"
2926
+ let beg = search('\%('.&l:define.'\).*'.src.'\>',"w")
2927
+ let end = s:endof(beg)
2928
+ endif
2929
+ if !beg || !end
2930
+ return s:error(err)
2931
+ endif
2932
+ let str = s:invertrange(beg+1,end-1)
2933
+ if str == -1
2934
+ return s:error(err)
2935
+ endif
2936
+ let beg = search('\%('.&l:define.'\).*'.dst.'\>',"w")
2937
+ let end = s:endof(beg)
2938
+ if !beg || !end
2939
+ return s:error(err)
2940
+ endif
2941
+ if beg + 1 < end
2942
+ exe (beg+1).",".(end-1)."delete _"
2943
+ endif
2944
+ if str != ""
2945
+ let reg_keep = @"
2946
+ let @" = str
2947
+ exe beg."put"
2948
+ exe 1+beg
2949
+ let @" = reg_keep
2950
+ endif
2951
+ endfunction
2952
+
2953
+ " }}}1
2954
+ " Cache {{{1
2955
+
2956
+ function! s:cacheworks()
2957
+ if v:version < 700 || RailsRoot() == ""
2958
+ return 0
2959
+ endif
2960
+ if !exists("s:cache")
2961
+ let s:cache = {}
2962
+ endif
2963
+ if !has_key(s:cache,RailsRoot())
2964
+ let s:cache[RailsRoot()] = {}
2965
+ endif
2966
+ return 1
2967
+ endfunction
2968
+
2969
+ function! s:cacheclear(...)
2970
+ if RailsRoot() == "" | return "" | endif
2971
+ if !s:cacheworks() | return "" | endif
2972
+ if a:0 == 1
2973
+ if s:cachehas(a:1)
2974
+ unlet! s:cache[RailsRoot()][a:1]
2975
+ endif
2976
+ else
2977
+ let s:cache[RailsRoot()] = {}
2978
+ endif
2979
+ endfunction
2980
+
2981
+ function! s:cache(...)
2982
+ if !s:cacheworks() | return "" | endif
2983
+ if a:0 == 1
2984
+ return s:cache[RailsRoot()][a:1]
2985
+ else
2986
+ return s:cache[RailsRoot()]
2987
+ endif
2988
+ endfunction
2989
+
2990
+ "function! RailsCache(...)
2991
+ "if !s:cacheworks() | return "" | endif
2992
+ "if a:0 == 1
2993
+ "if s:cachehas(a:1)
2994
+ "return s:cache(a:1)
2995
+ "else
2996
+ "return ""
2997
+ "endif
2998
+ "else
2999
+ "return s:cache()
3000
+ "endif
3001
+ "endfunction
3002
+
3003
+ function! s:cachehas(key)
3004
+ if !s:cacheworks() | return "" | endif
3005
+ return has_key(s:cache(),a:key)
3006
+ endfunction
3007
+
3008
+ function! s:cacheneeds(key)
3009
+ if !s:cacheworks() | return "" | endif
3010
+ return !has_key(s:cache(),a:key)
3011
+ endfunction
3012
+
3013
+ function! s:cacheset(key,value)
3014
+ if !s:cacheworks() | return "" | endif
3015
+ let s:cache[RailsRoot()][a:key] = a:value
3016
+ endfunction
3017
+
3018
+ " }}}1
3019
+ " Syntax {{{1
3020
+
3021
+ " Depends: s:rubyeval, s:gsub, cache functions
3022
+
3023
+ function! s:resetomnicomplete()
3024
+ if exists("+completefunc") && &completefunc == 'syntaxcomplete#Complete'
3025
+ if exists("g:loaded_syntax_completion")
3026
+ " Ugly but necessary, until we have our own completion
3027
+ unlet g:loaded_syntax_completion
3028
+ silent! delfunction syntaxcomplete#Complete
3029
+ endif
3030
+ endif
3031
+ endfunction
3032
+
3033
+ function! s:helpermethods()
3034
+ let s:rails_helper_methods = ""
3035
+ \."atom_feed auto_discovery_link_tag auto_link "
3036
+ \."benchmark button_to button_to_function "
3037
+ \."cache capture cdata_section check_box check_box_tag collection_select concat content_for content_tag content_tag_for country_options_for_select country_select cycle "
3038
+ \."date_select datetime_select debug define_javascript_functions distance_of_time_in_words distance_of_time_in_words_to_now div_for dom_class dom_id draggable_element draggable_element_js drop_receiving_element drop_receiving_element_js "
3039
+ \."error_message_on error_messages_for escape_javascript escape_once evaluate_remote_response excerpt "
3040
+ \."field_set_tag fields_for file_field file_field_tag form form_for form_remote_for form_remote_tag form_tag "
3041
+ \."hidden_field hidden_field_tag highlight "
3042
+ \."image_path image_submit_tag image_tag input "
3043
+ \."javascript_cdata_section javascript_include_tag javascript_path javascript_tag "
3044
+ \."label label_tag link_to link_to_function link_to_if link_to_remote link_to_unless link_to_unless_current "
3045
+ \."mail_to markdown "
3046
+ \."number_to_currency number_to_human_size number_to_percentage number_to_phone number_with_delimiter number_with_precision "
3047
+ \."observe_field observe_form option_groups_from_collection_for_select options_for_select options_from_collection_for_select "
3048
+ \."partial_path password_field password_field_tag path_to_image path_to_javascript path_to_stylesheet periodically_call_remote pluralize "
3049
+ \."radio_button radio_button_tag remote_form_for remote_function reset_cycle "
3050
+ \."sanitize sanitize_css select select_date select_datetime select_day select_hour select_minute select_month select_second select_tag select_time select_year simple_format sortable_element sortable_element_js strip_links strip_tags stylesheet_link_tag stylesheet_path submit_tag submit_to_remote "
3051
+ \."tag text_area text_area_tag text_field text_field_tag textilize textilize_without_paragraph time_ago_in_words time_select time_zone_options_for_select time_zone_select truncate "
3052
+ \."update_page update_page_tag url_for "
3053
+ \."visual_effect "
3054
+ \."word_wrap"
3055
+
3056
+ " The list of helper methods used to be derived automatically. Let's keep
3057
+ " this code around in case it's needed again.
3058
+ if !exists("s:rails_helper_methods")
3059
+ if g:rails_expensive
3060
+ let s:rails_helper_methods = ""
3061
+ if has("ruby")
3062
+ " && (has("win32") || has("win32unix"))
3063
+ ruby begin; require 'rubygems'; rescue LoadError; end
3064
+ if exists("g:rubycomplete_rails") && g:rubycomplete_rails
3065
+ ruby begin; require VIM::evaluate('RailsRoot()')+'/config/environment'; rescue Exception; end
3066
+ else
3067
+ ruby begin; require 'active_support'; require 'action_controller'; require 'action_view'; rescue LoadError; end
3068
+ end
3069
+ ruby begin; h = ActionView::Helpers.constants.grep(/Helper$/).collect {|c|ActionView::Helpers.const_get c}.collect {|c| c.public_instance_methods(false)}.collect {|es| es.reject {|e| e =~ /_with(out)?_deprecation$/ || es.include?("#{e}_without_deprecation")}}.flatten.sort.uniq.reject {|m| m =~ /[=?!]$/}; VIM::command('let s:rails_helper_methods = "%s"' % h.join(" ")); rescue Exception; end
3070
+ endif
3071
+ if s:rails_helper_methods == ""
3072
+ let s:rails_helper_methods = s:rubyeval('require %{action_controller}; require %{action_view}; h = ActionView::Helpers.constants.grep(/Helper$/).collect {|c|ActionView::Helpers.const_get c}.collect {|c| c.public_instance_methods(false)}.collect {|es| es.reject {|e| e =~ /_with(out)?_deprecation$/ || es.include?(%{#{e}_without_deprecation})}}.flatten.sort.uniq.reject {|m| m =~ /[=?!]$/}; puts h.join(%{ })',"link_to")
3073
+ endif
3074
+ else
3075
+ let s:rails_helper_methods = "link_to"
3076
+ endif
3077
+ endif
3078
+ "let g:rails_helper_methods = s:rails_helper_methods
3079
+ return s:rails_helper_methods
3080
+ endfunction
3081
+
3082
+ function! s:BufSyntax()
3083
+ if (!exists("g:rails_syntax") || g:rails_syntax)
3084
+ let t = RailsFileType()
3085
+ let s:prototype_functions = "$ $$ $A $F $H $R $w"
3086
+ " From the Prototype bundle for TextMate
3087
+ let s:prototype_classes = "Prototype Class Abstract Try PeriodicalExecuter Enumerable Hash ObjectRange Element Ajax Responders Base Request Updater PeriodicalUpdater Toggle Insertion Before Top Bottom After ClassNames Form Serializers TimedObserver Observer EventObserver Event Position Effect Effect2 Transitions ScopedQueue Queues DefaultOptions Parallel Opacity Move MoveBy Scale Highlight ScrollTo Fade Appear Puff BlindUp BlindDown SwitchOff DropOut Shake SlideDown SlideUp Squish Grow Shrink Pulsate Fold"
3088
+
3089
+ let rails_helper_methods = '+\.\@<!\<\('.s:gsub(s:helpermethods(),'\s+','\\|').'\)\>+'
3090
+ let classes = s:gsub(RailsUserClasses(),'::',' ')
3091
+ if &syntax == 'ruby'
3092
+ if classes != ''
3093
+ exe "syn keyword rubyRailsUserClass ".classes." containedin=rubyClassDeclaration,rubyModuleDeclaration,rubyClass,rubyModule"
3094
+ endif
3095
+ if t == ''
3096
+ syn keyword rubyRailsMethod params request response session headers cookies flash
3097
+ endif
3098
+ if t =~ '^api\>'
3099
+ syn keyword rubyRailsAPIMethod api_method inflect_names
3100
+ endif
3101
+ if t =~ '^model$' || t =~ '^model-arb\>'
3102
+ syn keyword rubyRailsARMethod named_scope serialize
3103
+ syn keyword rubyRailsARAssociationMethod belongs_to has_one has_many has_and_belongs_to_many composed_of
3104
+ syn keyword rubyRailsARCallbackMethod before_create before_destroy before_save before_update before_validation before_validation_on_create before_validation_on_update
3105
+ syn keyword rubyRailsARCallbackMethod after_create after_destroy after_save after_update after_validation after_validation_on_create after_validation_on_update
3106
+ syn keyword rubyRailsARClassMethod attr_accessible attr_protected establish_connection set_inheritance_column set_locking_column set_primary_key set_sequence_name set_table_name
3107
+ syn keyword rubyRailsARValidationMethod validate validate_on_create validate_on_update validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
3108
+ syn keyword rubyRailsMethod logger
3109
+ endif
3110
+ if t =~ '^model-aro\>'
3111
+ syn keyword rubyRailsARMethod observe
3112
+ endif
3113
+ if t =~ '^model-mailer\>'
3114
+ syn keyword rubyRailsMethod logger
3115
+ " Misnomer but who cares
3116
+ syn keyword rubyRailsControllerMethod helper helper_attr helper_method
3117
+ endif
3118
+ if t =~ '^controller\>' || t =~ '^view\>' || t=~ '^helper\>'
3119
+ syn keyword rubyRailsMethod params request response session headers cookies flash
3120
+ syn match rubyRailsError '[@:]\@<!@\%(params\|request\|response\|session\|headers\|cookies\|flash\)\>'
3121
+ syn match rubyRailsError '\<\%(render_partial\|puts\)\>'
3122
+ syn keyword rubyRailsRenderMethod render
3123
+ syn keyword rubyRailsMethod logger
3124
+ endif
3125
+ if t =~ '^helper\>' || t=~ '^view\>'
3126
+ "exe "syn match rubyRailsHelperMethod ".rails_helper_methods
3127
+ exe "syn keyword rubyRailsHelperMethod ".s:sub(s:helpermethods(),'<select\s+','')
3128
+ syn match rubyRailsHelperMethod '\<select\>\%(\s*{\|\s*do\>\|\s*(\=\s*&\)\@!'
3129
+ syn match rubyRailsViewMethod '\.\@<!\<\(h\|html_escape\|u\|url_encode\|controller\)\>'
3130
+ if t =~ '\<partial\>'
3131
+ syn keyword rubyRailsMethod local_assigns
3132
+ endif
3133
+ "syn keyword rubyRailsDeprecatedMethod start_form_tag end_form_tag link_to_image human_size update_element_function
3134
+ elseif t =~ '^controller\>'
3135
+ syn keyword rubyRailsControllerMethod helper helper_attr helper_method filter layout url_for serialize exempt_from_layout filter_parameter_logging hide_action cache_sweeper
3136
+ syn match rubyRailsDeprecatedMethod '\<render_\%(action\|text\|file\|template\|nothing\|without_layout\)\>'
3137
+ syn keyword rubyRailsRenderMethod render_to_string redirect_to head
3138
+ syn match rubyRailsRenderMethod '\<respond_to\>?\@!'
3139
+ syn keyword rubyRailsFilterMethod before_filter append_before_filter prepend_before_filter after_filter append_after_filter prepend_after_filter around_filter append_around_filter prepend_around_filter skip_before_filter skip_after_filter
3140
+ syn keyword rubyRailsFilterMethod verify
3141
+ endif
3142
+ if t =~ '^\%(db-\)\=\%(migration\|schema\)\>'
3143
+ syn keyword rubyRailsMigrationMethod create_table change_table drop_table rename_table add_column rename_column change_column change_column_default remove_column add_index remove_index
3144
+ endif
3145
+ if t =~ '^test\>'
3146
+ if s:cacheneeds("user_asserts") && filereadable(RailsRoot()."/test/test_helper.rb")
3147
+ call s:cacheset("user_asserts",map(filter(readfile(RailsRoot()."/test/test_helper.rb"),'v:val =~ "^ def assert_"'),'matchstr(v:val,"^ def \\zsassert_\\w\\+")'))
3148
+ endif
3149
+ if s:cachehas("user_asserts") && !empty(s:cache("user_asserts"))
3150
+ exe "syn keyword rubyRailsUserMethod ".join(s:cache("user_asserts"))
3151
+ endif
3152
+ syn keyword rubyRailsTestMethod add_assertion assert assert_block assert_equal assert_in_delta assert_instance_of assert_kind_of assert_match assert_nil assert_no_match assert_not_equal assert_not_nil assert_not_same assert_nothing_raised assert_nothing_thrown assert_operator assert_raise assert_respond_to assert_same assert_send assert_throws assert_recognizes assert_generates assert_routing flunk fixtures fixture_path use_transactional_fixtures use_instantiated_fixtures assert_difference assert_no_difference assert_valid
3153
+ if t !~ '^test-unit\>'
3154
+ syn match rubyRailsTestControllerMethod '\.\@<!\<\%(get\|post\|put\|delete\|head\|process\|assigns\)\>'
3155
+ syn keyword rubyRailsTestControllerMethod assert_response assert_redirected_to assert_template assert_recognizes assert_generates assert_routing assert_dom_equal assert_dom_not_equal assert_select assert_select_rjs assert_select_encoded assert_select_email assert_tag assert_no_tag
3156
+ endif
3157
+ elseif t=~ '^spec\>'
3158
+ syn keyword rubyRailsTestMethod describe context it specify it_should_behave_like before after fixtures controller_name helper_name
3159
+ syn keyword rubyRailsTestMethod violated pending
3160
+ if t !~ '^spec-model\>'
3161
+ syn match rubyRailsTestControllerMethod '\.\@<!\<\%(get\|post\|put\|delete\|head\|process\|assigns\)\>'
3162
+ syn keyword rubyRailsTestControllerMethod integrate_views
3163
+ syn keyword rubyRailsMethod params request response session flash
3164
+ endif
3165
+ endif
3166
+ if t =~ '^task\>'
3167
+ syn match rubyRailsRakeMethod '^\s*\zs\%(task\|file\|namespace\|desc\|before\|after\|on\)\>\%(\s*=\)\@!'
3168
+ endif
3169
+ if t =~ '^model-awss\>'
3170
+ syn keyword rubyRailsMethod member
3171
+ endif
3172
+ if t =~ '^config-routes\>'
3173
+ syn match rubyRailsMethod '\.\zs\%(connect\|resources\=\|root\|named_route\|namespace\)\>'
3174
+ endif
3175
+ syn keyword rubyRailsMethod debugger
3176
+ syn keyword rubyRailsMethod alias_attribute alias_method_chain attr_accessor_with_default attr_internal attr_internal_accessor attr_internal_reader attr_internal_writer delegate mattr_accessor mattr_reader mattr_writer superclass_delegating_accessor superclass_delegating_reader superclass_delegating_writer
3177
+ syn keyword rubyRailsMethod cattr_accessor cattr_reader cattr_writer class_inheritable_accessor class_inheritable_array class_inheritable_array_writer class_inheritable_hash class_inheritable_hash_writer class_inheritable_option class_inheritable_reader class_inheritable_writer inheritable_attributes read_inheritable_attribute reset_inheritable_attributes write_inheritable_array write_inheritable_attribute write_inheritable_hash
3178
+ syn keyword rubyRailsInclude require_dependency gem
3179
+
3180
+ syn region rubyString matchgroup=rubyStringDelimiter start=+\%(:order\s*=>\s*\)\@<="+ skip=+\\\\\|\\"+ end=+"+ contains=@rubyStringSpecial,railsOrderSpecial
3181
+ syn region rubyString matchgroup=rubyStringDelimiter start=+\%(:order\s*=>\s*\)\@<='+ skip=+\\\\\|\\'+ end=+'+ contains=@rubyStringSpecial,railsOrderSpecial
3182
+ syn match railsOrderSpecial +\c\<\%(DE\|A\)SC\>+ contained
3183
+ syn region rubyString matchgroup=rubyStringDelimiter start=+\%(:conditions\s*=>\s*\[\s*\)\@<="+ skip=+\\\\\|\\"+ end=+"+ contains=@rubyStringSpecial,railsConditionsSpecial
3184
+ syn region rubyString matchgroup=rubyStringDelimiter start=+\%(:conditions\s*=>\s*\[\s*\)\@<='+ skip=+\\\\\|\\'+ end=+'+ contains=@rubyStringSpecial,railsConditionsSpecial
3185
+ syn match railsConditionsSpecial +?\|:\h\w*+ contained
3186
+ syn cluster rubyNotTop add=railsOrderSpecial,railsConditionsSpecial
3187
+
3188
+ " XHTML highlighting inside %Q<>
3189
+ unlet! b:current_syntax
3190
+ let removenorend = !exists("g:html_no_rendering")
3191
+ let g:html_no_rendering = 1
3192
+ syn include @htmlTop syntax/xhtml.vim
3193
+ if removenorend
3194
+ unlet! g:html_no_rendering
3195
+ endif
3196
+ let b:current_syntax = "ruby"
3197
+ " Restore syn sync, as best we can
3198
+ if !exists("g:ruby_minlines")
3199
+ let g:ruby_minlines = 50
3200
+ endif
3201
+ syn sync fromstart
3202
+ exe "syn sync minlines=" . g:ruby_minlines
3203
+ syn case match
3204
+ syn region rubyString matchgroup=rubyStringDelimiter start=+%Q\=<+ end=+>+ contains=@htmlTop,@rubyStringSpecial
3205
+ "syn region rubyString matchgroup=rubyStringDelimiter start=+%q<+ end=+>+ contains=@htmlTop
3206
+ syn cluster htmlArgCluster add=@rubyStringSpecial
3207
+ syn cluster htmlPreProc add=@rubyStringSpecial
3208
+
3209
+ elseif &syntax == "eruby" || &syntax == "haml"
3210
+ syn case match
3211
+ if classes != ''
3212
+ exe "syn keyword erubyRailsUserClass ".classes." contained containedin=@erubyRailsRegions"
3213
+ endif
3214
+ if &syntax == "haml"
3215
+ syn cluster erubyRailsRegions contains=hamlRubyCodeIncluded,hamlRubyCode,hamlRubyHash,@hamlEmbeddedRuby,rubyInterpolation
3216
+ else
3217
+ syn cluster erubyRailsRegions contains=erubyOneLiner,erubyBlock,erubyExpression,rubyInterpolation
3218
+ endif
3219
+ syn match rubyRailsError '[@:]\@<!@\%(params\|request\|response\|session\|headers\|cookies\|flash\)\>' contained containedin=@erubyRailsRegions
3220
+ exe "syn keyword erubyRailsHelperMethod ".s:sub(s:helpermethods(),'<select\s+','')." contained containedin=@erubyRailsRegions"
3221
+ syn match erubyRailsHelperMethod '\<select\>\%(\s*{\|\s*do\>\|\s*(\=\s*&\)\@!' contained containedin=@erubyRailsRegions
3222
+ syn keyword erubyRailsMethod debugger logger contained containedin=@erubyRailsRegions
3223
+ syn keyword erubyRailsMethod params request response session headers cookies flash contained containedin=@erubyRailsRegions
3224
+ syn match erubyRailsViewMethod '\.\@<!\<\(h\|html_escape\|u\|url_encode\|controller\)\>' contained containedin=@erubyRailsRegions
3225
+ if t =~ '\<partial\>'
3226
+ syn keyword erubyRailsMethod local_assigns contained containedin=@erubyRailsRegions
3227
+ endif
3228
+ syn keyword erubyRailsRenderMethod render contained containedin=@erubyRailsRegions
3229
+ syn match rubyRailsError '[^@:]\@<!@\%(params\|request\|response\|session\|headers\|cookies\|flash\)\>' contained containedin=@erubyRailsRegions
3230
+ syn match rubyRailsError '\<\%(render_partial\|puts\)\>' contained containedin=@erubyRailsRegions
3231
+ syn case match
3232
+ set isk+=$
3233
+ exe "syn keyword javascriptRailsClass contained ".s:prototype_classes
3234
+ exe "syn keyword javascriptRailsFunction contained ".s:prototype_functions
3235
+ syn cluster htmlJavaScript add=javascriptRailsClass,javascriptRailsFunction
3236
+ elseif &syntax == "yaml"
3237
+ syn case match
3238
+ " Modeled after syntax/eruby.vim
3239
+ unlet! b:current_syntax
3240
+ let g:main_syntax = 'eruby'
3241
+ syn include @rubyTop syntax/ruby.vim
3242
+ unlet g:main_syntax
3243
+ syn cluster yamlRailsRegions contains=yamlRailsOneLiner,yamlRailsBlock,yamlRailsExpression
3244
+ syn region yamlRailsOneLiner matchgroup=yamlRailsDelimiter start="^%%\@!" end="$" contains=@rubyRailsTop containedin=ALLBUT,@yamlRailsRegions,yamlRailsComment keepend oneline
3245
+ syn region yamlRailsBlock matchgroup=yamlRailsDelimiter start="<%%\@!" end="%>" contains=@rubyTop containedin=ALLBUT,@yamlRailsRegions,yamlRailsComment
3246
+ syn region yamlRailsExpression matchgroup=yamlRailsDelimiter start="<%=" end="%>" contains=@rubyTop containedin=ALLBUT,@yamlRailsRegions,yamlRailsComment
3247
+ syn region yamlRailsComment matchgroup=yamlRailsDelimiter start="<%#" end="%>" contains=rubyTodo,@Spell containedin=ALLBUT,@yamlRailsRegions,yamlRailsComment keepend
3248
+ syn match yamlRailsMethod '\.\@<!\<\(h\|html_escape\|u\|url_encode\)\>' contained containedin=@yamlRailsRegions
3249
+ if classes != ''
3250
+ exe "syn keyword yamlRailsUserClass ".classes." contained containedin=@yamlRailsRegions"
3251
+ endif
3252
+ let b:current_syntax = "yaml"
3253
+ elseif &syntax == "html"
3254
+ syn case match
3255
+ set isk+=$
3256
+ exe "syn keyword javascriptRailsClass contained ".s:prototype_classes
3257
+ exe "syn keyword javascriptRailsFunction contained ".s:prototype_functions
3258
+ syn cluster htmlJavaScript add=javascriptRailsClass,javascriptRailsFunction
3259
+ elseif &syntax == "javascript"
3260
+ " The syntax file included with Vim incorrectly sets syn case ignore.
3261
+ syn case match
3262
+ set isk+=$
3263
+ exe "syn keyword javascriptRailsClass ".s:prototype_classes
3264
+ exe "syn keyword javascriptRailsFunction ".s:prototype_functions
3265
+
3266
+ endif
3267
+ endif
3268
+ call s:HiDefaults()
3269
+ endfunction
3270
+
3271
+ function! s:HiDefaults()
3272
+ hi def link rubyRailsAPIMethod rubyRailsMethod
3273
+ hi def link rubyRailsARAssociationMethod rubyRailsARMethod
3274
+ hi def link rubyRailsARCallbackMethod rubyRailsARMethod
3275
+ hi def link rubyRailsARClassMethod rubyRailsARMethod
3276
+ hi def link rubyRailsARValidationMethod rubyRailsARMethod
3277
+ hi def link rubyRailsARMethod rubyRailsMethod
3278
+ hi def link rubyRailsRenderMethod rubyRailsMethod
3279
+ hi def link rubyRailsHelperMethod rubyRailsMethod
3280
+ hi def link rubyRailsViewMethod rubyRailsMethod
3281
+ hi def link rubyRailsMigrationMethod rubyRailsMethod
3282
+ hi def link rubyRailsControllerMethod rubyRailsMethod
3283
+ hi def link rubyRailsDeprecatedMethod rubyRailsError
3284
+ hi def link rubyRailsFilterMethod rubyRailsMethod
3285
+ hi def link rubyRailsTestControllerMethod rubyRailsTestMethod
3286
+ hi def link rubyRailsTestMethod rubyRailsMethod
3287
+ hi def link rubyRailsRakeMethod rubyRailsMethod
3288
+ hi def link rubyRailsMethod railsMethod
3289
+ hi def link rubyRailsError rubyError
3290
+ hi def link rubyRailsInclude rubyInclude
3291
+ hi def link rubyRailsUserClass railsUserClass
3292
+ hi def link rubyRailsUserMethod railsUserMethod
3293
+ hi def link erubyRailsHelperMethod erubyRailsMethod
3294
+ hi def link erubyRailsViewMethod erubyRailsMethod
3295
+ hi def link erubyRailsRenderMethod erubyRailsMethod
3296
+ hi def link erubyRailsMethod railsMethod
3297
+ hi def link erubyRailsUserMethod railsUserMethod
3298
+ hi def link railsUserMethod railsMethod
3299
+ hi def link erubyRailsUserClass railsUserClass
3300
+ hi def link yamlRailsDelimiter Delimiter
3301
+ hi def link yamlRailsMethod railsMethod
3302
+ hi def link yamlRailsComment Comment
3303
+ hi def link yamlRailsUserClass railsUserClass
3304
+ hi def link yamlRailsUserMethod railsUserMethod
3305
+ hi def link javascriptRailsFunction railsMethod
3306
+ hi def link javascriptRailsClass railsClass
3307
+ hi def link railsUserClass railsClass
3308
+ hi def link railsMethod Function
3309
+ hi def link railsClass Type
3310
+ hi def link railsOrderSpecial railsStringSpecial
3311
+ hi def link railsConditionsSpecial railsStringSpecial
3312
+ hi def link railsStringSpecial Identifier
3313
+ endfunction
3314
+
3315
+ function! RailslogSyntax()
3316
+ syn match railslogRender '^\s*\<\%(Processing\|Rendering\|Rendered\|Redirected\|Completed\)\>'
3317
+ syn match railslogComment '^\s*# .*'
3318
+ syn match railslogModel '^\s*\u\%(\w\|:\)* \%(Load\%( Including Associations\| IDs For Limited Eager Loading\)\=\|Columns\|Count\|Update\|Destroy\|Delete all\)\>' skipwhite nextgroup=railslogModelNum
3319
+ syn match railslogModel '^\s*SQL\>' skipwhite nextgroup=railslogModelNum
3320
+ syn region railslogModelNum start='(' end=')' contains=railslogNumber contained skipwhite nextgroup=railslogSQL
3321
+ syn match railslogSQL '\u.*$' contained
3322
+ " Destroy generates multiline SQL, ugh
3323
+ syn match railslogSQL '^ \%(FROM\|WHERE\|ON\|AND\|OR\|ORDER\) .*$'
3324
+ syn match railslogNumber '\<\d\+\>%'
3325
+ syn match railslogNumber '[ (]\@<=\<\d\+\.\d\+\>'
3326
+ syn region railslogString start='"' skip='\\"' end='"' oneline contained
3327
+ syn region railslogHash start='{' end='}' oneline contains=railslogHash,railslogString
3328
+ syn match railslogIP '\<\d\{1,3\}\%(\.\d\{1,3}\)\{3\}\>'
3329
+ syn match railslogTimestamp '\<\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\>'
3330
+ syn match railslogSessionID '\<\x\{32\}\>'
3331
+ syn match railslogIdentifier '^\s*\%(Session ID\|Parameters\)\ze:'
3332
+ syn match railslogSuccess '\<2\d\d \u[A-Za-z0-9 ]*\>'
3333
+ syn match railslogRedirect '\<3\d\d \u[A-Za-z0-9 ]*\>'
3334
+ syn match railslogError '\<[45]\d\d \u[A-Za-z0-9 ]*\>'
3335
+ syn match railslogError '^DEPRECATION WARNING\>'
3336
+ syn keyword railslogHTTP OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT
3337
+ syn region railslogStackTrace start=":\d\+:in `\w\+'$" end="^\s*$" keepend fold
3338
+ hi def link railslogComment Comment
3339
+ hi def link railslogRender Keyword
3340
+ hi def link railslogModel Type
3341
+ hi def link railslogSQL PreProc
3342
+ hi def link railslogNumber Number
3343
+ hi def link railslogString String
3344
+ hi def link railslogSessionID Constant
3345
+ hi def link railslogIdentifier Identifier
3346
+ hi def link railslogRedirect railslogSuccess
3347
+ hi def link railslogSuccess Special
3348
+ hi def link railslogError Error
3349
+ hi def link railslogHTTP Special
3350
+ endfunction
3351
+
3352
+ " }}}1
3353
+ " Statusline {{{1
3354
+
3355
+ " Depends: nothing!
3356
+ " Provides: s:BufInitStatusline
3357
+
3358
+ function! s:addtostatus(letter,status)
3359
+ let status = a:status
3360
+ if status !~ 'Rails' && g:rails_statusline
3361
+ let status=substitute(status,'\C%'.tolower(a:letter),'%'.tolower(a:letter).'%{RailsStatusline()}','')
3362
+ if status !~ 'Rails'
3363
+ let status=substitute(status,'\C%'.toupper(a:letter),'%'.toupper(a:letter).'%{RailsSTATUSLINE()}','')
3364
+ endif
3365
+ endif
3366
+ return status
3367
+ endfunction
3368
+
3369
+ function! s:BufInitStatusline()
3370
+ if g:rails_statusline
3371
+ if &l:statusline == ''
3372
+ let &l:statusline = &g:statusline
3373
+ endif
3374
+ if &l:statusline == ''
3375
+ let &l:statusline='%<%f %h%m%r%='
3376
+ if &ruler
3377
+ let &l:statusline = &l:statusline . '%-16( %l,%c-%v %)%P'
3378
+ endif
3379
+ endif
3380
+ let &l:statusline = s:InjectIntoStatusline(&l:statusline)
3381
+ endif
3382
+ endfunction
3383
+
3384
+ function! s:InitStatusline()
3385
+ if g:rails_statusline
3386
+ if &g:statusline == ''
3387
+ let &g:statusline='%<%f %h%m%r%='
3388
+ if &ruler
3389
+ let &g:statusline = &g:statusline . '%-16( %l,%c-%v %)%P'
3390
+ endif
3391
+ endif
3392
+ let &g:statusline = s:InjectIntoStatusline(&g:statusline)
3393
+ endif
3394
+ endfunction
3395
+
3396
+ function! s:InjectIntoStatusline(status)
3397
+ let status = a:status
3398
+ if status !~ 'Rails'
3399
+ let status = s:addtostatus('y',status)
3400
+ let status = s:addtostatus('r',status)
3401
+ let status = s:addtostatus('m',status)
3402
+ let status = s:addtostatus('w',status)
3403
+ let status = s:addtostatus('h',status)
3404
+ if status !~ 'Rails'
3405
+ let status=substitute(status,'%=','%{RailsStatusline()}%=','')
3406
+ endif
3407
+ if status !~ 'Rails' && status != ''
3408
+ let status=status.'%{RailsStatusline()}'
3409
+ endif
3410
+ endif
3411
+ return status
3412
+ endfunction
3413
+
3414
+ function! RailsStatusline()
3415
+ if exists("b:rails_root")
3416
+ let t = RailsFileType()
3417
+ if t != ""
3418
+ return "[Rails-".t."]"
3419
+ else
3420
+ return "[Rails]"
3421
+ endif
3422
+ else
3423
+ return ""
3424
+ endif
3425
+ endfunction
3426
+
3427
+ function! RailsSTATUSLINE()
3428
+ if exists("b:rails_root")
3429
+ let t = RailsFileType()
3430
+ if t != ""
3431
+ return ",RAILS-".toupper(t)
3432
+ else
3433
+ return ",RAILS"
3434
+ endif
3435
+ else
3436
+ return ""
3437
+ endif
3438
+ endfunction
3439
+
3440
+ " }}}1
3441
+ " Mappings {{{1
3442
+
3443
+ " Depends: nothing!
3444
+ " Exports: s:BufMappings
3445
+
3446
+ function! s:BufMappings()
3447
+ map <buffer> <silent> <Plug>RailsAlternate :A<CR>
3448
+ map <buffer> <silent> <Plug>RailsRelated :R<CR>
3449
+ map <buffer> <silent> <Plug>RailsFind :REfind<CR>
3450
+ map <buffer> <silent> <Plug>RailsSplitFind :RSfind<CR>
3451
+ map <buffer> <silent> <Plug>RailsVSplitFind :RVfind<CR>
3452
+ map <buffer> <silent> <Plug>RailsTabFind :RTfind<CR>
3453
+ if g:rails_mappings
3454
+ if !hasmapto("<Plug>RailsFind")
3455
+ nmap <buffer> gf <Plug>RailsFind
3456
+ endif
3457
+ if !hasmapto("<Plug>RailsSplitFind")
3458
+ nmap <buffer> <C-W>f <Plug>RailsSplitFind
3459
+ endif
3460
+ if !hasmapto("<Plug>RailsTabFind")
3461
+ nmap <buffer> <C-W>gf <Plug>RailsTabFind
3462
+ endif
3463
+ if !hasmapto("<Plug>RailsAlternate")
3464
+ nmap <buffer> [f <Plug>RailsAlternate
3465
+ endif
3466
+ if !hasmapto("<Plug>RailsRelated")
3467
+ nmap <buffer> ]f <Plug>RailsRelated
3468
+ endif
3469
+ if exists("$CREAM")
3470
+ imap <buffer> <C-CR> <C-O><Plug>RailsFind
3471
+ " Are these a good idea?
3472
+ imap <buffer> <M-[> <C-O><Plug>RailsAlternate
3473
+ imap <buffer> <M-]> <C-O><Plug>RailsRelated
3474
+ endif
3475
+ endif
3476
+ " SelectBuf you're a dirty hack
3477
+ let v:errmsg = ""
3478
+ endfunction
3479
+
3480
+ " }}}1
3481
+ " Project {{{
3482
+
3483
+ " Depends: s:gsub, s:escarg, s:warn, s:sub, s:relglob
3484
+
3485
+ function! s:Project(bang,arg)
3486
+ let rr = RailsRoot()
3487
+ exe "Project ".a:arg
3488
+ let line = search('^[^ =]*="'.s:gsub(rr,'[\/]','[\\/]').'"')
3489
+ let projname = s:gsub(fnamemodify(rr,':t'),'\=','-') " .'_on_rails'
3490
+ if line && a:bang
3491
+ let projname = matchstr(getline('.'),'^[^=]*')
3492
+ " Most of this would be unnecessary if the project.vim author had just put
3493
+ " the newlines AFTER each project rather than before. Ugh.
3494
+ norm zR0"_d%
3495
+ if line('.') > 2
3496
+ delete _
3497
+ endif
3498
+ if line('.') != line('$')
3499
+ .-2
3500
+ endif
3501
+ let line = 0
3502
+ elseif !line
3503
+ $
3504
+ endif
3505
+ if !line
3506
+ if line('.') > 1
3507
+ append
3508
+
3509
+ .
3510
+ endif
3511
+ let line = line('.')+1
3512
+ call s:NewProject(projname,rr,a:bang)
3513
+ endif
3514
+ normal! zMzo
3515
+ if search("^ app=app {","W",line+10)
3516
+ normal! zo
3517
+ exe line
3518
+ endif
3519
+ normal! 0zt
3520
+ endfunction
3521
+
3522
+ function! s:NewProject(proj,rr,fancy)
3523
+ let line = line('.')+1
3524
+ let template = s:NewProjectTemplate(a:proj,a:rr,a:fancy)
3525
+ silent put =template
3526
+ exe line
3527
+ " Ugh. how else can I force detecting folds?
3528
+ setlocal foldmethod=manual
3529
+ norm! $%
3530
+ silent exe "doautocmd User ".s:escarg(a:rr)."/Rproject"
3531
+ let newline = line('.')
3532
+ exe line
3533
+ norm! $%
3534
+ if line('.') != newline
3535
+ call s:warn("Warning: Rproject autocommand failed to leave cursor at end of project")
3536
+ endif
3537
+ exe line
3538
+ setlocal foldmethod=marker
3539
+ setlocal nomodified
3540
+ " FIXME: make undo stop here
3541
+ if !exists("g:maplocalleader")
3542
+ silent! normal \R
3543
+ else " Needs to be tested
3544
+ exe 'silent! normal '.g:maplocalleader.'R'
3545
+ endif
3546
+ endfunction
3547
+
3548
+ function! s:NewProjectTemplate(proj,rr,fancy)
3549
+ let str = a:proj.'="'.a:rr."\" CD=. filter=\"*\" {\n"
3550
+ let str = str." app=app {\n"
3551
+ if isdirectory(a:rr.'/app/apis')
3552
+ let str = str." apis=apis {\n }\n"
3553
+ endif
3554
+ let str = str." controllers=controllers filter=\"**\" {\n }\n"
3555
+ let str = str." helpers=helpers filter=\"**\" {\n }\n"
3556
+ let str = str." models=models filter=\"**\" {\n }\n"
3557
+ if a:fancy
3558
+ let str = str." views=views {\n"
3559
+ let views = s:relglob(a:rr.'/app/views/','*')."\n"
3560
+ while views != ''
3561
+ let dir = matchstr(views,'^.\{-\}\ze\n')
3562
+ let views = s:sub(views,'^.{-}\n','')
3563
+ let str = str." ".dir."=".dir.' filter="**" {'."\n }\n"
3564
+ endwhile
3565
+ let str = str." }\n"
3566
+ else
3567
+ let str = str." views=views filter=\"**\" {\n }\n"
3568
+ endif
3569
+ let str = str . " }\n"
3570
+ let str = str . " config=config {\n environments=environments {\n }\n }\n"
3571
+ let str = str . " db=db {\n"
3572
+ if isdirectory(a:rr.'/db/migrate')
3573
+ let str = str . " migrate=migrate {\n }\n"
3574
+ endif
3575
+ let str = str . " }\n"
3576
+ let str = str . " lib=lib filter=\"* */**/*.rb \" {\n tasks=tasks filter=\"**/*.rake\" {\n }\n }\n"
3577
+ let str = str . " public=public {\n images=images {\n }\n javascripts=javascripts {\n }\n stylesheets=stylesheets {\n }\n }\n"
3578
+ if isdirectory(a:rr.'/spec')
3579
+ let str = str . " spec=spec {\n"
3580
+ let str = str . " controllers=controllers filter=\"**\" {\n }\n"
3581
+ let str = str . " fixtures=fixtures filter=\"**\" {\n }\n"
3582
+ let str = str . " helpers=helpers filter=\"**\" {\n }\n"
3583
+ let str = str . " models=models filter=\"**\" {\n }\n"
3584
+ let str = str . " views=views filter=\"**\" {\n }\n }\n"
3585
+ endif
3586
+ let str = str . " test=test {\n"
3587
+ if isdirectory(a:rr.'/test/fixtures')
3588
+ let str = str . " fixtures=fixtures filter=\"**\" {\n }\n"
3589
+ endif
3590
+ if isdirectory(a:rr.'/test/functional')
3591
+ let str = str . " functional=functional filter=\"**\" {\n }\n"
3592
+ endif
3593
+ if isdirectory(a:rr.'/test/integration')
3594
+ let str = str . " integration=integration filter=\"**\" {\n }\n"
3595
+ endif
3596
+ if isdirectory(a:rr.'/test/mocks')
3597
+ let str = str . " mocks=mocks filter=\"**\" {\n }\n"
3598
+ endif
3599
+ if isdirectory(a:rr.'/test/unit')
3600
+ let str = str . " unit=unit filter=\"**\" {\n }\n"
3601
+ endif
3602
+ let str = str . " }\n}\n"
3603
+ return str
3604
+ endfunction
3605
+
3606
+ " }}}1
3607
+ " Database {{{1
3608
+
3609
+ " Depends: s:environment, s:rubyeval, s:rv, reloadability
3610
+
3611
+ function! s:extractdbvar(str,arg)
3612
+ return matchstr("\n".a:str."\n",'\n'.a:arg.'=\zs.\{-\}\ze\n')
3613
+ endfunction
3614
+
3615
+ function! s:BufDatabase(...)
3616
+ if exists("s:lock_database")
3617
+ return
3618
+ endif
3619
+ let s:lock_database = 1
3620
+ let rv = s:rv()
3621
+ if (a:0 && a:1 > 1)
3622
+ unlet! s:dbext_type_{rv}
3623
+ endif
3624
+ if (a:0 > 1 && a:2 != '')
3625
+ let env = a:2
3626
+ else
3627
+ let env = s:environment()
3628
+ endif
3629
+ " Crude caching mechanism
3630
+ if !exists("s:dbext_type_".rv)
3631
+ if exists("g:loaded_dbext") && (g:rails_dbext + (a:0 ? a:1 : 0)) > 0 && filereadable(RailsRoot()."/config/database.yml")
3632
+ " Ideally we would filter this through ERB but that could be insecure.
3633
+ " It might be possible to make use of taint checking.
3634
+ let out = ""
3635
+ if has("ruby")
3636
+ ruby require 'yaml'; VIM::command('let out = %s' % File.open(VIM::evaluate("RailsRoot()")+"/config/database.yml") {|f| y = YAML::load(f); e = y[VIM::evaluate("env")]; i=0; e=y[e] while e.respond_to?(:to_str) && (i+=1)<16; e.map {|k,v| "#{k}=#{v}\n" if v}.compact.join }.inspect) rescue nil
3637
+ endif
3638
+ if out == ""
3639
+ let cmdb = 'require %{yaml}; File.open(%q{'.RailsRoot().'/config/database.yml}) {|f| y = YAML::load(f); e = y[%{'
3640
+ let cmde = '}]; i=0; e=y[e] while e.respond_to?(:to_str) && (i+=1)<16; e.each{|k,v|puts k.to_s+%{=}+v.to_s}}'
3641
+ if a:0 ? a:1 : g:rails_expensive
3642
+ let out = s:rubyeval(cmdb.env.cmde,'')
3643
+ else
3644
+ unlet! s:lock_database
3645
+ return
3646
+ endif
3647
+ endif
3648
+ let adapter = s:extractdbvar(out,'adapter')
3649
+ let s:dbext_bin_{rv} = ''
3650
+ let s:dbext_integratedlogin_{rv} = ''
3651
+ if adapter == 'postgresql'
3652
+ let adapter = 'pgsql'
3653
+ elseif adapter == 'sqlite3'
3654
+ let adapter = 'sqlite'
3655
+ " Does not appear to work
3656
+ let s:dbext_bin = 'sqlite3'
3657
+ elseif adapter == 'sqlserver'
3658
+ let adapter = 'sqlsrv'
3659
+ elseif adapter == 'sybase'
3660
+ let adapter = 'asa'
3661
+ elseif adapter == 'oci'
3662
+ let adapter = 'ora'
3663
+ endif
3664
+ let s:dbext_type_{rv} = toupper(adapter)
3665
+ let s:dbext_user_{rv} = s:extractdbvar(out,'username')
3666
+ let s:dbext_passwd_{rv} = s:extractdbvar(out,'password')
3667
+ if s:dbext_passwd_{rv} == '' && adapter == 'mysql'
3668
+ " Hack to override password from .my.cnf
3669
+ let s:dbext_extra_{rv} = ' --password='
3670
+ else
3671
+ let s:dbext_extra_{rv} = ''
3672
+ endif
3673
+ let s:dbext_dbname_{rv} = s:extractdbvar(out,'database')
3674
+ if s:dbext_dbname_{rv} != '' && s:dbext_dbname_{rv} !~ '^:' && adapter =~? '^sqlite'
3675
+ let s:dbext_dbname_{rv} = RailsRoot().'/'.s:dbext_dbname_{rv}
3676
+ endif
3677
+ let s:dbext_profile_{rv} = ''
3678
+ let s:dbext_host_{rv} = s:extractdbvar(out,'host')
3679
+ let s:dbext_port_{rv} = s:extractdbvar(out,'port')
3680
+ let s:dbext_dsnname_{rv} = s:extractdbvar(out,'dsn')
3681
+ if s:dbext_host_{rv} =~? '^\cDBI:'
3682
+ if s:dbext_host_{rv} =~? '\c\<Trusted[_ ]Connection\s*=\s*yes\>'
3683
+ let s:dbext_integratedlogin_{rv} = 1
3684
+ endif
3685
+ let s:dbext_host_{rv} = matchstr(s:dbext_host_{rv},'\c\<\%(Server\|Data Source\)\s*=\s*\zs[^;]*')
3686
+ endif
3687
+ endif
3688
+ endif
3689
+ if exists("s:dbext_type_".rv)
3690
+ silent! let b:dbext_type = s:dbext_type_{rv}
3691
+ silent! let b:dbext_profile = s:dbext_profile_{rv}
3692
+ silent! let b:dbext_bin = s:dbext_bin_{rv}
3693
+ silent! let b:dbext_user = s:dbext_user_{rv}
3694
+ silent! let b:dbext_passwd = s:dbext_passwd_{rv}
3695
+ silent! let b:dbext_dbname = s:dbext_dbname_{rv}
3696
+ silent! let b:dbext_host = s:dbext_host_{rv}
3697
+ silent! let b:dbext_port = s:dbext_port_{rv}
3698
+ silent! let b:dbext_dsnname = s:dbext_dsnname_{rv}
3699
+ silent! let b:dbext_extra = s:dbext_extra_{rv}
3700
+ silent! let b:dbext_integratedlogin = s:dbext_integratedlogin_{rv}
3701
+ if b:dbext_type == 'PGSQL'
3702
+ let $PGPASSWORD = b:dbext_passwd
3703
+ elseif exists('$PGPASSWORD')
3704
+ let $PGPASSWORD = ''
3705
+ endif
3706
+ endif
3707
+ if a:0 >= 3 && a:3 && exists(":Create")
3708
+ if exists("b:dbext_dbname") && exists("b:dbext_type") && b:dbext_type !~? 'sqlite'
3709
+ let db = b:dbext_dbname
3710
+ if b:dbext_type == 'PGSQL'
3711
+ " I don't always have a default database for a user so using the
3712
+ " default user's database is a better choice for my setup. It
3713
+ " probably won't work for everyone but nothing will.
3714
+ let b:dbext_dbname = 'postgres'
3715
+ else
3716
+ let b:dbext_dbname = ''
3717
+ endif
3718
+ exe "Create database ".db
3719
+ let b:dbext_dbname = db
3720
+ endif
3721
+ endif
3722
+ unlet! s:lock_database
3723
+ endfunction
3724
+
3725
+ " }}}1
3726
+ " Abbreviations {{{1
3727
+
3728
+ " Depends: s:sub, s:gsub, s:string, s:linepeak, s:error
3729
+
3730
+ function! s:selectiveexpand(pat,good,default,...)
3731
+ if a:0 > 0
3732
+ let nd = a:1
3733
+ else
3734
+ let nd = ""
3735
+ endif
3736
+ let c = nr2char(getchar(0))
3737
+ let good = a:good
3738
+ if c == "" " ^]
3739
+ return s:sub(good.(a:0 ? " ".a:1 : ''),'\s+$','')
3740
+ elseif c == "\t"
3741
+ return good.(a:0 ? " ".a:1 : '')
3742
+ elseif c =~ a:pat
3743
+ return good.c.(a:0 ? a:1 : '')
3744
+ else
3745
+ return a:default.c
3746
+ endif
3747
+ endfunction
3748
+
3749
+ function! s:TheMagicC()
3750
+ let l = s:linepeak()
3751
+ if l =~ '\<find\s*\((\|:first,\|:all,\)' || l =~ '\<paginate\>'
3752
+ return s:selectiveexpand('..',':conditions => ',':c')
3753
+ elseif l =~ '\<render\s*(\=\s*:partial\s\*=>\s*'
3754
+ return s:selectiveexpand('..',':collection => ',':c')
3755
+ elseif RailsFileType() =~ '^model\>'
3756
+ return s:selectiveexpand('..',':conditions => ',':c')
3757
+ else
3758
+ return s:selectiveexpand('..',':controller => ',':c')
3759
+ endif
3760
+ endfunction
3761
+
3762
+ function! s:AddSelectiveExpand(abbr,pat,expn,...)
3763
+ let expn = s:gsub(s:gsub(a:expn ,'[\"|]','\\&'),'\<','\\<Lt>')
3764
+ let expn2 = s:gsub(s:gsub(a:0 ? a:1 : '','[\"|]','\\&'),'\<','\\<Lt>')
3765
+ if a:0
3766
+ exe "inoreabbrev <buffer> <silent> ".a:abbr." <C-R>=<SID>selectiveexpand(".s:string(a:pat).",\"".expn."\",".s:string(a:abbr).",\"".expn2."\")<CR>"
3767
+ else
3768
+ exe "inoreabbrev <buffer> <silent> ".a:abbr." <C-R>=<SID>selectiveexpand(".s:string(a:pat).",\"".expn."\",".s:string(a:abbr).")<CR>"
3769
+ endif
3770
+ endfunction
3771
+
3772
+ function! s:AddTabExpand(abbr,expn)
3773
+ call s:AddSelectiveExpand(a:abbr,'..',a:expn)
3774
+ endfunction
3775
+
3776
+ function! s:AddBracketExpand(abbr,expn)
3777
+ call s:AddSelectiveExpand(a:abbr,'[[.]',a:expn)
3778
+ endfunction
3779
+
3780
+ function! s:AddColonExpand(abbr,expn)
3781
+ call s:AddSelectiveExpand(a:abbr,':',a:expn)
3782
+ endfunction
3783
+
3784
+ function! s:AddParenExpand(abbr,expn,...)
3785
+ if a:0
3786
+ call s:AddSelectiveExpand(a:abbr,'(',a:expn,a:1)
3787
+ else
3788
+ call s:AddSelectiveExpand(a:abbr,'(',a:expn,'')
3789
+ endif
3790
+ endfunction
3791
+
3792
+ function! s:BufAbbreviations()
3793
+ command! -buffer -bar -nargs=* -bang Rabbrev :call s:Abbrev(<bang>0,<f-args>)
3794
+ " Some of these were cherry picked from the TextMate snippets
3795
+ if g:rails_abbreviations
3796
+ let t = RailsFileType()
3797
+ " Limit to the right filetypes. But error on the liberal side
3798
+ if t =~ '^\(controller\|view\|helper\|test-functional\|test-integration\)\>'
3799
+ Rabbrev pa[ params
3800
+ Rabbrev rq[ request
3801
+ Rabbrev rs[ response
3802
+ Rabbrev se[ session
3803
+ Rabbrev hd[ headers
3804
+ Rabbrev co[ cookies
3805
+ Rabbrev fl[ flash
3806
+ Rabbrev rr( render
3807
+ Rabbrev ra( render :action\ =>\
3808
+ Rabbrev rc( render :controller\ =>\
3809
+ Rabbrev rf( render :file\ =>\
3810
+ Rabbrev ri( render :inline\ =>\
3811
+ Rabbrev rj( render :json\ =>\
3812
+ Rabbrev rl( render :layout\ =>\
3813
+ Rabbrev rp( render :partial\ =>\
3814
+ Rabbrev rt( render :text\ =>\
3815
+ Rabbrev rx( render :xml\ =>\
3816
+ endif
3817
+ if t =~ '^\%(view\|helper\)\>'
3818
+ Rabbrev dotiw distance_of_time_in_words
3819
+ Rabbrev taiw time_ago_in_words
3820
+ endif
3821
+ if t =~ '^controller\>'
3822
+ "call s:AddSelectiveExpand('rn','[,\r]','render :nothing => true')
3823
+ "let b:rails_abbreviations = b:rails_abbreviations . "rn\trender :nothing => true\n"
3824
+ Rabbrev re( redirect_to
3825
+ Rabbrev rea( redirect_to :action\ =>\
3826
+ Rabbrev rec( redirect_to :controller\ =>\
3827
+ Rabbrev rst( respond_to
3828
+ endif
3829
+ if t =~ '^model-arb\>' || t =~ '^model$'
3830
+ Rabbrev bt( belongs_to
3831
+ Rabbrev ho( has_one
3832
+ Rabbrev hm( has_many
3833
+ Rabbrev habtm( has_and_belongs_to_many
3834
+ Rabbrev co( composed_of
3835
+ Rabbrev va( validates_associated
3836
+ Rabbrev vb( validates_acceptance_of
3837
+ Rabbrev vc( validates_confirmation_of
3838
+ Rabbrev ve( validates_exclusion_of
3839
+ Rabbrev vf( validates_format_of
3840
+ Rabbrev vi( validates_inclusion_of
3841
+ Rabbrev vl( validates_length_of
3842
+ Rabbrev vn( validates_numericality_of
3843
+ Rabbrev vp( validates_presence_of
3844
+ Rabbrev vu( validates_uniqueness_of
3845
+ endif
3846
+ if t =~ '^\%(db-\)\=\%(migration\|schema\)\>'
3847
+ Rabbrev mac( add_column
3848
+ Rabbrev mrnc( rename_column
3849
+ Rabbrev mrc( remove_column
3850
+ Rabbrev mct( create_table
3851
+ Rabbrev mcht( change_table
3852
+ Rabbrev mrnt( rename_table
3853
+ Rabbrev mdt( drop_table
3854
+ Rabbrev mcc( t.column
3855
+ endif
3856
+ if t =~ '^test\>'
3857
+ "Rabbrev ae( assert_equal
3858
+ Rabbrev ase( assert_equal
3859
+ "Rabbrev ako( assert_kind_of
3860
+ Rabbrev asko( assert_kind_of
3861
+ "Rabbrev ann( assert_not_nil
3862
+ Rabbrev asnn( assert_not_nil
3863
+ "Rabbrev ar( assert_raise
3864
+ Rabbrev asr( assert_raise
3865
+ "Rabbrev are( assert_response
3866
+ Rabbrev asre( assert_response
3867
+ Rabbrev art( assert_redirected_to
3868
+ endif
3869
+ Rabbrev :a :action\ =>\
3870
+ inoreabbrev <buffer> <silent> :c <C-R>=<SID>TheMagicC()<CR>
3871
+ " Lie a little
3872
+ if t =~ '^view\>'
3873
+ let b:rails_abbreviations = b:rails_abbreviations . ":c\t:collection => \n"
3874
+ elseif s:controller() != ''
3875
+ let b:rails_abbreviations = b:rails_abbreviations . ":c\t:controller => \n"
3876
+ else
3877
+ let b:rails_abbreviations = b:rails_abbreviations . ":c\t:conditions => \n"
3878
+ endif
3879
+ Rabbrev :i :id\ =>\
3880
+ Rabbrev :o :object\ =>\
3881
+ Rabbrev :p :partial\ =>\
3882
+ Rabbrev logd( logger.debug
3883
+ Rabbrev logi( logger.info
3884
+ Rabbrev logw( logger.warn
3885
+ Rabbrev loge( logger.error
3886
+ Rabbrev logf( logger.fatal
3887
+ Rabbrev fi( find
3888
+ Rabbrev AR:: ActiveRecord
3889
+ Rabbrev AV:: ActionView
3890
+ Rabbrev AC:: ActionController
3891
+ Rabbrev AS:: ActiveSupport
3892
+ Rabbrev AM:: ActionMailer
3893
+ Rabbrev AE:: ActiveResource
3894
+ Rabbrev AWS:: ActionWebService
3895
+ endif
3896
+ endfunction
3897
+
3898
+ function! s:Abbrev(bang,...) abort
3899
+ if !exists("b:rails_abbreviations")
3900
+ let b:rails_abbreviations = "\n"
3901
+ endif
3902
+ if a:0 > 3 || (a:bang && (a:0 != 1))
3903
+ return s:error("Rabbrev: invalid arguments")
3904
+ endif
3905
+ if a:bang
3906
+ return s:unabbrev(a:1)
3907
+ endif
3908
+ if a:0 == 0
3909
+ echo s:sub(b:rails_abbreviations,'^\n','')
3910
+ return
3911
+ endif
3912
+ let lhs = a:1
3913
+ if a:0 > 3 || a:0 < 2
3914
+ return s:error("Rabbrev: invalid arguments")
3915
+ endif
3916
+ let rhs = a:2
3917
+ call s:unabbrev(lhs,1)
3918
+ if lhs =~ '($'
3919
+ let b:rails_abbreviations = b:rails_abbreviations . lhs . "\t" . rhs . "" . (a:0 > 2 ? "\t".a:3 : ""). "\n"
3920
+ let llhs = s:sub(lhs,'\($','')
3921
+ if a:0 > 2
3922
+ call s:AddParenExpand(llhs,rhs,a:3)
3923
+ else
3924
+ call s:AddParenExpand(llhs,rhs)
3925
+ endif
3926
+ return
3927
+ endif
3928
+ if a:0 > 2
3929
+ return s:error("Rabbrev: invalid arguments")
3930
+ endif
3931
+ if lhs =~ ':$'
3932
+ let llhs = s:sub(lhs,':=:$','')
3933
+ call s:AddColonExpand(llhs,rhs)
3934
+ elseif lhs =~ '\[$'
3935
+ let llhs = s:sub(lhs,'\[$','')
3936
+ call s:AddBracketExpand(llhs,rhs)
3937
+ elseif lhs =~ '\w$'
3938
+ call s:AddTabExpand(lhs,rhs)
3939
+ else
3940
+ return s:error("Rabbrev: unimplemented")
3941
+ endif
3942
+ let b:rails_abbreviations = b:rails_abbreviations . lhs . "\t" . rhs . "\n"
3943
+ endfunction
3944
+
3945
+ function! s:unabbrev(abbr,...)
3946
+ let abbr = s:sub(a:abbr,'%(::|\(|\[)$','')
3947
+ let pat = s:sub(abbr,'\\','\\\\')
3948
+ if !exists("b:rails_abbreviations")
3949
+ let b:rails_abbreviations = "\n"
3950
+ endif
3951
+ let b:rails_abbreviations = substitute(b:rails_abbreviations,'\V\C\n'.pat.'\(\t\|::\t\|(\t\|[\t\)\.\{-\}\n','\n','')
3952
+ if a:0 == 0 || a:1 == 0
3953
+ exe "iunabbrev <buffer> ".abbr
3954
+ endif
3955
+ endfunction
3956
+
3957
+ " }}}1
3958
+ " Settings {{{1
3959
+
3960
+ " Depends: s:error, s:sub, s:sname, s:escvar, s:lastmethod, s:environment, s:gsub, s:lastmethodlib, s:gsub
3961
+
3962
+ function! s:Set(bang,...)
3963
+ let c = 1
3964
+ let defscope = ''
3965
+ while c <= a:0
3966
+ let arg = a:{c}
3967
+ let c = c + 1
3968
+ if arg =~? '^<[abgl]\=>$'
3969
+ let defscope = (matchstr(arg,'<\zs.*\ze>'))
3970
+ elseif arg !~ '='
3971
+ if defscope != '' && arg !~ '^\w:'
3972
+ let arg = defscope.':'.opt
3973
+ endif
3974
+ let val = s:getopt(arg)
3975
+ if val == '' && s:opts() !~ '\<'.arg.'\n'
3976
+ call s:error("No such rails.vim option: ".arg)
3977
+ else
3978
+ echo arg."=".val
3979
+ endif
3980
+ else
3981
+ let opt = matchstr(arg,'[^=]*')
3982
+ let val = s:sub(arg,'^[^=]*\=','')
3983
+ if defscope != '' && opt !~ '^\w:'
3984
+ let opt = defscope.':'.opt
3985
+ endif
3986
+ call s:setopt(opt,val)
3987
+ endif
3988
+ endwhile
3989
+ endfunction
3990
+
3991
+ function! s:getopt(opt,...)
3992
+ let opt = a:opt
3993
+ if a:0
3994
+ let scope = a:1
3995
+ elseif opt =~ '^[abgl]:'
3996
+ let scope = tolower(matchstr(opt,'^\w'))
3997
+ let opt = s:sub(opt,'^\w:','')
3998
+ else
3999
+ let scope = 'abgl'
4000
+ endif
4001
+ let lnum = a:0 > 1 ? a:2 : line('.')
4002
+ if scope =~ 'l' && &filetype != 'ruby'
4003
+ let scope = s:sub(scope,'l','b')
4004
+ endif
4005
+ if scope =~ 'l'
4006
+ call s:LocalModelines(lnum)
4007
+ endif
4008
+ let opt = s:sub(opt,'<%(rake|rake_task|rake_target)$','task')
4009
+ " Get buffer option
4010
+ if scope =~ 'l' && exists("b:_".s:sname()."_".s:escvar(s:lastmethod())."_".opt)
4011
+ return b:_{s:sname()}_{s:escvar(s:lastmethod(lnum))}_{opt}
4012
+ elseif exists("b:".s:sname()."_".opt) && (scope =~ 'b' || (scope =~ 'l' && s:lastmethod(lnum) == ''))
4013
+ return b:{s:sname()}_{opt}
4014
+ elseif scope =~ 'a' && exists("s:_".s:rv()."_".s:environment()."_".opt)
4015
+ return s:_{s:rv()}_{s:environment()}_{opt}
4016
+ elseif scope =~ 'g' && exists("g:".s:sname()."_".opt)
4017
+ return g:{s:sname()}_{opt}
4018
+ else
4019
+ return ""
4020
+ endif
4021
+ endfunction
4022
+
4023
+ function! s:setopt(opt,val)
4024
+ if a:opt =~? '[abgl]:'
4025
+ let scope = matchstr(a:opt,'^\w')
4026
+ let opt = s:sub(a:opt,'^\w:','')
4027
+ else
4028
+ let scope = ''
4029
+ let opt = a:opt
4030
+ endif
4031
+ let opt = s:sub(opt,'<%(rake|rake_task|rake_target)$','task')
4032
+ let defscope = matchstr(s:opts(),'\n\zs\w\ze:'.opt,'\n')
4033
+ if defscope == ''
4034
+ let defscope = 'a'
4035
+ endif
4036
+ if scope == ''
4037
+ let scope = defscope
4038
+ endif
4039
+ if &filetype == 'ruby' && (scope == 'B' || scope == 'l')
4040
+ let scope = 'b'
4041
+ endif
4042
+ if opt =~ '\W'
4043
+ return s:error("Invalid option ".a:opt)
4044
+ elseif scope =~? 'a'
4045
+ let s:_{s:rv()}_{s:environment()}_{opt} = a:val
4046
+ elseif scope == 'B' && defscope == 'l'
4047
+ let b:_{s:sname()}_{s:escvar('')}_{opt} = a:val
4048
+ elseif scope =~? 'b'
4049
+ let b:{s:sname()}_{opt} = a:val
4050
+ elseif scope =~? 'g'
4051
+ let g:{s:sname()}_{opt} = a:val
4052
+ elseif scope =~? 'l'
4053
+ let b:_{s:sname()}_{s:escvar(s:lastmethod())}_{opt} = a:val
4054
+ else
4055
+ return s:error("Invalid scope for ".a:opt)
4056
+ endif
4057
+ endfunction
4058
+
4059
+ function! s:opts()
4060
+ return "\nb:alternate\nb:controller\na:gnu_screen\nb:model\nl:preview\nb:task\nl:related\na:root_url\n"
4061
+ endfunction
4062
+
4063
+ function! s:SetComplete(A,L,P)
4064
+ if a:A =~ '='
4065
+ let opt = matchstr(a:A,'[^=]*')
4066
+ return opt."=".s:getopt(opt)
4067
+ else
4068
+ let extra = matchstr(a:A,'^[abgl]:')
4069
+ let opts = s:gsub(s:sub(s:gsub(s:opts(),'\n\w:','\n'.extra),'^\n',''),'\n','=\n')
4070
+ return opts
4071
+ endif
4072
+ return ""
4073
+ endfunction
4074
+
4075
+ function! s:BufModelines()
4076
+ if !g:rails_modelines
4077
+ return
4078
+ endif
4079
+ let lines = getline("$")."\n".getline(line("$")-1)."\n".getline(1)."\n".getline(2)."\n".getline(3)."\n"
4080
+ let pat = '\s\+\zs.\{-\}\ze\%(\n\|\s\s\|#{\@!\|%>\|-->\|$\)'
4081
+ let cnt = 1
4082
+ let mat = matchstr(lines,'\C\<Rset'.pat)
4083
+ let matend = matchend(lines,'\C\<Rset'.pat)
4084
+ while mat != "" && cnt < 10
4085
+ let mat = s:sub(mat,'\s+$','')
4086
+ let mat = s:gsub(mat,'\|','\\|')
4087
+ if mat != ''
4088
+ silent! exe "Rset <B> ".mat
4089
+ endif
4090
+ let mat = matchstr(lines,'\C\<Rset'.pat,matend)
4091
+ let matend = matchend(lines,'\C\<Rset'.pat,matend)
4092
+ let cnt = cnt + 1
4093
+ endwhile
4094
+ endfunction
4095
+
4096
+ function! s:LocalModelines(lnum)
4097
+ if !g:rails_modelines
4098
+ return
4099
+ endif
4100
+ let lbeg = s:lastmethodline(a:lnum)
4101
+ let lend = s:endof(lbeg)
4102
+ if lbeg == 0 || lend == 0
4103
+ return
4104
+ endif
4105
+ let lines = "\n"
4106
+ let lnum = lbeg
4107
+ while lnum < lend && lnum < lbeg + 5
4108
+ let lines = lines . getline(lnum) . "\n"
4109
+ let lnum = lnum + 1
4110
+ endwhile
4111
+ let pat = '\s\+\zs.\{-\}\ze\%(\n\|\s\s\|#{\@!\|%>\|-->\|$\)'
4112
+ let cnt = 1
4113
+ let mat = matchstr(lines,'\C\<rset'.pat)
4114
+ let matend = matchend(lines,'\C\<rset'.pat)
4115
+ while mat != "" && cnt < 10
4116
+ let mat = s:sub(mat,'\s+$','')
4117
+ let mat = s:gsub(mat,'\|','\\|')
4118
+ if mat != ''
4119
+ silent! exe "Rset <l> ".mat
4120
+ endif
4121
+ let mat = matchstr(lines,'\C\<rset'.pat,matend)
4122
+ let matend = matchend(lines,'\C\<rset'.pat,matend)
4123
+ let cnt = cnt + 1
4124
+ endwhile
4125
+ endfunction
4126
+
4127
+ " }}}1
4128
+ " Detection {{{1
4129
+
4130
+ function! s:callback(file)
4131
+ if RailsRoot() != ""
4132
+ let var = "callback_".s:rv()."_".s:escvar(a:file)
4133
+ if !exists("s:".var) || exists("b:rails_refresh")
4134
+ let s:{var} = s:hasfile(a:file)
4135
+ endif
4136
+ if s:{var}
4137
+ if exists(":sandbox")
4138
+ sandbox source `=RailsRoot().'/'.a:file`
4139
+ elseif g:rails_modelines
4140
+ source `=RailsRoot().'/'.a:file`
4141
+ endif
4142
+ endif
4143
+ endif
4144
+ endfunction
4145
+
4146
+ function! RailsBufInit(path)
4147
+ let cpo_save = &cpo
4148
+ set cpo&vim
4149
+ let firsttime = !(exists("b:rails_root") && b:rails_root == a:path)
4150
+ let b:rails_root = a:path
4151
+ " Apparently RailsFileType() can be slow if the underlying file system is
4152
+ " slow (even though it doesn't really do anything IO related). This caching
4153
+ " is a temporary hack; if it doesn't cause problems it should probably be
4154
+ " refactored.
4155
+ unlet! b:rails_cached_file_type
4156
+ let b:rails_cached_file_type = RailsFileType()
4157
+ if g:rails_history_size > 0
4158
+ if !exists("g:RAILS_HISTORY")
4159
+ let g:RAILS_HISTORY = ""
4160
+ endif
4161
+ let path = a:path
4162
+ let g:RAILS_HISTORY = s:scrub(g:RAILS_HISTORY,path)
4163
+ if has("win32")
4164
+ let g:RAILS_HISTORY = s:scrub(g:RAILS_HISTORY,s:gsub(path,'\\','/'))
4165
+ endif
4166
+ let path = fnamemodify(path,':p:~:h')
4167
+ let g:RAILS_HISTORY = s:scrub(g:RAILS_HISTORY,path)
4168
+ if has("win32")
4169
+ let g:RAILS_HISTORY = s:scrub(g:RAILS_HISTORY,s:gsub(path,'\\','/'))
4170
+ endif
4171
+ let g:RAILS_HISTORY = path."\n".g:RAILS_HISTORY
4172
+ let g:RAILS_HISTORY = s:sub(g:RAILS_HISTORY,'%(.{-}\n){,'.g:rails_history_size.'}\zs.*','')
4173
+ endif
4174
+ call s:callback("config/syntax.vim")
4175
+ if &ft == "mason"
4176
+ setlocal filetype=eruby
4177
+ elseif &ft =~ '^\%(conf\|ruby\)\=$' && expand("%:e") =~ '^\%(rjs\|rxml\|builder\|rake\|mab\)$'
4178
+ setlocal filetype=ruby
4179
+ elseif &ft =~ '^\%(conf\|ruby\)\=$' && expand("%:t") =~ '^\%(Rake\|Cap\)file$'
4180
+ setlocal filetype=ruby
4181
+ elseif &ft =~ '^\%(liquid\)\=$' && expand("%:e") == "liquid"
4182
+ setlocal filetype=liquid
4183
+ elseif &ft =~ '^\%(haml\|x\=html\)\=$' && expand("%:e") == "haml"
4184
+ setlocal filetype=haml
4185
+ elseif &ft =~ '^\%(sass\|conf\)\=$' && expand("%:e") == "sass"
4186
+ setlocal filetype=sass
4187
+ elseif &ft =~ '^\%(dryml\)\=$' && expand("%:e") == "dryml"
4188
+ setlocal filetype=dryml
4189
+ elseif (&ft == "" || v:version < 701) && expand("%:e") =~ '^\%(rhtml\|erb\)$'
4190
+ setlocal filetype=eruby
4191
+ elseif (&ft == "" || v:version < 700) && expand("%:e") == 'yml'
4192
+ setlocal filetype=yaml
4193
+ elseif firsttime
4194
+ " Activate custom syntax
4195
+ let &syntax = &syntax
4196
+ endif
4197
+ if firsttime
4198
+ call s:BufInitStatusline()
4199
+ endif
4200
+ if expand("%:e") == "log"
4201
+ setlocal modifiable filetype=railslog
4202
+ silent! %s/\%(\e\[[0-9;]*m\|\r$\)//g
4203
+ setlocal readonly nomodifiable noswapfile autoread foldmethod=syntax
4204
+ nnoremap <buffer> <silent> R :checktime<CR>
4205
+ nnoremap <buffer> <silent> G :checktime<Bar>$<CR>
4206
+ nnoremap <buffer> <silent> q :bwipe<CR>
4207
+ $
4208
+ endif
4209
+ call s:BufSettings()
4210
+ call s:BufCommands()
4211
+ call s:BufAbbreviations()
4212
+ call s:BufDatabase()
4213
+ " snippetsEmu.vim
4214
+ if exists('g:loaded_snippet')
4215
+ silent! runtime! ftplugin/rails_snippets.vim
4216
+ " filetype snippets need to come last for higher priority
4217
+ exe "silent! runtime! ftplugin/".&filetype."_snippets.vim"
4218
+ endif
4219
+ let t = RailsFileType()
4220
+ let t = "-".t
4221
+ let f = '/'.RailsFilePath()
4222
+ if f =~ '[ !#$%\,]'
4223
+ let f = ''
4224
+ endif
4225
+ runtime! macros/rails.vim
4226
+ silent doautocmd User Rails
4227
+ if t != '-'
4228
+ exe "silent doautocmd User Rails".s:gsub(t,'-','.')
4229
+ endif
4230
+ if f != ''
4231
+ exe "silent doautocmd User Rails".f
4232
+ endif
4233
+ call s:callback("config/rails.vim")
4234
+ call s:BufModelines()
4235
+ call s:BufMappings()
4236
+ "unlet! b:rails_cached_file_type
4237
+ let &cpo = cpo_save
4238
+ return b:rails_root
4239
+ endfunction
4240
+
4241
+ function! s:SetBasePath()
4242
+ let rp = s:gsub(RailsRoot(),'[ ,]','\\&')
4243
+ let t = RailsFileType()
4244
+ let oldpath = s:sub(&l:path,'^\.,','')
4245
+ if stridx(oldpath,rp) == 2
4246
+ let oldpath = ''
4247
+ endif
4248
+ let &l:path = '.,'.rp.",".rp."/app/controllers,".rp."/app,".rp."/app/models,".rp."/app/helpers,".rp."/config,".rp."/lib,".rp."/vendor,".rp."/vendor/plugins/*/lib,".rp."/test/unit,".rp."/test/functional,".rp."/test/integration,".rp."/app/apis,".rp."/app/services,".rp."/test,"."/vendor/plugins/*/test,".rp."/vendor/rails/*/lib,".rp."/vendor/rails/*/test,".rp."/spec,".rp."/spec/*,"
4249
+ if s:controller() != ''
4250
+ let &l:path = &l:path . rp . '/app/views/' . s:controller() . ',' . rp . '/app/views,' . rp . '/public,'
4251
+ endif
4252
+ if t =~ '^log\>'
4253
+ let &l:path = &l:path . rp . '/app/views,'
4254
+ endif
4255
+ if &l:path =~ '://'
4256
+ let &l:path = ".,"
4257
+ endif
4258
+ let &l:path = &l:path . oldpath
4259
+ endfunction
4260
+
4261
+ function! s:BufSettings()
4262
+ if !exists('b:rails_root')
4263
+ return ''
4264
+ endif
4265
+ call s:SetBasePath()
4266
+ let rp = s:gsub(RailsRoot(),'[ ,]','\\&')
4267
+ let &l:errorformat = s:efm
4268
+ setlocal makeprg=rake
4269
+ if stridx(&tags,rp) == -1
4270
+ let &l:tags = &tags . "," . rp . "/tags," . rp . "/.tags"
4271
+ endif
4272
+ if has("gui_win32") || has("gui_running")
4273
+ let code = '*.rb;*.rake;Rakefile'
4274
+ let templates = '*.'.s:gsub(s:view_types,',',';*.')
4275
+ let fixtures = '*.yml;*.csv'
4276
+ let statics = '*.html;*.css;*.js;*.xml;*.xsd;*.sql;.htaccess;README;README_FOR_APP'
4277
+ let b:browsefilter = ""
4278
+ \."All Rails Files\t".code.';'.templates.';'.fixtures.';'.statics."\n"
4279
+ \."Source Code (*.rb, *.rake)\t".code."\n"
4280
+ \."Templates (*.rhtml, *.rxml, *.rjs)\t".templates."\n"
4281
+ \."Fixtures (*.yml, *.csv)\t".fixtures."\n"
4282
+ \."Static Files (*.html, *.css, *.js)\t".statics."\n"
4283
+ \."All Files (*.*)\t*.*\n"
4284
+ endif
4285
+ setlocal includeexpr=RailsIncludeexpr()
4286
+ let &l:suffixesadd=".rb,.".s:gsub(s:view_types,',',',.').",.css,.js,.yml,.csv,.rake,.sql,.html,.xml"
4287
+ if &ft =~ '^\%(e\=ruby\|[yh]aml\|javascript\|css\|sass\)$'
4288
+ setlocal sw=2 sts=2 et
4289
+ "set include=\\<\\zsAct\\f*::Base\\ze\\>\\\|^\\s*\\(require\\\|load\\)\\s\\+['\"]\\zs\\f\\+\\ze
4290
+ if exists('+completefunc')
4291
+ if &completefunc == ''
4292
+ set completefunc=syntaxcomplete#Complete
4293
+ endif
4294
+ endif
4295
+ endif
4296
+ if &filetype == "ruby"
4297
+ let &l:suffixesadd=".rb,.".s:gsub(s:view_types,',',',.').",.yml,.csv,.rake,s.rb"
4298
+ if expand('%:e') == 'rake'
4299
+ setlocal define=^\\s*def\\s\\+\\(self\\.\\)\\=\\\|^\\s*\\%(task\\\|file\\)\\s\\+[:'\"]
4300
+ else
4301
+ setlocal define=^\\s*def\\s\\+\\(self\\.\\)\\=
4302
+ endif
4303
+ " This really belongs in after/ftplugin/ruby.vim but we'll be nice
4304
+ if exists("g:loaded_surround") && !exists("b:surround_101")
4305
+ let b:surround_5 = "\r\nend"
4306
+ let b:surround_69 = "\1expr: \1\rend"
4307
+ let b:surround_101 = "\r\nend"
4308
+ endif
4309
+ elseif &filetype == 'yaml' || expand('%:e') == 'yml'
4310
+ setlocal define=^\\%(\\h\\k*:\\)\\@=
4311
+ let &l:suffixesadd=".yml,.csv,.rb,.".s:gsub(s:view_types,',',',.').",.rake,s.rb"
4312
+ elseif &filetype == "eruby"
4313
+ let &l:suffixesadd=".".s:gsub(s:view_types,',',',.').",.rb,.css,.js,.html,.yml,.csv"
4314
+ if exists("g:loaded_allml")
4315
+ " allml is available on vim.org.
4316
+ let b:allml_stylesheet_link_tag = "<%= stylesheet_link_tag '\r' %>"
4317
+ let b:allml_javascript_include_tag = "<%= javascript_include_tag '\r' %>"
4318
+ let b:allml_doctype_index = 10
4319
+ endif
4320
+ endif
4321
+ if &filetype == "eruby" || &filetype == "yaml"
4322
+ " surround.vim
4323
+ if exists("g:loaded_surround")
4324
+ " The idea behind the || part here is that one can normally define the
4325
+ " surrounding to omit the hyphen (since standard ERuby does not use it)
4326
+ " but have it added in Rails ERuby files. Unfortunately, this makes it
4327
+ " difficult if you really don't want a hyphen in Rails ERuby files. If
4328
+ " this is your desire, you will need to accomplish it via a rails.vim
4329
+ " autocommand.
4330
+ if !exists("b:surround_45") || b:surround_45 == "<% \r %>" " -
4331
+ let b:surround_45 = "<% \r -%>"
4332
+ endif
4333
+ if !exists("b:surround_61") " =
4334
+ let b:surround_61 = "<%= \r %>"
4335
+ endif
4336
+ if !exists("b:surround_35") " #
4337
+ let b:surround_35 = "<%# \r %>"
4338
+ endif
4339
+ if !exists("b:surround_101") || b:surround_101 == "<% \r %>\n<% end %>" "e
4340
+ let b:surround_5 = "<% \r -%>\n<% end -%>"
4341
+ let b:surround_69 = "<% \1expr: \1 -%>\r<% end -%>"
4342
+ let b:surround_101 = "<% \r -%>\n<% end -%>"
4343
+ endif
4344
+ endif
4345
+ endif
4346
+ endfunction
4347
+
4348
+ " }}}1
4349
+ " Autocommands {{{1
4350
+
4351
+ augroup railsPluginAuto
4352
+ autocmd!
4353
+ autocmd User BufEnterRails call s:RefreshBuffer()
4354
+ autocmd User BufEnterRails call s:resetomnicomplete()
4355
+ autocmd User BufEnterRails call s:BufDatabase(-1)
4356
+ autocmd BufWritePost */config/database.yml unlet! s:dbext_type_{s:rv()} " Force reload
4357
+ autocmd BufWritePost */test/test_helper.rb call s:cacheclear("user_asserts")
4358
+ autocmd BufWritePost */config/routes.rb call s:cacheclear("named_routes")
4359
+ autocmd FileType * if exists("b:rails_root") | call s:BufSettings() | endif
4360
+ autocmd Syntax ruby,eruby,yaml,haml,javascript,railslog if exists("b:rails_root") | call s:BufSyntax() | endif
4361
+ silent! autocmd QuickFixCmdPre make* call s:QuickFixCmdPre()
4362
+ silent! autocmd QuickFixCmdPost make* call s:QuickFixCmdPost()
4363
+ augroup END
4364
+
4365
+ " }}}1
4366
+ " Initialization {{{1
4367
+
4368
+ map <SID>xx <SID>xx
4369
+ let s:sid = s:sub(maparg("<SID>xx"),'xx$','')
4370
+ unmap <SID>xx
4371
+ let s:file = expand('<sfile>:p')
4372
+
4373
+ " }}}1
4374
+
4375
+ let &cpo = s:cpo_save
4376
+
4377
+ " vim:set sw=2 sts=2: