pax_global_header00006660000000000000000000000064116267645470014534gustar00rootroot0000000000000052 comment=d6a745a2af8d821d29cdd9e2ca414350684a60de tpope-vim-rails-d6a745a/000077500000000000000000000000001162676454700152015ustar00rootroot00000000000000tpope-vim-rails-d6a745a/.gitignore000066400000000000000000000000401162676454700171630ustar00rootroot00000000000000/rails.zip /rails.vba /doc/tags tpope-vim-rails-d6a745a/README.markdown000066400000000000000000000132361162676454700177070ustar00rootroot00000000000000rails.vim ========= Remember when everybody and their mother was using TextMate for Ruby on Rails development? Well if it wasn't for rails.vim, we'd still be in that era. So shut up and pay some respect. And check out these features: * Easy navigation of the Rails directory structure. `gf` considers context and knows about partials, fixtures, and much more. There are two commands, `:A` (alternate) and `:R` (related) for easy jumping between files, including favorites like model to migration, template to helper, and controller to functional test. For more advanced usage, `:Rmodel`, `:Rview`, `:Rcontroller`, and several other commands are provided. `:help rails-navigation` * Enhanced syntax highlighting. From `has_and_belongs_to_many` to `distance_of_time_in_words`, it's here. For easy completion of these long method names, `'completefunc'` is set to enable syntax based completion on CTRL-X CTRL-U. * Interface to rake. Use `:Rake` to run the current test, spec, or feature. Use `:.Rake` to do a focused run of just the method, example, or scenario on the current line. `:Rake` can also run arbitrary migrations, load individual fixtures, and more. `:help rails-rake` * Interface to `script/*`. Generally, use `:Rscript about` to call `script/about` or `script/rails about`. Most commands have wrappers with additional features: `:Rgenerate controller Blog` generates a blog controller and edits `app/controllers/blog_controller.rb`. `:help rails-scripts` * Partial extraction and migration inversion. `:Rextract {file}` replaces the desired range (ideally selected in visual line mode) with `render :partial => '{file}'`, which is automatically created with your content. The `@{file}` instance variable is replaced with the `{file}` local variable. `:Rinvert` takes a `self.up` migration and writes a `self.down`. `:help rails-refactoring` * Integration with other plugins. `:Rtree` spawns [NERDTree.vim](https://github.com/scrooloose/nerdtree). If [dbext.vim](http://www.vim.org/scripts/script.php?script_id=356) is installed, it will be transparently configured to reflect `database.yml`. Users of [abolish.vim](https://github.com/tpope/vim-abolish) get pluralize and tableize coercions, and users of [bundler.vim](https://github.com/tpope/vim-bundler) get `bundle exec rake`. `:help rails-integration` Installation ------------ If you don't have a preferred installation method, I recommend installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and then simply copy and paste: cd ~/.vim/bundle git clone git://github.com/tpope/vim-rails.git Once help tags have been generated, you can view the manual with `:help rails`. FAQ --- > I installed the plugin and started Vim. Why does only the :Rails > command exist? This plugin cares about the current file, not the current working directory. Edit a file from a Rails application. > I opened a new tab. Why does only the :Rails command exist? This plugin cares about the current file, not the current working directory. Edit a file from a Rails application. You can use the `:RT` family of commands to open a new tab and edit a file at the same time. > Can I use rails.vim to edit other Ruby projects? I wrote [rake.vim](https://github.com/tpope/vim-rake) for exactly that purpose. It activates for any project with a `Rakefile` that's not a Rails application. > Is Rails 3 supported yet? Of course. > Is Rails 2 still supported? Baby, you can go all the way back to Rails 1 if you like (give or take some syntax highlighting). > Rake is slow. How about making `:Rake` run > `testrb`/`rspec`/`cucumber` directly instead of `rake`? Well then it wouldn't make sense to call it `:Rake`, now, would it? Maybe one day I'll add a separate `:Run` command or something. In the meantime, here's how you can set up `:make` to run the current test: autocmd FileType cucumber compiler cucumber | setl makeprg=cucumber\ \"%:p\" autocmd FileType ruby \ if expand('%') =~# '_test\.rb$' | \ compiler rubyunit | setl makeprg=testrb\ \"%:p\" | \ elseif expand('%') =~# '_spec\.rb$' | \ compiler rspec | setl makeprg=rspec\ \"%:p\" | \ else | \ compiler ruby | setl makeprg=ruby\ -wc\ \"%:p\" | \ endif autocmd User Bundler \ if &makeprg !~ 'bundle' | setl makeprg^=bundle\ exec\ | endif Contributing ------------ If your [commit message sucks](http://stopwritingramblingcommitmessages.com/), I'm not going to accept your pull request. I've explained very politely dozens of times that [my general guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) are absolute rules on my own repositories, so I may lack the energy to explain it to you yet another time. And please, if I ask you to change something, `git commit --amend`. Beyond that, don't be shy about asking before patching. What takes you hours might take me minutes simply because I have both domain knowledge and a perverse knowledge of VimScript so vast that many would consider it a symptom of mental illness. On the flip side, some ideas I'll reject no matter how good the implementation is. "Send a patch" is an edge case answer in my book. Self-Promotion -------------- Like rails.vim? Follow the repository on [GitHub](https://github.com/tpope/vim-rails) and vote for it on [vim.org](http://www.vim.org/scripts/script.php?script_id=1567). And if you're feeling especially charitable, follow [tpope](http://tpo.pe/) on [Twitter](http://twitter.com/tpope) and [GitHub](https://github.com/tpope). License ------- Copyright (c) Tim Pope. Distributed under the same terms as Vim itself. See `:help license`. tpope-vim-rails-d6a745a/autoload/000077500000000000000000000000001162676454700170115ustar00rootroot00000000000000tpope-vim-rails-d6a745a/autoload/rails.vim000066400000000000000000005065161162676454700206550ustar00rootroot00000000000000" autoload/rails.vim " Author: Tim Pope " Install this file as autoload/rails.vim. if exists('g:autoloaded_rails') || &cp finish endif let g:autoloaded_rails = '4.4' let s:cpo_save = &cpo set cpo&vim " Utility Functions {{{1 let s:app_prototype = {} let s:file_prototype = {} let s:buffer_prototype = {} let s:readable_prototype = {} function! s:add_methods(namespace, method_names) for name in a:method_names let s:{a:namespace}_prototype[name] = s:function('s:'.a:namespace.'_'.name) endfor endfunction function! s:function(name) return function(substitute(a:name,'^s:',matchstr(expand(''), '\d\+_'),'')) endfunction function! s:sub(str,pat,rep) return substitute(a:str,'\v\C'.a:pat,a:rep,'') endfunction function! s:gsub(str,pat,rep) return substitute(a:str,'\v\C'.a:pat,a:rep,'g') endfunction function! s:startswith(string,prefix) return strpart(a:string, 0, strlen(a:prefix)) ==# a:prefix endfunction function! s:compact(ary) return s:sub(s:sub(s:gsub(a:ary,'\n\n+','\n'),'\n$',''),'^\n','') endfunction function! s:uniq(list) let seen = {} let i = 0 while i < len(a:list) if has_key(seen,a:list[i]) call remove(a:list, i) else let seen[a:list[i]] = 1 let i += 1 endif endwhile return a:list endfunction function! s:scrub(collection,item) " Removes item from a newline separated collection let col = "\n" . a:collection let idx = stridx(col,"\n".a:item."\n") let cnt = 0 while idx != -1 && cnt < 100 let col = strpart(col,0,idx).strpart(col,idx+strlen(a:item)+1) let idx = stridx(col,"\n".a:item."\n") let cnt += 1 endwhile return strpart(col,1) endfunction function! s:escarg(p) return s:gsub(a:p,'[ !%#]','\\&') endfunction function! s:esccmd(p) return s:gsub(a:p,'[!%#]','\\&') endfunction function! s:rquote(str) " Imperfect but adequate for Ruby arguments if a:str =~ '^[A-Za-z0-9_/.:-]\+$' return a:str elseif &shell =~? 'cmd' return '"'.s:gsub(s:gsub(a:str,'\','\\'),'"','\\"').'"' else return "'".s:gsub(s:gsub(a:str,'\','\\'),"'","'\\\\''")."'" endif endfunction function! s:sname() return fnamemodify(s:file,':t:r') endfunction function! s:pop_command() if exists("s:command_stack") && len(s:command_stack) > 0 exe remove(s:command_stack,-1) endif endfunction function! s:push_chdir(...) if !exists("s:command_stack") | let s:command_stack = [] | endif if exists("b:rails_root") && (a:0 ? getcwd() !=# rails#app().path() : !s:startswith(getcwd(), rails#app().path())) let chdir = exists("*haslocaldir") && haslocaldir() ? "lchdir " : "chdir " call add(s:command_stack,chdir.s:escarg(getcwd())) exe chdir.s:escarg(rails#app().path()) else call add(s:command_stack,"") endif endfunction function! s:app_path(...) dict return join([self.root]+a:000,'/') endfunction function! s:app_has_file(file) dict return filereadable(self.path(a:file)) endfunction function! s:app_find_file(name, ...) dict abort let trim = strlen(self.path())+1 if a:0 let path = s:pathjoin(map(s:pathsplit(a:1),'self.path(v:val)')) else let path = s:pathjoin([self.path()]) endif let suffixesadd = s:pathjoin(get(a:000,1,&suffixesadd)) let default = get(a:000,2,'') let oldsuffixesadd = &l:suffixesadd try let &suffixesadd = suffixesadd " Versions before 7.1.256 returned directories from findfile if type(default) == type(0) && (v:version < 702 || default == -1) let all = findfile(a:name,path,-1) if v:version < 702 call filter(all,'!isdirectory(v:val)') endif call map(all,'s:gsub(strpart(fnamemodify(v:val,":p"),trim),"\\\\","/")') return default < 0 ? all : get(all,default-1,'') elseif type(default) == type(0) let found = findfile(a:name,path,default) else let i = 1 let found = findfile(a:name,path) while v:version < 702 && found != "" && isdirectory(found) let i += 1 let found = findfile(a:name,path,i) endwhile endif return found == "" ? default : s:gsub(strpart(fnamemodify(found,':p'),trim),'\\','/') finally let &l:suffixesadd = oldsuffixesadd endtry endfunction call s:add_methods('app',['path','has_file','find_file']) " Split a path into a list. From pathogen.vim function! s:pathsplit(path) abort if type(a:path) == type([]) | return copy(a:path) | endif let split = split(a:path,'\\\@' if matchstr(self.getline(a:lnum+1),'^'.spc) && !matchstr(self.getline(a:lnum+1),'^'.spc.endpat) && matchstr(cline,endpat) return a:lnum endif let endl = a:lnum while endl <= self.line_count() let endl += 1 if self.getline(endl) =~ '^'.spc.endpat return endl elseif self.getline(endl) =~ '^=begin\>' while self.getline(endl) !~ '^=end\>' && endl <= self.line_count() let endl += 1 endwhile let endl += 1 elseif self.getline(endl) !~ '^'.spc && self.getline(endl) !~ '^\s*\%(#.*\)\=$' return 0 endif endwhile return 0 endfunction function! s:endof(lnum) return rails#buffer().end_of(a:lnum) endfunction function! s:readable_last_opening_line(start,pattern,limit) dict abort let line = a:start while line > a:limit && self.getline(line) !~ a:pattern let line -= 1 endwhile let lend = self.end_of(line) if line > a:limit && (lend < 0 || lend >= a:start) return line else return -1 endif endfunction function! s:lastopeningline(pattern,limit,start) return rails#buffer().last_opening_line(a:start,a:pattern,a:limit) endfunction function! s:readable_define_pattern() dict abort if self.name() =~ '\.yml$' return '^\%(\h\k*:\)\@=' endif let define = '^\s*def\s\+\(self\.\)\=' if self.name() =~# '\.rake$' let define .= "\\\|^\\s*\\%(task\\\|file\\)\\s\\+[:'\"]" endif if self.name() =~# '/schema\.rb$' let define .= "\\\|^\\s*create_table\\s\\+[:'\"]" endif if self.type_name('test') let define .= '\|^\s*test\s*[''"]' endif return define endfunction function! s:readable_last_method_line(start) dict abort return self.last_opening_line(a:start,self.define_pattern(),0) endfunction function! s:lastmethodline(start) return rails#buffer().last_method_line(a:start) endfunction function! s:readable_last_method(start) dict abort let lnum = self.last_method_line(a:start) let line = self.getline(lnum) if line =~# '^\s*test\s*\([''"]\).*\1' let string = matchstr(line,'^\s*\w\+\s*\([''"]\)\zs.*\ze\1') return 'test_'.s:gsub(string,' +','_') elseif lnum return s:sub(matchstr(line,'\%('.self.define_pattern().'\)\zs\h\%(\k\|[:.]\)*[?!=]\='),':$','') else return "" endif endfunction function! s:lastmethod(...) return rails#buffer().last_method(a:0 ? a:1 : line(".")) endfunction function! s:readable_last_format(start) dict abort if self.type_name('view') let format = fnamemodify(self.path(),':r:e') if format == '' return get({'rhtml': 'html', 'rxml': 'xml', 'rjs': 'js', 'haml': 'html'},fnamemodify(self.path(),':e'),'') else return format endif endif let rline = self.last_opening_line(a:start,'\C^\s*\%(mail\>.*\|respond_to\)\s*\%(\.*\|respond_to\)\s*\%(\ rline let match = matchstr(self.getline(line),'\C^\s*'.variable.'\s*\.\s*\zs\h\k*') if match != '' return match endif let line -= 1 endwhile endif return "" endfunction function! s:lastformat(start) return rails#buffer().last_format(a:start) endfunction function! s:format(...) let format = rails#buffer().last_format(a:0 > 1 ? a:2 : line(".")) return format ==# '' && a:0 ? a:1 : format endfunction call s:add_methods('readable',['end_of','last_opening_line','last_method_line','last_method','last_format','define_pattern']) let s:view_types = split('rhtml,erb,rxml,builder,rjs,mab,liquid,haml,dryml,mn,slim',',') function! s:viewspattern() return '\%('.join(s:view_types,'\|').'\)' endfunction function! s:controller(...) return rails#buffer().controller_name(a:0 ? a:1 : 0) endfunction function! s:readable_controller_name(...) dict abort let f = self.name() if has_key(self,'getvar') && self.getvar('rails_controller') != '' return self.getvar('rails_controller') elseif f =~ '\ get(self,last_lines_ftime,0) let self.last_lines = readfile(self.path()) let self.last_lines_ftime = ftime endif return get(self,'last_lines',[]) endfunction function! s:file_getline(lnum,...) dict abort if a:0 return self.lines[lnum-1 : a:1-1] else return self.lines[lnum-1] endif endfunction function! s:buffer_lines() dict abort return self.getline(1,'$') endfunction function! s:buffer_getline(...) dict abort if a:0 == 1 return get(call('getbufline',[self.number()]+a:000),0,'') else return call('getbufline',[self.number()]+a:000) endif endfunction function! s:readable_line_count() dict abort return len(self.lines()) endfunction function! s:environment() if exists('$RAILS_ENV') return $RAILS_ENV else return "development" endif endfunction function! s:Complete_environments(...) return s:completion_filter(rails#app().environments(),a:0 ? a:1 : "") endfunction function! s:warn(str) echohl WarningMsg echomsg a:str echohl None " Sometimes required to flush output echo "" let v:warningmsg = a:str endfunction function! s:error(str) echohl ErrorMsg echomsg a:str echohl None let v:errmsg = a:str endfunction function! s:debug(str) if exists("g:rails_debug") && g:rails_debug echohl Debug echomsg a:str echohl None endif endfunction function! s:buffer_getvar(varname) dict abort return getbufvar(self.number(),a:varname) endfunction function! s:buffer_setvar(varname, val) dict abort return setbufvar(self.number(),a:varname,a:val) endfunction call s:add_methods('buffer',['getvar','setvar']) " }}}1 " "Public" Interface {{{1 " RailsRoot() is the only official public function function! rails#underscore(str) let str = s:gsub(a:str,'::','/') let str = s:gsub(str,'(\u+)(\u\l)','\1_\2') let str = s:gsub(str,'(\l|\d)(\u)','\1_\2') let str = tolower(str) return str endfunction function! rails#camelize(str) let str = s:gsub(a:str,'/(.=)','::\u\1') let str = s:gsub(str,'%([_-]|<)(.)','\u\1') return str endfunction function! rails#singularize(word) " Probably not worth it to be as comprehensive as Rails but we can " still hit the common cases. let word = a:word if word =~? '\.js$' || word == '' return word endif let word = s:sub(word,'eople$','ersons') let word = s:sub(word,'%([Mm]ov|[aeio])@ 0 && getbufvar(nr,'rails_file_type') != '' return getbufvar(nr,'rails_file_type') elseif f =~ '_controller\.rb$' || f =~ '\' let r = "controller-api" else let r = "controller" endif elseif f =~ '_api\.rb' let r = "api" elseif f =~ '\') if class == "ActiveResource::Base" let class = "ares" let r = "model-ares" elseif class == 'ActionMailer::Base' let r = "mailer" elseif class != '' let class = tolower(s:gsub(class,'[^A-Z]','')) let r = "model-".class elseif f =~ '_mailer\.rb$' let r = "mailer" elseif top =~ '\<\%(validates_\w\+_of\|set_\%(table_name\|primary_key\)\|has_one\|has_many\|belongs_to\)\>' let r = "model-arb" else let r = "model" endif elseif f =~ '\.*\.' let r = "view-layout-" . e elseif f =~ '\<\%(app/views\|components\)/.*/_\k\+\.\k\+\%(\.\k\+\)\=$' let r = "view-partial-" . e elseif f =~ '\.*\.' || f =~ '\' if e == "yml" let r = "fixtures-yaml" else let r = "fixtures" . (e == "" ? "" : "-" . e) endif elseif f =~ '\' let r = "db-migration" elseif f=~ '\.*\.rb$' let r = "config-routes" elseif f =~ '\' let cmd = 'script/rails '.a:cmd else let cmd = 'script/'.a:cmd endif return self.ruby_shell_command(cmd) endfunction function! s:app_background_script_command(cmd) dict abort let cmd = s:esccmd(self.script_shell_command(a:cmd)) if has_key(self,'options') && has_key(self.options,'gnu_screen') let screen = self.options.gnu_screen else let screen = g:rails_gnu_screen endif if has("gui_win32") if &shellcmdflag == "-c" && ($PATH . &shell) =~? 'cygwin' silent exe "!cygstart -d ".s:rquote(self.path())." ruby ".a:cmd else exe "!start ".cmd endif elseif exists("$STY") && !has("gui_running") && screen && executable("screen") silent exe "!screen -ln -fn -t ".s:sub(s:sub(a:cmd,'\s.*',''),'^%(script|-rcommand)/','rails-').' '.cmd elseif exists("$TMUX") && !has("gui_running") && screen && executable("tmux") silent exe '!tmux new-window -d -n "'.s:sub(s:sub(a:cmd,'\s.*',''),'^%(script|-rcommand)/','rails-').'" "'.cmd.'"' else exe "!".cmd endif return v:shell_error endfunction function! s:app_execute_script_command(cmd) dict abort exe '!'.s:esccmd(self.script_shell_command(a:cmd)) return v:shell_error endfunction function! s:app_lightweight_ruby_eval(ruby,...) dict abort let def = a:0 ? a:1 : "" if !executable("ruby") return def endif let args = '-e '.s:rquote('begin; require %{rubygems}; rescue LoadError; end; begin; require %{active_support}; rescue LoadError; end; '.a:ruby) let cmd = self.ruby_shell_command(args) " If the shell is messed up, this command could cause an error message silent! let results = system(cmd) return v:shell_error == 0 ? results : def endfunction function! s:app_eval(ruby,...) dict abort let def = a:0 ? a:1 : "" if !executable("ruby") return def endif let args = "-r./config/boot -r ".s:rquote(self.path("config/environment"))." -e ".s:rquote(a:ruby) let cmd = self.ruby_shell_command(args) " If the shell is messed up, this command could cause an error message silent! let results = system(cmd) return v:shell_error == 0 ? results : def endfunction call s:add_methods('app', ['ruby_shell_command','script_shell_command','execute_script_command','background_script_command','lightweight_ruby_eval','eval']) " }}}1 " Commands {{{1 function! s:prephelp() let fn = fnamemodify(s:file,':h:h').'/doc/' if filereadable(fn.'rails.txt') if !filereadable(fn.'tags') || getftime(fn.'tags') <= getftime(fn.'rails.txt') silent! helptags `=fn` endif endif endfunction function! RailsHelpCommand(...) call s:prephelp() let topic = a:0 ? a:1 : "" if topic == "" || topic == "-" return "help rails" elseif topic =~ '^g:' return "help ".topic elseif topic =~ '^-' return "help rails".topic else return "help rails-".topic endif endfunction function! s:BufCommands() call s:BufFinderCommands() call s:BufNavCommands() call s:BufScriptWrappers() command! -buffer -bar -nargs=? -bang -count -complete=customlist,s:Complete_rake Rake :call s:Rake(0,! && ? -1 : ,) command! -buffer -bar -nargs=? -bang -range -complete=customlist,s:Complete_preview Rpreview :call s:Preview(0,,) command! -buffer -bar -nargs=? -bang -complete=customlist,s:Complete_environments Rlog :call s:Log(0,) command! -buffer -bar -nargs=* -bang -complete=customlist,s:Complete_set Rset :call s:Set(0,) command! -buffer -bar -nargs=0 Rtags :call rails#app().tags_command() " Embedding all this logic directly into the command makes the error " messages more concise. command! -buffer -bar -nargs=? -bang Rdoc : \ if 0 || =~ "^\\([:'-]\\|g:\\)" | \ exe RailsHelpCommand() | \ else | call s:Doc(0,) | endif command! -buffer -bar -nargs=0 -bang Rrefresh :if 0|unlet! g:autoloaded_rails|source `=s:file`|endif|call s:Refresh(0) if exists(":NERDTree") command! -buffer -bar -nargs=? -complete=customlist,s:Complete_cd Rtree :NERDTree `=rails#app().path()` endif if exists("g:loaded_dbext") command! -buffer -bar -nargs=? -complete=customlist,s:Complete_environments Rdbext :call s:BufDatabase(2,)|let b:dbext_buffer_defaulted = 1 endif let ext = expand("%:e") if ext =~ s:viewspattern() " TODO: complete controller names with trailing slashes here command! -buffer -bar -bang -nargs=? -range -complete=customlist,s:controllerList Rextract :,call s:Extract(0,) endif if RailsFilePath() =~ '\0) endif endfunction function! s:Doc(bang, string) if a:string != "" if exists("g:rails_search_url") let query = substitute(a:string,'[^A-Za-z0-9_.~-]','\="%".printf("%02X",char2nr(submatch(0)))','g') let url = printf(g:rails_search_url, query) else return s:error("specify a g:rails_search_url with %s for a query placeholder") endif elseif isdirectory(rails#app().path("doc/api/classes")) let url = rails#app().path("/doc/api/index.html") elseif s:getpidfor("0.0.0.0","8808") > 0 let url = "http://localhost:8808" else let url = "http://api.rubyonrails.org" endif call s:initOpenURL() if exists(":OpenURL") exe "OpenURL ".s:escarg(url) else return s:error("No :OpenURL command found") endif endfunction function! s:Log(bang,arg) if a:arg == "" let lf = "log/".s:environment().".log" else let lf = "log/".a:arg.".log" endif let size = getfsize(rails#app().path(lf)) if size >= 1048576 call s:warn("Log file is ".((size+512)/1024)."KB. Consider :Rake log:clear") endif if a:bang exe "cgetfile ".lf clast else if exists(":Tail") Tail `=rails#app().path(lf)` else pedit `=rails#app().path(lf)` endif endif endfunction function! rails#new_app_command(bang,...) if a:0 == 0 let msg = "rails.vim ".g:autoloaded_rails if a:bang && exists('b:rails_root') && rails#buffer().type_name() == '' echo msg." (Rails)" elseif a:bang && exists('b:rails_root') echo msg." (Rails-".rails#buffer().type_name().")" elseif a:bang echo msg else !rails endif return endif let args = map(copy(a:000),'expand(v:val)') if a:bang let args = ['--force'] + args endif exe '!rails '.join(map(copy(args),'s:rquote(v:val)'),' ') for dir in args if dir !~# '^-' && filereadable(dir.'/'.g:rails_default_file) edit `=dir.'/'.g:rails_default_file` return endif endfor endfunction function! s:app_tags_command() dict if exists("g:Tlist_Ctags_Cmd") let cmd = g:Tlist_Ctags_Cmd elseif executable("exuberant-ctags") let cmd = "exuberant-ctags" elseif executable("ctags-exuberant") let cmd = "ctags-exuberant" elseif executable("ctags") let cmd = "ctags" elseif executable("ctags.exe") let cmd = "ctags.exe" else return s:error("ctags not found") endif exe '!'.cmd.' -f '.s:escarg(self.path("tmp/tags")).' -R --langmap="ruby:+.rake.builder.rjs" '.g:rails_ctags_arguments.' '.s:escarg(self.path()) endfunction call s:add_methods('app',['tags_command']) function! s:Refresh(bang) if exists("g:rubycomplete_rails") && g:rubycomplete_rails && has("ruby") && exists('g:rubycomplete_completions') silent! ruby ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord) silent! ruby if defined?(ActiveSupport::Dependencies); ActiveSupport::Dependencies.clear; elsif defined?(Dependencies); Dependencies.clear; end if a:bang silent! ruby ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord) endif endif call rails#app().cache.clear() silent doautocmd User BufLeaveRails if a:bang for key in keys(s:apps) if type(s:apps[key]) == type({}) call s:apps[key].cache.clear() endif call extend(s:apps[key],filter(copy(s:app_prototype),'type(v:val) == type(function("tr"))'),'force') endfor endif let i = 1 let max = bufnr('$') while i <= max let rr = getbufvar(i,"rails_root") if rr != "" call setbufvar(i,"rails_refresh",1) endif let i += 1 endwhile silent doautocmd User BufEnterRails endfunction function! s:RefreshBuffer() if exists("b:rails_refresh") && b:rails_refresh let oldroot = b:rails_root unlet! b:rails_root let b:rails_refresh = 0 call RailsBufInit(oldroot) unlet! b:rails_refresh endif endfunction " }}}1 " Rake {{{1 function! s:app_rake_tasks() dict if self.cache.needs('rake_tasks') call s:push_chdir() try let lines = split(system("rake -T"),"\n") finally call s:pop_command() endtry if v:shell_error != 0 return [] endif call map(lines,'matchstr(v:val,"^rake\\s\\+\\zs\\S*")') call filter(lines,'v:val != ""') call self.cache.set('rake_tasks',lines) endif return self.cache.get('rake_tasks') endfunction call s:add_methods('app', ['rake_tasks']) let s:efm_backtrace='%D(in\ %f),' \.'%\\s%#from\ %f:%l:%m,' \.'%\\s%#from\ %f:%l:,' \.'%\\s#{RAILS_ROOT}/%f:%l:\ %#%m,' \.'%\\s%##\ %f:%l:%m,' \.'%\\s%##\ %f:%l,' \.'%\\s%#[%f:%l:\ %#%m,' \.'%\\s%#%f:%l:\ %#%m,' \.'%\\s%#%f:%l:,' \.'%m\ [%f:%l]:' function! s:makewithruby(arg,bang,...) let old_make = &makeprg try let &l:makeprg = rails#app().ruby_shell_command(a:arg) exe 'make'.(a:bang ? '!' : '') if !a:bang cwindow endif finally let &l:makeprg = old_make endtry endfunction function! s:Rake(bang,lnum,arg) let self = rails#app() let lnum = a:lnum < 0 ? 0 : a:lnum let old_makeprg = &l:makeprg let old_errorformat = &l:errorformat try if exists('b:bundler_root') && b:bundler_root ==# rails#app().path() let &l:makeprg = 'bundle exec rake' else let &l:makeprg = 'rake' endif let &l:errorformat = s:efm_backtrace let arg = a:arg if &filetype == "ruby" && arg == '' && g:rails_modelines let mnum = s:lastmethodline(lnum) let str = getline(mnum)."\n".getline(mnum+1)."\n".getline(mnum+2)."\n" let pat = '\s\+\zs.\{-\}\ze\%(\n\|\s\s\|#{\@!\|$\)' let mat = matchstr(str,'#\s*rake'.pat) let mat = s:sub(mat,'\s+$','') if mat != "" let arg = mat endif endif if arg == '' let opt = s:getopt('task','bl') if opt != '' let arg = opt else let arg = rails#buffer().default_rake_task(lnum) endif endif if !has_key(self,'options') | let self.options = {} | endif if arg == '-' let arg = get(self.options,'last_rake_task','') endif let self.options['last_rake_task'] = arg let withrubyargs = '-r ./config/boot -r '.s:rquote(self.path('config/environment')).' -e "puts \%((in \#{Dir.getwd}))" ' if arg =~# '^notes\>' let &l:errorformat = '%-P%f:,\ \ *\ [%*[\ ]%l]\ [%t%*[^]]] %m,\ \ *\ [%*[\ ]%l] %m,%-Q' " %D to chdir is apparently incompatible with %P multiline messages call s:push_chdir(1) exe 'make! '.arg call s:pop_command() if !a:bang cwindow endif elseif arg =~# '^\%(stats\|routes\|secret\|time:zones\|db:\%(charset\|collation\|fixtures:identify\>.*\|migrate:status\|version\)\)\%([: ]\|$\)' let &l:errorformat = '%D(in\ %f),%+G%.%#' exe 'make! '.arg if !a:bang copen endif elseif arg =~ '^preview\>' exe (lnum == 0 ? '' : lnum).'R'.s:gsub(arg,':','/') elseif arg =~ '^runner:' let arg = s:sub(arg,'^runner:','') let root = matchstr(arg,'%\%(:\w\)*') let file = expand(root).matchstr(arg,'%\%(:\w\)*\zs.*') if file =~ '#.*$' let extra = " -- -n ".matchstr(file,'#\zs.*') let file = s:sub(file,'#.*','') else let extra = '' endif if self.has_file(file) || self.has_file(file.'.rb') call s:makewithruby(withrubyargs.'-r"'.file.'"'.extra,a:bang,file !~# '_\%(spec\|test\)\%(\.rb\)\=$') else call s:makewithruby(withrubyargs.'-e '.s:esccmd(s:rquote(arg)),a:bang) endif elseif arg == 'run' || arg == 'runner' call s:makewithruby(withrubyargs.'-r"'.RailsFilePath().'"',a:bang,RailsFilePath() !~# '_\%(spec\|test\)\%(\.rb\)\=$') elseif arg =~ '^run:' let arg = s:sub(arg,'^run:','') let arg = s:sub(arg,'^\%:h',expand('%:h')) let arg = s:sub(arg,'^%(\%|$|#@=)',expand('%')) let arg = s:sub(arg,'#(\w+[?!=]=)$',' -- -n\1') call s:makewithruby(withrubyargs.'-r'.arg,a:bang,arg !~# '_\%(spec\|test\)\.rb$') else exe 'make! '.arg if !a:bang cwindow endif endif finally let &l:errorformat = old_errorformat let &l:makeprg = old_makeprg endtry endfunction function! s:readable_default_rake_task(lnum) dict abort let app = self.app() let lnum = a:lnum < 0 ? 0 : a:lnum if self.getvar('&buftype') == 'quickfix' return '-' elseif self.getline(lnum) =~# '# rake ' return matchstr(self.getline(lnum),'\C# rake \zs.*') elseif self.getline(self.last_method_line(lnum)-1) =~# '# rake ' return matchstr(self.getline(self.last_method_line(lnum)-1),'\C# rake \zs.*') elseif self.getline(self.last_method_line(lnum)) =~# '# rake ' return matchstr(self.getline(self.last_method_line(lnum)),'\C# rake \zs.*') elseif self.getline(1) =~# '# rake ' && !lnum return matchstr(self.getline(1),'\C# rake \zs.*') elseif self.type_name('config-routes') return 'routes' elseif self.type_name('fixtures-yaml') && lnum return "db:fixtures:identify LABEL=".self.last_method(lnum) elseif self.type_name('fixtures') && lnum == 0 return "db:fixtures:load FIXTURES=".s:sub(fnamemodify(self.name(),':r'),'^.{-}/fixtures/','') elseif self.type_name('task') let mnum = self.last_method_line(lnum) let line = getline(mnum) " We can't grab the namespace so only run tasks at the start of the line if line =~# '^\%(task\|file\)\>' return self.last_method(a:lnum) else return matchstr(self.getline(1),'\C# rake \zs.*') endif elseif self.type_name('spec') if self.name() =~# '\ 0 return 'spec SPEC="'.self.path().'":'.lnum else return 'spec SPEC="'.self.path().'"' endif elseif self.type_name('test') let meth = self.last_method(lnum) if meth =~ '^test_' let call = " -n".meth."" else let call = "" endif if self.type_name('test-unit','test-functional','test-integration') return s:sub(s:gsub(self.type_name(),'-',':'),'unit$|functional$','&s').' TEST="'.self.path().'"'.s:sub(call,'^ ',' TESTOPTS=') elseif self.name() =~# '\ 0 return 'cucumber FEATURE="'.self.path().'":'.lnum else return 'cucumber FEATURE="'.self.path().'"' endif elseif self.type_name('cucumber') return 'cucumber' else return '' endif endfunction function! s:Complete_rake(A,L,P) return s:completion_filter(rails#app().rake_tasks(),a:A) endfunction call s:add_methods('readable',['default_rake_task']) " }}}1 " Preview {{{1 function! s:initOpenURL() if !exists(":OpenURL") if has("gui_mac") || has("gui_macvim") || exists("$SECURITYSESSIONID") command -bar -nargs=1 OpenURL :!open elseif has("gui_win32") command -bar -nargs=1 OpenURL :!start cmd /cstart /b elseif executable("sensible-browser") command -bar -nargs=1 OpenURL :!sensible-browser endif endif endfunction function! s:scanlineforuris(line) let url = matchstr(a:line,"\\v\\C%(%(GET|PUT|POST|DELETE)\\s+|\\w+://[^/]*)/[^ \n\r\t<>\"]*[^] .,;\n\r\t<>\":]") if url =~ '\C^\u\+\s\+' let method = matchstr(url,'^\u\+') let url = matchstr(url,'\s\+\zs.*') if method !=? "GET" let url .= (url =~ '?' ? '&' : '?') . '_method='.tolower(method) endif endif if url != "" return [url] else return [] endif endfunction function! s:readable_preview_urls(lnum) dict abort let urls = [] let start = self.last_method_line(a:lnum) - 1 while start > 0 && self.getline(start) =~ '^\s*\%(\%(-\=\|<%\)#.*\)\=$' let urls = s:scanlineforuris(self.getline(start)) + urls let start -= 1 endwhile let start = 1 while start < self.line_count() && self.getline(start) =~ '^\s*\%(\%(-\=\|<%\)#.*\)\=$' let urls += s:scanlineforuris(self.getline(start)) let start += 1 endwhile if has_key(self,'getvar') && self.getvar('rails_preview') != '' let url += [self.getvar('rails_preview')] end if self.name() =~ '^public/stylesheets/sass/' let urls = urls + [s:sub(s:sub(self.name(),'^public/stylesheets/sass/','/stylesheets/'),'\.s[ac]ss$','.css')] elseif self.name() =~ '^public/' let urls = urls + [s:sub(self.name(),'^public','')] elseif self.name() =~ '^app/assets/stylesheets/' let urls = urls + ['/assets/application.css'] elseif self.name() =~ '^app/assets/javascripts/' let urls = urls + ['/assets/application.js'] elseif self.name() =~ '^app/stylesheets/' let urls = urls + [s:sub(s:sub(self.name(),'^app/stylesheets/','/stylesheets/'),'\.less$','.css')] elseif self.name() =~ '^app/scripts/' let urls = urls + [s:sub(s:sub(self.name(),'^app/scripts/','/javascripts/'),'\.coffee$','.js')] elseif self.controller_name() != '' && self.controller_name() != 'application' if self.type_name('controller') && self.last_method(a:lnum) != '' let urls += ['/'.self.controller_name().'/'.self.last_method(a:lnum).'/'] elseif self.type_name('controller','view-layout','view-partial') let urls += ['/'.self.controller_name().'/'] elseif self.type_name('view') let urls += ['/'.s:controller().'/'.fnamemodify(self.name(),':t:r:r').'/'] endif endif return urls endfunction call s:add_methods('readable',['preview_urls']) function! s:Preview(bang,lnum,arg) let root = s:getopt("root_url") if root == '' let root = s:getopt("url") endif let root = s:sub(root,'/$','') if a:arg =~ '://' let uri = a:arg elseif a:arg != '' let uri = root.'/'.s:sub(a:arg,'^/','') else let uri = get(rails#buffer().preview_urls(a:lnum),0,'') let uri = root.'/'.s:sub(s:sub(uri,'^/',''),'/$','') endif call s:initOpenURL() if exists(':OpenURL') && !a:bang exe 'OpenURL '.uri else " Work around bug where URLs ending in / get handled as FTP let url = uri.(uri =~ '/$' ? '?' : '') silent exe 'pedit '.url wincmd w if &filetype == '' if uri =~ '\.css$' setlocal filetype=css elseif uri =~ '\.js$' setlocal filetype=javascript elseif getline(1) =~ '^\s*<' setlocal filetype=xhtml endif endif call RailsBufInit(rails#app().path()) map q :bwipe wincmd p if !a:bang call s:warn("Define a :OpenURL command to use a browser") endif endif endfunction function! s:Complete_preview(A,L,P) return rails#buffer().preview_urls(a:L =~ '^\d' ? matchstr(a:L,'^\d\+') : line('.')) endfunction " }}}1 " Script Wrappers {{{1 function! s:BufScriptWrappers() command! -buffer -bar -nargs=* -complete=customlist,s:Complete_script Rscript :call rails#app().script_command(0,) command! -buffer -bar -nargs=* -complete=customlist,s:Complete_generate Rgenerate :call rails#app().generate_command(0,) command! -buffer -bar -nargs=* -complete=customlist,s:Complete_destroy Rdestroy :call rails#app().destroy_command(0,) command! -buffer -bar -nargs=? -bang -complete=customlist,s:Complete_server Rserver :call rails#app().server_command(0,) command! -buffer -bang -nargs=1 -range=0 -complete=customlist,s:Complete_ruby Rrunner :call rails#app().runner_command(0 ? -2 : (==?:-1),) command! -buffer -nargs=1 -range=0 -complete=customlist,s:Complete_ruby Rp :call rails#app().runner_command(==?:-1,'p begin '..' end') command! -buffer -nargs=1 -range=0 -complete=customlist,s:Complete_ruby Rpp :call rails#app().runner_command(==?:-1,'require %{pp}; pp begin '..' end') command! -buffer -nargs=1 -range=0 -complete=customlist,s:Complete_ruby Ry :call rails#app().runner_command(==?:-1,'y begin '..' end') endfunction function! s:app_generators() dict if self.cache.needs('generators') let generators = self.relglob("vendor/plugins/","*/generators/*") let generators += self.relglob("","lib/generators/*") call filter(generators,'v:val =~ "/$"') let generators += split(glob(expand("~/.rails/generators")."/*"),"\n") call map(generators,'s:sub(v:val,"^.*[\\\\/]generators[\\\\/]\\ze.","")') call map(generators,'s:sub(v:val,"[\\\\/]$","")') call self.cache.set('generators',generators) endif return sort(split(g:rails_generators,"\n") + self.cache.get('generators')) endfunction function! s:app_script_command(bang,...) dict let str = "" let cmd = a:0 ? a:1 : "console" let c = 2 while c <= a:0 let str .= " " . s:rquote(a:{c}) let c += 1 endwhile if cmd ==# "plugin" call self.cache.clear('generators') endif if a:bang || cmd =~# 'console' return self.background_script_command(cmd.str) else return self.execute_script_command(cmd.str) endif endfunction function! s:app_runner_command(count,args) dict if a:count == -2 return self.script_command(a:bang,"runner",a:args) else let str = self.ruby_shell_command('-r./config/boot -e "require '."'commands/runner'".'" '.s:rquote(a:args)) let res = s:sub(system(str),'\n$','') if a:count < 0 echo res else exe a:count.'put =res' endif endif endfunction function! s:getpidfor(bind,port) if has("win32") || has("win64") let netstat = system("netstat -anop tcp") let pid = matchstr(netstat,'\<'.a:bind.':'.a:port.'\>.\{-\}LISTENING\s\+\zs\d\+') elseif executable('lsof') let pid = system("lsof -i 4tcp@".a:bind.':'.a:port."|grep LISTEN|awk '{print $2}'") let pid = s:sub(pid,'\n','') else let pid = "" endif return pid endfunction function! s:app_server_command(bang,arg) dict let port = matchstr(a:arg,'\%(-p\|--port=\=\)\s*\zs\d\+') if port == '' let port = "3000" endif " TODO: Extract bind argument let bind = "0.0.0.0" if a:bang && executable("ruby") let pid = s:getpidfor(bind,port) if pid =~ '^\d\+$' echo "Killing server with pid ".pid if !has("win32") call system("ruby -e 'Process.kill(:TERM,".pid.")'") sleep 100m endif call system("ruby -e 'Process.kill(9,".pid.")'") sleep 100m endif if a:arg == "-" return endif endif if has_key(self,'options') && has_key(self.options,'gnu_screen') let screen = self.options.gnu_screen else let screen = g:rails_gnu_screen endif if has("win32") || has("win64") || (exists("$STY") && !has("gui_running") && screen && executable("screen")) || (exists("$TMUX") && !has("gui_running") && screen && executable("tmux")) call self.background_script_command('server '.a:arg) else " --daemon would be more descriptive but lighttpd does not support it call self.execute_script_command('server '.a:arg." -d") endif call s:setopt('a:root_url','http://'.(bind=='0.0.0.0'?'localhost': bind).':'.port.'/') endfunction function! s:app_destroy_command(bang,...) dict if a:0 == 0 return self.execute_script_command('destroy') elseif a:0 == 1 return self.execute_script_command('destroy '.s:rquote(a:1)) endif let str = "" let c = 1 while c <= a:0 let str .= " " . s:rquote(a:{c}) let c += 1 endwhile call self.execute_script_command('destroy'.str) call self.cache.clear('user_classes') endfunction function! s:app_generate_command(bang,...) dict if a:0 == 0 return self.execute_script_command('generate') elseif a:0 == 1 return self.execute_script_command('generate '.s:rquote(a:1)) endif let cmd = join(map(copy(a:000),'s:rquote(v:val)'),' ') if cmd !~ '-p\>' && cmd !~ '--pretend\>' let execstr = self.script_shell_command('generate '.cmd.' -p -f') let res = system(execstr) let g:res = res let junk = '\%(\e\[[0-9;]*m\)\=' let file = matchstr(res,junk.'\s\+\%(create\|force\)'.junk.'\s\+\zs\f\+\.rb\ze\n') if file == "" let file = matchstr(res,junk.'\s\+\%(identical\)'.junk.'\s\+\zs\f\+\.rb\ze\n') endif else let file = "" endif if !self.execute_script_command('generate '.cmd) && file != '' call self.cache.clear('user_classes') call self.cache.clear('features') if file =~ '^db/migrate/\d\d\d\d' let file = get(self.relglob('',s:sub(file,'\d+','[0-9]*[0-9]')),-1,file) endif edit `=self.path(file)` endif endfunction call s:add_methods('app', ['generators','script_command','runner_command','server_command','destroy_command','generate_command']) function! s:Complete_script(ArgLead,CmdLine,P) let cmd = s:sub(a:CmdLine,'^\u\w*\s+','') if cmd !~ '^[ A-Za-z0-9_=:-]*$' return [] elseif cmd =~# '^\w*$' return s:completion_filter(rails#app().relglob("script/","**/*"),a:ArgLead) elseif cmd =~# '^\%(plugin\)\s\+'.a:ArgLead.'$' return s:completion_filter(["discover","list","install","update","remove","source","unsource","sources"],a:ArgLead) elseif cmd =~# '\%(plugin\)\s\+\%(install\|remove\)\s\+'.a:ArgLead.'$' || cmd =~ '\%(generate\|destroy\)\s\+plugin\s\+'.a:ArgLead.'$' return s:pluginList(a:ArgLead,a:CmdLine,a:P) elseif cmd =~# '^\%(generate\|destroy\)\s\+'.a:ArgLead.'$' return s:completion_filter(rails#app().generators(),a:ArgLead) elseif cmd =~# '^\%(generate\|destroy\)\s\+\w\+\s\+'.a:ArgLead.'$' let target = matchstr(cmd,'^\w\+\s\+\%(\w\+:\)\=\zs\w\+\ze\s\+') if target =~# '^\w*controller$' return filter(s:controllerList(a:ArgLead,"",""),'v:val !=# "application"') elseif target ==# 'generator' return s:completion_filter(map(rails#app().relglob('lib/generators/','*'),'s:sub(v:val,"/$","")')) elseif target ==# 'helper' return s:helperList(a:ArgLead,"","") elseif target ==# 'integration_test' || target ==# 'integration_spec' || target ==# 'feature' return s:integrationtestList(a:ArgLead,"","") elseif target ==# 'metal' return s:metalList(a:ArgLead,"","") elseif target ==# 'migration' || target ==# 'session_migration' return s:migrationList(a:ArgLead,"","") elseif target =~# '^\w*\%(model\|resource\)$' || target =~# '\w*scaffold\%(_controller\)\=$' || target ==# 'mailer' return s:modelList(a:ArgLead,"","") elseif target ==# 'observer' let observers = s:observerList("","","") let models = s:modelList("","","") if cmd =~# '^destroy\>' let models = [] endif call filter(models,'index(observers,v:val) < 0') return s:completion_filter(observers + models,a:ArgLead) else return [] endif elseif cmd =~# '^\%(generate\|destroy\)\s\+scaffold\s\+\w\+\s\+'.a:ArgLead.'$' return filter(s:controllerList(a:ArgLead,"",""),'v:val !=# "application"') return s:completion_filter(rails#app().environments()) elseif cmd =~# '^\%(console\)\s\+\(--\=\w\+\s\+\)\='.a:ArgLead."$" return s:completion_filter(rails#app().environments()+["-s","--sandbox"],a:ArgLead) elseif cmd =~# '^\%(server\)\s\+.*-e\s\+'.a:ArgLead."$" return s:completion_filter(rails#app().environments(),a:ArgLead) elseif cmd =~# '^\%(server\)\s\+' if a:ArgLead =~# '^--environment=' return s:completion_filter(map(copy(rails#app().environments()),'"--environment=".v:val'),a:ArgLead) else 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)') endif endif return "" endfunction function! s:CustomComplete(A,L,P,cmd) let L = "Rscript ".a:cmd." ".s:sub(a:L,'^\h\w*\s+','') let P = a:P - strlen(a:L) + strlen(L) return s:Complete_script(a:A,L,P) endfunction function! s:Complete_server(A,L,P) return s:CustomComplete(a:A,a:L,a:P,"server") endfunction function! s:Complete_console(A,L,P) return s:CustomComplete(a:A,a:L,a:P,"console") endfunction function! s:Complete_generate(A,L,P) return s:CustomComplete(a:A,a:L,a:P,"generate") endfunction function! s:Complete_destroy(A,L,P) return s:CustomComplete(a:A,a:L,a:P,"destroy") endfunction function! s:Complete_ruby(A,L,P) return s:completion_filter(rails#app().user_classes()+["ActiveRecord::Base"],a:A) endfunction " }}}1 " Navigation {{{1 function! s:BufNavCommands() command! -buffer -bar -nargs=? -complete=customlist,s:Complete_cd Rcd :cd `=rails#app().path()` command! -buffer -bar -nargs=? -complete=customlist,s:Complete_cd Rlcd :lcd `=rails#app().path()` 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(,'' ,) 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(,'E',) 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(,'S',) 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(,'V',) 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(,'T',) 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')|RSfind 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')|RTfind 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(,'' ,) 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(,'E',) 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(,'S',) 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(,'V',) 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(,'T',) 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(,'D',) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related A :call s:Alternate('', ,,,) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related AE :call s:Alternate('E',,,,) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related AS :call s:Alternate('S',,,,) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related AV :call s:Alternate('V',,,,) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related AT :call s:Alternate('T',,,,) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related AD :call s:Alternate('D',,,,) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related AN :call s:Related('' ,,,,) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related R :call s:Related('' ,,,,) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related RE :call s:Related('E',,,,) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related RS :call s:Related('S',,,,) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related RV :call s:Related('V',,,,) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related RT :call s:Related('T',,,,) command! -buffer -bar -nargs=* -range=0 -complete=customlist,s:Complete_related RD :call s:Related('D',,,,) endfunction function! s:djump(def) let def = s:sub(a:def,'^[#:]','') if def =~ '^\d\+$' exe def elseif def =~ '^!' if expand('%') !~ '://' && !isdirectory(expand('%:p:h')) call mkdir(expand('%:p:h'),'p') endif elseif def != '' let ext = matchstr(def,'\.\zs.*') let def = matchstr(def,'[^.]*') let v:errmsg = '' silent! exe "djump ".def if ext != '' && (v:errmsg == '' || v:errmsg =~ '^E387') let rpat = '\C^\s*\%(mail\>.*\|respond_to\)\s*\%(\ 0 let variable = matchstr(getline(rline),rpat) let success = search('\C^\s*'.variable.'\s*\.\s*\zs'.ext.'\>','',end) if !success silent! exe "djump ".def endif endif endif endif endfunction function! s:Find(count,cmd,...) let str = "" if a:0 let i = 1 while i < a:0 let str .= s:escarg(a:{i}) . " " let i += 1 endwhile let file = a:{i} let tail = matchstr(file,'[#!].*$\|:\d*\%(:in\>.*\)\=$') if tail != "" let file = s:sub(file,'[#!].*$|:\d*%(:in>.*)=$','') endif if file != "" let file = s:RailsIncludefind(file) endif else let file = s:RailsFind() let tail = "" endif call s:findedit((a:count==1?'' : a:count).a:cmd,file.tail,str) endfunction function! s:Edit(count,cmd,...) if a:0 let str = "" let i = 1 while i < a:0 let str .= "`=a:".i."` " let i += 1 endwhile let file = a:{i} call s:findedit(s:editcmdfor(a:cmd),file,str) else exe s:editcmdfor(a:cmd) endif endfunction function! s:fuzzyglob(arg) return s:gsub(s:gsub(a:arg,'[^/.]','[&]*'),'%(/|^)\.@!|\.','&*') endfunction function! s:Complete_find(ArgLead, CmdLine, CursorPos) let paths = s:pathsplit(&l:path) let seen = {} for path in paths if s:startswith(path,rails#app().path()) && path !~ '[][*]' let path = path[strlen(rails#app().path()) + 1 : ] for file in rails#app().relglob(path == '' ? '' : path.'/',s:fuzzyglob(rails#underscore(a:ArgLead)), a:ArgLead =~# '\u' ? '.rb' : '') let seen[file] = 1 endfor endif endfor return s:autocamelize(sort(keys(seen)),a:ArgLead) endfunction function! s:Complete_edit(ArgLead, CmdLine, CursorPos) return s:completion_filter(rails#app().relglob("",s:fuzzyglob(a:ArgLead)),a:ArgLead) endfunction function! s:Complete_cd(ArgLead, CmdLine, CursorPos) let all = rails#app().relglob("",a:ArgLead."*") call filter(all,'v:val =~ "/$"') return filter(all,'s:startswith(v:val,a:ArgLead)') endfunction function! RailsIncludeexpr() " Is this foolproof? if mode() =~ '[iR]' || expand("") != v:fname return s:RailsIncludefind(v:fname) else return s:RailsIncludefind(v:fname,1) endif endfunction function! s:linepeak() let line = getline(line(".")) let line = s:sub(line,'^(.{'.col(".").'}).*','\1') let line = s:sub(line,'([:"'."'".']|\%[qQ]=[[({<])=\f*$','') return line endfunction function! s:matchcursor(pat) let line = getline(".") let lastend = 0 while lastend >= 0 let beg = match(line,'\C'.a:pat,lastend) let end = matchend(line,'\C'.a:pat,lastend) if beg < col(".") && end >= col(".") return matchstr(line,'\C'.a:pat,lastend) endif let lastend = end endwhile return "" endfunction function! s:findit(pat,repl) let res = s:matchcursor(a:pat) if res != "" return substitute(res,'\C'.a:pat,a:repl,'') else return "" endif endfunction function! s:findamethod(func,repl) return s:findit('\s*\<\%('.a:func.'\)\s*(\=\s*[@:'."'".'"]\(\f\+\)\>.\=',a:repl) endfunction function! s:findasymbol(sym,repl) return s:findit('\s*\%(:\%('.a:sym.'\)\s*=>\|\<'.a:sym.':\)\s*(\=\s*[@:'."'".'"]\(\f\+\)\>.\=',a:repl) endfunction function! s:findfromview(func,repl) " ( ) ( ) ( \1 ) ( ) return s:findit('\s*\%(<%\)\==\=\s*\<\%('.a:func.'\)\s*(\=\s*[@:'."'".'"]\(\f\+\)\>['."'".'"]\=\s*\%(%>\s*\)\=',a:repl) endfunction function! s:RailsFind() if filereadable(expand("")) return expand("") endif " UGH let buffer = rails#buffer() let format = s:format('html') let res = s:findit('\v\s*.=',expand('%:h').'/\1') if res != ""|return res.(fnamemodify(res,':e') == '' ? '.rb' : '')|endif let res = s:findit('\v['."'".'"]=',expand('%:h').'\1') if res != ""|return res|endif let res = rails#underscore(s:findit('\v\s*<%(include|extend)\(=\s*<([[:alnum:]_:]+)>','\1')) if res != ""|return res.".rb"|endif let res = s:findamethod('require','\1') if res != ""|return res.(fnamemodify(res,':e') == '' ? '.rb' : '')|endif let res = s:findamethod('belongs_to\|has_one\|composed_of\|validates_associated\|scaffold','app/models/\1.rb') if res != ""|return res|endif let res = rails#singularize(s:findamethod('has_many\|has_and_belongs_to_many','app/models/\1')) if res != ""|return res.".rb"|endif let res = rails#singularize(s:findamethod('create_table\|change_table\|drop_table\|add_column\|rename_column\|remove_column\|add_index','app/models/\1')) if res != ""|return res.".rb"|endif let res = rails#singularize(s:findasymbol('through','app/models/\1')) if res != ""|return res.".rb"|endif let res = s:findamethod('fixtures','fixtures/\1') if res != "" return RailsFilePath() =~ '\\|\\|,\s*to:\)\s*','app/controllers/\1') if res =~ '#'|return s:sub(res,'#','_controller.rb#')|endif let res = s:findamethod('layout','\=s:findlayout(submatch(1))') if res != ""|return res|endif let res = s:findasymbol('layout','\=s:findlayout(submatch(1))') if res != ""|return res|endif let res = s:findamethod('helper','app/helpers/\1_helper.rb') if res != ""|return res|endif let res = s:findasymbol('controller','app/controllers/\1_controller.rb') if res != ""|return res|endif let res = s:findasymbol('action','\1') if res != ""|return res|endif let res = s:findasymbol('template','app/views/\1') if res != ""|return res|endif let res = s:sub(s:sub(s:findasymbol('partial','\1'),'^/',''),'[^/]+$','_&') if res != ""|return res."\n".s:findview(res)|endif let res = s:sub(s:sub(s:findfromview('render\s*(\=\s*\%(:partial\s\+=>\|partial:\)\s*','\1'),'^/',''),'[^/]+$','_&') if res != ""|return res."\n".s:findview(res)|endif let res = s:findamethod('render\>\s*\%(:\%(template\|action\)\s\+=>\|template:\|action:\)\s*','\1.'.format.'\n\1') if res != ""|return res|endif let res = s:sub(s:findfromview('render','\1'),'^/','') if buffer.type_name('view') | let res = s:sub(res,'[^/]+$','_&') | endif if res != ""|return res."\n".s:findview(res)|endif let res = s:findamethod('redirect_to\s*(\=\s*\%\(:action\s\+=>\|\','/application') if res != '' && fnamemodify(res, ':e') == '' " Append the default extension iff the filename doesn't already contains an extension let res .= '.js' end if res != ""|return res|endif if buffer.type_name('controller') let contr = s:controller() let view = s:findit('\s*\(\=','/\1') let res = s:findview(contr.'/'.view) if res != ""|return res|endif endif let old_isfname = &isfname try set isfname=@,48-57,/,-,_,:,# " TODO: grab visual selection in visual mode let cfile = expand("") finally let &isfname = old_isfname endtry let res = s:RailsIncludefind(cfile,1) return res endfunction function! s:app_named_route_file(route) dict call self.route_names() if self.cache.has("named_routes") && has_key(self.cache.get("named_routes"),a:route) return self.cache.get("named_routes")[a:route] endif return "" endfunction function! s:app_route_names() dict if self.cache.needs("named_routes") let exec = "ActionController::Routing::Routes.named_routes.each {|n,r| puts %{#{n} app/controllers/#{r.requirements[:controller]}_controller.rb##{r.requirements[:action]}}}" let string = self.eval(exec) let routes = {} for line in split(string,"\n") let route = split(line," ") let name = route[0] let routes[name] = route[1] endfor call self.cache.set("named_routes",routes) endif return keys(self.cache.get("named_routes")) endfunction call s:add_methods('app', ['route_names','named_route_file']) function! RailsNamedRoutes() return rails#app().route_names() endfunction function! s:RailsIncludefind(str,...) if a:str ==# "ApplicationController" return "application_controller.rb\napp/controllers/application.rb" elseif a:str ==# "Test::Unit::TestCase" return "test/unit/testcase.rb" endif let str = a:str if a:0 == 1 " Get the text before the filename under the cursor. " We'll cheat and peak at this in a bit let line = s:linepeak() let line = s:sub(line,'([:"'."'".']|\%[qQ]=[[({<])=\f*$','') else let line = "" endif let str = s:sub(str,'^\s*','') let str = s:sub(str,'\s*$','') let str = s:sub(str,'^:=[:@]','') let str = s:sub(str,':0x\x+$','') " For # style output let str = s:gsub(str,"[\"']",'') if line =~# '\<\(require\|load\)\s*(\s*$' return str elseif str =~# '^\l\w*#\w\+$' return 'app/controllers/'.s:sub(str,'#','_controller.rb#') endif let str = rails#underscore(str) let fpat = '\(\s*\%("\f*"\|:\f*\|'."'\\f*'".'\)\s*,\s*\)*' if a:str =~# '\u' " Classes should always be in .rb files let str .= '.rb' elseif line =~# ':partial\s*=>\s*' let str = s:sub(str,'[^/]+$','_&') let str = s:findview(str) elseif line =~# '\\s*' let str = s:findview(s:sub(str,'^/=','layouts/')) elseif line =~# ':controller\s*=>\s*' let str = 'app/controllers/'.str.'_controller.rb' elseif line =~# '\\s*$' && rails#buffer().type_name('config-routes')) if line !~# ':as\s*=>\s*$' let str = s:sub(str,'_%(path|url)$','') let str = s:sub(str,'^hash_for_','') endif let file = rails#app().named_route_file(str) if file == "" let str = s:sub(str,'^formatted_','') if str =~# '^\%(new\|edit\)_' let str = 'app/controllers/'.s:sub(rails#pluralize(str),'^(new|edit)_(.*)','\2_controller.rb#\1') elseif str ==# rails#singularize(str) " If the word can't be singularized, it's probably a link to the show " method. We should verify by checking for an argument, but that's " difficult the way things here are currently structured. let str = 'app/controllers/'.rails#pluralize(str).'_controller.rb#show' else let str = 'app/controllers/'.str.'_controller.rb#index' endif else let str = file endif elseif str !~ '/' " If we made it this far, we'll risk making it singular. let str = rails#singularize(str) let str = s:sub(str,'_id$','') endif if str =~ '^/' && !filereadable(str) let str = s:sub(str,'^/','') endif if str =~# '^lib/' && !filereadable(str) let str = s:sub(str,'^lib/','') endif return str endfunction " }}}1 " File Finders {{{1 function! s:addfilecmds(type) let l = s:sub(a:type,'^.','\l&') let cmds = 'ESVTD ' let cmd = '' while cmds != '' let cplt = " -complete=customlist,".s:sid.l."List" exe "command! -buffer -bar ".(cmd == 'D' ? '-range=0 ' : '')."-nargs=*".cplt." R".cmd.l." :call s:".l.'Edit("'.(cmd == 'D' ? '' : '').cmd.'",)' let cmd = strpart(cmds,0,1) let cmds = strpart(cmds,1) endwhile endfunction function! s:BufFinderCommands() command! -buffer -bar -nargs=+ Rnavcommand :call s:Navcommand(0,) call s:addfilecmds("metal") call s:addfilecmds("model") call s:addfilecmds("view") call s:addfilecmds("controller") call s:addfilecmds("mailer") call s:addfilecmds("migration") call s:addfilecmds("observer") call s:addfilecmds("helper") call s:addfilecmds("layout") call s:addfilecmds("fixtures") call s:addfilecmds("locale") if rails#app().has('test') || rails#app().has('spec') call s:addfilecmds("unittest") call s:addfilecmds("functionaltest") endif if rails#app().has('test') || rails#app().has('spec') || rails#app().has('cucumber') call s:addfilecmds("integrationtest") endif if rails#app().has('spec') call s:addfilecmds("spec") endif call s:addfilecmds("stylesheet") call s:addfilecmds("javascript") call s:addfilecmds("plugin") call s:addfilecmds("task") call s:addfilecmds("lib") call s:addfilecmds("environment") call s:addfilecmds("initializer") endfunction function! s:completion_filter(results,A) let results = sort(type(a:results) == type("") ? split(a:results,"\n") : copy(a:results)) call filter(results,'v:val !~# "\\~$"') let filtered = filter(copy(results),'s:startswith(v:val,a:A)') if !empty(filtered) | return filtered | endif let regex = s:gsub(a:A,'[^/]','[&].*') let filtered = filter(copy(results),'v:val =~# "^".regex') if !empty(filtered) | return filtered | endif let regex = s:gsub(a:A,'.','[&].*') let filtered = filter(copy(results),'v:val =~# regex') return filtered endfunction function! s:autocamelize(files,test) if a:test =~# '^\u' return s:completion_filter(map(copy(a:files),'rails#camelize(v:val)'),a:test) else return s:completion_filter(a:files,a:test) endif endfunction function! s:app_relglob(path,glob,...) dict if exists("+shellslash") && ! &shellslash let old_ss = &shellslash let &shellslash = 1 endif let path = a:path if path !~ '^/' && path !~ '^\w:' let path = self.path(path) endif let suffix = a:0 ? a:1 : '' let full_paths = split(glob(path.a:glob.suffix),"\n") let relative_paths = [] for entry in full_paths if suffix == '' && isdirectory(entry) && entry !~ '/$' let entry .= '/' endif let relative_paths += [entry[strlen(path) : -strlen(suffix)-1]] endfor if exists("old_ss") let &shellslash = old_ss endif return relative_paths endfunction call s:add_methods('app', ['relglob']) function! s:relglob(...) return join(call(rails#app().relglob,a:000,rails#app()),"\n") endfunction function! s:helperList(A,L,P) return s:autocamelize(rails#app().relglob("app/helpers/","**/*","_helper.rb"),a:A) endfunction function! s:controllerList(A,L,P) let con = rails#app().relglob("app/controllers/","**/*",".rb") call map(con,'s:sub(v:val,"_controller$","")') return s:autocamelize(con,a:A) endfunction function! s:mailerList(A,L,P) return s:autocamelize(rails#app().relglob("app/mailers/","**/*",".rb"),a:A) endfunction function! s:viewList(A,L,P) let c = s:controller(1) let top = rails#app().relglob("app/views/",s:fuzzyglob(a:A)) call filter(top,'v:val !~# "\\~$"') if c != '' && a:A !~ '/' let local = rails#app().relglob("app/views/".c."/","*.*[^~]") return s:completion_filter(local+top,a:A) endif return s:completion_filter(top,a:A) endfunction function! s:layoutList(A,L,P) return s:completion_filter(rails#app().relglob("app/views/layouts/","*"),a:A) endfunction function! s:stylesheetList(A,L,P) let list = rails#app().relglob('app/assets/stylesheets/','**/*.*','') call map(list,'s:sub(v:val,"\\..*$","")') let list += rails#app().relglob('public/stylesheets/','**/*','.css') if rails#app().has('sass') call extend(list,rails#app().relglob('public/stylesheets/sass/','**/*','.s?ss')) call s:uniq(list) endif return s:completion_filter(list,a:A) endfunction function! s:javascriptList(A,L,P) let list = rails#app().relglob('app/assets/javascripts/','**/*.*','') call map(list,'s:sub(v:val,"\\..*$","")') let list += rails#app().relglob("public/javascripts/","**/*",".js") return s:completion_filter(list,a:A) endfunction function! s:metalList(A,L,P) return s:autocamelize(rails#app().relglob("app/metal/","**/*",".rb"),a:A) endfunction function! s:modelList(A,L,P) let models = rails#app().relglob("app/models/","**/*",".rb") call filter(models,'v:val !~# "_observer$"') return s:autocamelize(models,a:A) endfunction function! s:observerList(A,L,P) return s:autocamelize(rails#app().relglob("app/models/","**/*","_observer.rb"),a:A) endfunction function! s:fixturesList(A,L,P) return s:completion_filter(rails#app().relglob("test/fixtures/","**/*")+rails#app().relglob("spec/fixtures/","**/*"),a:A) endfunction function! s:localeList(A,L,P) return s:completion_filter(rails#app().relglob("config/locales/","**/*"),a:A) endfunction function! s:migrationList(A,L,P) if a:A =~ '^\d' let migrations = rails#app().relglob("db/migrate/",a:A."[0-9_]*",".rb") return map(migrations,'matchstr(v:val,"^[0-9]*")') else let migrations = rails#app().relglob("db/migrate/","[0-9]*[0-9]_*",".rb") call map(migrations,'s:sub(v:val,"^[0-9]*_","")') return s:autocamelize(migrations,a:A) endif endfunction function! s:unittestList(A,L,P) let found = [] if rails#app().has('test') let found += rails#app().relglob("test/unit/","**/*","_test.rb") endif if rails#app().has('spec') let found += rails#app().relglob("spec/models/","**/*","_spec.rb") endif return s:autocamelize(found,a:A) endfunction function! s:functionaltestList(A,L,P) let found = [] if rails#app().has('test') let found += rails#app().relglob("test/functional/","**/*","_test.rb") endif if rails#app().has('spec') let found += rails#app().relglob("spec/controllers/","**/*","_spec.rb") let found += rails#app().relglob("spec/mailers/","**/*","_spec.rb") endif return s:autocamelize(found,a:A) endfunction function! s:integrationtestList(A,L,P) if a:A =~# '^\u' return s:autocamelize(rails#app().relglob("test/integration/","**/*","_test.rb"),a:A) endif let found = [] if rails#app().has('test') let found += rails#app().relglob("test/integration/","**/*","_test.rb") endif if rails#app().has('spec') let found += rails#app().relglob("spec/requests/","**/*","_spec.rb") let found += rails#app().relglob("spec/integration/","**/*","_spec.rb") endif if rails#app().has('cucumber') let found += rails#app().relglob("features/","**/*",".feature") endif return s:completion_filter(found,a:A) endfunction function! s:specList(A,L,P) return s:completion_filter(rails#app().relglob("spec/","**/*","_spec.rb"),a:A) endfunction function! s:pluginList(A,L,P) if a:A =~ '/' return s:completion_filter(rails#app().relglob('vendor/plugins/',matchstr(a:A,'.\{-\}/').'**/*'),a:A) else return s:completion_filter(rails#app().relglob('vendor/plugins/',"*","/init.rb"),a:A) endif endfunction " Task files, not actual rake tasks function! s:taskList(A,L,P) let all = rails#app().relglob("lib/tasks/","**/*",".rake") if RailsFilePath() =~ '\','".name."',\"".prefix."\",".string(suffix).",".string(filter).",".string(default).",)" let cmd = strpart(cmds,0,1) let cmds = strpart(cmds,1) endwhile endfunction function! s:CommandList(A,L,P) let cmd = matchstr(a:L,'\CR[A-Z]\=\w\+') exe cmd." &" let lp = s:last_prefix . "\n" let res = [] while lp != "" let p = matchstr(lp,'.\{-\}\ze\n') let lp = s:sub(lp,'.{-}\n','') let res += rails#app().relglob(p,s:last_filter,s:last_suffix) endwhile if s:last_camelize return s:autocamelize(res,a:A) else return s:completion_filter(res,a:A) endif endfunction function! s:CommandEdit(cmd,name,prefix,suffix,filter,default,...) if a:0 && a:1 == "&" let s:last_prefix = a:prefix let s:last_suffix = a:suffix let s:last_filter = a:filter let s:last_camelize = (a:suffix =~# '\.rb$') else if a:default == "both()" if s:model() != "" let default = s:model() else let default = s:controller() endif elseif a:default == "model()" let default = s:model(1) elseif a:default == "controller()" let default = s:controller(1) else let default = a:default endif call s:EditSimpleRb(a:cmd,a:name,a:0 ? a:1 : default,a:prefix,a:suffix) endif endfunction function! s:EditSimpleRb(cmd,name,target,prefix,suffix,...) let cmd = s:findcmdfor(a:cmd) if a:target == "" " Good idea to emulate error numbers like this? return s:error("E471: Argument required") endif let f = a:0 ? a:target : rails#underscore(a:target) let jump = matchstr(f,'[#!].*\|:\d*\%(:in\)\=$') let f = s:sub(f,'[#!].*|:\d*%(:in)=$','') if jump =~ '^!' let cmd = s:editcmdfor(cmd) endif if f == '.' let f = s:sub(f,'\.$','') else let f .= a:suffix.jump endif let f = s:gsub(a:prefix,'\n',f.'\n').f return s:findedit(cmd,f) endfunction function! s:app_migration(file) dict let arg = a:file if arg =~ '^0$\|^0\=[#:]' let suffix = s:sub(arg,'^0*','') if self.has_file('db/schema.rb') return 'db/schema.rb'.suffix elseif self.has_file('db/'.s:environment().'_structure.sql') return 'db/'.s:environment().'_structure.sql'.suffix else return 'db/schema.rb'.suffix endif elseif arg =~ '^\d$' let glob = '00'.arg.'_*.rb' elseif arg =~ '^\d\d$' let glob = '0'.arg.'_*.rb' elseif arg =~ '^\d\d\d$' let glob = ''.arg.'_*.rb' elseif arg == '' let glob = '*.rb' else let glob = '*'.rails#underscore(arg).'*rb' endif let files = split(glob(self.path('db/migrate/').glob),"\n") if arg == '' return get(files,-1,'') endif call map(files,'strpart(v:val,1+strlen(self.path()))') let keep = get(files,0,'') if glob =~# '^\*.*\*rb' let pattern = glob[1:-4] call filter(files,'v:val =~# ''db/migrate/\d\+_''.pattern.''\.rb''') let keep = get(files,0,keep) endif return keep endfunction call s:add_methods('app', ['migration']) function! s:migrationEdit(cmd,...) let cmd = s:findcmdfor(a:cmd) let arg = a:0 ? a:1 : '' let migr = arg == "." ? "db/migrate" : rails#app().migration(arg) if migr != '' call s:findedit(cmd,migr) else return s:error("Migration not found".(arg=='' ? '' : ': '.arg)) endif endfunction function! s:fixturesEdit(cmd,...) if a:0 let c = rails#underscore(a:1) else let c = rails#pluralize(s:model(1)) endif if c == "" return s:error("E471: Argument required") endif let e = fnamemodify(c,':e') let e = e == '' ? e : '.'.e let c = fnamemodify(c,':r') let file = get(rails#app().test_suites(),0,'test').'/fixtures/'.c.e if file =~ '\.\w\+$' && rails#app().find_file(c.e,["test/fixtures","spec/fixtures"]) ==# '' call s:edit(a:cmd,file) else call s:findedit(a:cmd,rails#app().find_file(c.e,["test/fixtures","spec/fixtures"],[".yml",".csv"],file)) endif endfunction function! s:localeEdit(cmd,...) let c = a:0 ? a:1 : rails#app().default_locale() if c =~# '\.' call s:edit(a:cmd,rails#app().find_file(c,'config/locales',[],'config/locales/'.c)) else call s:findedit(a:cmd,rails#app().find_file(c,'config/locales',['.yml','.rb'],'config/locales/'.c)) endif endfunction function! s:metalEdit(cmd,...) if a:0 call s:EditSimpleRb(a:cmd,"metal",a:1,"app/metal/",".rb") else call s:EditSimpleRb(a:cmd,"metal",'config/boot',"",".rb") endif endfunction function! s:modelEdit(cmd,...) call s:EditSimpleRb(a:cmd,"model",a:0? a:1 : s:model(1),"app/models/",".rb") endfunction function! s:observerEdit(cmd,...) call s:EditSimpleRb(a:cmd,"observer",a:0? a:1 : s:model(1),"app/models/","_observer.rb") endfunction function! s:viewEdit(cmd,...) if a:0 && a:1 =~ '^[^!#:]' let view = matchstr(a:1,'[^!#:]*') elseif rails#buffer().type_name('controller','mailer') let view = s:lastmethod(line('.')) else let view = '' endif if view == '' return s:error("No view name given") elseif view == '.' return s:edit(a:cmd,'app/views') elseif view !~ '/' && s:controller(1) != '' let view = s:controller(1) . '/' . view endif if view !~ '/' return s:error("Cannot find view without controller") endif let file = "app/views/".view let found = s:findview(view) if found != '' let dir = fnamemodify(rails#app().path(found),':h') if !isdirectory(dir) if a:0 && a:1 =~ '!' call mkdir(dir,'p') else return s:error('No such directory') endif endif call s:edit(a:cmd,found) elseif file =~ '\.\w\+$' call s:findedit(a:cmd,file) else let format = s:format(rails#buffer().type_name('mailer') ? 'text' : 'html') if glob(rails#app().path(file.'.'.format).'.*[^~]') != '' let file .= '.' . format endif call s:findedit(a:cmd,file) endif endfunction function! s:findview(name) let self = rails#buffer() let name = a:name let pre = 'app/views/' if name !~# '/' let controller = self.controller_name(1) if controller != '' let name = controller.'/'.name endif endif if name =~# '\.\w\+\.\w\+$' || name =~# '\.'.s:viewspattern().'$' return pre.name else for format in ['.'.s:format('html'), ''] for type in s:view_types if self.app().has_file(pre.name.format.'.'.type) return pre.name.format.'.'.type endif endfor endfor endif return '' endfunction function! s:findlayout(name) return s:findview("layouts/".(a:name == '' ? 'application' : a:name)) endfunction function! s:layoutEdit(cmd,...) if a:0 return s:viewEdit(a:cmd,"layouts/".a:1) endif let file = s:findlayout(s:controller(1)) if file == "" let file = s:findlayout("application") endif if file == "" let file = "app/views/layouts/application.html.erb" endif call s:edit(a:cmd,s:sub(file,'^/','')) endfunction function! s:controllerEdit(cmd,...) let suffix = '.rb' if a:0 == 0 let controller = s:controller(1) if rails#buffer().type_name() =~# '^view\%(-layout\|-partial\)\@!' let suffix .= '#'.expand('%:t:r') endif else let controller = a:1 endif if rails#app().has_file("app/controllers/".controller."_controller.rb") || !rails#app().has_file("app/controllers/".controller.".rb") let suffix = "_controller".suffix endif return s:EditSimpleRb(a:cmd,"controller",controller,"app/controllers/",suffix) endfunction function! s:mailerEdit(cmd,...) return s:EditSimpleRb(a:cmd,"mailer",a:0? a:1 : s:controller(1),"app/mailers/\napp/models/",".rb") endfunction function! s:helperEdit(cmd,...) return s:EditSimpleRb(a:cmd,"helper",a:0? a:1 : s:controller(1),"app/helpers/","_helper.rb") endfunction function! s:stylesheetEdit(cmd,...) let name = a:0 ? a:1 : s:controller(1) if rails#app().has('sass') && rails#app().has_file('public/stylesheets/sass/'.name.'.sass') return s:EditSimpleRb(a:cmd,"stylesheet",name,"public/stylesheets/sass/",".sass",1) elseif rails#app().has('sass') && rails#app().has_file('public/stylesheets/sass/'.name.'.scss') return s:EditSimpleRb(a:cmd,"stylesheet",name,"public/stylesheets/sass/",".scss",1) elseif rails#app().has('lesscss') && rails#app().has_file('app/stylesheets/'.name.'.less') return s:EditSimpleRb(a:cmd,"stylesheet",name,"app/stylesheets/",".less",1) else let types = rails#app().relglob('app/assets/stylesheets/'.name,'.*','') if !empty(types) return s:EditSimpleRb(a:cmd,'stylesheet',name,'app/assets/stylesheets/',types[0],1) else return s:EditSimpleRb(a:cmd,'stylesheet',name,'public/stylesheets/','.css',1) endif endif endfunction function! s:javascriptEdit(cmd,...) let name = a:0 ? a:1 : s:controller(1) if rails#app().has('coffee') && rails#app().has_file('app/scripts/'.name.'.coffee') return s:EditSimpleRb(a:cmd,'javascript',name,'app/scripts/','.coffee',1) elseif rails#app().has('coffee') && rails#app().has_file('app/scripts/'.name.'.js') return s:EditSimpleRb(a:cmd,'javascript',name,'app/scripts/','.js',1) else let types = rails#app().relglob('app/assets/javascripts/'.name,'.*','') if !empty(types) return s:EditSimpleRb(a:cmd,'javascript',name,'app/assets/javascripts/',types[0],1) else return s:EditSimpleRb(a:cmd,'javascript',name,'public/javascripts/','.js',1) endif endif endfunction function! s:unittestEdit(cmd,...) let f = rails#underscore(a:0 ? matchstr(a:1,'[^!#:]*') : s:model(1)) let jump = a:0 ? matchstr(a:1,'[!#:].*') : '' if jump =~ '!' let cmd = s:editcmdfor(a:cmd) else let cmd = s:findcmdfor(a:cmd) endif let mapping = {'test': ['test/unit/','_test.rb'], 'spec': ['spec/models/','_spec.rb']} let tests = map(filter(rails#app().test_suites(),'has_key(mapping,v:val)'),'get(mapping,v:val)') if empty(tests) let tests = [mapping['test']] endif for [prefix, suffix] in tests if !a:0 && rails#buffer().type_name('model-aro') && f != '' && f !~# '_observer$' if rails#app().has_file(prefix.f.'_observer'.suffix) return s:findedit(cmd,prefix.f.'_observer'.suffix.jump) endif endif endfor for [prefix, suffix] in tests if rails#app().has_file(prefix.f.suffix) return s:findedit(cmd,prefix.f.suffix.jump) endif endfor return s:EditSimpleRb(a:cmd,"unittest",f.jump,tests[0][0],tests[0][1],1) endfunction function! s:functionaltestEdit(cmd,...) let f = rails#underscore(a:0 ? matchstr(a:1,'[^!#:]*') : s:controller(1)) let jump = a:0 ? matchstr(a:1,'[!#:].*') : '' if jump =~ '!' let cmd = s:editcmdfor(a:cmd) else let cmd = s:findcmdfor(a:cmd) endif let mapping = {'test': [['test/functional/'],['_test.rb','_controller_test.rb']], 'spec': [['spec/controllers/','spec/mailers/'],['_spec.rb','_controller_spec.rb']]} let tests = map(filter(rails#app().test_suites(),'has_key(mapping,v:val)'),'get(mapping,v:val)') if empty(tests) let tests = [mapping[tests]] endif for [prefixes, suffixes] in tests for prefix in prefixes for suffix in suffixes if rails#app().has_file(prefix.f.suffix) return s:findedit(cmd,prefix.f.suffix.jump) endif endfor endfor endfor return s:EditSimpleRb(a:cmd,"functionaltest",f.jump,tests[0][0][0],tests[0][1][0],1) endfunction function! s:integrationtestEdit(cmd,...) if !a:0 return s:EditSimpleRb(a:cmd,"integrationtest","test/test_helper\nfeatures/support/env\nspec/spec_helper","",".rb") endif let f = rails#underscore(matchstr(a:1,'[^!#:]*')) let jump = matchstr(a:1,'[!#:].*') if jump =~ '!' let cmd = s:editcmdfor(a:cmd) else let cmd = s:findcmdfor(a:cmd) endif let tests = [['test/integration/','_test.rb'], [ 'spec/requests/','_spec.rb'], [ 'spec/integration/','_spec.rb'], [ 'features/','.feature']] call filter(tests, 'isdirectory(rails#app().path(v:val[0]))') if empty(tests) let tests = [['test/integration/','_test.rb']] endif for [prefix, suffix] in tests if rails#app().has_file(prefix.f.suffix) return s:findedit(cmd,prefix.f.suffix.jump) elseif rails#app().has_file(prefix.rails#underscore(f).suffix) return s:findedit(cmd,prefix.rails#underscore(f).suffix.jump) endif endfor return s:EditSimpleRb(a:cmd,"integrationtest",f.jump,tests[0][0],tests[0][1],1) endfunction function! s:specEdit(cmd,...) if a:0 return s:EditSimpleRb(a:cmd,"spec",a:1,"spec/","_spec.rb") else call s:EditSimpleRb(a:cmd,"spec","spec_helper","spec/",".rb") endif endfunction function! s:pluginEdit(cmd,...) let cmd = s:findcmdfor(a:cmd) let plugin = "" let extra = "" if RailsFilePath() =~ '\','split') let cmd = s:sub(cmd,'find>','edit') return cmd endfunction function! s:try(cmd) abort if !exists(":try") " I've seen at least one weird setup without :try exe a:cmd else try exe a:cmd catch call s:error(s:sub(v:exception,'^.{-}:\zeE','')) return 0 endtry endif return 1 endfunction function! s:findedit(cmd,files,...) abort let cmd = s:findcmdfor(a:cmd) let files = type(a:files) == type([]) ? copy(a:files) : split(a:files,"\n") if len(files) == 1 let file = files[0] else let file = get(filter(copy(files),'rails#app().has_file(s:sub(v:val,"#.*|:\\d*$",""))'),0,get(files,0,'')) endif if file =~ '[#!]\|:\d*\%(:in\)\=$' let djump = matchstr(file,'!.*\|#\zs.*\|:\zs\d*\ze\%(:in\)\=$') let file = s:sub(file,'[#!].*|:\d*%(:in)=$','') else let djump = '' endif if file == '' let testcmd = "edit" elseif isdirectory(rails#app().path(file)) let arg = file == "." ? rails#app().path() : rails#app().path(file) let testcmd = s:editcmdfor(cmd).' '.(a:0 ? a:1 . ' ' : '').s:escarg(arg) exe testcmd return elseif rails#app().path() =~ '://' || cmd =~ 'edit' || cmd =~ 'split' if file !~ '^/' && file !~ '^\w:' && file !~ '://' let file = s:escarg(rails#app().path(file)) endif let testcmd = s:editcmdfor(cmd).' '.(a:0 ? a:1 . ' ' : '').file else let testcmd = cmd.' '.(a:0 ? a:1 . ' ' : '').file endif if s:try(testcmd) call s:djump(djump) endif endfunction function! s:edit(cmd,file,...) let cmd = s:editcmdfor(a:cmd) let cmd .= ' '.(a:0 ? a:1 . ' ' : '') let file = a:file if file !~ '^/' && file !~ '^\w:' && file !~ '://' exe cmd."`=fnamemodify(rails#app().path(file),':.')`" else exe cmd.file endif endfunction function! s:Alternate(cmd,line1,line2,count,...) if a:0 if a:count && a:cmd !~# 'D' return call('s:Find',[1,a:line1.a:cmd]+a:000) elseif a:count return call('s:Edit',[1,a:line1.a:cmd]+a:000) else return call('s:Edit',[1,a:cmd]+a:000) endif else let file = s:getopt(a:count ? 'related' : 'alternate', 'bl') if file == '' let file = rails#buffer().related(a:count) endif if file != '' call s:findedit(a:cmd,file) else call s:warn("No alternate file is defined") endif endif endfunction function! s:Related(cmd,line1,line2,count,...) if a:count == 0 && a:0 == 0 return s:Alternate(a:cmd,a:line1,a:line1,a:line1) else return call('s:Alternate',[a:cmd,a:line1,a:line2,a:count]+a:000) endif endfunction function! s:Complete_related(A,L,P) if a:L =~# '^[[:alpha:]]' return s:Complete_edit(a:A,a:L,a:P) else return s:Complete_find(a:A,a:L,a:P) endif endfunction function! s:readable_related(...) dict abort let f = self.name() if a:0 && a:1 let lastmethod = self.last_method(a:1) if self.type_name('controller','mailer') && lastmethod != "" let root = s:sub(s:sub(s:sub(f,'/application%(_controller)=\.rb$','/shared_controller.rb'),'/%(controllers|models|mailers)/','/views/'),'%(_controller)=\.rb$','/'.lastmethod) let format = self.last_format(a:1) if format == '' let format = self.type_name('mailer') ? 'text' : 'html' endif if glob(self.app().path().'/'.root.'.'.format.'.*[^~]') != '' return root . '.' . format else return root endif elseif f =~ '\ me') let migration = "db/migrate/".get(candidates,0,migrations[0]).".rb" endif return migration . (exists('l:lastmethod') && lastmethod != '' ? '#'.lastmethod : '') elseif f =~ '\??').'/layout.'.fnamemodify(f,':e') else let dest = f endif return s:sub(s:sub(dest,' 1 return s:error("Incorrect number of arguments") endif if a:1 =~ '[^a-z0-9_/.]' return s:error("Invalid partial name") endif let rails_root = rails#app().path() let ext = expand("%:e") let file = s:sub(a:1,'%(/|^)\zs_\ze[^/]*$','') let first = a:firstline let last = a:lastline let range = first.",".last if rails#buffer().type_name('view-layout') if RailsFilePath() =~ '\' let curdir = 'app/views/shared' if file !~ '/' let file = "shared/" .file endif else let curdir = s:sub(RailsFilePath(),'.*]+)'.erub2.'\s*$' let collection = s:sub(getline(first-1),'^'.fspaces.erub1.'for\s+(\k+)\s+in\s+([^ >]+)'.erub2.'\s*$','\1>\2') elseif getline(first-1) =~ '\v^'.fspaces.erub1.'([^ %>]+)\.each\s+do\s+\|\s*(\k+)\s*\|'.erub2.'\s*$' let collection = s:sub(getline(first-1),'^'.fspaces.erub1.'([^ %>]+)\.each\s+do\s+\|\s*(\k+)\s*\|'.erub2.'\s*$','\2>\1') endif if collection != '' let var = matchstr(collection,'^\k\+') let collection = s:sub(collection,'^\k+\>','') let first -= 1 let last += 1 endif else let fspaces = spaces endif let renderstr = "render :partial => '".fnamemodify(file,":r:r")."'" if collection != "" let renderstr .= ", :collection => ".collection elseif "@".name != var let renderstr .= ", :object => ".var endif if ext =~? '^\%(rhtml\|erb\|dryml\)$' let renderstr = "<%= ".renderstr." %>" elseif ext == "rxml" || ext == "builder" let renderstr = "xml << ".s:sub(renderstr,"render ","render(").")" elseif ext == "rjs" let renderstr = "page << ".s:sub(renderstr,"render ","render(").")" elseif ext == "haml" let renderstr = "= ".renderstr elseif ext == "mn" let renderstr = "_".renderstr endif let buf = @@ silent exe range."yank" let partial = @@ let @@ = buf let old_ai = &ai try let &ai = 0 silent exe "norm! :".first.",".last."change\".fspaces.renderstr."\.\" finally let &ai = old_ai endtry if renderstr =~ '<%' norm ^6w else norm ^5w endif let ft = &ft let shortout = fnamemodify(out,':.') silent split `=shortout` silent %delete let &ft = ft let @@ = partial silent put 0delete let @@ = buf if spaces != "" silent! exe '%substitute/^'.spaces.'//' endif silent! exe '%substitute?\%(\w\|[@:"'."'".'-]\)\@?'.name.'?g' 1 endfunction " }}}1 " Migration Inversion {{{1 function! s:mkeep(str) " Things to keep (like comments) from a migration statement return matchstr(a:str,' #[^{].*') endfunction function! s:mextargs(str,num) if a:str =~ '^\s*\w\+\s*(' return s:sub(matchstr(a:str,'^\s*\w\+\s*\zs(\%([^,)]\+[,)]\)\{,'.a:num.'\}'),',$',')') else return s:sub(s:sub(matchstr(a:str,'\w\+\>\zs\s*\%([^,){ ]*[, ]*\)\{,'.a:num.'\}'),'[, ]*$',''),'^\s+',' ') endif endfunction function! s:migspc(line) return matchstr(a:line,'^\s*') endfunction function! s:invertrange(beg,end) let str = "" let lnum = a:beg while lnum <= a:end let line = getline(lnum) let add = "" if line == '' let add = ' ' elseif line =~ '^\s*\(#[^{].*\)\=$' let add = line elseif line =~ '\' let add = s:migspc(line)."drop_table".s:mextargs(line,1).s:mkeep(line) let lnum = s:endof(lnum) elseif line =~ '\' let add = s:sub(line,'\s*\(=\s*([^,){ ]*).*','create_table \1 do |t|'."\n".matchstr(line,'^\s*').'end').s:mkeep(line) elseif line =~ '\' let add = s:migspc(line).'remove_column'.s:mextargs(line,2).s:mkeep(line) elseif line =~ '\' let add = s:sub(line,'','add_column') elseif line =~ '\' let add = s:migspc(line).'remove_index'.s:mextargs(line,1) let mat = matchstr(line,':name\s*=>\s*\zs[^ ,)]*') if mat != '' let add = s:sub(add,'\)=$',', :name => '.mat.'&') else let mat = matchstr(line,'\[^,]*,\s*\zs\%(\[[^]]*\]\|[:"'."'".']\w*["'."'".']\=\)') if mat != '' let add = s:sub(add,'\)=$',', :column => '.mat.'&') endif endif let add .= s:mkeep(line) elseif line =~ '\' let add = s:sub(s:sub(line,'\s*','') elseif line =~ '\' let add = s:sub(line,'' let add = s:migspc(line).'change_column'.s:mextargs(line,2).s:mkeep(line) elseif line =~ '\' let add = s:migspc(line).'change_column_default'.s:mextargs(line,2).s:mkeep(line) elseif line =~ '\.update_all(\(["'."'".']\).*\1)$' || line =~ '\.update_all \(["'."'".']\).*\1$' " .update_all('a = b') => .update_all('b = a') let pre = matchstr(line,'^.*\.update_all[( ][}'."'".'"]') let post = matchstr(line,'["'."'".'])\=$') let mat = strpart(line,strlen(pre),strlen(line)-strlen(pre)-strlen(post)) let mat = s:gsub(','.mat.',','%(,\s*)@<=([^ ,=]{-})(\s*\=\s*)([^,=]{-})%(\s*,)@=','\3\2\1') let add = pre.s:sub(s:sub(mat,'^,',''),',$','').post elseif line =~ '^s\*\%(if\|unless\|while\|until\|for\)\>' let lnum = s:endof(lnum) endif if lnum == 0 return -1 endif if add == "" let add = s:sub(line,'^\s*\zs.*','raise ActiveRecord::IrreversibleMigration') elseif add == " " let add = "" endif let str = add."\n".str let lnum += 1 endwhile let str = s:gsub(str,'(\s*raise ActiveRecord::IrreversibleMigration\n)+','\1') return str endfunction function! s:Invert(bang) let err = "Could not parse method" let src = "up" let dst = "down" let beg = search('\%('.&l:define.'\).*'.src.'\>',"w") let end = s:endof(beg) if beg + 1 == end let src = "down" let dst = "up" let beg = search('\%('.&l:define.'\).*'.src.'\>',"w") let end = s:endof(beg) endif if !beg || !end return s:error(err) endif let str = s:invertrange(beg+1,end-1) if str == -1 return s:error(err) endif let beg = search('\%('.&l:define.'\).*'.dst.'\>',"w") let end = s:endof(beg) if !beg || !end return s:error(err) endif if foldclosed(beg) > 0 exe beg."foldopen!" endif if beg + 1 < end exe (beg+1).",".(end-1)."delete _" endif if str != '' exe beg.'put =str' exe 1+beg endif endfunction " }}}1 " Cache {{{1 let s:cache_prototype = {'dict': {}} function! s:cache_clear(...) dict if a:0 == 0 let self.dict = {} elseif has_key(self,'dict') && has_key(self.dict,a:1) unlet! self.dict[a:1] endif endfunction function! rails#cache_clear(...) if exists('b:rails_root') return call(rails#app().cache.clear,a:000,rails#app().cache) endif endfunction function! s:cache_get(...) dict if a:0 == 1 return self.dict[a:1] else return self.dict endif endfunction function! s:cache_has(key) dict return has_key(self.dict,a:key) endfunction function! s:cache_needs(key) dict return !has_key(self.dict,a:key) endfunction function! s:cache_set(key,value) dict let self.dict[a:key] = a:value endfunction call s:add_methods('cache', ['clear','needs','has','get','set']) let s:app_prototype.cache = s:cache_prototype " }}}1 " Syntax {{{1 function! s:resetomnicomplete() if exists("+completefunc") && &completefunc == 'syntaxcomplete#Complete' if exists("g:loaded_syntax_completion") " Ugly but necessary, until we have our own completion unlet g:loaded_syntax_completion silent! delfunction syntaxcomplete#Complete endif endif endfunction function! s:helpermethods() return "" \."atom_feed audio_path audio_tag auto_discovery_link_tag auto_link " \."button_to button_to_function " \."cache capture cdata_section check_box check_box_tag collection_select concat content_for content_tag content_tag_for csrf_meta_tag current_cycle cycle " \."date_select datetime_select debug distance_of_time_in_words distance_of_time_in_words_to_now div_for dom_class dom_id draggable_element draggable_element_js drop_receiving_element drop_receiving_element_js " \."email_field email_field_tag error_message_on error_messages_for escape_javascript escape_once excerpt " \."favicon_link_tag field_set_tag fields_for file_field file_field_tag form form_for form_tag " \."grouped_collection_select grouped_options_for_select " \."hidden_field hidden_field_tag highlight " \."image_path image_submit_tag image_tag input " \."javascript_cdata_section javascript_include_tag javascript_path javascript_tag " \."l label label_tag link_to link_to_function link_to_if link_to_unless link_to_unless_current localize " \."mail_to " \."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 " \."option_groups_from_collection_for_select options_for_select options_from_collection_for_select " \."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 " \."radio_button radio_button_tag range_field range_field_tag raw remote_function reset_cycle " \."safe_concat 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 simple_format sortable_element sortable_element_js strip_links strip_tags stylesheet_link_tag stylesheet_path submit_tag " \."t tag telephone_field telephone_field_tag text_area text_area_tag text_field text_field_tag time_ago_in_words time_select time_zone_options_for_select time_zone_select translate truncate " \."update_page update_page_tag url_field url_field_tag url_for url_options " \."video_path video_tag visual_effect " \."word_wrap" endfunction function! s:app_user_classes() dict if self.cache.needs("user_classes") let controllers = self.relglob("app/controllers/","**/*",".rb") call map(controllers,'v:val == "application" ? v:val."_controller" : v:val') let classes = \ self.relglob("app/models/","**/*",".rb") + \ controllers + \ self.relglob("app/helpers/","**/*",".rb") + \ self.relglob("lib/","**/*",".rb") call map(classes,'rails#camelize(v:val)') call self.cache.set("user_classes",classes) endif return self.cache.get('user_classes') endfunction function! s:app_user_assertions() dict if self.cache.needs("user_assertions") if self.has_file("test/test_helper.rb") let assertions = map(filter(s:readfile(self.path("test/test_helper.rb")),'v:val =~ "^ def assert_"'),'matchstr(v:val,"^ def \\zsassert_\\w\\+")') else let assertions = [] endif call self.cache.set("user_assertions",assertions) endif return self.cache.get('user_assertions') endfunction call s:add_methods('app', ['user_classes','user_assertions']) function! s:BufSyntax() if (!exists("g:rails_syntax") || g:rails_syntax) let buffer = rails#buffer() let s:javascript_functions = "$ $$ $A $F $H $R $w jQuery" let classes = s:gsub(join(rails#app().user_classes(),' '),'::',' ') if &syntax == 'ruby' if classes != '' exe "syn keyword rubyRailsUserClass ".classes." containedin=rubyClassDeclaration,rubyModuleDeclaration,rubyClass,rubyModule" endif if buffer.type_name() == '' syn keyword rubyRailsMethod params request response session headers cookies flash endif if buffer.type_name('api') syn keyword rubyRailsAPIMethod api_method inflect_names endif if buffer.type_name() ==# 'model' || buffer.type_name('model-arb') syn keyword rubyRailsARMethod default_scope named_scope scope serialize syn keyword rubyRailsARAssociationMethod belongs_to has_one has_many has_and_belongs_to_many composed_of accepts_nested_attributes_for syn keyword rubyRailsARCallbackMethod before_create before_destroy before_save before_update before_validation before_validation_on_create before_validation_on_update syn keyword rubyRailsARCallbackMethod after_create after_destroy after_save after_update after_validation after_validation_on_create after_validation_on_update syn keyword rubyRailsARCallbackMethod around_create around_destroy around_save around_update syn keyword rubyRailsARCallbackMethod after_commit after_find after_initialize after_rollback after_touch 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 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 syn keyword rubyRailsMethod logger endif if buffer.type_name('model-aro') syn keyword rubyRailsARMethod observe endif if buffer.type_name('mailer') syn keyword rubyRailsMethod logger url_for polymorphic_path polymorphic_url syn keyword rubyRailsRenderMethod mail render syn keyword rubyRailsControllerMethod attachments default helper helper_attr helper_method endif if buffer.type_name('controller','view','helper') syn keyword rubyRailsMethod params request response session headers cookies flash syn keyword rubyRailsRenderMethod render syn keyword rubyRailsMethod logger polymorphic_path polymorphic_url endif if buffer.type_name('helper','view') exe "syn keyword rubyRailsHelperMethod ".s:gsub(s:helpermethods(),'<%(content_for|select)\s+','') syn match rubyRailsHelperMethod '\\%(\s*{\|\s*do\>\|\s*(\=\s*&\)\@!' syn match rubyRailsHelperMethod '\<\%(content_for?\=\|current_page?\)' syn match rubyRailsViewMethod '\.\@' if buffer.type_name('view-partial') syn keyword rubyRailsMethod local_assigns endif elseif buffer.type_name('controller') 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 syn keyword rubyRailsRenderMethod head redirect_to render_to_string respond_with syn match rubyRailsRenderMethod '\?\@!' 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 syn keyword rubyRailsFilterMethod verify endif if buffer.type_name('db-migration','db-schema') 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 endif if buffer.type_name('test') if !empty(rails#app().user_assertions()) exe "syn keyword rubyRailsUserMethod ".join(rails#app().user_assertions()) endif 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 syn keyword rubyRailsTestMethod test setup teardown if !buffer.type_name('test-unit') syn match rubyRailsTestControllerMethod '\.\@' syn keyword rubyRailsTestControllerMethod get_via_redirect post_via_redirect put_via_redirect delete_via_redirect request_via_redirect 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 endif elseif buffer.type_name('spec') syn keyword rubyRailsTestMethod describe context it its specify shared_examples_for it_should_behave_like before after around subject fixtures controller_name helper_name syn match rubyRailsTestMethod '\!\=' syn keyword rubyRailsTestMethod violated pending expect double mock mock_model stub_model syn match rubyRailsTestMethod '\.\@!\@!' if !buffer.type_name('spec-model') syn match rubyRailsTestControllerMethod '\.\@' syn keyword rubyRailsTestControllerMethod integrate_views syn keyword rubyRailsMethod params request response session flash syn keyword rubyRailsMethod polymorphic_path polymorphic_url endif endif if buffer.type_name('task') syn match rubyRailsRakeMethod '^\s*\zs\%(task\|file\|namespace\|desc\|before\|after\|on\)\>\%(\s*=\)\@!' endif if buffer.type_name('model-awss') syn keyword rubyRailsMethod member endif if buffer.type_name('config-routes') syn match rubyRailsMethod '\.\zs\%(connect\|named_route\)\>' syn keyword rubyRailsMethod match get put post delete redirect root resource resources collection member nested scope namespace controller constraints endif syn keyword rubyRailsMethod debugger 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 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 syn keyword rubyRailsInclude require_dependency syn region rubyString matchgroup=rubyStringDelimiter start=+\%(:order\s*=>\s*\)\@<="+ skip=+\\\\\|\\"+ end=+"+ contains=@rubyStringSpecial,railsOrderSpecial syn region rubyString matchgroup=rubyStringDelimiter start=+\%(:order\s*=>\s*\)\@<='+ skip=+\\\\\|\\'+ end=+'+ contains=@rubyStringSpecial,railsOrderSpecial syn match railsOrderSpecial +\c\<\%(DE\|A\)SC\>+ contained syn region rubyString matchgroup=rubyStringDelimiter start=+\%(:conditions\s*=>\s*\[\s*\)\@<="+ skip=+\\\\\|\\"+ end=+"+ contains=@rubyStringSpecial,railsConditionsSpecial syn region rubyString matchgroup=rubyStringDelimiter start=+\%(:conditions\s*=>\s*\[\s*\)\@<='+ skip=+\\\\\|\\'+ end=+'+ contains=@rubyStringSpecial,railsConditionsSpecial syn match railsConditionsSpecial +?\|:\h\w*+ contained syn cluster rubyNotTop add=railsOrderSpecial,railsConditionsSpecial " XHTML highlighting inside %Q<> unlet! b:current_syntax let removenorend = !exists("g:html_no_rendering") let g:html_no_rendering = 1 syn include @htmlTop syntax/xhtml.vim if removenorend unlet! g:html_no_rendering endif let b:current_syntax = "ruby" " Restore syn sync, as best we can if !exists("g:ruby_minlines") let g:ruby_minlines = 50 endif syn sync fromstart exe "syn sync minlines=" . g:ruby_minlines syn case match syn region rubyString matchgroup=rubyStringDelimiter start=+%Q\=<+ end=+>+ contains=@htmlTop,@rubyStringSpecial syn cluster htmlArgCluster add=@rubyStringSpecial syn cluster htmlPreProc add=@rubyStringSpecial elseif &syntax =~# '^eruby\>' || &syntax == 'haml' syn case match if classes != '' exe 'syn keyword '.&syntax.'RailsUserClass '.classes.' contained containedin=@'.&syntax.'RailsRegions' endif if &syntax == 'haml' exe 'syn cluster hamlRailsRegions contains=hamlRubyCodeIncluded,hamlRubyCode,hamlRubyHash,@hamlEmbeddedRuby,rubyInterpolation' else exe 'syn cluster erubyRailsRegions contains=erubyOneLiner,erubyBlock,erubyExpression,rubyInterpolation' endif exe 'syn keyword '.&syntax.'RailsHelperMethod '.s:gsub(s:helpermethods(),'<%(content_for|select)\s+','').' contained containedin=@'.&syntax.'RailsRegions' exe 'syn match '.&syntax.'RailsHelperMethod "\\%(\s*{\|\s*do\>\|\s*(\=\s*&\)\@!" contained containedin=@'.&syntax.'RailsRegions' exe 'syn match '.&syntax.'RailsHelperMethod "\<\%(content_for?\=\|current_page?\)" contained containedin=@'.&syntax.'RailsRegions' exe 'syn keyword '.&syntax.'RailsMethod debugger logger polymorphic_path polymorphic_url contained containedin=@'.&syntax.'RailsRegions' exe 'syn keyword '.&syntax.'RailsMethod params request response session headers cookies flash contained containedin=@'.&syntax.'RailsRegions' exe 'syn match '.&syntax.'RailsViewMethod "\.\@" contained containedin=@'.&syntax.'RailsRegions' if buffer.type_name('view-partial') exe 'syn keyword '.&syntax.'RailsMethod local_assigns contained containedin=@'.&syntax.'RailsRegions' endif exe 'syn keyword '.&syntax.'RailsRenderMethod render contained containedin=@'.&syntax.'RailsRegions' exe 'syn case match' set isk+=$ exe 'syn keyword javascriptRailsFunction contained '.s:javascript_functions exe 'syn cluster htmlJavaScript add=javascriptRailsFunction' elseif &syntax == "yaml" syn case match " Modeled after syntax/eruby.vim unlet! b:current_syntax let g:main_syntax = 'eruby' syn include @rubyTop syntax/ruby.vim unlet g:main_syntax syn cluster yamlRailsRegions contains=yamlRailsOneLiner,yamlRailsBlock,yamlRailsExpression syn region yamlRailsOneLiner matchgroup=yamlRailsDelimiter start="^%%\@!" end="$" contains=@rubyRailsTop containedin=ALLBUT,@yamlRailsRegions,yamlRailsComment keepend oneline syn region yamlRailsBlock matchgroup=yamlRailsDelimiter start="<%%\@!" end="%>" contains=@rubyTop containedin=ALLBUT,@yamlRailsRegions,yamlRailsComment syn region yamlRailsExpression matchgroup=yamlRailsDelimiter start="<%=" end="%>" contains=@rubyTop containedin=ALLBUT,@yamlRailsRegions,yamlRailsComment syn region yamlRailsComment matchgroup=yamlRailsDelimiter start="<%#" end="%>" contains=rubyTodo,@Spell containedin=ALLBUT,@yamlRailsRegions,yamlRailsComment keepend syn match yamlRailsMethod '\.\@' contained containedin=@yamlRailsRegions if classes != '' exe "syn keyword yamlRailsUserClass ".classes." contained containedin=@yamlRailsRegions" endif let b:current_syntax = "yaml" elseif &syntax == "html" syn case match set isk+=$ exe "syn keyword javascriptRailsFunction contained ".s:javascript_functions syn cluster htmlJavaScript add=javascriptRailsFunction elseif &syntax == "javascript" || &syntax == "coffee" " The syntax file included with Vim incorrectly sets syn case ignore. syn case match set isk+=$ exe "syn keyword javascriptRailsFunction ".s:javascript_functions endif endif call s:HiDefaults() endfunction function! s:HiDefaults() hi def link rubyRailsAPIMethod rubyRailsMethod hi def link rubyRailsARAssociationMethod rubyRailsARMethod hi def link rubyRailsARCallbackMethod rubyRailsARMethod hi def link rubyRailsARClassMethod rubyRailsARMethod hi def link rubyRailsARValidationMethod rubyRailsARMethod hi def link rubyRailsARMethod rubyRailsMethod hi def link rubyRailsRenderMethod rubyRailsMethod hi def link rubyRailsHelperMethod rubyRailsMethod hi def link rubyRailsViewMethod rubyRailsMethod hi def link rubyRailsMigrationMethod rubyRailsMethod hi def link rubyRailsControllerMethod rubyRailsMethod hi def link rubyRailsFilterMethod rubyRailsMethod hi def link rubyRailsTestControllerMethod rubyRailsTestMethod hi def link rubyRailsTestMethod rubyRailsMethod hi def link rubyRailsRakeMethod rubyRailsMethod hi def link rubyRailsMethod railsMethod hi def link rubyRailsInclude rubyInclude hi def link rubyRailsUserClass railsUserClass hi def link rubyRailsUserMethod railsUserMethod hi def link erubyRailsHelperMethod erubyRailsMethod hi def link erubyRailsViewMethod erubyRailsMethod hi def link erubyRailsRenderMethod erubyRailsMethod hi def link erubyRailsMethod railsMethod hi def link erubyRailsUserMethod railsUserMethod hi def link erubyRailsUserClass railsUserClass hi def link hamlRailsHelperMethod hamlRailsMethod hi def link hamlRailsViewMethod hamlRailsMethod hi def link hamlRailsRenderMethod hamlRailsMethod hi def link hamlRailsMethod railsMethod hi def link hamlRailsUserMethod railsUserMethod hi def link hamlRailsUserClass railsUserClass hi def link railsUserMethod railsMethod hi def link yamlRailsDelimiter Delimiter hi def link yamlRailsMethod railsMethod hi def link yamlRailsComment Comment hi def link yamlRailsUserClass railsUserClass hi def link yamlRailsUserMethod railsUserMethod hi def link javascriptRailsFunction railsMethod hi def link railsUserClass railsClass hi def link railsMethod Function hi def link railsClass Type hi def link railsOrderSpecial railsStringSpecial hi def link railsConditionsSpecial railsStringSpecial hi def link railsStringSpecial Identifier endfunction function! rails#log_syntax() if has('conceal') syn match railslogEscape '\e\[[0-9;]*m' conceal syn match railslogEscapeMN '\e\[[0-9;]*m' conceal nextgroup=railslogModelNum,railslogEscapeMN skipwhite contained syn match railslogEscapeSQL '\e\[[0-9;]*m' conceal nextgroup=railslogSQL,railslogEscapeSQL skipwhite contained else syn match railslogEscape '\e\[[0-9;]*m' syn match railslogEscapeMN '\e\[[0-9;]*m' nextgroup=railslogModelNum,railslogEscapeMN skipwhite contained syn match railslogEscapeSQL '\e\[[0-9;]*m' nextgroup=railslogSQL,railslogEscapeSQL skipwhite contained endif syn match railslogRender '\%(^\s*\%(\e\[[0-9;]*m\)\=\)\@<=\%(Processing\|Rendering\|Rendered\|Redirected\|Completed\)\>' syn match railslogComment '^\s*# .*' 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 syn match railslogModel '\%(^\s*\%(\e\[[0-9;]*m\)\=\)\@<=SQL\>' skipwhite nextgroup=railslogModelNum,railslogEscapeMN syn region railslogModelNum start='(' end=')' contains=railslogNumber contained skipwhite nextgroup=railslogSQL,railslogEscapeSQL syn match railslogSQL '\u[^\e]*' contained " Destroy generates multiline SQL, ugh syn match railslogSQL '\%(^ \%(\e\[[0-9;]*m\)\=\)\@<=\%(FROM\|WHERE\|ON\|AND\|OR\|ORDER\) .*$' syn match railslogNumber '\<\d\+\>%' syn match railslogNumber '[ (]\@<=\<\d\+\.\d\+\>\.\@!' syn region railslogString start='"' skip='\\"' end='"' oneline contained syn region railslogHash start='{' end='}' oneline contains=railslogHash,railslogString syn match railslogIP '\<\d\{1,3\}\%(\.\d\{1,3}\)\{3\}\>' syn match railslogTimestamp '\<\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\>' syn match railslogSessionID '\<\x\{32\}\>' syn match railslogIdentifier '^\s*\%(Session ID\|Parameters\)\ze:' syn match railslogSuccess '\<2\d\d \u[A-Za-z0-9 ]*\>' syn match railslogRedirect '\<3\d\d \u[A-Za-z0-9 ]*\>' syn match railslogError '\<[45]\d\d \u[A-Za-z0-9 ]*\>' syn match railslogError '^DEPRECATION WARNING\>' syn keyword railslogHTTP OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT syn region railslogStackTrace start=":\d\+:in `\w\+'$" end="^\s*$" keepend fold hi def link railslogEscapeMN railslogEscape hi def link railslogEscapeSQL railslogEscape hi def link railslogEscape Ignore hi def link railslogComment Comment hi def link railslogRender Keyword hi def link railslogModel Type hi def link railslogSQL PreProc hi def link railslogNumber Number hi def link railslogString String hi def link railslogSessionID Constant hi def link railslogIdentifier Identifier hi def link railslogRedirect railslogSuccess hi def link railslogSuccess Special hi def link railslogError Error hi def link railslogHTTP Special endfunction " }}}1 " Mappings {{{1 function! s:BufMappings() nnoremap RailsFind :call Find(v:count1,'E') nnoremap RailsSplitFind :call Find(v:count1,'S') nnoremap RailsVSplitFind :call Find(v:count1,'V') nnoremap RailsTabFind :call Find(v:count1,'T') if g:rails_mappings if !hasmapto("RailsFind") nmap gf RailsFind endif if !hasmapto("RailsSplitFind") nmap f RailsSplitFind endif if !hasmapto("RailsTabFind") nmap gf RailsTabFind endif if exists("$CREAM") imap RailsFind imap RailsAlternate imap RailsRelated endif endif " SelectBuf you're a dirty hack let v:errmsg = "" endfunction " }}}1 " Database {{{1 function! s:extractdbvar(str,arg) return matchstr("\n".a:str."\n",'\n'.a:arg.'=\zs.\{-\}\ze\n') endfunction function! s:app_dbext_settings(environment) dict if self.cache.needs('dbext_settings') call self.cache.set('dbext_settings',{}) endif let cache = self.cache.get('dbext_settings') if !has_key(cache,a:environment) let dict = {} if self.has_file("config/database.yml") let cmdb = 'require %{yaml}; File.open(%q{'.self.path().'/config/database.yml}) {|f| y = YAML::load(f); e = y[%{' 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}}' let out = self.lightweight_ruby_eval(cmdb.a:environment.cmde) let adapter = s:extractdbvar(out,'adapter') let adapter = get({'mysql2': 'mysql', 'postgresql': 'pgsql', 'sqlite3': 'sqlite', 'sqlserver': 'sqlsrv', 'sybase': 'asa', 'oracle': 'ora'},adapter,adapter) let dict['type'] = toupper(adapter) let dict['user'] = s:extractdbvar(out,'username') let dict['passwd'] = s:extractdbvar(out,'password') if dict['passwd'] == '' && adapter == 'mysql' " Hack to override password from .my.cnf let dict['extra'] = ' --password=' else let dict['extra'] = '' endif let dict['dbname'] = s:extractdbvar(out,'database') if dict['dbname'] == '' let dict['dbname'] = s:extractdbvar(out,'dbfile') endif if dict['dbname'] != '' && dict['dbname'] !~ '^:' && adapter =~? '^sqlite' let dict['dbname'] = self.path(dict['dbname']) endif let dict['profile'] = '' if adapter == 'ora' let dict['srvname'] = s:extractdbvar(out,'database') else let dict['srvname'] = s:extractdbvar(out,'host') endif let dict['host'] = s:extractdbvar(out,'host') let dict['port'] = s:extractdbvar(out,'port') let dict['dsnname'] = s:extractdbvar(out,'dsn') if dict['host'] =~? '^\cDBI:' if dict['host'] =~? '\c\' let dict['integratedlogin'] = 1 endif let dict['host'] = matchstr(dict['host'],'\c\<\%(Server\|Data Source\)\s*=\s*\zs[^;]*') endif call filter(dict,'v:val != ""') endif let cache[a:environment] = dict endif return cache[a:environment] endfunction function! s:BufDatabase(...) if exists("s:lock_database") || !exists('g:loaded_dbext') || !exists('b:rails_root') return endif let self = rails#app() let s:lock_database = 1 if (a:0 && a:1 > 1) call self.cache.clear('dbext_settings') endif if (a:0 > 1 && a:2 != '') let env = a:2 else let env = s:environment() endif if (!self.cache.has('dbext_settings') || !has_key(self.cache.get('dbext_settings'),env)) && (a:0 ? a:1 : 0) <= 0 unlet! s:lock_database return endif let dict = self.dbext_settings(env) for key in ['type', 'profile', 'bin', 'user', 'passwd', 'dbname', 'srvname', 'host', 'port', 'dsnname', 'extra', 'integratedlogin'] let b:dbext_{key} = get(dict,key,'') endfor if b:dbext_type == 'PGSQL' let $PGPASSWORD = b:dbext_passwd elseif exists('$PGPASSWORD') let $PGPASSWORD = '' endif unlet! s:lock_database endfunction call s:add_methods('app', ['dbext_settings']) " }}}1 " Abbreviations {{{1 function! s:selectiveexpand(pat,good,default,...) if a:0 > 0 let nd = a:1 else let nd = "" endif let c = nr2char(getchar(0)) let good = a:good if c == "" " ^] return s:sub(good.(a:0 ? " ".a:1 : ''),'\s+$','') elseif c == "\t" return good.(a:0 ? " ".a:1 : '') elseif c =~ a:pat return good.c.(a:0 ? a:1 : '') else return a:default.c endif endfunction function! s:TheCWord() let l = s:linepeak() if l =~ '\<\%(find\|first\|last\|all\|paginate\)\>' return s:selectiveexpand('..',':conditions => ',':c') elseif l =~ '\\s*' return s:selectiveexpand('..',':collection => ',':c') elseif l =~ '\<\%(url_for\|link_to\|form_tag\)\>' || l =~ ':url\s*=>\s*{\s*' return s:selectiveexpand('..',':controller => ',':c') else return s:selectiveexpand('..',':conditions => ',':c') endif endfunction function! s:AddSelectiveExpand(abbr,pat,expn,...) let expn = s:gsub(s:gsub(a:expn ,'[\"|]','\\&'),'\<','\\') let expn2 = s:gsub(s:gsub(a:0 ? a:1 : '','[\"|]','\\&'),'\<','\\') if a:0 exe "inoreabbrev ".a:abbr." =selectiveexpand(".string(a:pat).",\"".expn."\",".string(a:abbr).",\"".expn2."\")" else exe "inoreabbrev ".a:abbr." =selectiveexpand(".string(a:pat).",\"".expn."\",".string(a:abbr).")" endif endfunction function! s:AddTabExpand(abbr,expn) call s:AddSelectiveExpand(a:abbr,'..',a:expn) endfunction function! s:AddBracketExpand(abbr,expn) call s:AddSelectiveExpand(a:abbr,'[[.]',a:expn) endfunction function! s:AddColonExpand(abbr,expn) call s:AddSelectiveExpand(a:abbr,'[:.]',a:expn) endfunction function! s:AddParenExpand(abbr,expn,...) if a:0 call s:AddSelectiveExpand(a:abbr,'(',a:expn,a:1) else call s:AddSelectiveExpand(a:abbr,'(',a:expn,'') endif endfunction function! s:BufAbbreviations() command! -buffer -bar -nargs=* -bang Rabbrev :call s:Abbrev(0,) " Some of these were cherry picked from the TextMate snippets if g:rails_abbreviations let buffer = rails#buffer() " Limit to the right filetypes. But error on the liberal side if buffer.type_name('controller','view','helper','test-functional','test-integration') Rabbrev pa[ params Rabbrev rq[ request Rabbrev rs[ response Rabbrev se[ session Rabbrev hd[ headers Rabbrev coo[ cookies Rabbrev fl[ flash Rabbrev rr( render Rabbrev ra( render :action\ =>\ Rabbrev rc( render :controller\ =>\ Rabbrev rf( render :file\ =>\ Rabbrev ri( render :inline\ =>\ Rabbrev rj( render :json\ =>\ Rabbrev rl( render :layout\ =>\ Rabbrev rp( render :partial\ =>\ Rabbrev rt( render :text\ =>\ Rabbrev rx( render :xml\ =>\ endif if buffer.type_name('view','helper') Rabbrev dotiw distance_of_time_in_words Rabbrev taiw time_ago_in_words endif if buffer.type_name('controller') Rabbrev re( redirect_to Rabbrev rea( redirect_to :action\ =>\ Rabbrev rec( redirect_to :controller\ =>\ Rabbrev rst( respond_to endif if buffer.type_name() ==# 'model' || buffer.type_name('model-arb') Rabbrev bt( belongs_to Rabbrev ho( has_one Rabbrev hm( has_many Rabbrev habtm( has_and_belongs_to_many Rabbrev co( composed_of Rabbrev va( validates_associated Rabbrev vb( validates_acceptance_of Rabbrev vc( validates_confirmation_of Rabbrev ve( validates_exclusion_of Rabbrev vf( validates_format_of Rabbrev vi( validates_inclusion_of Rabbrev vl( validates_length_of Rabbrev vn( validates_numericality_of Rabbrev vp( validates_presence_of Rabbrev vu( validates_uniqueness_of endif if buffer.type_name('db-migration','db-schema') Rabbrev mac( add_column Rabbrev mrnc( rename_column Rabbrev mrc( remove_column Rabbrev mct( create_table Rabbrev mcht( change_table Rabbrev mrnt( rename_table Rabbrev mdt( drop_table Rabbrev mcc( t.column endif if buffer.type_name('test') Rabbrev ase( assert_equal Rabbrev asko( assert_kind_of Rabbrev asnn( assert_not_nil Rabbrev asr( assert_raise Rabbrev asre( assert_response Rabbrev art( assert_redirected_to endif Rabbrev :a :action\ =>\ " hax Rabbrev :c :co________\ =>\ inoreabbrev :c =TheCWord() Rabbrev :i :id\ =>\ Rabbrev :o :object\ =>\ Rabbrev :p :partial\ =>\ Rabbrev logd( logger.debug Rabbrev logi( logger.info Rabbrev logw( logger.warn Rabbrev loge( logger.error Rabbrev logf( logger.fatal Rabbrev fi( find Rabbrev AR:: ActiveRecord Rabbrev AV:: ActionView Rabbrev AC:: ActionController Rabbrev AD:: ActionDispatch Rabbrev AS:: ActiveSupport Rabbrev AM:: ActionMailer Rabbrev AO:: ActiveModel Rabbrev AE:: ActiveResource endif endfunction function! s:Abbrev(bang,...) abort if !exists("b:rails_abbreviations") let b:rails_abbreviations = {} endif if a:0 > 3 || (a:bang && (a:0 != 1)) return s:error("Rabbrev: invalid arguments") endif if a:0 == 0 for key in sort(keys(b:rails_abbreviations)) echo key . join(b:rails_abbreviations[key],"\t") endfor return endif let lhs = a:1 let root = s:sub(lhs,'%(::|\(|\[)$','') if a:bang if has_key(b:rails_abbreviations,root) call remove(b:rails_abbreviations,root) endif exe "iunabbrev ".root return endif if a:0 > 3 || a:0 < 2 return s:error("Rabbrev: invalid arguments") endif let rhs = a:2 if has_key(b:rails_abbreviations,root) call remove(b:rails_abbreviations,root) endif if lhs =~ '($' let b:rails_abbreviations[root] = ["(", rhs . (a:0 > 2 ? "\t".a:3 : "")] if a:0 > 2 call s:AddParenExpand(root,rhs,a:3) else call s:AddParenExpand(root,rhs) endif return endif if a:0 > 2 return s:error("Rabbrev: invalid arguments") endif if lhs =~ ':$' call s:AddColonExpand(root,rhs) elseif lhs =~ '\[$' call s:AddBracketExpand(root,rhs) elseif lhs =~ '\w$' call s:AddTabExpand(lhs,rhs) else return s:error("Rabbrev: unimplemented") endif let b:rails_abbreviations[root] = [matchstr(lhs,'\W*$'),rhs] endfunction " }}}1 " Settings {{{1 function! s:Set(bang,...) let c = 1 let defscope = '' for arg in a:000 if arg =~? '^<[abgl]\=>$' let defscope = (matchstr(arg,'<\zs.*\ze>')) elseif arg !~ '=' if defscope != '' && arg !~ '^\w:' let arg = defscope.':'.opt endif let val = s:getopt(arg) if val == '' && !has_key(s:opts(),arg) call s:error("No such rails.vim option: ".arg) else echo arg."=".val endif else let opt = matchstr(arg,'[^=]*') let val = s:sub(arg,'^[^=]*\=','') if defscope != '' && opt !~ '^\w:' let opt = defscope.':'.opt endif call s:setopt(opt,val) endif endfor endfunction function! s:getopt(opt,...) let app = rails#app() let opt = a:opt if a:0 let scope = a:1 elseif opt =~ '^[abgl]:' let scope = tolower(matchstr(opt,'^\w')) let opt = s:sub(opt,'^\w:','') else let scope = 'abgl' endif let lnum = a:0 > 1 ? a:2 : line('.') if scope =~ 'l' && &filetype != 'ruby' let scope = s:sub(scope,'l','b') endif if scope =~ 'l' call s:LocalModelines(lnum) endif let var = s:sname().'_'.opt let lastmethod = s:lastmethod(lnum) if lastmethod == '' | let lastmethod = ' ' | endif " Get buffer option if scope =~ 'l' && exists('b:_'.var) && has_key(b:_{var},lastmethod) return b:_{var}[lastmethod] elseif exists('b:'.var) && (scope =~ 'b' || (scope =~ 'l' && lastmethod == ' ')) return b:{var} elseif scope =~ 'a' && has_key(app,'options') && has_key(app.options,opt) return app.options[opt] elseif scope =~ 'g' && exists("g:".s:sname()."_".opt) return g:{var} else return "" endif endfunction function! s:setopt(opt,val) let app = rails#app() if a:opt =~? '[abgl]:' let scope = matchstr(a:opt,'^\w') let opt = s:sub(a:opt,'^\w:','') else let scope = '' let opt = a:opt endif let defscope = get(s:opts(),opt,'a') if scope == '' let scope = defscope endif if &filetype != 'ruby' && (scope ==# 'B' || scope ==# 'l') let scope = 'b' endif let var = s:sname().'_'.opt if opt =~ '\W' return s:error("Invalid option ".a:opt) elseif scope ==# 'B' && defscope == 'l' if !exists('b:_'.var) | let b:_{var} = {} | endif let b:_{var}[' '] = a:val elseif scope =~? 'b' let b:{var} = a:val elseif scope =~? 'a' if !has_key(app,'options') | let app.options = {} | endif let app.options[opt] = a:val elseif scope =~? 'g' let g:{var} = a:val elseif scope =~? 'l' if !exists('b:_'.var) | let b:_{var} = {} | endif let lastmethod = s:lastmethod(lnum) let b:_{var}[lastmethod == '' ? ' ' : lastmethod] = a:val else return s:error("Invalid scope for ".a:opt) endif endfunction function! s:opts() return {'alternate': 'b', 'controller': 'b', 'gnu_screen': 'a', 'model': 'b', 'preview': 'l', 'task': 'b', 'related': 'l', 'root_url': 'a'} endfunction function! s:Complete_set(A,L,P) if a:A =~ '=' let opt = matchstr(a:A,'[^=]*') return [opt."=".s:getopt(opt)] else let extra = matchstr(a:A,'^[abgl]:') return filter(sort(map(keys(s:opts()),'extra.v:val')),'s:startswith(v:val,a:A)') endif return [] endfunction function! s:BufModelines() if !g:rails_modelines return endif let lines = getline("$")."\n".getline(line("$")-1)."\n".getline(1)."\n".getline(2)."\n".getline(3)."\n" let pat = '\s\+\zs.\{-\}\ze\%(\n\|\s\s\|#{\@!\|%>\|-->\|$\)' let cnt = 1 let mat = matchstr(lines,'\C\ ".mat endif let mat = matchstr(lines,'\C\ ".mat endif let mat = matchstr(lines,'\C\ 0 if !exists("g:RAILS_HISTORY") let g:RAILS_HISTORY = "" endif let path = a:path let g:RAILS_HISTORY = s:scrub(g:RAILS_HISTORY,path) if has("win32") let g:RAILS_HISTORY = s:scrub(g:RAILS_HISTORY,s:gsub(path,'\\','/')) endif let path = fnamemodify(path,':p:~:h') let g:RAILS_HISTORY = s:scrub(g:RAILS_HISTORY,path) if has("win32") let g:RAILS_HISTORY = s:scrub(g:RAILS_HISTORY,s:gsub(path,'\\','/')) endif let g:RAILS_HISTORY = path."\n".g:RAILS_HISTORY let g:RAILS_HISTORY = s:sub(g:RAILS_HISTORY,'%(.{-}\n){,'.g:rails_history_size.'}\zs.*','') endif call app.source_callback("config/syntax.vim") if expand('%:t') =~ '\.yml\.example$' setlocal filetype=yaml elseif expand('%:e') =~ '^\%(rjs\|rxml\|builder\)$' setlocal filetype=ruby elseif firsttime " Activate custom syntax let &syntax = &syntax endif if expand('%:e') == 'log' nnoremap R :checktime nnoremap G :checktime$ nnoremap q :bwipe setlocal modifiable filetype=railslog noswapfile autoread foldmethod=syntax if exists('+concealcursor') setlocal concealcursor=nc conceallevel=2 else silent %s/\%(\e\[[0-9;]*m\|\r$\)//ge endif setlocal readonly nomodifiable $ endif call s:BufSettings() call s:BufCommands() call s:BufAbbreviations() " snippetsEmu.vim if exists('g:loaded_snippet') silent! runtime! ftplugin/rails_snippets.vim " filetype snippets need to come last for higher priority exe "silent! runtime! ftplugin/".&filetype."_snippets.vim" endif let t = rails#buffer().type_name() let t = "-".t let f = '/'.RailsFilePath() if f =~ '[ !#$%\,]' let f = '' endif runtime! macros/rails.vim silent doautocmd User Rails if t != '-' exe "silent doautocmd User Rails".s:gsub(t,'-','.') endif if f != '' exe "silent doautocmd User Rails".f endif call app.source_callback("config/rails.vim") call s:BufModelines() call s:BufMappings() return b:rails_root endfunction function! s:SetBasePath() let self = rails#buffer() if self.app().path() =~ '://' return endif let transformed_path = s:pathsplit(s:pathjoin([self.app().path()]))[0] let add_dot = self.getvar('&path') =~# '^\.\%(,\|$\)' let old_path = s:pathsplit(s:sub(self.getvar('&path'),'^\.%(,|$)','')) call filter(old_path,'!s:startswith(v:val,transformed_path)') let path = ['app', 'app/models', 'app/controllers', 'app/helpers', 'config', 'lib', 'app/views'] if self.controller_name() != '' let path += ['app/views/'.self.controller_name(), 'public'] endif if self.app().has('test') let path += ['test', 'test/unit', 'test/functional', 'test/integration'] endif if self.app().has('spec') let path += ['spec', 'spec/models', 'spec/controllers', 'spec/helpers', 'spec/views', 'spec/lib', 'spec/requests', 'spec/integration'] endif let path += ['app/*', 'vendor', 'vendor/plugins/*/lib', 'vendor/plugins/*/test', 'vendor/rails/*/lib', 'vendor/rails/*/test'] call map(path,'self.app().path(v:val)') call self.setvar('&path',(add_dot ? '.,' : '').s:pathjoin([self.app().path()],path,old_path)) endfunction function! s:BufSettings() if !exists('b:rails_root') return '' endif let self = rails#buffer() call s:SetBasePath() let rp = s:gsub(self.app().path(),'[ ,]','\\&') if stridx(&tags,rp.'/tmp/tags') == -1 let &l:tags = rp . '/tmp/tags,' . &tags . ',' . rp . '/tags' endif if has("gui_win32") || has("gui_running") let code = '*.rb;*.rake;Rakefile' let templates = '*.'.join(s:view_types,';*.') let fixtures = '*.yml;*.csv' let statics = '*.html;*.css;*.js;*.xml;*.xsd;*.sql;.htaccess;README;README_FOR_APP' let b:browsefilter = "" \."All Rails Files\t".code.';'.templates.';'.fixtures.';'.statics."\n" \."Source Code (*.rb, *.rake)\t".code."\n" \."Templates (*.rhtml, *.rxml, *.rjs)\t".templates."\n" \."Fixtures (*.yml, *.csv)\t".fixtures."\n" \."Static Files (*.html, *.css, *.js)\t".statics."\n" \."All Files (*.*)\t*.*\n" endif call self.setvar('&includeexpr','RailsIncludeexpr()') call self.setvar('&suffixesadd', ".rb,.".join(s:view_types,',.')) let ft = self.getvar('&filetype') if ft =~ '^\%(e\=ruby\|[yh]aml\|coffee\|css\|s[ac]ss\|lesscss\)$' call self.setvar('&shiftwidth',2) call self.setvar('&softtabstop',2) call self.setvar('&expandtab',1) if exists('+completefunc') && self.getvar('&completefunc') == '' call self.setvar('&completefunc','syntaxcomplete#Complete') endif endif if ft == 'ruby' call self.setvar('&define',self.define_pattern()) " This really belongs in after/ftplugin/ruby.vim but we'll be nice if exists('g:loaded_surround') && self.getvar('surround_101') == '' call self.setvar('surround_5', "\r\nend") call self.setvar('surround_69', "\1expr: \1\rend") call self.setvar('surround_101', "\r\nend") endif elseif ft == 'yaml' || fnamemodify(self.name(),':e') == 'yml' call self.setvar('&define',self.define_pattern()) elseif ft =~# '^eruby\>' if exists("g:loaded_allml") call self.setvar('allml_stylesheet_link_tag', "<%= stylesheet_link_tag '\r' %>") call self.setvar('allml_javascript_include_tag', "<%= javascript_include_tag '\r' %>") call self.setvar('allml_doctype_index', 10) endif if exists("g:loaded_ragtag") call self.setvar('ragtag_stylesheet_link_tag', "<%= stylesheet_link_tag '\r' %>") call self.setvar('ragtag_javascript_include_tag', "<%= javascript_include_tag '\r' %>") call self.setvar('ragtag_doctype_index', 10) endif elseif ft == 'haml' if exists("g:loaded_allml") call self.setvar('allml_stylesheet_link_tag', "= stylesheet_link_tag '\r'") call self.setvar('allml_javascript_include_tag', "= javascript_include_tag '\r'") call self.setvar('allml_doctype_index', 10) endif if exists("g:loaded_ragtag") call self.setvar('ragtag_stylesheet_link_tag', "= stylesheet_link_tag '\r'") call self.setvar('ragtag_javascript_include_tag', "= javascript_include_tag '\r'") call self.setvar('ragtag_doctype_index', 10) endif endif if ft =~# '^eruby\>' || ft ==# 'yaml' " surround.vim if exists("g:loaded_surround") " The idea behind the || part here is that one can normally define the " surrounding to omit the hyphen (since standard ERuby does not use it) " but have it added in Rails ERuby files. Unfortunately, this makes it " difficult if you really don't want a hyphen in Rails ERuby files. If " this is your desire, you will need to accomplish it via a rails.vim " autocommand. if self.getvar('surround_45') == '' || self.getvar('surround_45') == "<% \r %>" " - call self.setvar('surround_45', "<% \r -%>") endif if self.getvar('surround_61') == '' " = call self.setvar('surround_61', "<%= \r %>") endif if self.getvar("surround_35") == '' " # call self.setvar('surround_35', "<%# \r %>") endif if self.getvar('surround_101') == '' || self.getvar('surround_101')== "<% \r %>\n<% end %>" "e call self.setvar('surround_5', "<% \r -%>\n<% end -%>") call self.setvar('surround_69', "<% \1expr: \1 -%>\r<% end -%>") call self.setvar('surround_101', "<% \r -%>\n<% end -%>") endif endif endif endfunction " }}}1 " Autocommands {{{1 augroup railsPluginAuto autocmd! autocmd User BufEnterRails call s:RefreshBuffer() autocmd User BufEnterRails call s:resetomnicomplete() autocmd User BufEnterRails call s:BufDatabase(-1) autocmd User dbextPreConnection call s:BufDatabase(1) autocmd BufWritePost */config/database.yml call rails#cache_clear("dbext_settings") autocmd BufWritePost */test/test_helper.rb call rails#cache_clear("user_assertions") autocmd BufWritePost */config/routes.rb call rails#cache_clear("named_routes") autocmd BufWritePost */config/environment.rb call rails#cache_clear("default_locale") autocmd BufWritePost */config/environments/*.rb call rails#cache_clear("environments") autocmd BufWritePost */tasks/**.rake call rails#cache_clear("rake_tasks") autocmd BufWritePost */generators/** call rails#cache_clear("generators") autocmd FileType * if exists("b:rails_root") | call s:BufSettings() | endif autocmd Syntax ruby,eruby,yaml,haml,javascript,coffee,railslog if exists("b:rails_root") | call s:BufSyntax() | endif autocmd QuickFixCmdPre *make* call s:push_chdir() autocmd QuickFixCmdPost *make* call s:pop_command() augroup END " }}}1 " Initialization {{{1 map xx xx let s:sid = s:sub(maparg("xx"),'xx$','') unmap xx let s:file = expand(':p') if !exists('s:apps') let s:apps = {} endif " }}}1 let &cpo = s:cpo_save " vim:set sw=2 sts=2: tpope-vim-rails-d6a745a/doc/000077500000000000000000000000001162676454700157465ustar00rootroot00000000000000tpope-vim-rails-d6a745a/doc/rails.txt000066400000000000000000001162371162676454700176330ustar00rootroot00000000000000*rails.txt* Plugin for working with Ruby on Rails applications Author: Tim Pope |rails-introduction| Introduction and Feature Summary |rails-commands| General Commands |rails-navigation| Navigation |rails-gf| File Under Cursor - gf |rails-alternate-related| Alternate and Related Files |rails-type-navigation| File Type Commands |rails-custom-navigation| Custom Navigation Commands |rails-rake| Rake |rails-scripts| Script Wrappers |rails-refactoring| Refactoring Helpers |rails-partials| Partial Extraction |rails-migrations| Migration Inversion |rails-integration| Integration |rails-vim-integration| Integration with the Vim Universe |rails-rails-integration| Integration with the Rails Universe |rails-abbreviations| Abbreviations |rails-syntax| Syntax Highlighting |rails-options| Managed Vim Options |rails-configuration| Configuration |rails-global-settings| Global Settings |rails-about| About rails.vim |rails-license| License This plugin is only available if 'compatible' is not set. {Vi does not have any of this} INTRODUCTION *rails-introduction* *rails* Whenever you edit a file in a Rails application, this plugin will be automatically activated. This sets various options and defines a few buffer-specific commands. If you are in a hurry to get started, with a minimal amount of reading, you are encouraged to at least skim through the headings and command names in this file, to get a better idea of what is offered. If you only read one thing, make sure it is the navigation section: |rails-navigation|. GENERAL COMMANDS *rails-commands* All commands are buffer local, unless otherwise stated. This means you must actually edit a file from a Rails application. *rails-:Rails* :Rails new {directory} The only global command. Creates a new Rails application in {directory}, and loads the README. :Rails! Show the version of rails.vim installed. If rails.vim is active for the current buffer, also show the type of Rails file detected. *rails-:Rcd* :Rcd [{directory}] |:cd| to /path/to/railsapp/{directory}. *rails-:Rlcd* :Rlcd [{directory}] |:lcd| to /path/to/railsapp/{directory}. *rails-:Rdoc* :Rdoc Browse to the Rails API, either in doc/api in the current Rails application, gem_server if it is running, or http://api.rubyonrails.org/ . Requires :OpenURL to be defined (see |rails-:OpenURL|). *rails-:Rdoc!* :Rdoc! Make the appropriate |:helptags| call and invoke |:help| rails. *rails-:Redit* :Redit {file} Deprecated in favor of |:R|. *rails-:Rfind* :Rfind [{file}] Deprecated in favor of |:R| or |:find|. *rails-:Rlog* :Rlog [{logfile}] Split window and open {logfile} ($RAILS_ENV or development by default). The control characters used for highlighting are removed. If you have a :Tail command (provided by |tailminusf|.vim), that is used; otherwise, the file does NOT reload upon change. Use |:checktime| to tell Vim to check for changes. |G| has been mapped to do just that prior to jumping to the end of the file, and q is mapped to close the window. If the delay in loading is too long, you might like :Rake log:clear. *rails-:Rpreview* :Rpreview [{path}] Creates a URL from http://localhost:3000/ and the {path} given. The not too useful default is to then edit this URL using Vim itself, allowing |netrw| to download it. More useful is to define a :OpenURL command, which will be used instead (see |rails-:OpenURL|). If {path} is omitted, a sensible default is used (considers the current controller/template, but does not take routing into account). The default is overridden by comments like the following that are either before the current method call or at the top of the file: > # GET /users # PUT /users/1 < *rails-:Rpreview!* :Rpreview! [{path}] As with :Rpreview, except :OpenURL is never used. *rails-:Rtags* :Rtags Calls ctags -R on the current application root and writes the result to tmp/tags. Exuberant ctags must be installed. Additional arguments can be passed to ctags with |g:rails_ctags_arguments|. *rails-:Rrefresh* :Rrefresh Refreshes certain cached settings. Most noticeably, this clears the cached list of classes that are syntax highlighted as railsUserClass. *rails-:Rrefresh!* :Rrefresh! As above, and also reloads rails.vim. *rails-:OpenURL* :OpenURL {url} This is not a command provided by the plugin, but rather provided by user and utilized by other plugin features. This command should be defined to open the provided {url} in a web browser. An example command on a Mac might be: > :command -bar -nargs=1 OpenURL :!open < The following appears to work on Windows: > :command -bar -nargs=1 OpenURL :!start cmd /cstart /b < On Debian compatible distributions, the following is the preferred method: > :command -bar -nargs=1 OpenURL :!sensible-browser < If exists("$SECURITYSESSIONID"), has("gui_win32"), or executable("sensible-browser") is true, the corresponding command above will be automatically defined. Otherwise, you must provide your own (which is recommended, regardless). NAVIGATION *rails-navigation* Navigation is where the real power of this plugin lies. Efficient use of the following features will greatly ease navigating the Rails file structure. The 'path' has been modified to include all the best places to be. > :find application_controller.rb < File Under Cursor - gf ~ *rails-gf* The |gf| command, which normally edits the current file under the cursor, has been remapped to take context into account. |CTRL-W_f| (open in new window) and |CTRL-W_gf| (open in new tab) are also remapped. Example uses of |gf|, and where they might lead. (* indicates cursor position) > Pos*t.first < app/models/post.rb ~ > has_many :c*omments < app/models/comment.rb ~ > link_to 'Home', :controller => 'bl*og' < app/controllers/blog_controller.rb ~ > <%= render 'sh*ared/sidebar' %> < app/views/shared/_sidebar.html.erb ~ > <%= stylesheet_link_tag 'scaf*fold' %> < public/stylesheets/scaffold.css ~ > class BlogController < Applica*tionController < app/controllers/application_controller.rb ~ > class ApplicationController < ActionCont*roller::Base < .../action_controller/base.rb ~ > fixtures :pos*ts < test/fixtures/posts.yml ~ > layout :pri*nt < app/views/layouts/print.html.erb ~ > <%= link_to "New", new_comme*nt_path %> < app/controllers/comments_controller.rb (jumps to def new) ~ In the last example, the controller and action for the named route are determined by evaluating routes.rb as Ruby and doing some introspection. This means code from the application is executed. Keep this in mind when navigating unfamiliar applications. Alternate and Related Files ~ *rails-alternate-related* Two commands, :A and :R, are used quickly jump to an "alternate" and a "related" file, defined below. *rails-:A* *rails-:AE* *rails-:AS* *rails-:AV* *rails-:AT* *rails-:AD* :A These commands were picked to mimic Michael Sharpe's :AE a.vim. Briefly, they edit the "alternate" file, in :AS either the same window (:A and :AE), a new split :AV window (:AS), a new vertically split window (:AV), a :AT new tab (:AT), or read it into the current buffer :AD (:AD). *rails-:R* *rails-:RE* *rails-:RS* *rails-:RV* *rails-:RT* *rails-:RD* :R These are similar |rails-:A| and friends above, only :RE they jump to the "related" file rather than the :RS "alternate." With a file name argument, they edit :RV a file relative to the application root (:R Rakefile), :RT and with a count and a file name argument, they find a :RD file in 'path' (e.g., :1R PostsController.) You can also append a line number (post.rb:42) or a method (PostsController#32) to both forms. *rails-alternate* *rails-related* The alternate file is most frequently the test file, though there are exceptions. The related file varies, and is sometimes dependent on current location in the file. For example, when editing a controller, the related file is template for the method currently being edited. The easiest way to learn these commands is to experiment. A few examples of alternate and related files for a Test::Unit application follow: Current file Alternate file Related file ~ model unit test schema definition controller (in method) functional test template (view) template (view) functional test controller (jump to method) migration previous migration next migration config/database.yml config/routes.rb config/environments/*.rb Suggestions for further contexts to consider for the alternate file, related file, and file under the cursor are welcome. They are subtly tweaked from release to release. File Type Navigation Commands ~ *rails-type-navigation* For the less common cases, a more deliberate set of commands are provided. Each of the upcoming commands takes an optional argument (with tab completion) but defaults to a reasonable guess. Commands that default to the current model or controller generally behave like you'd expect in other file types. For example, in app/helpers/posts_helper.rb, the current controller is "posts", and in test/fixtures/comments.yml, the current model is "comment". In model related files, the current controller is the pluralized model name, and in controller related files, the current model is the singularized controller name. Each of the following commands has variants for splitting, vertical splitting, opening in a new tab, and reading the file into the current buffer. For :Rmodel, those variants would be :RSmodel, :RVmodel, :RTmodel, and :RDmodel. There is also :REmodel which is a synonym for :Rmodel (future versions might allow customization of the behavior of :Rmodel). They also allow for jumping to methods or line numbers using the same syntax as |:R|, and file creation can be forced by adding a ! after the filename (not after the command itself!). :Rcontroller |rails-:Rcontroller| :Renvironment |rails-:Renvironment| :Rfixtures |rails-:Rfixtures| :Rfunctionaltest |rails-:Rfunctionaltest| :Rhelper |rails-:Rhelper| :Rinitializer |rails-:Rinitializer| :Rintegrationtest |rails-:Rintegrationtest| :Rjavascript |rails-:Rjavascript| :Rlayout |rails-:Rlayout| :Rlib |rails-:Rlib| :Rlocale |rails-:Rlocale| :Rmailer |rails-:Rmailer| :Rmetal |rails-:Rmetal| :Rmigration |rails-:Rmigration| :Rmodel |rails-:Rmodel| :Robserver |rails-:Robserver| :Rplugin |rails-:Rplugin| :Rspec |rails-:Rspec| :Rstylesheet |rails-:Rstylesheet| :Rtask |rails-:Rtask| :Runittest |rails-:Runittest| :Rview |rails-:Rview| *rails-:Rcontroller* :Rcontroller [{name}] Edit the specified or current controller. *rails-:Renvironment* :Renvironment [{name}] Edit the config/environments file specified. With no argument, defaults to editing config/application.rb or config/environment.rb. *rails-:Rfixtures* :Rfixtures [{name}] Edit the fixtures for the given or current model. If an argument is given, it must be pluralized, like the final filename (this may change in the future). If omitted, the current model is pluralized. An optional extension can be given, to distinguish between YAML and CSV fixtures. *rails-:Rfunctionaltest* :Rfunctionaltest [{name}] Edit the functional test or controller spec for the specified or current controller. *rails-:Rhelper* :Rhelper [{name}] Edit the helper for the specified name or current controller. *rails-:Rinitializer* :Rinitializer [{name}] Edit the config/initializers file specified. With no argument, defaults to editing config/routes.rb. *rails-:Rintegrationtest* :Rintegrationtest [{name}] Edit the integration test, integration spec, or cucumber feature specified. With no argument, defaults to editing test/test_helper.rb. *rails-:Rjavascript* :Rjavascript [{name}] Edit the JavaScript for the specified name or current controller. Also supports CoffeeScript in app/scripts/. *rails-:Rlayout* :Rlayout [{name}] Edit the specified layout. Defaults to the layout for the current controller, or the application layout if that cannot be found. A new layout will be created if an extension is given. *rails-:Rlib* :Rlib [{name}] Edit the library from the lib directory for the specified name. If the current file is part of a plugin, the libraries from that plugin can be specified as well. With no argument, defaults to editing db/seeds.rb. *rails-:Rlocale* :Rlocale [{name}] Edit the config/locale file specified, optionally adding a yml or rb extension if none is given. With no argument, checks config/environment.rb for the default locale. *rails-:Rmailer* :Rmailer [{name}] Edit the mailer specified. This looks in both app/mailers for Rails 3 and app/models for older versions of Rails but only tab completes the former. *rails-:Rmetal* :Rmetal [{name}] Edit the app/metal file specified. With no argument, defaults to editing config/boot.rb. *rails-:Rmigration* :Rmigration [{pattern}] If {pattern} is a number, find the migration for that particular set of digits, zero-padding if necessary. Otherwise, find the newest migration containing the given pattern. Omitting the pattern selects the latest migration. Give a numeric argument of 0 to edit db/schema.rb. *rails-:Rmodel* :Rmodel [{name}] Edit the specified or current model. *rails-:Robserver* :Robserver [{name}] Find the observer with a name like {model}_observer.rb. When in an observer, most commands (like :Rmodel) will seek based on the observed model ({model}) and not the actual observer ({model}_observer). However, for the command :Runittest, a file of the form {model}_observer_test.rb will be found. *rails-:Rplugin* :Rplugin [{plugin}[/{path}]] Edits a file within a plugin. If the path to the file is omitted, it defaults to init.rb. If no argument is given, it defaults to editing the application Gemfile. *rails-:Rspec* :Rspec [{name}] Edit the given spec. With no argument, defaults to editing spec/spec_helper.rb (If you want to jump to the spec for the given file, use |:A| instead). This command is only defined if there is a spec folder in the root of the application. *rails-:Rstylesheet* :Rstylesheet [{name}] Edit the stylesheet for the specified name or current controller. Also supports Sass and SCSS. *rails-:Rtask* :Rtask [{name}] Edit the .rake file from lib/tasks for the specified name. If the current file is part of a plugin, the tasks for that plugin can be specified as well. If no argument is given, either the current plugin's Rakefile or the application Rakefile will be edited. *rails-:Runittest* :Runittest [{name}] Edit the unit test or model spec for the specified name or current model. *rails-:Rview* :Rview [[{controller}/]{view}] Edit the specified view. The controller will default sensibly, and the view name can be omitted when editing a method of a controller. If a view name is given with an extension, a new file will be created. This is a quick way to create a new view. Custom Navigation Commands ~ *rails-custom-navigation* It is also possible to create custom navigation commands. This is best done in an initialization routine of some sort (e.g., an autocommand); see |rails-configuration| for details. *rails-:Rnavcommand* :Rnavcommand [options] {name} [{path} ...] Create a navigation command with the supplied name, looking in the supplied paths, using the supplied options. The -suffix option specifies what suffix to filter on, and strip from the filename, and defaults to -suffix=.rb . The -glob option specifies a file glob to use to find files, _excluding_ the suffix. Useful values include -glob=* and -glob=**/*. The -default option specifies a default argument (not a full path). If it is specified as -default=model(), -default=controller(), or -default=both(), the current model, controller, or both (as with :Rintegrationtest) is used as a default. *rails-:Rcommand* :Rcommand Obsolete alias for |:Rnavcommand|. Examples: > Rnavcommand api app/apis -glob=**/* -suffix=_api.rb Rnavcommand config config -glob=*.* -suffix= -default=routes.rb Rnavcommand concern app/concerns -glob=**/* Rnavcommand exemplar test/exemplars spec/exemplars -glob=**/* \ -default=model() -suffix=_exemplar.rb Finally, one Vim feature that proves helpful in conjunction with all of the above is |CTRL-^|. This keystroke edits the previous file, and is helpful to back out of any of the above commands. RAKE *rails-rake* Rake integration happens through the :Rake command. *rails-:Rake* :[range]Rake {targets} Calls |:make!| {targets} (with 'makeprg' being rake, or `bundle exec rake` if bundler.vim is active) and opens the quickfix window if there were any errors. An argument of "-" reruns the last task. If {targets} are omitted, :Rake defaults to something sensible as described below. Giving a line number argument may affect that default. *rails-:Rake!* :[range]Rake! {targets} Called with a bang, :Rake will forgo opening the quickfix window. *rails-rake-defaults* Generally, the default task is one that runs the test you'd expect. For example, if you're in a view in an RSpec application, the view spec is run, but if it's a Test::Unit application, the functional test for the corresponding controller is run. The following table lists the most interesting mappings: File Task ~ unit test test:units TEST=... functional test test:functionals TEST=... integration test test:integration TEST=... spec spec SPEC=... feature cucumber FEATURE=... model test:units TEST=... spec SPEC=... controller test:functionals TEST=... spec SPEC=... helper test:functionals TEST=... spec SPEC=... view test:functionals TEST=... spec SPEC=... fixtures db:fixtures:load FIXTURES=... migration db:migrate VERSION=... config/routes.rb routes db/seeds.rb db:seed Additionally, when :Rake is given a line number (e.g., :.Rake), the following additional tasks can be invoked: File Task ~ unit test test:units TEST=... TESTOPTS=-n... functional test test:functionals TEST=... TESTOPTS=-n... integration test test:integration TEST=... TESTOPTS=-n... spec spec SPEC=...:... feature cucumber FEATURE=...:... controller routes CONTROLLER=... fixtures db:fixtures:identify LABEL=... migration in self.up db:migrate:up VERSION=... migration in self.down db:migrate:down VERSION=... migration elsewhere db:migrate:redo VERSION=... task ... (try to guess currently edited declaration) Finally, you can override the default task with a comment like "# rake ..." before the method pointed to by [range] or at the top of the file. SCRIPT WRAPPERS *rails-scripts* The following commands are wrappers around the scripts in the script directory of the Rails application. Most have extra features beyond calling the script. A limited amount of completion with is supported. *rails-:Rscript* :Rscript {script} {options} Call ruby script/{script} {options}. Defaults to calling script/console. *rails-:Rconsole* :Rconsole {options} Obsolete. Call |:Rscript| instead. *rails-:Rrunner* :[range]Rrunner {code} Executes {code} with script/runner. Differs from :Rscript runner {code} in that the code is passed as one argument. Also, |system()| is used instead of |:!|. This is to help eliminate annoying "Press ENTER" prompts. If a line number is given in the range slot, the output is pasted into the buffer after that line. *rails-:Rp* :[range]Rp {code} Like :Rrunner, but call the Ruby p method on the result. Literally "p begin {code} end". *rails-:Rpp* *rails-:Ry* :[range]Rpp {code} Like :Rp, but with pp (pretty print) or y (YAML :[range]Ry {code} output). *rails-:Rgenerate* :Rgenerate {options} Calls script/generate {options}, and then edits the first file generated. *rails-:Rdestroy* :Rdestroy {options} Calls script/destroy {options}. *rails-:Rserver* :Rserver {options} Launches script/server {options} in the background. On win32, this means |!start|. On other systems, this uses the --daemon option. *rails-:Rserver!* :Rserver! {options} Same as |:Rserver|, only first attempts to kill any other server using the same port. On non-Windows systems, lsof must be installed for this to work. REFACTORING HELPERS *rails-refactoring* A few features are dedicated to helping you refactor your code. Partial Extraction ~ *rails-partials* The :Rextract command can be used to extract a partial to a new file. *rails-:Rextract* :[range]Rextract [{controller}/]{name} Create a {name} partial from [range] lines (default: current line). *rails-:Rpartial* :[range]Rpartial [{controller}/]{name} Obsolete alias for :Rextract. If this is your file, in app/views/blog/show.html.erb: > 1
2

