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