From 82fd1452155e0aa87295a30feed055cd715767ec Mon Sep 17 00:00:00 2001 From: Artem Sheremet Date: Wed, 31 Jul 2013 22:37:06 +0300 Subject: [PATCH] Flush current state: rcfiles, vim plugins upd etc --- .local/share/applications/mimeapps.list | 1 + .rc | 2 +- .toprc | 12 +- .vim/bundle/vim-rails/autoload/rails.vim | 2624 ++++++++--------- .vim/bundle/vundle/.gitignore | 1 + .vim/bundle/vundle/README.md | 10 +- .vim/bundle/vundle/autoload/vundle.vim | 2 + .vim/bundle/vundle/autoload/vundle/config.vim | 3 + .../vundle/autoload/vundle/installer.vim | 41 +- .../bundle/vundle/autoload/vundle/scripts.vim | 11 +- .vim/bundle/vundle/doc/vundle.txt | 2 + .zandronum/zandronum.ini | 118 +- 12 files changed, 1417 insertions(+), 1410 deletions(-) diff --git a/.local/share/applications/mimeapps.list b/.local/share/applications/mimeapps.list index 1114eb0..4719656 100644 --- a/.local/share/applications/mimeapps.list +++ b/.local/share/applications/mimeapps.list @@ -9,6 +9,7 @@ application/x-shockwave-flash=chromium.desktop x-scheme-handler/http=chromium.desktop image/png=shotwell-viewer.desktop image/jpeg=shotwell-viewer.desktop +image/gif=shotwell-viewer.desktop [Default Applications] text/html=chromium.desktop diff --git a/.rc b/.rc index c2ccceb..e692719 100644 --- a/.rc +++ b/.rc @@ -43,7 +43,7 @@ alias nc='nc -vv' alias snc='openssl s_client -connect ' alias vsnc='openssl s_client -showcerts -state -msg -debug -connect ' alias killall='killall -v' -alias scrot='scrot -e "mv \$f ~/screenshots/ 2>/dev/null" -cd 5' +alias scrot='scrot -e "mv \$f ~/Pictures/ 2>/dev/null" -cd 5' alias qiv='qiv -fml -M' alias qivr='qiv -u' alias grep='grep --line-buffered --color=auto' diff --git a/.toprc b/.toprc index 8d4de98..aa3e07f 100644 --- a/.toprc +++ b/.toprc @@ -1,14 +1,16 @@ top's Config File (Linux processes with windows) -Id:f, Mode_altscr=0, Mode_irixps=1, Delay_time=3.000, Curwin=0 +Id:g, Mode_altscr=0, Mode_irixps=1, Delay_time=3.0, Curwin=0 Def fieldscur=¥¨³´»½ÀÄ·º¹Å&')*+,-./012568<>?ABCFGHIJKLMNOPQRSTUVWXYZ[ - winflags=32564, sortindx=18, maxtasks=0 + winflags=163636, sortindx=18, maxtasks=0 summclr=1, msgsclr=1, headclr=3, taskclr=2 Job fieldscur=¥¦¹·º³´Ä»¼½§Å()*+,-./012568>?@ABCFGHIJKLMNOPQRSTUVWXYZ[ - winflags=62772, sortindx=0, maxtasks=0 + winflags=193844, sortindx=0, maxtasks=0 summclr=6, msgsclr=6, headclr=7, taskclr=6 Mem fieldscur=¥º»¼½¾¿ÀÁÃij´·Å&'()*+,-./0125689BFGHIJKLMNOPQRSTUVWXYZ[ - winflags=62772, sortindx=21, maxtasks=0 + winflags=193844, sortindx=21, maxtasks=0 summclr=5, msgsclr=5, headclr=4, taskclr=5 Usr fieldscur=¥¦§¨ª°¹·ºÄÅ)+,-./1234568;<=>?@ABCFGHIJKLMNOPQRSTUVWXYZ[ - winflags=62772, sortindx=3, maxtasks=0 + winflags=193844, sortindx=3, maxtasks=0 summclr=3, msgsclr=3, headclr=2, taskclr=3 +Fixed_widest=0, Summ_mscale=0, Task_mscale=0, Zero_suppress=0 + diff --git a/.vim/bundle/vim-rails/autoload/rails.vim b/.vim/bundle/vim-rails/autoload/rails.vim index c1f5404..b5d0dda 100644 --- a/.vim/bundle/vim-rails/autoload/rails.vim +++ b/.vim/bundle/vim-rails/autoload/rails.vim @@ -6,10 +6,7 @@ if exists('g:autoloaded_rails') || &cp finish endif -let g:autoloaded_rails = '4.4' - -let s:cpo_save = &cpo -set cpo&vim +let g:autoloaded_rails = '5.0' " Utility Functions {{{1 @@ -40,12 +37,19 @@ function! s:startswith(string,prefix) return strpart(a:string, 0, strlen(a:prefix)) ==# a:prefix endfunction -function! s:uniq(list) - let seen = {} +function! s:endswith(string,suffix) + return strpart(a:string, len(a:string) - len(a:suffix), len(a:suffix)) ==# a:suffix +endfunction + +function! s:uniq(list) abort let i = 0 + let seen = {} while i < len(a:list) - if has_key(seen,a:list[i]) - call remove(a:list, i) + if (a:list[i] ==# '' && exists('empty')) || has_key(seen,a:list[i]) + call remove(a:list,i) + elseif a:list[i] ==# '' + let i += 1 + let empty = 1 else let seen[a:list[i]] = 1 let i += 1 @@ -54,6 +58,19 @@ function! s:uniq(list) return a:list endfunction +function! s:getlist(arg, key) + let value = get(a:arg, a:key, []) + return type(value) == type([]) ? copy(value) : [value] +endfunction + +function! s:split(arg, ...) + return type(a:arg) == type([]) ? copy(a:arg) : split(a:arg, a:0 ? a:1 : "\n") +endfunction + +function! rails#lencmp(i1, i2) abort + return len(a:i1) - len(a:i2) +endfunc + function! s:escarg(p) return s:gsub(a:p,'[ !%#]','\\&') endfunction @@ -63,13 +80,20 @@ function! s:esccmd(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,'\','\\'),'"','\\"').'"' + return '"'.s:gsub(s:gsub(a:str, '"', '""'), '\%', '"%"').'"' else - return "'".s:gsub(s:gsub(a:str,'\','\\'),"'","'\\\\''")."'" + return shellescape(a:str) + endif +endfunction + +function! s:fnameescape(file) abort + if exists('*fnameescape') + return fnameescape(a:file) + else + return escape(a:file," \t\n*?[{`$\\%#'\"|!<") endif endfunction @@ -98,6 +122,10 @@ function! s:app_path(...) dict return join([self.root]+a:000,'/') endfunction +function! s:app_has_path(path) dict + return getftime(self.path(a:path)) != -1 +endfunction + function! s:app_has_file(file) dict return filereadable(self.path(a:file)) endfunction @@ -138,7 +166,7 @@ function! s:app_find_file(name, ...) dict abort endtry endfunction -call s:add_methods('app',['path','has_file','find_file']) +call s:add_methods('app',['path','has_path','has_file','find_file']) " Split a path into a list. From pathogen.vim function! s:pathsplit(path) abort @@ -298,6 +326,22 @@ endfunction call s:add_methods('readable',['end_of','last_opening_line','last_method_line','last_method','format','define_pattern']) +function! s:readable_find_affinity() dict abort + let f = self.name() + let all = self.app().projections() + for pattern in reverse(sort(filter(keys(all), 'v:val =~# "^[^*]*\\*[^*]*$"'), s:function('rails#lencmp'))) + if !has_key(all[pattern], 'affinity') + continue + endif + let [prefix, suffix; _] = split(pattern, '\*', 1) + if s:startswith(f, prefix) && s:endswith(f, suffix) + let root = f[strlen(prefix) : -strlen(suffix)-1] + return [all[pattern].affinity, root] + endif + endfor + return ['', ''] +endfunction + function! s:controller(...) return rails#buffer().controller_name(a:0 ? a:1 : 0) endfunction @@ -306,7 +350,14 @@ 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 =~ '\.*\.' let r = "view-" . e - elseif f =~ '\' if e == "yml" let r = "fixtures-yaml" @@ -724,7 +780,7 @@ function! s:readable_calculate_file_type() dict abort let r = "db-migration" elseif f=~ '\' +function! s:app_prepare_rails_command(cmd) dict abort + if self.has_path('.zeus.sock') && a:cmd =~# '^\%(console\|dbconsole\|destroy\|generate\|server\|runner\)\>' + return 'zeus '.a:cmd + elseif self.has_path('script/rails') let cmd = 'script/rails '.a:cmd - else + elseif self.has_path('script/' . matchstr(a:cmd, '\w\+')) let cmd = 'script/'.a:cmd + elseif self.has_path('bin/rails') + let cmd = 'bin/rails '.a:cmd + elseif self.has('bundler') + return 'bundle exec rails ' . a:cmd + else + return 'rails '.a:cmd endif - return self.ruby_shell_command(cmd) + return self.ruby_script_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 +function! s:app_start_rails_command(cmd, ...) dict abort + let cmd = s:esccmd(self.prepare_rails_command(a:cmd)) + let title = s:sub(a:cmd, '\s.*', '') + let title = get({ + \ 'g': 'generate', + \ 'd': 'destroy', + \ 'c': 'console', + \ 'db': 'dbconsole', + \ 's': 'server', + \ 'r': 'runner', + \ }, title, title) + call s:push_chdir(1) + try + if exists(':Start') == 2 + exe 'Start'.(a:0 && a:1 ? '!' : '').' -title=rails\ '.title.' '.cmd + elseif has("win32") exe "!start ".cmd + else + exe "!".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 + finally + call s:pop_command() + endtry return '' endfunction -function! s:app_execute_script_command(cmd) dict abort - exe '!'.s:esccmd(self.script_shell_command(a:cmd)) +function! s:app_execute_rails_command(cmd) dict abort + call s:push_chdir(1) + try + exe '!'.s:esccmd(self.prepare_rails_command(a:cmd)) + finally + call s:pop_command() + endtry return '' endfunction @@ -863,9 +943,8 @@ function! s:app_lightweight_ruby_eval(ruby,...) dict abort 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 + let args = '-e '.s:rquote(a:ruby) + let cmd = self.ruby_command(args) silent! let results = system(cmd) return v:shell_error == 0 ? results : def endfunction @@ -876,59 +955,33 @@ function! s:app_eval(ruby,...) dict abort 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) + let cmd = self.ruby_command(args) + call s:push_chdir(1) + try + silent! let results = system(cmd) + finally + call s:pop_command() + endtry 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']) +call s:add_methods('app', ['ruby_command','ruby_script_command','prepare_rails_command','execute_rails_command','start_rails_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=+ Rnavcommand :call s:Navcommand(0,) + command! -buffer -bar -nargs=* -bang Rabbrev :call s:Abbrev(0,) + command! -buffer -bar -nargs=? -bang -count -complete=customlist,rails#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=* -bang Rset :call s:Set(0,) command! -buffer -bar -nargs=0 Rtags :execute 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 Ctags :execute rails#app().tags_command() 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 @@ -936,35 +989,16 @@ function! s:BufCommands() if RailsFilePath() =~ '\,call s:Extract(0,) + elseif rails#buffer().name() =~# '^app/helpers/.*\.rb$' + command! -buffer -bar -bang -nargs=1 -range Rextract :,call s:RubyExtract(0, 'app/helpers', [], s:sub(, '_helper$|Helper$|$', '_helper')) + elseif rails#buffer().name() =~# '^app/\w\+/.*\.rb$' + command! -buffer -bar -bang -nargs=1 -range Rextract :,call s:RubyExtract(0, matchstr(rails#buffer().name(), '^app/\w\+/').'concerns', [' extend ActiveSupport::Concern', ''], ) 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" @@ -979,7 +1013,7 @@ function! s:Log(bang,arg) exe "cgetfile ".lf clast else - if exists(":Tail") + if exists(":Tail") == 2 Tail `=rails#app().path(lf)` else pedit `=rails#app().path(lf)` @@ -987,31 +1021,48 @@ function! s:Log(bang,arg) 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 +function! rails#new_app_command(bang,...) abort + if !a:0 && a:bang + echo "rails.vim ".g:autoloaded_rails + elseif !a:0 || a:1 !=# 'new' + return 'echoerr '.string('Usage: rails new ') endif - let args = map(copy(a:000),'expand(v:val)') + + let args = copy(a:000) if a:bang - let args = ['--force'] + args + let args += ['--force'] 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 + + if &shellpipe !~# 'tee' && index(args, '--skip') < 0 && index(args, '--force') < 0 + let args += ['--skip'] + endif + + let temp = tempname() + try + if &shellpipe =~# '%s' + let pipe = s:sub(&shellpipe, '%s', temp, 'g') + else + let pipe = &shellpipe . ' ' . temp endif - endfor + exe '!rails' join(map(copy(args),'s:rquote(v:val)'),' ') pipe + catch /^Vim:Interrupt/ + endtry + + if isdirectory(expand(args[1])) + let old_errorformat = &l:errorformat + let chdir = exists("*haslocaldir") && haslocaldir() ? 'lchdir' : 'chdir' + let cwd = getcwd() + try + exe chdir s:fnameescape(expand(args[1])) + let &l:errorformat = s:efm_generate + exe 'cgetfile' temp + return 'cfirst' + finally + let &l:errorformat = old_errorformat + exe chdir s:fnameescape(cwd) + endtry + endif + return '' endfunction function! s:app_tags_command() dict @@ -1031,10 +1082,8 @@ function! s:app_tags_command() dict call s:error("ctags not found") return '' endif - if !isdirectory(self.path('tmp')) - call mkdir(self.path('tmp'), 'p') - endif - exe '!'.cmd.' -f '.s:escarg(self.path("tmp/tags")).' -R --langmap="ruby:+.rake.builder.rjs" '.g:rails_ctags_arguments.' '.s:escarg(self.path()) + let args = s:split(get(g:, 'rails_ctags_arguments', '--languages=-javascript')) + exe '!'.cmd.' -f '.s:escarg(self.path("tags")).' -R --langmap="ruby:+.rake.builder.jbuilder.rjs" '.join(args,' ').' '.s:escarg(self.path()) return '' endfunction @@ -1087,7 +1136,8 @@ function! s:app_rake_tasks() dict if self.cache.needs('rake_tasks') call s:push_chdir() try - let lines = split(system("rake -T"),"\n") + let output = system(self.has_path('bin/rake') ? self.ruby_script_command('bin/rake -T') : 'rake -T') + let lines = split(output, "\n") finally call s:pop_command() endtry @@ -1103,7 +1153,7 @@ endfunction call s:add_methods('app', ['rake_tasks']) -let s:efm_backtrace='%D(in\ %f),' +let g:rails#rake_errorformat = '%D(in\ %f),' \.'%\\s%#from\ %f:%l:%m,' \.'%\\s%#from\ %f:%l:,' \.'%\\s#{RAILS_ROOT}/%f:%l:\ %#%m,' @@ -1114,17 +1164,15 @@ let s:efm_backtrace='%D(in\ %f),' \.'%\\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 ? '!' : '') +function! s:make(bang, args, ...) + if exists(':Make') == 2 + exe 'Make'.(a:bang ? '! ' : ' ').a:args + else + exe 'make! '.a:args if !a:bang - cwindow + exe (a:0 ? a:1 : 'cwindow') endif - finally - let &l:makeprg = old_make - endtry + endif endfunction function! s:Rake(bang,lnum,arg) @@ -1132,15 +1180,22 @@ function! s:Rake(bang,lnum,arg) let lnum = a:lnum < 0 ? 0 : a:lnum let old_makeprg = &l:makeprg let old_errorformat = &l:errorformat + let old_compiler = get(b:, 'current_compiler', '') try - if exists('b:bundler_root') && b:bundler_root ==# rails#app().path() + call s:push_chdir(1) + let b:current_compiler = 'rake' + if rails#app().has_path('.zeus.sock') && executable('zeus') + let &l:makeprg = 'zeus rake' + elseif rails#app().has_path('bin/rake') + let &l:makeprg = rails#app().ruby_script_command('bin/rake') + elseif rails#app().has('bundler') let &l:makeprg = 'bundle exec rake' else let &l:makeprg = 'rake' endif - let &l:errorformat = s:efm_backtrace + let &l:errorformat = g:rails#rake_errorformat let arg = a:arg - if &filetype =~# '^ruby\>' && arg == '' && g:rails_modelines + if &filetype =~# '^ruby\>' && arg == '' 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\|#{\@!\|$\)' @@ -1151,12 +1206,7 @@ function! s:Rake(bang,lnum,arg) 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 + let arg = rails#buffer().default_rake_task(lnum) endif if !has_key(self,'options') | let self.options = {} | endif if arg == '-' @@ -1166,59 +1216,94 @@ function! s:Rake(bang,lnum,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 + call s:make(a:bang, arg) 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$') + call s:make(a:bang, arg, 'copen') else - exe 'make! '.arg - if !a:bang - cwindow - endif + call s:make(a:bang, arg) endif finally let &l:errorformat = old_errorformat let &l:makeprg = old_makeprg + let b:current_compiler = old_compiler + if empty(b:current_compiler) + unlet b:current_compiler + endif + call s:pop_command() endtry endfunction -function! s:readable_default_rake_task(lnum) dict abort +function! s:readable_test_file_candidates() dict abort + let f = self.name() + let projected = self.projected('test') + if self.type_name('view') + let tests = [ + \ fnamemodify(f,':s?\\)' || f =~# '\%(\')] + elseif self.type_name('test', 'spec', 'cucumber') + let tests = [f] + else + let tests = [] + endif + if !self.app().has('test') + call filter(tests, 'v:val !~# "^test/"') + endif + if !self.app().has('spec') + call filter(tests, 'v:val !~# "^spec/"') + endif + if !self.app().has('cucumber') + call filter(tests, 'v:val !~# "^cucumber/"') + endif + return projected + tests +endfunction + +function! s:readable_test_file() dict abort + let candidates = self.test_file_candidates() + for file in candidates + if self.app().has_path(file) + return file + endif + endfor + return get(candidates, 0, '') +endfunction + +function! s:readable_default_rake_task(...) dict abort let app = self.app() - let lnum = a:lnum < 0 ? 0 : a:lnum + let lnum = a:0 ? (a:1 < 0 ? 0 : a:1) : 0 + if self.getvar('&buftype') == 'quickfix' return '-' elseif self.getline(lnum) =~# '# rake ' @@ -1229,7 +1314,22 @@ function! s:readable_default_rake_task(lnum) dict abort 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') + endif + + let placeholders = {} + if lnum + let placeholders.l = lnum + let last = self.last_method(lnum) + if !empty(last) + let placeholders.d = last + endif + endif + let tasks = self.projected('task', placeholders) + if !empty(tasks) + return tasks[0] + endif + + if self.type_name('config-routes') return 'routes' elseif self.type_name('fixtures-yaml') && lnum return "db:fixtures:identify LABEL=".self.last_method(lnum) @@ -1240,32 +1340,10 @@ function! s:readable_default_rake_task(lnum) dict abort 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) + return self.last_method(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 '' + let test = self.test_file() + let with_line = test + if test ==# self.name() + let with_line .= (lnum > 0 ? ':'.lnum : '') + endif + if empty(test) + return '' + elseif test =~# '^test\>' + let opts = '' + if test ==# self.name() + let method = self.app().file(test).last_method(lnum) + if method =~ '^test_' + let opts = ' TESTOPTS=-n'.method + endif + endif + if test =~# '^test/\%(unit\|models\)\>' + return 'test:units TEST='.s:rquote(test).opts + elseif test =~# '^test/\%(functional\|controllers\)\>' + return 'test:functionals TEST='.s:rquote(test).opts + elseif test =~# '^test/integration\>' + return 'test:integration TEST='.s:rquote(test).opts + elseif test ==# 'test' + return 'test' + else + return 'test:recent TEST='.s:rquote(test).opts + endif + elseif test =~# '^spec\>' + return 'spec SPEC='.s:rquote(with_line) + elseif test =~# '^features\>' + return 'cucumber FEATURE='.s:rquote(with_line) + else + let task = matchstr(test, '^\w*') + return task . ' ' . toupper(task) . '=' . s:rquote(with_line) + endif endif endfunction -function! s:Complete_rake(A,L,P) +function! rails#complete_rake(A,L,P) return s:completion_filter(rails#app().rake_tasks(),a:A) endfunction -call s:add_methods('readable',['default_rake_task']) +call s:add_methods('readable', ['test_file_candidates', 'test_file', 'default_rake_task']) " }}}1 " Preview {{{1 function! s:initOpenURL() - if !exists(":OpenURL") + if !exists(":OpenURL") == 2 if has("gui_mac") || has("gui_macvim") || exists("$SECURITYSESSIONID") command -bar -nargs=1 OpenURL :!open elseif has("gui_win32") @@ -1403,24 +1490,55 @@ function! s:readable_preview_urls(lnum) dict abort return urls endfunction -call s:add_methods('readable',['preview_urls']) +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") +function! s:app_server_binding() dict abort + let pidfile = self.path('tmp/pids/server.pid') + let pid = get(readfile(pidfile, 'b', 1), 0, 0) + if pid + if self.cache.has('server') + let old = self.cache.get('server') + else + let old = {'pid': 0, 'binding': ''} + endif + if !empty(old.binding) && pid == old.pid + return old.binding + endif + let binding = rails#get_binding_for(pid) + call self.cache.set('server', {'pid': pid, 'binding': binding}) + if !empty(binding) + return binding + endif endif - let root = s:sub(root,'/$','') - if a:arg =~ '://' - let uri = a:arg - elseif a:arg != '' - let uri = root.'/'.s:sub(a:arg,'^/','') + for app in s:split(glob("~/.pow/*")) + if resolve(app) ==# resolve(self.path()) + return fnamemodify(app, ':t').'.dev' + endif + endfor + return '' +endfunction + +call s:add_methods('app', ['server_binding']) + +function! s:Preview(bang, lnum, uri) abort + let binding = rails#app().server_binding() + if empty(binding) + let binding = '0.0.0.0:3000' + endif + let binding = s:sub(binding, '^0\.0\.0\.0>|^127\.0\.0\.1>', 'localhost') + let uri = empty(a:uri) ? get(rails#buffer().preview_urls(a:lnum),0,'') : a:uri + if uri =~ '://' + " + elseif uri =~# '^[[:alnum:]-]\+\.' + let uri = 'http://'.s:sub(uri, '^[^/]*\zs', matchstr(root, ':\d\+$')) + elseif uri =~# '^[[:alnum:]-]\+\%(/\|$\)' + let domain = s:sub(binding, '^localhost>', 'lvh.me') + let uri = 'http://'.s:sub(uri, '^[^/]*\zs', '.'.domain) else - let uri = get(rails#buffer().preview_urls(a:lnum),0,'') - let uri = root.'/'.s:sub(s:sub(uri,'^/',''),'/$','') + let uri = 'http://'.binding.'/'.s:sub(uri,'^/','') endif call s:initOpenURL() - if exists(':OpenURL') && !a:bang + if (exists(':OpenURL') == 2) && !a:bang exe 'OpenURL '.uri else " Work around bug where URLs ending in / get handled as FTP @@ -1453,85 +1571,186 @@ endfunction " Script Wrappers {{{1 function! s:BufScriptWrappers() - command! -buffer -bar -nargs=* -complete=customlist,s:Complete_script Rscript :execute rails#app().script_command(0,) - command! -buffer -bar -nargs=* -complete=customlist,s:Complete_generate Rgenerate :execute rails#app().generate_command(0,) - command! -buffer -bar -nargs=* -complete=customlist,s:Complete_destroy Rdestroy :execute rails#app().destroy_command(0,) + command! -buffer -bang -bar -nargs=* -complete=customlist,s:Complete_script Rscript :execute empty() ? rails#app().script_command(0, 'console') ? rails#app().script_command(0,) + command! -buffer -bang -bar -nargs=* -complete=customlist,s:Complete_script Rails :execute rails#app().script_command(0,) + command! -buffer -bang -bar -nargs=* -complete=customlist,s:Complete_generate Rgenerate :execute rails#app().generator_command(0,'generate',) + command! -buffer -bar -nargs=* -complete=customlist,s:Complete_destroy Rdestroy :execute rails#app().generator_command(1,'destroy',) command! -buffer -bar -nargs=? -bang -complete=customlist,s:Complete_server Rserver :execute rails#app().server_command(0,) - command! -buffer -bang -nargs=1 -range=0 -complete=customlist,s:Complete_ruby Rrunner :execute rails#app().runner_command(0 ? -2 : (==?:-1),) - command! -buffer -nargs=1 -range=0 -complete=customlist,s:Complete_ruby Rp :execute rails#app().runner_command(==?:-1,'p begin '..' end') - command! -buffer -nargs=1 -range=0 -complete=customlist,s:Complete_ruby Rpp :execute rails#app().runner_command(==?:-1,'require %{pp}; pp begin '..' end') - command! -buffer -nargs=1 -range=0 -complete=customlist,s:Complete_ruby Ry :execute rails#app().runner_command(==?:-1,'y begin '..' end') + command! -buffer -bang -nargs=? -range=0 -complete=customlist,s:Complete_edit Rrunner :execute rails#buffer().runner_command(0, ?:0, ) + command! -buffer -nargs=1 -range=0 -complete=customlist,s:Complete_ruby Rp :execute rails#app().output_command(==?:-1, 'p begin '..' end') + command! -buffer -nargs=1 -range=0 -complete=customlist,s:Complete_ruby Rpp :execute rails#app().output_command(==?:-1, 'require %{pp}; pp begin '..' end') endfunction -function! s:app_generators() dict +function! s:app_generators() dict abort 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) + let paths = [self.path('vendor/plugins/*'), self.path('lib'), expand("~/.rails")] + if !empty(self.gems()) + let gems = values(self.gems()) + let paths += map(gems, 'v:val . "/lib/rails"') + let paths += map(gems, 'v:val . "/lib"') + let builtin = [] + else + let builtin = ['assets', 'controller', 'generator', 'helper', 'integration_test', 'jbuilder', 'jbuilder_scaffold_controller', 'mailer', 'migration', 'model', 'resource', 'scaffold', 'scaffold_controller', 'task'] + endif + let generators = s:split(globpath(s:pathjoin(paths), 'generators/**/*_generator.rb')) + call map(generators, 's:sub(v:val,"^.*[\\\\/]generators[\\\\/]\\ze.","")') + call map(generators, 's:sub(v:val,"[\\\\/][^\\\\/]*_generator\.rb$","")') + call map(generators, 'tr(v:val, "/", ":")') + let builtin += map(filter(copy(generators), 'v:val =~# "^rails:"'), 'v:val[6:-1]') + call filter(generators,'v:val !~# "^rails:"') + call self.cache.set('generators',s:uniq(builtin + generators)) endif - return sort(split(g:rails_generators,"\n") + self.cache.get('generators')) + return 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') + let msg = "rails.vim ".g:autoloaded_rails + if a:0 == 0 && a:bang && rails#buffer().type_name() == '' + echo msg." (Rails)" + return + elseif a:0 == 0 && a:bang + echo msg." (Rails-".rails#buffer().type_name().")" + return endif - if a:bang || cmd =~# 'console' - return self.background_script_command(cmd.str) + let str = join(map(copy(a:000), 's:rquote(v:val)'), ' ') + if a:bang || str =~# '^\%(c\|console\|db\|dbconsole\|s\|server\)\>' + return self.start_rails_command(str, a:bang) else - return self.execute_script_command(cmd.str) + return self.execute_rails_command(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 +function! s:readable_runner_command(bang, count, arg) dict abort + let old_makeprg = &l:makeprg + let old_errorformat = &l:errorformat + let old_compiler = get(b:, 'current_compiler', '') + call s:push_chdir(1) + try + if !empty(a:arg) + let arg = a:arg + elseif a:count + let arg = self.name() else - exe a:count.'put =res' + let arg = self.test_file() + if empty(arg) + let arg = a:arg + endif endif + + let extra = '' + if a:count > 0 + let extra = ':'.a:count + endif + + let file = arg ==# self.name() ? self : self.app().file(arg) + if arg =~# '^test/.*_test\.rb$' + let compiler = 'rubyunit' + if a:count > 0 + let method = file.last_method(lnum) + if method =~ '^test_' + let extra = ' -n'.method + else + let extra = '' + endif + endif + elseif arg =~# '^spec/.*\%(_spec\.rb\|\.feature\)$' + let compiler = 'rspec' + elseif arg =~# '^features/.*\.feature$' + let compiler = 'cucumber' + else + let compiler = 'ruby' + endif + + let compiler = get(file.projected('compiler'), 0, compiler) + if compiler ==# 'testrb' || compiler ==# 'minitest' + let compiler = 'rubyunit' + elseif empty(findfile('compiler/'.compiler.'.vim', escape(&rtp, ' '))) + let compiler = 'ruby' + endif + + execute 'compiler '.compiler + + if compiler ==# 'ruby' + let &l:makeprg = self.app().prepare_rails_command('runner') + let extra = '' + elseif &makeprg =~# '^\%(testrb\|rspec\|cucumber\)\>' && self.app().has_path('.zeus.sock') + let &l:makeprg = 'zeus ' . &l:makeprg + elseif compiler ==# 'rubyunit' + let &l:makeprg = 'ruby -Itest' + elseif self.app().has_path('bin/' . &l:makeprg) + let &l:makeprg = self.app().ruby_script_command('bin/' . &l:makeprg) + elseif &l:makeprg !~# '^bundle\>' && self.app().has('bundler') + let &l:makeprg = 'bundle exec ' . &l:makeprg + endif + + call s:make(a:bang, arg . extra) + return '' + + finally + call s:pop_command() + let &l:errorformat = old_errorformat + let &l:makeprg = old_makeprg + let b:current_compiler = old_compiler + if empty(b:current_compiler) + unlet b:current_compiler + endif + endtry + return '' +endfunction + +call s:add_methods('readable', ['runner_command']) + +function! s:app_output_command(count, code) dict + let str = self.prepare_rails_command('runner '.s:rquote(a:code)) + call s:push_chdir(1) + try + let res = s:sub(system(str),'\n$','') + finally + call s:pop_command() + endtry + if a:count < 0 + echo res + else + exe a:count.'put =res' endif return '' 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 +function! rails#get_binding_for(pid) + if empty(a:pid) + return '' + endif + if has('win32') + let output = system('netstat -anop tcp') + return matchstr(output, '\n\s*TCP\s\+\zs\S\+\ze\s\+\S\+\s\+LISTENING\s\+'.a:pid.'\>') + endif + if executable('lsof') + let lsof = 'lsof' + elseif executable('/usr/sbin/lsof') + let lsof = '/usr/sbin/lsof' + endif + if exists('lsof') + let output = system(lsof.' -an -itcp -sTCP:LISTEN -p'.a:pid) + let binding = matchstr(output, '\S\+:\d\+\ze\s\+(LISTEN)\n') + return s:sub(binding, '^\*', '0.0.0.0') + endif + if executable('netstat') + let output = system('netstat -antp') + return matchstr(output, '\S\+:\d\+\ze\s\+\S\+\s\+LISTEN\s\+'.a:pid.'/') + return binding + endif + return '' endfunction function! s:app_server_command(bang,arg) dict - let port = matchstr(a:arg,'\%(-p\|--port=\=\)\s*\zs\d\+') - if port == '' - let port = "3000" + if a:arg =~# '--help' + call self.execute_rails_command('server '.a:arg) + return '' endif - " TODO: Extract bind argument - let bind = "0.0.0.0" + let pidfile = self.path('tmp/pids/server.pid') if a:bang && executable("ruby") - let pid = s:getpidfor(bind,port) - if pid =~ '^\d\+$' + let pid = get(s:readfile(pidfile), 0, 0) + if pid echo "Killing server with pid ".pid if !has("win32") call system("ruby -e 'Process.kill(:TERM,".pid.")'") @@ -1544,80 +1763,60 @@ function! s:app_server_command(bang,arg) dict return endif endif - if has_key(self,'options') && has_key(self.options,'gnu_screen') - let screen = self.options.gnu_screen + if (exists(':Start') == 2) || has('win32') + call self.start_rails_command('server '.a:arg, 1) else - let screen = g:rails_gnu_screen + call self.execute_rails_command('server '.a:arg.' -d') 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.'/') return '' 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) +function! s:color_efm(pre, before, after) + return a:pre . '%\S%# %#' . a:before . "\e[0m %#" . a:after . ',' . + \ a:pre . ' %#'.a:before.' %#'.a:after . ',' +endfunction + +let s:efm_generate = + \ s:color_efm('%-G', 'invoke', '%f') . + \ s:color_efm('%-G', 'conflict', '%f') . + \ s:color_efm('%-G', 'run', '%f') . + \ s:color_efm('%-G', 'create', ' ') . + \ s:color_efm('%-G', 'exist', ' ') . + \ s:color_efm('Overwrite%.%#', '%m', '%f') . + \ s:color_efm('', '%m', '%f') . + \ '%-G%.%#' + +function! s:app_generator_command(bang,...) dict call self.cache.clear('user_classes') - return '' -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 + call self.cache.clear('features') 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') + let old_makeprg = &l:makeprg + let old_errorformat = &l:errorformat + try + let &l:makeprg = self.prepare_rails_command(cmd) + let &l:errorformat = s:efm_generate + call s:push_chdir(1) + if a:bang + make! + else + make 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 + finally + call s:pop_command() + let &l:errorformat = old_errorformat + let &l:makeprg = old_makeprg + endtry return '' endfunction -call s:add_methods('app', ['generators','script_command','runner_command','server_command','destroy_command','generate_command']) +call s:add_methods('app', ['generators','script_command','output_command','server_command','generator_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) + return s:completion_filter(['generate', 'console', 'server', 'dbconsole', 'application', 'destroy', 'plugin', 'runner'],a:ArgLead) 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.'$' @@ -1625,25 +1824,22 @@ function! s:Complete_script(ArgLead,CmdLine,P) 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,"/$","")')) + return s:completion_filter(map(rails#app().relglob('lib/generators/','*'),'s:sub(v:val,"/$","")'), a:ArgLead) elseif target ==# 'helper' - return s:helperList(a:ArgLead,"","") + return s:autocamelize(rails#app().relglob('app/helpers/','**/*','_helper.rb'),a:ArgLead) elseif target ==# 'integration_test' || target ==# 'integration_spec' || target ==# 'feature' - return s:integrationtestList(a:ArgLead,"","") - elseif target ==# 'metal' - return s:metalList(a:ArgLead,"","") + return s:autocamelize( + \ rails#app().relglob('test/integration/','**/*','_test.rb') + + \ rails#app().relglob('spec/features/', '**/*', '_spec.rb') + + \ rails#app().relglob('spec/requests/', '**/*', '_spec.rb') + + \ rails#app().relglob('features/', '**/*', '.feature'), 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) + elseif target ==# 'mailer' + return s:mailerList(a:ArgLead,"","") + return s:completion_filter(rails#app().relglob("app/mailers/","**/*",".rb"),a:ArgLead) + elseif target =~# '^\w*\%(model\|resource\)$' || target =~# '\w*scaffold\%(_controller\)\=$' + return s:completion_filter(rails#app().relglob('app/models/','**/*','.rb'), a:ArgLead) else return [] endif @@ -1658,7 +1854,7 @@ function! s:Complete_script(ArgLead,CmdLine,P) 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)') + return filter(["-p","-b","-c","-d","-u","-e","-P","-h","--port=","--binding=","--config=","--daemon","--debugger","--environment=","--pid=","--help"],'s:startswith(v:val,a:ArgLead)') endif endif return "" @@ -1694,28 +1890,17 @@ endfunction " Navigation {{{1 function! s:BufNavCommands() + command! -buffer -bar -nargs=? -complete=customlist,s:Complete_cd Cd :cd `=rails#app().path()` + command! -buffer -bar -nargs=? -complete=customlist,s:Complete_cd Lcd :lcd `=rails#app().path()` 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 AR :call s:Alternate('D',,,,) 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',,,,) @@ -1750,6 +1935,7 @@ function! s:djump(def) endif endif endif + return '' endfunction function! s:Find(count,cmd,...) @@ -1780,7 +1966,7 @@ function! s:Edit(count,cmd,...) let str = "" let i = 1 while i < a:0 - let str .= "`=a:".i."` " + let str .= s:escarg(a:{i}) . " " let i += 1 endwhile let file = a:{i} @@ -1891,16 +2077,16 @@ function! s:RailsFind() 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') + let res = s:findamethod('belongs_to\|has_one\|embedded_in\|embeds_one\|composed_of\|validates_associated\|scaffold','\1.rb') if res != ""|return res|endif - let res = rails#singularize(s:findamethod('has_many\|has_and_belongs_to_many','app/models/\1')) + let res = rails#singularize(s:findamethod('has_many\|has_and_belongs_to_many\|embeds_many','\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')) + let res = rails#singularize(s:findamethod('create_table\|change_table\|drop_table\|rename_table\|\%(add\|remove\)_\%(column\|index\|timestamps\|reference\|belongs_to\)\|rename_column\|remove_columns\|rename_index','\1')) if res != ""|return res.".rb"|endif - let res = rails#singularize(s:findasymbol('through','app/models/\1')) + let res = rails#singularize(s:findasymbol('through','\1')) if res != ""|return res.".rb"|endif let res = s:findamethod('fixtures','fixtures/\1') @@ -1908,19 +2094,19 @@ function! s:RailsFind() return RailsFilePath() =~ '\\|\\|\\|,\s*to:\)\s*','app/controllers/\1') + let res = s:findamethod('\%(match\|get\|put\|patch\|post\|delete\|redirect\)\s*(\=\s*[:''"][^''"]*[''"]\=\s*\%(\%(,\s*:to\s*\)\==>\|,\s*to:\)\s*','\1') if res =~ '#'|return s:sub(res,'#','_controller.rb#')|endif if !buffer.type_name('controller', 'mailer') @@ -1936,17 +2122,17 @@ function! s:RailsFind() let res = s:findasymbol('layout','\=s:findlayout(submatch(1))') if res != ""|return res|endif - let res = s:findamethod('helper','app/helpers/\1_helper.rb') + let res = s:findamethod('helper','\1_helper.rb') if res != ""|return res|endif - let res = s:findasymbol('controller','app/controllers/\1_controller.rb') + let res = s:findasymbol('controller','\1_controller.rb') if res != ""|return res|endif let res = s:findasymbol('action','\1') - if res != ""|return res|endif + if res != ""|return s:findview(res)|endif - let res = s:findasymbol('template','app/views/\1') - if res != ""|return res|endif + let res = s:findasymbol('template','\1') + if res != ""|return s:findview(res)|endif let res = s:sub(s:sub(s:findasymbol('partial','\1'),'^/',''),'[^/]+$','_&') if res != ""|return res."\n".s:findview(res)|endif @@ -1954,8 +2140,8 @@ function! s:RailsFind() 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:findamethod('render\>\s*\%(:\%(template\|action\)\s\+=>\|template:\|action:\)\s*','\1') + if res != ""|return s:findview(res)|endif let res = s:sub(s:findfromview('render','\1'),'^/','') if !buffer.type_name('controller', 'mailer') @@ -2009,7 +2195,7 @@ 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 exec = "ActionController::Routing::Routes.named_routes.each {|n,r| puts %{#{n} #{r.requirements[:controller]}_controller.rb##{r.requirements[:action]}}}" let string = self.eval(exec) let routes = {} for line in split(string,"\n") @@ -2052,7 +2238,7 @@ function! s:RailsIncludefind(str,...) if line =~# '\<\(require\|load\)\s*(\s*$' return str elseif str =~# '^\l\w*#\w\+$' - return 'app/controllers/'.s:sub(str,'#','_controller.rb#') + return s:sub(str,'#','_controller.rb#') endif let str = rails#underscore(str) let fpat = '\(\s*\%("\f*"\|:\f*\|'."'\\f*'".'\)\s*,\s*\)*' @@ -2065,9 +2251,9 @@ function! s:RailsIncludefind(str,...) elseif line =~# '\\s*' let str = s:findview(s:sub(str,'^/=','layouts/')) elseif line =~# ':controller\s*=>\s*' - let str = 'app/controllers/'.str.'_controller.rb' + let str = str.'_controller.rb' elseif line =~# '\\s*$' && rails#buffer().type_name('config-routes')) @@ -2102,14 +2288,14 @@ function! s:RailsIncludefind(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') + let str = 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' + let str = rails#pluralize(str).'_controller.rb#show' else - let str = 'app/controllers/'.str.'_controller.rb#index' + let str = str.'_controller.rb#index' endif else let str = file @@ -2129,51 +2315,113 @@ function! s:RailsIncludefind(str,...) endfunction " }}}1 -" File Finders {{{1 +" Projection Commands {{{1 + +function! s:app_commands() dict abort + let commands = {} + + let commands.environment = [ + \ {'pattern': 'config/environments/*.rb'}, + \ {'pattern': 'config/application.rb'}, + \ {'pattern': 'config/environment.rb'}] + let commands.helper = [{ + \ 'pattern': 'app/helpers/*_helper.rb', + \ 'template': "module %SHelper\nend", + \ 'affinity': 'controller'}] + let commands.initializer = [ + \ {'pattern': 'config/initializers/*.rb'}, + \ {'pattern': 'config/routes.rb'}] + let commands.lib = [ + \ {'pattern': 'lib/*.rb'}, + \ {'pattern': 'Gemfile'}] + let commands.mailer = [ + \ {'pattern': 'app/mailers/*.rb', 'template': "class %S < ActionMailer::Base\nend", 'affinity': 'controller'}, + \ {'pattern': 'app/models/*.rb', 'template': "class %S < ActionMailer::Base\nend", 'affinity': 'controller', 'complete': 0}] + let commands.model = [{ + \ 'pattern': 'app/models/*.rb', + \ 'template': "class %S\nend", + \ 'affinity': 'model'}] + let commands.task = [ + \ {'pattern': 'lib/tasks/*.rake'}, + \ {'pattern': 'Rakefile'}] + + let commands['unit test'] = map(filter([ + \ ['test', 'test/unit/*_test.rb', "require 'test_helper'\n\nclass %STest < ActiveSupport::TestCase\nend", 'model', 1], + \ ['test', 'test/models/*_test.rb', "require 'test_helper'\n\nclass %STest < ActiveSupport::TestCase\nend", 'model', 1], + \ ['test', 'test/helpers/*_test.rb', "require 'test_helper'\n\nclass %STest < ActionView::TestCase\nend", '', 1], + \ ['test', 'test/helpers/*_helper_test.rb', "require 'test_helper'\n\nclass %SHelperTest < ActionView::TestCase\nend", 'controller', 0], + \ ['spec', 'spec/models/*_spec.rb', "require 'spec_helper'\n\ndescribe %S do\nend", 'model', 1], + \ ['spec', 'spec/helpers/*_spec.rb', "require 'spec_helper'\n\ndescribe %S do\nend", '', 1], + \ ['spec', 'spec/helpers/*_helper_spec.rb', "require 'spec_helper'\n\ndescribe %SHelper do\nend", 'controller', 0]], + \ 'rails#app().has(v:val[0])'), + \ '{"pattern": v:val[1], "template": v:val[2], "affinity": v:val[3], "complete": v:val[4]}') + let commands['functional test'] = map(filter([ + \ ['test', 'test/functional/*_test.rb', "require 'test_helper'\n\nclass %STest < ActionController::TestCase\nend", '', 1], + \ ['test', 'test/functional/*_controller_test.rb', "require 'test_helper'\n\nclass %SControllerTest < ActionController::TestCase\nend", 'controller', 0], + \ ['test', 'test/controllers/*_test.rb', "require 'test_helper'\n\nclass %STest < ActionController::TestCase\nend", '', 1], + \ ['test', 'test/controllers/*_controller_test.rb', "require 'test_helper'\n\nclass %SControllerTest < ActionController::TestCase\nend", 'controller', 0], + \ ['test', 'test/mailers/', "require 'test_helper'\n\nclass %STest < ActionMailer::TestCase\nend", 'model', 1], + \ ['spec', 'spec/controllers/*_spec.rb', "require 'spec_helper'\n\ndescribe %S do\nend", '', 1], + \ ['spec', 'spec/controllers/*_controller_spec.rb', "require 'spec_helper'\n\ndescribe %SController do\nend", 'controller', 0], + \ ['spec', 'spec/mailers/*_spec.rb', "require 'spec_helper'\n\ndescribe %S do\nend", 'controller', 0]], + \ 'rails#app().has(v:val[0])'), + \ '{"pattern": v:val[1], "template": v:val[2], "affinity": v:val[3], "complete": v:val[4]}') + let commands['integration test'] = map(filter([ + \ ['test', 'test/integration/*_test.rb', "require 'test_helper'\n\nclass %STest < ActionDispatch::IntegrationTest\nend"], + \ ['spec', 'spec/features/*_spec.rb', "require 'spec_helper'\n\ndescribe \"%h\" do\nend"], + \ ['spec', 'spec/requests/*_spec.rb', "require 'spec_helper'\n\ndescribe \"%h\" do\nend"], + \ ['spec', 'spec/integration/*_spec.rb', "require 'spec_helper'\n\ndescribe \"%h\" do\nend"], + \ ['cucumber', 'features/*.feature', "Feature: %h"], + \ ['turnip', 'spec/acceptance/*.feature', "Feature: %h"], + \ ['test', 'test/test_helper.rb', ""], + \ ['cucumber', 'features/support/env.rb', ""], + \ ['spec', 'spec/spec_helper.rb', ""]], + \ 'rails#app().has(v:val[0])'), + \ '{"pattern": v:val[1], "template": v:val[2]}') + + let all = self.projections() + for pattern in reverse(sort(keys(all), function('rails#lencmp'))) + let projection = all[pattern] + for name in s:split(get(projection, 'command', get(projection, 'label', get(projection, 'name', get(projection, 'description', ''))))) + let command = { + \ 'pattern': pattern, + \ 'affinity': get(projection, 'affinity', '')} + if !has_key(commands, name) + let commands[name] = [] + endif + call extend(commands[name], [command]) + endfor + endfor + call filter(commands, '!empty(v:val)') + return commands +endfunction + +call s:add_methods('app', ['commands']) function! s:addfilecmds(type) let l = s:sub(a:type,'^.','\l&') - let cmds = 'ESVTD ' - let cmd = '' - while cmds != '' + for prefix in ['E', 'S', 'V', 'T', 'D', 'R', 'RE', 'RS', 'RV', 'RT', 'RD'] 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 + exe "command! -buffer -bar ".(prefix =~# 'D' ? '-range=0 ' : '')."-nargs=*".cplt." ".prefix.l." :execute s:".l.'Edit("'.(prefix =~# 'D' ? '' : '').s:sub(prefix, '^R', '').'",)' + endfor endfunction -function! s:BufFinderCommands() - command! -buffer -bar -nargs=+ Rnavcommand :call s:Navcommand(0,) - call s:addfilecmds("metal") - call s:addfilecmds("model") +function! s:BufProjectionCommands() call s:addfilecmds("view") call s:addfilecmds("controller") - call s:addfilecmds("mailer") call s:addfilecmds("migration") call s:addfilecmds("schema") - 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") + for [name, command] in items(rails#app().commands()) + call s:define_navcommand(name, command) + endfor endfunction function! s:completion_filter(results,A) @@ -2181,6 +2429,9 @@ function! s:completion_filter(results,A) call filter(results,'v:val !~# "\\~$"') let filtered = filter(copy(results),'s:startswith(v:val,a:A)') if !empty(filtered) | return filtered | endif + let prefix = s:sub(a:A,'(.*[/]|^)','&_') + let filtered = filter(copy(results),"s:startswith(v:val,prefix)") + 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 @@ -2227,20 +2478,12 @@ 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)) @@ -2274,20 +2517,6 @@ function! s:javascriptList(A,L,P) 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/', '**/*') + @@ -2320,177 +2549,81 @@ function! s:schemaList(A,L,P) return s:autocamelize(tables, a:A) 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 - if rails#app().has('turnip') - let found += rails#app().relglob("spec/acceptance/","**/*",".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 + let name = s:gsub(a:name, '[[:punct:][:space:]]', '') + if name !~# '^[a-z]\+$' + return s:error("E182: Invalid command name ".name) + endif + for prefix in ['E', 'S', 'V', 'T', 'D', 'R', 'RE', 'RS', 'RV', 'RT', 'RD'] + exe 'command! -buffer -bar -bang -nargs=* ' . + \ (prefix =~# 'D' ? '-range=0 ' : '') . + \ '-complete=customlist,'.s:sid.'CommandList ' . + \ prefix . name . ' :execute s:CommandEdit(' . + \ string((prefix =~# 'D' ? '' : '') . s:sub(prefix, '^R', '') . "") . ',' . + \ string(a:name) . ',' . string(a:projection) . ',)' . + \ (a:0 ? '|' . a:1 : '') + endfor endfunction function! s:CommandList(A,L,P) - let cmd = matchstr(a:L,'\CR[A-Z]\=\w\+') + let cmd = matchstr(a:L,'\C[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 + let matches = [] + for projection in s:last_projections + if projection.pattern !~# '\*' || !get(projection, 'complete', 1) + continue endif - call s:EditSimpleRb(a:cmd,a:name,a:0 ? a:1 : default,a:prefix,a:suffix) + let [prefix, suffix; _] = split(projection.pattern, '\*', 1) + let results = rails#app().relglob(prefix, '**/*', suffix) + if suffix =~# '\.rb$' && a:A =~# '^\u' + let matches += map(results, 'rails#camelize(v:val)') + else + let matches += results + endif + endfor + return s:completion_filter(matches, a:A) +endfunction + +function! s:CommandEdit(cmd, name, projections, ...) + if a:0 && a:1 == "&" + let s:last_projections = a:projections + return '' + else + return rails#buffer().open_command(a:cmd, a:0 ? a:1 : '', a:name, a:projections) endif endfunction -function! s:EditSimpleRb(cmd,name,target,prefix,suffix,...) +function! s:LegacyCommandEdit(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)=$','') + let jump = matchstr(a:target, '[#!].*\|:\d*\%(:in\)\=$') + let f = s:sub(a:target, '[#!].*|:\d*%(:in)=$', '') if jump =~ '^!' let cmd = s:editcmdfor(cmd) endif @@ -2499,7 +2632,7 @@ function! s:EditSimpleRb(cmd,name,target,prefix,suffix,...) else let f .= a:suffix.jump endif - let f = s:gsub(a:prefix,'\n',f.'\n').f + let f = a:prefix.f return s:findedit(cmd,f) endfunction @@ -2548,9 +2681,21 @@ call s:add_methods('app', ['migration']) function! s:migrationEdit(cmd,...) let cmd = s:findcmdfor(a:cmd) let arg = a:0 ? a:1 : '' + if arg =~# '!' + " This will totally miss the mark if we cross into or out of DST. + let ts = localtime() + let local = strftime('%H', ts) * 3600 + strftime('%M', ts) * 60 + strftime('%S') + let offset = local - ts % 86400 + if offset <= -12 * 60 * 60 + let offset += 86400 + endif + let template = 'class ' . rails#camelize(matchstr(arg, '[^!]*')) . " < ActiveRecord::Migration\nend" + return rails#buffer().open_command(a:cmd, strftime('%Y%m%d%H%M%S', ts - offset).'_'.arg, 'migration', + \ [{'pattern': 'db/migrate/*.rb', 'template': template}]) + endif let migr = arg == "." ? "db/migrate" : rails#app().migration(arg) if migr != '' - call s:findedit(cmd,migr) + return s:findedit(cmd,migr) else return s:error("Migration not found".(arg=='' ? '' : ': '.arg)) endif @@ -2562,7 +2707,7 @@ function! s:schemaEdit(cmd,...) if rails#app().has_file('db/schema.rb') || !rails#app().has_file(schema) let schema = 'db/schema.rb' endif - call s:findedit(cmd,schema.(a:0 ? '#'.a:1 : '')) + return s:findedit(cmd,schema.(a:0 ? '#'.a:1 : '')) endfunction function! s:fixturesEdit(cmd,...) @@ -2580,37 +2725,22 @@ function! s:fixturesEdit(cmd,...) let dirs = ['test/fixtures', 'spec/fixtures', 'test/factories', 'spec/factories'] let file = get(filter(copy(dirs), 'isdirectory(rails#app().path(v:val))'), 0, dirs[0]).'/'.c.e if file =~ '\.\w\+$' && rails#app().find_file(c.e, dirs) ==# '' - call s:edit(a:cmd,file) + return s:edit(a:cmd,file) else - call s:findedit(a:cmd, rails#app().find_file(c.e, dirs, ['.yml', '.csv', '.rb'], file)) + return s:findedit(a:cmd, rails#app().find_file(c.e, dirs, ['.yml', '.csv', '.rb'], 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)) + return 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)) + return rails#buffer().open_command(a:cmd, c, 'locale', + \ [{'pattern': 'config/locales/*.yml'}, {'pattern': 'config/locales/*.rb'}]) 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:dotcmp(i1, i2) return strlen(s:gsub(a:i1,'[^.]', '')) - strlen(s:gsub(a:i2,'[^.]', '')) endfunc @@ -2686,11 +2816,13 @@ function! s:viewEdit(cmd,...) if found != '' call s:edit(a:cmd,found) call s:djump(djump) + return '' elseif a:0 && a:1 =~# '!' call s:edit(a:cmd,'app/views/'.view) call s:djump(djump) + return '' else - call s:findedit(a:cmd,view) + return s:findedit(a:cmd,view) endif endfunction @@ -2702,47 +2834,45 @@ function! s:layoutEdit(cmd,...) if file ==# "" let file = "app/views/layouts/application.html.erb" endif - call s:edit(a:cmd,s:sub(file,'^/','')) + return s:edit(a:cmd,s:sub(file,'^/','')) endfunction function! s:controllerEdit(cmd,...) let suffix = '.rb' + let template = "class %S < ApplicationController\nend" if a:0 == 0 let controller = s:controller(1) if rails#buffer().type_name() =~# '^view\%(-layout\|-partial\)\@!' - let suffix .= '#'.expand('%:t:r') + let jump = '#'.expand('%:t:r') + else + let jump = '' endif else - let controller = a:1 + let controller = matchstr(a:1, '[^#!]*') + let jump = matchstr(a:1, '[#!].*') endif if rails#app().has_file("app/controllers/".controller."_controller.rb") || !rails#app().has_file("app/controllers/".controller.".rb") + let template = "class %SController < ApplicationController\nend" 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") + return rails#buffer().open_command(a:cmd, controller . jump, 'controller', + \ [{'template': template, 'pattern': 'app/controllers/*'.suffix}]) 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) + return s:LegacyCommandEdit(a:cmd,"stylesheet",name,"public/stylesheets/sass/",".sass") 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) + return s:LegacyCommandEdit(a:cmd,"stylesheet",name,"public/stylesheets/sass/",".scss") elseif rails#app().has('lesscss') && rails#app().has_file('app/stylesheets/'.name.'.less') - return s:EditSimpleRb(a:cmd,"stylesheet",name,"app/stylesheets/",".less",1) + return s:LegacyCommandEdit(a:cmd,"stylesheet",name,"app/stylesheets/",".less") 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) + return s:LegacyCommandEdit(a:cmd,'stylesheet',name,'app/assets/stylesheets/',types[0]) else - return s:EditSimpleRb(a:cmd,'stylesheet',name,'public/stylesheets/','.css',1) + return s:LegacyCommandEdit(a:cmd,'stylesheet',name,'public/stylesheets/','.css') endif endif endfunction @@ -2750,168 +2880,24 @@ 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) + return s:LegacyCommandEdit(a:cmd,'javascript',name,'app/scripts/','.coffee') elseif rails#app().has('coffee') && rails#app().has_file('app/scripts/'.name.'.js') - return s:EditSimpleRb(a:cmd,'javascript',name,'app/scripts/','.js',1) + return s:LegacyCommandEdit(a:cmd,'javascript',name,'app/scripts/','.js') 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) + return s:LegacyCommandEdit(a:cmd,'javascript',name,'app/assets/javascripts/',types[0]) else - return s:EditSimpleRb(a:cmd,'javascript',name,'public/javascripts/','.js',1) + return s:LegacyCommandEdit(a:cmd,'javascript',name,'public/javascripts/','.js') 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'], ['spec/acceptance/','.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() =~ '\ 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 @@ -3254,8 +3289,6 @@ function! s:Extract(bang,...) range abort elseif fnamemodify(fname, ':e') !=# ext let fname .= '.'.ext endif - let var = "@".name - let collection = "" if dir =~ '^/' let out = (rails_root).dir."/_".fname elseif dir == "" || dir == "." @@ -3275,7 +3308,6 @@ function! s:Extract(bang,...) range abort return s:error('No such directory') endif endif - " No tabs, they'll just complicate things if ext =~? '^\%(rhtml\|erb\|dryml\)$' let erub1 = '\<\%\s*' let erub2 = '\s*-=\%\>' @@ -3284,35 +3316,14 @@ function! s:Extract(bang,...) range abort let erub2 = '' endif let spaces = matchstr(getline(first),"^ *") - if getline(last+1) =~ '\v^\s*'.erub1.'end'.erub2.'\s*$' - let fspaces = matchstr(getline(last+1),"^ *") - if getline(first-1) =~ '\v^'.fspaces.erub1.'for\s+(\k+)\s+in\s+([^ %>]+)'.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 + let renderstr = "render '".fnamemodify(file,":r:r")."'" 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" + elseif ext == "haml" || ext == "slim" let renderstr = "= ".renderstr elseif ext == "mn" let renderstr = "_".renderstr @@ -3324,7 +3335,7 @@ function! s:Extract(bang,...) range abort let old_ai = &ai try let &ai = 0 - silent exe "norm! :".first.",".last."change\".fspaces.renderstr."\.\" + silent exe "norm! :".first.",".last."change\".spaces.renderstr."\.\" finally let &ai = old_ai endtry @@ -3335,8 +3346,8 @@ function! s:Extract(bang,...) range abort endif let ft = &ft let shortout = fnamemodify(out,':.') - silent split `=shortout` - silent %delete + silent execute 'split '.s:fnameescape(shortout) + silent %delete _ let &ft = ft let @@ = partial silent put @@ -3345,10 +3356,29 @@ function! s:Extract(bang,...) range abort if spaces != "" silent! exe '%substitute/^'.spaces.'//' endif - silent! exe '%substitute?\%(\w\|[@:"'."'".'-]\)\@?'.name.'?g' 1 endfunction +function! s:RubyExtract(bang, root, before, name) range abort + let content = getline(a:firstline, a:lastline) + execute a:firstline.','.a:lastline.'delete_' + let indent = get(sort(map(filter(copy(content), '!empty(v:val)'), 'len(matchstr(v:val, "^ \\+"))')), 0, 0) + if indent + call map(content, 's:sub(v:val, "^".repeat(" ", indent), " ")') + endif + call append(a:firstline-1, repeat(' ', indent).'include '.rails#camelize(a:name)) + let out = rails#app().path(a:root, a:name . '.rb') + if filereadable(out) && !a:bang + return s:error('E13: File exists (add ! to override)') + endif + if !isdirectory(fnamemodify(out, ':h')) + call mkdir(fnamemodify(out, ':h'), 'p') + endif + execute 'split '.s:fnameescape(out) + silent %delete_ + call setline(1, ['module '.rails#camelize(a:name)] + a:before + content + ['end']) +endfunction + " }}}1 " Migration Inversion {{{1 @@ -3527,27 +3557,27 @@ endfunction function! s:helpermethods() return "" - \."action_name atom_feed audio_path audio_tag auto_discovery_link_tag " + \."action_name asset_path asset_url atom_feed audio_path audio_tag audio_url auto_discovery_link_tag " \."button_tag button_to button_to_function " - \."cache capture cdata_section check_box check_box_tag collection_select concat content_for content_tag content_tag_for controller controller_name controller_path convert_to_model cookies csrf_meta_tag csrf_meta_tags current_cycle cycle " - \."date_select datetime_select debug distance_of_time_in_words distance_of_time_in_words_to_now div_for dom_class dom_id " + \."cache cache_fragment_name cache_if cache_unless capture cdata_section check_box check_box_tag collection_check_boxes collection_radio_buttons collection_select color_field color_field_tag compute_asset_extname compute_asset_host compute_asset_path concat content_for content_tag content_tag_for controller controller_name controller_path convert_to_model cookies csrf_meta_tag csrf_meta_tags current_cycle cycle " + \."date_field date_field_tag date_select datetime_field datetime_field_tag datetime_local_field datetime_local_field_tag datetime_select debug distance_of_time_in_words distance_of_time_in_words_to_now div_for dom_class dom_id " \."email_field email_field_tag escape_javascript escape_once excerpt " - \."favicon_link_tag field_set_tag fields_for file_field file_field_tag flash form_for form_tag " + \."favicon_link_tag field_set_tag fields_for file_field file_field_tag flash font_path font_url form_for form_tag " \."grouped_collection_select grouped_options_for_select " \."headers hidden_field hidden_field_tag highlight " - \."image_alt image_path image_submit_tag image_tag " - \."j javascript_cdata_section javascript_include_tag javascript_path javascript_tag " + \."image_alt image_path image_submit_tag image_tag image_url " + \."j javascript_cdata_section javascript_include_tag javascript_path javascript_tag javascript_url " \."l label label_tag link_to link_to_function link_to_if link_to_unless link_to_unless_current localize logger " - \."mail_to " + \."mail_to month_field month_field_tag " \."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 " - \."params password_field password_field_tag path_to_audio path_to_image path_to_javascript path_to_stylesheet path_to_video phone_field phone_field_tag pluralize provide " + \."params password_field password_field_tag path_to_asset path_to_audio path_to_font path_to_image path_to_javascript path_to_stylesheet path_to_video phone_field phone_field_tag pluralize provide " \."radio_button radio_button_tag range_field range_field_tag raw render request request_forgery_protection_token reset_cycle response " - \."safe_concat safe_join sanitize sanitize_css search_field search_field_tag select select_date select_datetime select_day select_hour select_minute select_month select_second select_tag select_time select_year session simple_format strip_links strip_tags stylesheet_link_tag stylesheet_path submit_tag " - \."t tag telephone_field telephone_field_tag text_area text_area_tag text_field text_field_tag time_ago_in_words time_select time_tag time_zone_options_for_select time_zone_select translate truncate " - \."url_field url_field_tag url_for url_options " - \."video_path video_tag " - \."word_wrap" + \."safe_concat safe_join sanitize sanitize_css search_field search_field_tag select select_date select_datetime select_day select_hour select_minute select_month select_second select_tag select_time select_year session simple_format strip_links strip_tags stylesheet_link_tag stylesheet_path stylesheet_url submit_tag " + \."t tag telephone_field telephone_field_tag text_area text_area_tag text_field text_field_tag time_ago_in_words time_field time_field_tag time_select time_tag time_zone_options_for_select time_zone_select translate truncate " + \."url_field url_field_tag url_for url_to_asset url_to_audio url_to_font url_to_image url_to_javascript url_to_stylesheet url_to_video utf8_enforcer_tag " + \."video_path video_tag video_url " + \."week_field week_field_tag word_wrap" endfunction function! s:app_user_classes() dict @@ -3580,28 +3610,34 @@ endfunction call s:add_methods('app', ['user_classes','user_assertions']) function! s:BufSyntax() - if (!exists("g:rails_syntax") || g:rails_syntax) + if !exists("g:rails_no_syntax") let buffer = rails#buffer() - let s:javascript_functions = "$ $$ $A $F $H $R $w jQuery" + let javascript_functions = "$ jQuery" let classes = s:gsub(join(rails#app().user_classes(),' '),'::',' ') if &syntax == 'ruby' + let keywords = split(join(buffer.projected('keywords'), ' ')) + let special = filter(copy(keywords), 'v:val =~# ''^\h\k*[?!]$''') + let regular = filter(copy(keywords), 'v:val =~# ''^\h\k*$''') + if !empty(special) + exe 'syn match rubyRailsMethod "\<\%('.join(special, '\|').'\)"' + endif + if !empty(regular) + exe 'syn keyword rubyRailsMethod '.join(regular, ' ') + endif 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 rubyRailsARMethod default_scope named_scope scope serialize store 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 + syn keyword rubyRailsARClassMethod attr_accessible attr_protected attr_readonly has_secure_password store_accessor 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 validates_with syn keyword rubyRailsMethod logger endif @@ -3629,30 +3665,36 @@ function! s:BufSyntax() 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 skip_filter + 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 skip_filter before_action append_before_action prepend_before_action after_action append_after_action prepend_after_action around_action append_around_action prepend_around_action skip_before_action skip_after_action skip_action 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 + syn keyword rubyRailsMigrationMethod create_table change_table drop_table rename_table create_join_table drop_join_table + syn keyword rubyRailsMigrationMethod add_column rename_column change_column change_column_default remove_column remove_columns + syn keyword rubyRailsMigrationMethod add_timestamps remove_timestamps + syn keyword rubyRailsMigrationMethod add_reference remove_reference add_belongs_to remove_belongs_to + syn keyword rubyRailsMigrationMethod add_index remove_index rename_index + syn keyword rubyRailsMigrationMethod execute transaction reversible revert 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 refute refute_empty refute_equal refute_in_delta refute_in_epsilon refute_includes refute_instance_of refute_kind_of refute_match refute_nil refute_operator refute_predicate refute_respond_to refute_same 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 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_context shared_examples_for it_should_behave_like before after around subject fixtures controller_name helper_name scenario feature background + syn keyword rubyRailsTestMethod describe context it its specify shared_context shared_examples_for it_should_behave_like it_behaves_like before after around subject fixtures controller_name helper_name scenario feature background 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 match rubyRailsTestControllerMethod '\.\@' syn keyword rubyRailsTestControllerMethod integrate_views render_views syn keyword rubyRailsMethod params request response session flash syn keyword rubyRailsMethod polymorphic_path polymorphic_url @@ -3661,12 +3703,9 @@ function! s:BufSyntax() 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 + syn keyword rubyRailsMethod match get put patch post delete redirect root resource resources collection member nested scope namespace controller constraints mount concern 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 @@ -3722,11 +3761,10 @@ function! s:BufSyntax() 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 keyword javascriptRailsFunction contained '.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 @@ -3744,13 +3782,13 @@ function! s:BufSyntax() elseif &syntax == "html" syn case match set isk+=$ - exe "syn keyword javascriptRailsFunction contained ".s:javascript_functions + exe "syn keyword javascriptRailsFunction contained ".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 + exe "syn keyword javascriptRailsFunction ".javascript_functions elseif &syntax == "scss" || &syntax == "sass" syn match sassFunction "\<\%(\%(asset\|image\|font\|video\|audio\|javascript\|stylesheet\)-\%(url\|path\)\)\>(\@=" contained @@ -3864,24 +3902,15 @@ function! s:BufMappings() 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 + if !hasmapto("RailsFind") + nmap gf RailsFind + endif + if !hasmapto("RailsSplitFind") + nmap f RailsSplitFind + endif + if !hasmapto("RailsTabFind") + nmap gf RailsTabFind endif - " SelectBuf you're a dirty hack - let v:errmsg = "" endfunction " }}}1 @@ -3898,7 +3927,7 @@ function! s:app_dbext_settings(environment) dict let cache = self.cache.get('dbext_settings') if !has_key(cache,a:environment) let dict = {} - if self.has_file("config/database.yml") + if self.has_path("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) @@ -3947,7 +3976,6 @@ function! s:BufDatabase(...) return endif let self = rails#app() - let s:lock_database = 1 if (a:0 && a:1 > 1) call self.cache.clear('dbext_settings') endif @@ -3957,19 +3985,21 @@ function! s:BufDatabase(...) 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 == 'SQLITE' + " dbext seems to have overlooked the release of sqlite3 a decade ago + let g:dbext_default_SQLITE_bin = "sqlite3" + endif 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']) @@ -3996,19 +4026,6 @@ function! s:selectiveexpand(pat,good,default,...) 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 : '','[\"|]','\\&'),'\<','\\') @@ -4039,10 +4056,14 @@ function! s:AddParenExpand(abbr,expn,...) endif endfunction +if !exists('g:rails_no_abbreviations') && type(get(g:, 'rails_abbreviations', {})) == type(0) + call s:error('Use rails_no_abbreviations not rails_abbreviations to disable abbreviations') + let g:rails_no_abbreviations = 1 +endif + 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 + if !exists('g:rails_no_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') @@ -4054,12 +4075,8 @@ function! s:BufAbbreviations() 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\ =>\ @@ -4070,8 +4087,6 @@ function! s:BufAbbreviations() 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') @@ -4099,7 +4114,6 @@ function! s:BufAbbreviations() 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 @@ -4109,19 +4123,11 @@ function! s:BufAbbreviations() 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 @@ -4129,7 +4135,15 @@ function! s:BufAbbreviations() Rabbrev AS:: ActiveSupport Rabbrev AM:: ActionMailer Rabbrev AO:: ActiveModel - Rabbrev AE:: ActiveResource + for pairs in + \ items(type(get(g:, 'rails_abbreviations', 0)) == type({}) ? g:rails_abbreviations : {}) + call call(function(s:sid.'Abbrev'), [0, pairs[0]] + s:split(pairs[1])) + endfor + for hash in reverse(rails#buffer().projected('abbreviations')) + for pairs in items(hash) + call call(function(s:sid.'Abbrev'), [0, pairs[0]] + s:split(pairs[1])) + endfor + endfor endif endfunction @@ -4187,193 +4201,169 @@ function! s:Abbrev(bang,...) abort endfunction " }}}1 -" Settings {{{1 +" Projections {{{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 +function! rails#json_parse(string) abort + let [null, false, true] = ['', 0, 1] + let string = type(a:string) == type([]) ? join(a:string, ' ') : a:string + let stripped = substitute(string,'\C"\(\\.\|[^"\\]\)*"','','g') + if stripped !~# "[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \n\r\t]" + try + return eval(substitute(string,"[\r\n]"," ",'g')) + catch + endtry + endif + throw "invalid JSON: ".string +endfunction + +function! s:app_gems() dict abort + if self.has('bundler') && exists('*bundler#project') + return bundler#project(self.path()).gems() + else + return {} + endif +endfunction + +function! s:app_has_gem(gem) dict abort + if self.has('bundler') && exists('*bundler#project') + let project = bundler#project(self.path()) + if has_key(project, 'has') + return project.has(a:gem) + elseif has_key(project, 'gems') + return has_key(bundler#project(self.path()).gems(), a:gem) + endif + else + return 0 + endif +endfunction + +function! s:app_engines() dict abort + let gems = escape(join(values(self.gems()),','), ' ') + if empty(gems) + return [] + else + return sort(map(finddir('app', gems, -1), 'fnamemodify(v:val, ":h")')) + endif +endfunction + +function! s:extend_projection(dest, src) + let dest = copy(a:dest) + for key in keys(a:src) + if !has_key(dest, key) || key ==# 'affinity' + let dest[key] = a:src[key] + elseif type(a:src[key]) == type({}) && type(dest[key]) == type({}) + let dest[key] = extend(copy(dest[key]), a:src[key]) else - let opt = matchstr(arg,'[^=]*') - let val = s:sub(arg,'^[^=]*\=','') - if defscope != '' && opt !~ '^\w:' - let opt = defscope.':'.opt - endif - call s:setopt(opt,val) + let dest[key] = s:uniq(s:getlist(a:src, key) + s:getlist(dest, key)) endif endfor + return dest 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 "" +function! s:combine_projections(dest, src, ...) abort + let extra = a:0 ? a:1 : {} + if type(a:src) == type({}) + for [pattern, original] in items(a:src) + let projection = extend(copy(original), extra) + if !has_key(projection, 'prefix') && !has_key(projection, 'format') + let a:dest[pattern] = s:extend_projection(get(a:dest, pattern, {}), projection) + endif + endfor endif + return a:dest 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 +let s:projections_for_gems = {} +function! s:app_projections() dict abort + let dict = {} + call s:combine_projections(dict, get(g:, 'rails_projections', ''), {'check': 1}) + for gem in keys(get(g:, 'rails_gem_projections', {})) + if self.has_gem(gem) + call s:combine_projections(dict, g:rails_gem_projections[gem]) endif - let mat = matchstr(lines,'\C\ ".mat + for pattern in reverse(sort(filter(keys(all), 'v:val =~# "^[^*]*\\*[^*]*$"'), s:function('rails#lencmp'))) + let [prefix, suffix; _] = split(pattern, '\*', 1) + if s:startswith(f, prefix) && s:endswith(f, suffix) + let root = f[strlen(prefix) : -strlen(suffix)-1] + let ph = extend({ + \ 's': root, + \ 'S': rails#camelize(root), + \ 'h': toupper(root[0]) . tr(rails#underscore(root), '_', ' ')[1:-1], + \ 'p': rails#pluralize(root), + \ 'i': rails#singularize(root), + \ '%': '%'}, a:0 ? a:1 : {}) + if suffix =~# '\.js\>' + let ph.S = s:gsub(ph.S, '::', '.') + endif + let mine += map(s:getlist(all[pattern], a:key), 's:expand_placeholders(v:val, ph)') endif - let mat = matchstr(lines,'\C\' - call self.setvar('&shiftwidth',2) - call self.setvar('&softtabstop',2) - call self.setvar('&expandtab',1) - if exists('+completefunc') && self.getvar('&completefunc') ==# '' && &g:completefunc ==# '' - call self.setvar('&completefunc','syntaxcomplete#Complete') - endif + if ft =~# '^\%(e\=ruby\|haml\)\>' && exists('+completefunc') && self.getvar('&completefunc') ==# '' && &g:completefunc ==# '' + call self.setvar('&completefunc','syntaxcomplete#Complete') endif if ft =~# '^ruby\>' call self.setvar('&define',self.define_pattern()) @@ -4488,40 +4475,29 @@ function! s:BufSettings() call self.setvar('surround_69', "\1expr: \1\rend") call self.setvar('surround_101', "\r\nend") endif - if exists(':UltiSnipsAddFiletypes') + if exists(':UltiSnipsAddFiletypes') == 2 UltiSnipsAddFiletypes rails 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 elseif ft == 'javascript' - call self.setvar('&shiftwidth',4) - call self.setvar('&softtabstop',4) - call self.setvar('&expandtab',1) + call self.setvar('&shiftwidth', 4) + call self.setvar('&softtabstop', 4) + call self.setvar('&expandtab', 1) endif if ft =~# '^eruby\>' || ft =~# '^yaml\>' - " surround.vim if exists("g:loaded_surround") if self.getvar('surround_45') == '' || self.getvar('surround_45') == "<% \r %>" " - call self.setvar('surround_45', "<% \r %>") @@ -4551,9 +4527,10 @@ augroup railsPluginAuto 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 */config/editor.json call rails#cache_clear("config") 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/application.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") @@ -4574,7 +4551,4 @@ if !exists('s:apps') endif " }}}1 - -let &cpo = s:cpo_save - " vim:set sw=2 sts=2: diff --git a/.vim/bundle/vundle/.gitignore b/.vim/bundle/vundle/.gitignore index 926ccaa..f276604 100644 --- a/.vim/bundle/vundle/.gitignore +++ b/.vim/bundle/vundle/.gitignore @@ -1 +1,2 @@ doc/tags +.netrwhist diff --git a/.vim/bundle/vundle/README.md b/.vim/bundle/vundle/README.md index a25c77c..70d0ce8 100644 --- a/.vim/bundle/vundle/README.md +++ b/.vim/bundle/vundle/README.md @@ -1,6 +1,6 @@ ## About -[Vundle] is short for **V**imb**undle** and is a [Vim] plugin manager. +[Vundle] is short for _Vim bundle_ and is a [Vim] plugin manager. ![Vundle-installer](http://25.media.tumblr.com/tumblr_m8m96w06G81r39828o1_1280.png) @@ -39,6 +39,8 @@ Bundle 'FuzzyFinder' " non github repos Bundle 'git://git.wincent.com/command-t.git' + " git repos on your local machine (ie. when working on your own plugin) + Bundle 'file:///Users/gmarik/path/to/plugin' " ... filetype plugin indent on " required! @@ -90,11 +92,11 @@ see [`:h vundle`](vundle/blob/master/doc/vundle.txt#L1) vimdoc for more details. ## People Using Vundle -see [Examples](/gmarik/vundle/wiki/Examples) +see [Examples](https://github.com/gmarik/vundle/wiki/Examples) ## FAQ -see [wiki](/gmarik/vundle/wiki) +see [wiki](https://github.com/gmarik/vundle/wiki) ## Contributors @@ -131,7 +133,7 @@ see [wiki](/gmarik/vundle/wiki) [Vundle]:http://github.com/gmarik/vundle [Pathogen]:http://github.com/tpope/vim-pathogen/ [Bundler]:http://github.com/wycats/bundler/ -[Vim]:http://vim.org +[Vim]:http://www.vim.org [Git]:http://git-scm.com [all available vim scripts]:http://vim-scripts.org/vim/scripts.html diff --git a/.vim/bundle/vundle/autoload/vundle.vim b/.vim/bundle/vundle/autoload/vundle.vim index 1ac74e1..0bc7bf5 100644 --- a/.vim/bundle/vundle/autoload/vundle.vim +++ b/.vim/bundle/vundle/autoload/vundle.vim @@ -25,6 +25,8 @@ com! -nargs=? -bang BundleClean com! -nargs=0 BundleDocs \ call vundle#installer#helptags(g:bundles) +" Aliases +com! BundleUpdate BundleInstall! if (has('signs')) sign define Vu_error text=! texthl=Error diff --git a/.vim/bundle/vundle/autoload/vundle/config.vim b/.vim/bundle/vundle/autoload/vundle/config.vim index 55c7d7d..5bb6e3f 100644 --- a/.vim/bundle/vundle/autoload/vundle/config.vim +++ b/.vim/bundle/vundle/autoload/vundle/config.vim @@ -24,6 +24,9 @@ func! vundle#config#require(bundles) abort endf func! vundle#config#init_bundle(name, opts) + if a:name != substitute(a:name, '^\s*\(.\{-}\)\s*$', '\1', '') + echo "Spurious leading and/or trailing whitespace found in bundle spec '" . a:name . "'" + endif let opts = extend(s:parse_options(a:opts), s:parse_name(substitute(a:name,"['".'"]\+','','g'))) let b = extend(opts, copy(s:bundle)) let b.rtpath = s:rtpath(opts) diff --git a/.vim/bundle/vundle/autoload/vundle/installer.vim b/.vim/bundle/vundle/autoload/vundle/installer.vim index f7e4375..8386aae 100644 --- a/.vim/bundle/vundle/autoload/vundle/installer.vim +++ b/.vim/bundle/vundle/autoload/vundle/installer.vim @@ -106,7 +106,10 @@ func! vundle#installer#install(bang, name) abort endf func! vundle#installer#docs() abort - call vundle#installer#helptags(g:bundles) + let error_count = vundle#installer#helptags(g:bundles) + if error_count > 0 + return 'error' + endif return 'helptags' endf @@ -117,11 +120,12 @@ func! vundle#installer#helptags(bundles) abort call s:log('') call s:log('Helptags:') - call map(copy(help_dirs), 's:helptags(v:val)') + let statuses = map(copy(help_dirs), 's:helptags(v:val)') + let errors = filter(statuses, 'v:val == 0') call s:log('Helptags: '.len(help_dirs).' bundles processed') - return help_dirs + return len(errors) endf func! vundle#installer#list(bang) abort @@ -198,10 +202,12 @@ func! s:helptags(rtp) abort let doc_path = a:rtp.'/doc/' call s:log(':helptags '.doc_path) try - helptags `=doc_path` + execute 'helptags ' . doc_path catch call s:log("> Error running :helptags ".doc_path) + return 0 endtry + return 1 endf func! s:sync(bang, bundle) abort @@ -210,15 +216,13 @@ func! s:sync(bang, bundle) abort if !(a:bang) | return 'todate' | endif let cmd = 'cd '.shellescape(a:bundle.path()).' && git pull && git submodule update --init --recursive' - if (has('win32') || has('win64')) - let cmd = substitute(cmd, '^cd ','cd /d ','') " add /d switch to change drives - let cmd = '"'.cmd.'"' " enclose in quotes - endif + let cmd = g:shellesc_cd(cmd) let get_current_sha = 'cd '.shellescape(a:bundle.path()).' && git rev-parse HEAD' + let get_current_sha = g:shellesc_cd(get_current_sha) let initial_sha = s:system(get_current_sha)[0:15] else - let cmd = 'git clone --recursive '.a:bundle.uri.' '.shellescape(a:bundle.path()) + let cmd = 'git clone --recursive '.shellescape(a:bundle.uri).' '.shellescape(a:bundle.path()) let initial_sha = '' endif @@ -246,6 +250,25 @@ func! s:sync(bang, bundle) abort return 'updated' endf +func! g:shellesc(cmd) abort + if (has('win32') || has('win64')) + if &shellxquote != '(' " workaround for patch #445 + return '"'.a:cmd.'"' " enclose in quotes so && joined cmds work + endif + endif + return a:cmd +endf + +func! g:shellesc_cd(cmd) abort + if (has('win32') || has('win64')) + let cmd = substitute(a:cmd, '^cd ','cd /d ','') " add /d switch to change drives + let cmd = g:shellesc(cmd) + return cmd + else + return a:cmd + endif +endf + func! s:system(cmd) abort return system(a:cmd) endf diff --git a/.vim/bundle/vundle/autoload/vundle/scripts.vim b/.vim/bundle/vundle/autoload/vundle/scripts.vim index 53a77e1..ded6a46 100644 --- a/.vim/bundle/vundle/autoload/vundle/scripts.vim +++ b/.vim/bundle/vundle/autoload/vundle/scripts.vim @@ -28,7 +28,7 @@ func! s:view_log() endif call writefile(g:vundle_log, g:vundle_log_file) - silent pedit `=g:vundle_log_file` + execute 'silent pedit ' . g:vundle_log_file wincmd P | wincmd H endf @@ -43,10 +43,7 @@ func! s:create_changelog() abort \ ' && git log --pretty=format:"%s %an, %ar" --graph '. \ initial_sha.'..'.updated_sha - if (has('win32') || has('win64')) - let cmd = substitute(cmd, '^cd ','cd /d ','') " add /d switch to change drives - let cmd = '"'.cmd.'"' " enclose in quotes - endif + let cmd = g:shellesc_cd(cmd) let updates = system(cmd) @@ -72,7 +69,7 @@ func! s:view_changelog() endif call writefile(g:vundle_changelog, g:vundle_changelog_file) - silent pedit `=g:vundle_changelog_file` + execute 'silent pedit ' . g:vundle_changelog_file wincmd P | wincmd H endf @@ -164,7 +161,7 @@ func! s:fetch_scripts(to) let cmd = 'wget -q -O '.temp.' '.l:vim_scripts_json. ' && mv -f '.temp.' '.shellescape(a:to) if (has('win32') || has('win64')) let cmd = substitute(cmd, 'mv -f ', 'move /Y ', '') " change force flag - let cmd = '"'.cmd.'"' " enclose in quotes so && joined cmds work + let cmd = g:shellesc(cmd) end else echoerr 'Error curl or wget is not available!' diff --git a/.vim/bundle/vundle/doc/vundle.txt b/.vim/bundle/vundle/doc/vundle.txt index 57e7260..eb9d82f 100644 --- a/.vim/bundle/vundle/doc/vundle.txt +++ b/.vim/bundle/vundle/doc/vundle.txt @@ -73,6 +73,8 @@ in order to install/search [all available vim scripts] Bundle 'rails.vim' " non github repos Bundle 'git://git.wincent.com/command-t.git' + " git repos on your local machine (ie. when working on your own plugin) + Bundle 'file:///Users/gmarik/path/to/plugin' " ... filetype plugin indent on " required! diff --git a/.zandronum/zandronum.ini b/.zandronum/zandronum.ini index bdf8d87..357f0d2 100644 --- a/.zandronum/zandronum.ini +++ b/.zandronum/zandronum.ini @@ -1,4 +1,4 @@ -# This file was generated by Zandronum 1.0 on Sun Mar 24 12:44:33 2013 +# This file was generated by Zandronum 1.0 on Wed Jun 26 13:14:31 2013 # These are the directories to automatically search for IWADs. # Each directory should be on a separate line, preceded by Path= @@ -113,6 +113,8 @@ sdl_nokeyrepeat=false m_filter=false m_noprescale=false use_mouse=true +gl_vid_allowsoftware=false +gl_vid_multisample=0 bgamma=1 ggamma=1 rgamma=1 @@ -178,10 +180,50 @@ crosshairscale=false crosshairhealth=true crosshaircolor=ff 00 00 crosshair=2 +gl_usearrays=false +gl_texture_hqresize_targets=7 +gl_texture_hqresize_maxinputsize=512 +gl_texture_hqresize=0 +gl_distfog=70 +gl_lights_additive=false +gl_light_ambient=20 +gl_light_particles=true +gl_light_sprites=true +gl_lights_size=1 +gl_lights_intensity=1 +gl_lights_checkside=true +gl_bulletlight=true +gl_attachedlights=true +gl_lights=true vid_contrast=1 vid_brightness=0.3 -gl_nearclip=5 gl_vid_compatibility=false +gl_nogl=false +gl_plane_reflection=true +r_mirror_recursions=4 +gl_blendcolormaps=true +gl_mask_threshold=0.5 +gl_nearclip=5 +gl_no_skyclear=false +gl_glow_shader=false +gl_brightmap_shader=false +gl_colormap_shader=false +gl_fog_shader=false +gl_warp_shader=false +gl_sky_detail=16 +gl_billboard_mode=0 +gl_particles_style=2 +gl_sprite_blend=false +gl_usecolorblending=true +gl_clamp_per_texture=false +gl_texture_format=0 +gl_texture_filter=2 +gl_texture_filter_anisotropic=1 +gl_render_precise=false +gl_fakecontrast=true +gl_seamless=false +gl_render_segs=false +gl_mirror_envmap=true snd_waterlp=250 snd_midipatchset= snd_output_format=PCM-16 @@ -222,47 +264,6 @@ midi_voices=32 midi_config=timidity.cfg [GlobalSettings.Unknown] -gl_mirror_envmap=true -gl_render_segs=false -gl_seamless=false -gl_fakecontrast=true -gl_render_precise=false -gl_texture_filter_anisotropic=1 -gl_texture_filter=2 -gl_texture_format=0 -gl_clamp_per_texture=false -gl_usecolorblending=true -gl_sprite_blend=false -gl_particles_style=2 -gl_billboard_mode=0 -gl_sky_detail=16 -gl_warp_shader=false -gl_fog_shader=false -gl_colormap_shader=false -gl_brightmap_shader=false -gl_glow_shader=false -gl_no_skyclear=false -gl_mask_threshold=0.5 -gl_blendcolormaps=true -r_mirror_recursions=4 -gl_plane_reflection=true -gl_lights=true -gl_attachedlights=true -gl_bulletlight=true -gl_lights_checkside=true -gl_lights_intensity=1 -gl_lights_size=1 -gl_light_sprites=true -gl_light_particles=true -gl_light_ambient=20 -gl_lights_additive=false -gl_distfog=70 -gl_texture_hqresize=0 -gl_texture_hqresize_maxinputsize=512 -gl_texture_hqresize_targets=7 -gl_usearrays=false -gl_vid_multisample=0 -gl_vid_allowsoftware=false [Doom.Player] cl_ticsperupdate=3 @@ -547,7 +548,15 @@ blood_fade_scalar=0.5 cl_identifytarget=true st_scale=true cl_drawcoopinfo=true +gl_lightmode=3 +gl_fogmode=1 +gl_enhanced_nightvision=true +gl_weaponlight=8 +gl_use_models=true +gl_interpolate_model_frames=true +gl_spriteclip=2 gl_precache=true +gl_texture_usehires=true snd_pitched=false [Doom.LocalServerInfo] @@ -560,23 +569,14 @@ sv_corpsequeuesize=64 maxviewpitch=90 [Doom.UnknownConsoleVariables] -maxviewpitch=90 -gl_texture_usehires=true -gl_spriteclip=2 -gl_interpolate_model_frames=true -gl_use_models=true -gl_weaponlight=8 -gl_enhanced_nightvision=true -gl_fogmode=1 -gl_lightmode=3 -samsara_cl_printpickup=0 -samsara_cl_pickupmode=1 -samsara_cl_moremessages=0 -samsara_cl_ballgag=0 -samsara_cl_weaponhud=1 -samsara_cl_vanilladoom=0 -samsara_cl_wolfmove=0 samsara_cl_exists=2601 +samsara_cl_wolfmove=0 +samsara_cl_vanilladoom=0 +samsara_cl_weaponhud=1 +samsara_cl_ballgag=0 +samsara_cl_moremessages=0 +samsara_cl_pickupmode=1 +samsara_cl_printpickup=0 [Doom.ConsoleAliases]