<%= @post.title %>

3

<%= @post.body %>

4
And you issue this command: > :2,3Rextract post Your file will change to this: > 1
2 <%= render :partial => 'post' %> 3
And app/views/blog/_post.html.erb will now contain: > 1

<%= post.title %>

2

<%= post.body %>

As a special case, if the file had looked like this: > 1 <% for object in @posts -%> 2

<%= object.title %>

3

<%= object.body %>

4 <% end -%> < The end result would have been this: > 1 <%= render :partial => 'post', :collection => @posts %> < The easiest way to choose what to extract is to use |linewise-visual| mode. Then, a simple > :'<,'>Rextract blog/post will suffice. (Note the use of a controller name in this example.) Migration Inversion ~ *rails-migrations* *rails-:Rinvert* :Rinvert In a migration, rewrite the self.up method into a self.down method. If self.up is empty, the process is reversed. This chokes on more complicated instructions, but works reasonably well for simple calls to create_table, add_column, and the like. INTEGRATION *rails-integration* Having one foot in Rails and one in Vim, rails.vim has two worlds with which to interact. Integration with the Vim Universe ~ *rails-vim-integration* A handful of Vim plugins are enhanced by rails.vim. All plugins mentioned can be found at http://www.vim.org/. Cream and GUI menus (for lack of a better place) are also covered in this section. *rails-:Rtree* :Rtree [{arg}] If |NERDTree| is installed, open a tree for the application root or the given subdirectory. *rails-:Rdbext* *rails-dbext* :Rdbext [{environment}] This command is only provided when the |dbext| plugin is installed. Loads the {environment} configuration (defaults to $RAILS_ENV or development) from config/database.yml and uses it to configure dbext. The configuration is cached on a per application basis. With dbext version 8.00 and newer, this command is called automatically when needed. When dbext is configured, you can execute SQL directly from Vim: > :Select * from posts order by id desc :Update comments set author_id = 1 < *rails-surround* The |surround| plugin available from vim.org enables adding and removing "surroundings" like parentheses, quotes, and HTML tags. Even by itself, it is quite useful for Rails development, particularly eRuby editing. When coupled with this plugin, a few additional replacement surroundings are available in eRuby files. See the |surround| documentation for details on how to use them. The table below uses ^ to represent the position of the surrounded text. Key Surrounding ~ = <%= ^ %> - <% ^ -%> # <%# ^ %> <% ^ -%>\n<% end -%> The last surrounding is particularly useful in insert mode with the following map in one's vimrc. Use Alt+o to open a new line below the current one. This works nicely even in a terminal (where most alt/meta maps will fail) because most terminals send as o anyways. > imap o < One can also use the surrounding in a plain Ruby file to append a bare "end" on the following line. *rails-abolish* Among the many features of |abolish| on vim.org is the ability to change the inflection of the word under the cursor. For example, one can hit crs to change from MixedCase to snake_case. This plugin adds two additional inflections: crl for alternating between the singular and plural, and crt for altering between tableize and classify. The latter is useful in changing constructs like BlogPost.all to current_user.blog_posts.all and vice versa. *rails-cream* This plugin provides a few additional key bindings if it is running under Cream, the user friendly editor which uses Vim as a back-end. Ctrl+Enter finds the file under the cursor (as in |rails-gf|), and Alt+[ and Alt+] find the alternate (|rails-alternate|) and related (|rails-related|) files. *rails-menu* If the GUI is running, a menu for several commonly used features is provided. Also on this menu is a list of recently accessed projects. This list of projects can persist across restarts if a 'viminfo' flag is set to enable retaining certain global variables. If this interests you, add something like the following to your vimrc: > set viminfo^=! < Integration with the Rails Universe ~ *rails-rails-integration* The general policy of rails.vim is to focus exclusively on the Ruby on Rails core. Supporting plugins and other add-ons to Rails has the potential to rapidly get out of hand. However, a few pragmatic exceptions have been made. *rails-template-types* Commands like :Rview use a hardwired list of extensions (erb, rjs, etc.) when searching for files. In order to facilitate working with non-standard template types, several popular extensions are featured in this list, including haml, liquid, and mab (markaby). These extensions will disappear once a related configuration option is added to rails.vim. *rails-rspec* The presence of a spec directory causes several additional behaviors to activate. :A knows about specs and will jump to them (but Test::Unit files still get priority). The associated controller or model of a spec is detected, so all navigation commands should work as expected inside a spec file. :Rake in a spec runs just that spec, and in a model, controller, or helper, runs the associated spec. |:Runittest| and |:Rfunctionaltest| lead double lives, handling model and controller specs respectively. For helper and view specs, you can use |:Rspec| or define your own navigation commands: > Rnavcommand spechelper spec/helpers -glob=**/* \ -suffix=_helper_spec.rb -default=controller() Rnavcommand specview spec/views -glob=**/* -suffix=_spec.rb < ABBREVIATIONS *rails-abbreviations* *rails-snippets* Abbreviations are "snippets lite". They may later be extracted into a separate plugin, or removed entirely. *rails-:Rabbrev* :Rabbrev List all Rails abbreviations. :Rabbrev {abbr} {expn} [{extra}] Define a new Rails abbreviation. {extra} is permitted if and only if {expn} ends with "(". *rails-:Rabbrev!* :Rabbrev! {abbr} Remove an abbreviation. Rails abbreviations differ from regular abbreviations in that they only expand after a (see |i_CTRL-]|) or a (if does not work, it is likely mapped by another plugin). If the abbreviation ends in certain punctuation marks, additional expansions are possible. A few examples will hopefully clear this up (all of the following are enabled by default in appropriate file types). Command Sequence typed Resulting text ~ Rabbrev rp( render :partial\ => rp( render(:partial => Rabbrev rp( render :partial\ => rp render :partial => Rabbrev vs( validates_size_of vs( validates_size_of( Rabbrev pa[ params pa[:id] params[:id] Rabbrev pa[ params pa params Rabbrev pa[ params pa.inspect params.inspect Rabbrev AR:: ActionRecord AR::Base ActiveRecord::Base Rabbrev :a :action\ =>\ render :a render :action => In short, ( expands on (, :: expands on . and :, and [ expands on . and [. These trailing punctuation marks are NOT part of the final abbreviation, and you cannot have two mappings that differ only by punctuation. You must escape spaces in your expansion, either as "\ " or as "". For an abbreviation ending with "(", you may define where to insert the parenthesis by splitting the expansion into two parts (divided by an unescaped space). Many abbreviations are provided by default: use :Rabbrev to list them. They vary depending on the type of file (models have different abbreviations than controllers). There is one "smart" abbreviation, :c, which expands to ":controller => ", ":collection => ", or ":conditions => " depending on context. SYNTAX HIGHLIGHTING *rails-syntax* Syntax highlighting is by and large a transparent process. For the full effect, however, you need a colorscheme which accentuates rails.vim extensions. One such colorscheme is vividchalk, available from vim.org. The following is a summary of the changes made by rails.vim to the standard syntax highlighting. *rails-syntax-keywords* Rails specific keywords are highlighted in a filetype specific manner. For example, in a model, has_many is highlighted, whereas in a controller, before_filter is highlighted. A wide variety of syntax groups are used but they all link by default to railsMethod. If you feel a method has been wrongfully omitted, submit it to the |rails-plugin-author|. *rails-syntax-classes* Models, helpers, and controllers are given special highlighting. Depending on the version of Vim installed, you may need a rails.vim aware colorscheme in order to see this. Said colorscheme needs to provide highlighting for the railsUserClass syntax group. The class names are determined by camelizing filenames from certain directories of your application. If app/models/line_item.rb exists, the class "LineItem" will be highlighted. The list of classes is refreshed automatically after certain commands like |:Rgenerate|. Use |:Rrefresh| to trigger the process manually. *rails-syntax-assertions* If you define custom assertions in test_helper.rb, these will be highlighted in your tests. These are found by scanning test_helper.rb for lines of the form " def assert_..." and extracting the method name. The railsUserMethod syntax group is used. The list of assertions can be refreshed with |:Rrefresh|. *rails-syntax-strings* In the following line of code, the "?" in the conditions clause and the "ASC" in the order clause will be highlighted: > Post.find(:all, :conditions => ["body like ?","%e%"], :order => "title ASC") < A string literal using %Q<> or %<> delimiters will have its contents highlighted as HTML. This is sometimes useful when writing helpers. > link = %<Vim> < *rails-syntax-yaml* YAML syntax highlighting has been extended to highlight eRuby, which can be used in most Rails YAML files (including database.yml and fixtures). MANAGED VIM OPTIONS *rails-options* The following options are set local to buffers where the plugin is active. *rails-'shiftwidth'* *rails-'sw'* *rails-'softtabstop'* *rails-'sts'* *rails-'expandtab'* *rails-'et'* A value of 2 is used for 'shiftwidth' (and 'softtabstop'), and 'expandtab' is enabled. This is a strong convention in Rails, so the conventional wisdom that this is a user preference has been ignored. *rails-'path'* *rails-'pa'* All the relevant directories from your application are added to your 'path'. This makes it easy to access a buried file: > :find blog_controller.rb < *rails-'suffixesadd'* *rails-'sua'* This is filetype dependent, but typically includes .rb, .rake, and several others. This allows shortening the above example: > :find blog_controller < *rails-'includeexpr'* *rails-'inex'* The 'includeexpr' option is set to enable the magic described in |rails-gf|. *rails-'filetype'* *rails-'ft'* The 'filetype' is sometimes adjusted for Rails files. Most notably, *.rxml and *.rjs are treated as Ruby files, and files that have been falsely identified as Mason sources are changed back to eRuby files (but only when they are part of a Rails application). *rails-'completefunc'* *rails-'cfu'* A 'completefunc' is provided (if not already set). It is very simple, as it uses syntax highlighting to make its guess. See |i_CTRL-X_CTRL-U|. CONFIGURATION *rails-configuration* Very little configuration is actually required; this plugin automatically detects your Rails application and adjusts Vim sensibly. *rails-:autocmd* *rails-autocommands* If you would like to set your own custom Vim settings whenever a Rails file is loaded, you can use an autocommand like the following in your vimrc: > autocmd User Rails silent! Rlcd autocmd User Rails map :Rake You can also have autocommands that only apply to certain types of files. These are based off the information shown when running the |:Rails!| command, with hyphens changed to periods. A few examples: > autocmd User Rails.controller* iabbr wsn wsdl_service_name autocmd User Rails.model.arb* iabbr vfo validates_format_of autocmd User Rails.view.erb* imap <%= %>3h End all such Rails autocommands with asterisks, even if you have an exact specification, to allow for more specific subtypes to be added in the future. There is also a filename matching syntax: > autocmd User Rails/config/environment.rb Rabbrev c config autocmd User Rails/**/foo_bar.rb Rabbrev FB:: FooBar Use the filetype based syntax whenever possible, reserving the filename based syntax for more advanced cases. *macros/rails.vim* If you have several commands to run on initialization for all file types, they can be placed in a "macros/rails.vim" file in the 'runtimepath' (for example, "~/.vim/macros/rails.vim"). This file is sourced by rails.vim each time a Rails file is loaded. *config/rails.vim* If you have settings particular to a specific project, they can be put in a config/rails.vim file in the root directory of the application. The file is sourced in the |sandbox| for security reasons. *rails-:Rset* :Rset {option}[={value}] Query or set a local option. This command may be called directly, from an autocommand, or from config/rails.vim. Options may be set in one of four scopes, which may be indicated by an optional prefix. These scopes determine how broadly an option will apply. Generally, the default scope is sufficient. Scope Description ~ a: All files in one Rails application b: Buffer (file) specific g: Global to all applications l: Local to method (same as b: in non-Ruby files) Options are shown below with their default scope, which should be omitted. While you may override the scope with a prefix, this is rarely necessary and oftentimes useless. (For example, setting g:task is useless because the default rake task will apply before considering this option.) Option Meaning ~ b:alternate Custom alternate file for :A, relative to the Rails root b:controller Default controller for certain commands (e.g., :Rhelper) b:model Default model for certain commands (e.g., :Rfixtures) l:related Custom related file for :R, relative to the Rails root a:root_url Root URL for commands like :Rpreview Examples: > :Rset root_url=http://localhost:12345 :Rset related=app/views/blog/edit.html.erb < *rails-modelines* If |g:rails_modelines| is enabled, these options can also be set from modelines near the beginning or end of the file. These modelines will always set buffer-local options; scope should never be specified. Examples: > # Rset task=db:schema:load <%# Rset alternate=app/views/layouts/application.html.erb %> Modelines can also be local to a method. Example: > def test_comment # rset alternate=app/models/comment.rb These two forms differ only in case. Modelines are deprecated. GLOBAL SETTINGS *rails-global-settings* A few global variables control the behavior of this plugin. In general, they can be enabled by setting them to 1 in your vimrc, and disabled by setting them to 0. > let g:rails_some_option=1 let g:rails_some_option=0 Most of these seldom need to be used. So seldom, in fact, that you should notify the |rails-plugin-author| if you find any of them useful, as nearly all are being considered for removal. *g:loaded_rails* > let g:loaded_rails=1 Set this include guard to prevent the plugin from being loaded. *g:rails_abbreviations* Enable Rails abbreviations. See |rails-abbreviations|. Enabled by default. *g:rails_ctags_arguments* > let g:rails_ctags_arguments='--languages=-javascript' Additional arguments to pass to ctags from |:Rtags|. Defaults to ignoring JavaScript files, since ctags has a tendency to choke on those. *g:rails_default_file* > let g:rails_default_file='config/database.yml' File to load when a new Rails application is created. Defaults to the README. *rails-screen* *g:rails_gnu_screen* > let g:rails_gnu_screen=1 Use GNU Screen or Tmux (if it is running) to launch |:Rscript| console and |:Rserver| in the background. Enabled by default. *g:rails_history_size* > let g:rails_history_size=5 Number of projects to remember. Set to 0 to disable. See |rails-menu| for information on retaining these projects across a restart. *g:rails_mappings* > let g:rails_mappings=1 Enables a few mappings (mostly for |rails-navigation|). Enabled by default. *g:rails_modelines* > let g:rails_modelines=1 Enable modelines like the following: > # Rset task=db:schema:load Modelines set buffer-local options using the :Rset command. Also enables method specific modelines (note the case difference): > def show # rset preview=blog/show/1 Modelines are deprecated and disabled by default. *g:rails_menu* > let g:rails_menu=1 When 2, a Rails menu is created. When 1, this menu is a submenu under the Plugin menu. The default is 0, as the menu is slated for removal from future versions of rails.vim. *g:rails_url* > let g:rails_url='http://localhost:3000/' Used for the |:Rpreview| command. Default is as shown above. Overridden by b:rails_url. *g:rails_syntax* > let g:rails_syntax=1 When enabled, this tweaks the syntax highlighting to be more Rails friendly. Enabled by default. See |rails-syntax|. *rails-tabs* *g:rails_tabstop* > let g:rails_tabstop=4 This option now requires the plugin railstab.vim from vim.org: http://www.vim.org/scripts/script.php?script_id=2253 If your goal is simply just override this plugin's settings and use your own custom 'shiftwidth', adjust things manually in an autocommand: > autocmd User Rails set sw=4 sts=4 noet This is highly discouraged: don't fight Rails. ABOUT *rails-about* *rails-plugin-author* This plugin was written by Tim Pope. Email all comments, complaints, and compliments to him at vim at tpope. org. The latest stable version can be found at http://www.vim.org/scripts/script.php?script_id=1567 Bugs can be reported and the very latest development version can be retrieved from GitHub: https://github.com/tpope/vim-rails git clone git://github.com/tpope/vim-rails.git *rails-license* Copyright (c) Tim Pope. Distributed under the same terms as Vim itself. See |license|. vim:tw=78:ts=8:ft=help:norl: tpope-vim-rails-d6a745a/plugin/000077500000000000000000000000001162676454700164775ustar00rootroot00000000000000tpope-vim-rails-d6a745a/plugin/rails.vim000066400000000000000000000323531162676454700203340ustar00rootroot00000000000000" rails.vim - Detect a rails application " Author: Tim Pope " GetLatestVimScripts: 1567 1 :AutoInstall: rails.vim " Install this file as plugin/rails.vim. See doc/rails.txt for details. (Grab " it from the URL above if you don't have it.) To access it from Vim, see " :help add-local-help (hint: :helptags ~/.vim/doc) Afterwards, you should be " able to do :help rails if exists('g:loaded_rails') || &cp || v:version < 700 finish endif let g:loaded_rails = 1 " Utility Functions {{{1 function! s:error(str) echohl ErrorMsg echomsg a:str echohl None let v:errmsg = a:str endfunction function! s:autoload(...) if !exists("g:autoloaded_rails") && v:version >= 700 runtime! autoload/rails.vim endif if exists("g:autoloaded_rails") if a:0 exe a:1 endif return 1 endif if !exists("g:rails_no_autoload_warning") let g:rails_no_autoload_warning = 1 if v:version >= 700 call s:error("Disabling rails.vim: autoload/rails.vim is missing") else call s:error("Disabling rails.vim: Vim version 7 or higher required") endif endif return "" endfunction " }}}1 " Configuration {{{ function! s:SetOptDefault(opt,val) if !exists("g:".a:opt) let g:{a:opt} = a:val endif endfunction call s:SetOptDefault("rails_statusline",1) call s:SetOptDefault("rails_syntax",1) call s:SetOptDefault("rails_mappings",1) call s:SetOptDefault("rails_abbreviations",1) call s:SetOptDefault("rails_ctags_arguments","--languages=-javascript") call s:SetOptDefault("rails_default_file","README") call s:SetOptDefault("rails_root_url",'http://localhost:3000/') call s:SetOptDefault("rails_modelines",0) call s:SetOptDefault("rails_menu",0) call s:SetOptDefault("rails_gnu_screen",1) call s:SetOptDefault("rails_history_size",5) call s:SetOptDefault("rails_generators","controller\ngenerator\nhelper\nintegration_test\nmailer\nmetal\nmigration\nmodel\nobserver\nperformance_test\nplugin\nresource\nscaffold\nscaffold_controller\nsession_migration\nstylesheets") if exists("g:loaded_dbext") && executable("sqlite3") && ! executable("sqlite") " Since dbext can't find it by itself call s:SetOptDefault("dbext_default_SQLITE_bin","sqlite3") endif " }}}1 " Detection {{{1 function! s:escvar(r) let r = fnamemodify(a:r,':~') let r = substitute(r,'\W','\="_".char2nr(submatch(0))."_"','g') let r = substitute(r,'^\d','_&','') return r endfunction function! s:Detect(filename) let fn = substitute(fnamemodify(a:filename,":p"),'\c^file://','','') let sep = matchstr(fn,'^[^\\/]\{3,\}\zs[\\/]') if sep != "" let fn = getcwd().sep.fn endif if fn =~ '[\/]config[\/]environment\.rb$' return s:BufInit(strpart(fn,0,strlen(fn)-22)) endif if isdirectory(fn) let fn = fnamemodify(fn,':s?[\/]$??') else let fn = fnamemodify(fn,':s?\(.*\)[\/][^\/]*$?\1?') endif let ofn = "" let nfn = fn while nfn != ofn && nfn != "" if exists("s:_".s:escvar(nfn)) return s:BufInit(nfn) endif let ofn = nfn let nfn = fnamemodify(nfn,':h') endwhile let ofn = "" while fn != ofn if filereadable(fn . "/config/environment.rb") return s:BufInit(fn) endif let ofn = fn let fn = fnamemodify(ofn,':s?\(.*\)[\/]\(app\|config\|db\|doc\|features\|lib\|log\|public\|script\|spec\|stories\|test\|tmp\|vendor\)\($\|[\/].*$\)?\1?') endwhile return 0 endfunction function! s:BufInit(path) let s:_{s:escvar(a:path)} = 1 if s:autoload() return RailsBufInit(a:path) endif endfunction " }}}1 " Initialization {{{1 augroup railsPluginDetect autocmd! autocmd BufNewFile,BufRead * call s:Detect(expand(":p")) autocmd VimEnter * if expand("") == "" && !exists("b:rails_root") | call s:Detect(getcwd()) | endif | if exists("b:rails_root") | silent doau User BufEnterRails | endif autocmd FileType netrw if !exists("b:rails_root") | call s:Detect(expand(":p")) | endif | if exists("b:rails_root") | silent doau User BufEnterRails | endif autocmd BufEnter * if exists("b:rails_root")|silent doau User BufEnterRails|endif autocmd BufLeave * if exists("b:rails_root")|silent doau User BufLeaveRails|endif autocmd Syntax railslog if s:autoload()|call rails#log_syntax()|endif augroup END command! -bar -bang -nargs=* -complete=dir Rails :if s:autoload()|call rails#new_app_command(0,)|endif " }}}1 " abolish.vim support {{{1 function! s:function(name) return function(substitute(a:name,'^s:',matchstr(expand(''), '\d\+_'),'')) endfunction augroup railsPluginAbolish autocmd! autocmd VimEnter * call s:abolish_setup() augroup END function! s:abolish_setup() if exists('g:Abolish') && has_key(g:Abolish,'Coercions') if !has_key(g:Abolish.Coercions,'l') let g:Abolish.Coercions.l = s:function('s:abolish_l') endif if !has_key(g:Abolish.Coercions,'t') let g:Abolish.Coercions.t = s:function('s:abolish_t') endif endif endfunction function! s:abolish_l(word) let singular = rails#singularize(a:word) return a:word ==? singular ? rails#pluralize(a:word) : singular endfunction function! s:abolish_t(word) if a:word =~# '\u' return rails#pluralize(rails#underscore(a:word)) else return rails#singularize(rails#camelize(a:word)) endif endfunction " }}}1 " Menus {{{1 if !(g:rails_menu && has("menu")) finish endif function! s:sub(str,pat,rep) return substitute(a:str,'\v\C'.a:pat,a:rep,'') endfunction function! s:gsub(str,pat,rep) return substitute(a:str,'\v\C'.a:pat,a:rep,'g') endfunction function! s:menucmd(priority) return 'anoremenu