├── .gitignore ├── after ├── ftplugin │ ├── less │ │ └── rails.vim │ ├── sass │ │ └── rails.vim │ ├── scss │ │ └── rails.vim │ ├── coffee │ │ └── rails.vim │ ├── ruby │ │ └── rails.vim │ ├── css │ │ └── rails.vim │ └── javascript │ │ └── rails.vim └── syntax │ ├── less │ └── rails.vim │ ├── sass │ └── rails.vim │ ├── scss │ └── rails.vim │ ├── coffee │ └── rails.vim │ ├── eruby │ └── rails.vim │ ├── haml │ └── rails.vim │ ├── css │ └── rails.vim │ ├── javascript │ └── rails.vim │ └── ruby │ └── rails.vim ├── .github └── FUNDING.yml ├── CONTRIBUTING.markdown ├── ftplugin └── railslog.vim ├── compiler └── rails.vim ├── syntax └── railslog.vim ├── README.markdown ├── plugin └── rails.vim └── doc └── rails.txt /.gitignore: -------------------------------------------------------------------------------- 1 | /rails.zip 2 | /rails.vba 3 | /doc/tags 4 | -------------------------------------------------------------------------------- /after/ftplugin/less/rails.vim: -------------------------------------------------------------------------------- 1 | source :h:h/css/rails.vim 2 | -------------------------------------------------------------------------------- /after/ftplugin/sass/rails.vim: -------------------------------------------------------------------------------- 1 | source :h:h/scss/rails.vim 2 | -------------------------------------------------------------------------------- /after/ftplugin/scss/rails.vim: -------------------------------------------------------------------------------- 1 | source :h:h/css/rails.vim 2 | -------------------------------------------------------------------------------- /after/syntax/less/rails.vim: -------------------------------------------------------------------------------- 1 | source :h:h/css/rails.vim 2 | -------------------------------------------------------------------------------- /after/syntax/sass/rails.vim: -------------------------------------------------------------------------------- 1 | source :h:h/scss/rails.vim 2 | -------------------------------------------------------------------------------- /after/syntax/scss/rails.vim: -------------------------------------------------------------------------------- 1 | source :h:h/css/rails.vim 2 | -------------------------------------------------------------------------------- /after/syntax/coffee/rails.vim: -------------------------------------------------------------------------------- 1 | source :h:h/javascript/rails.vim 2 | -------------------------------------------------------------------------------- /after/ftplugin/coffee/rails.vim: -------------------------------------------------------------------------------- 1 | source :h:h/javascript/rails.vim 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: tpope 2 | custom: ["https://www.paypal.me/vimpope"] 3 | -------------------------------------------------------------------------------- /after/syntax/eruby/rails.vim: -------------------------------------------------------------------------------- 1 | syn include @rubyTop :h:h/ruby/rails.vim 2 | -------------------------------------------------------------------------------- /after/syntax/haml/rails.vim: -------------------------------------------------------------------------------- 1 | syn include @hamlRubyTop :h:h/ruby/rails.vim 2 | -------------------------------------------------------------------------------- /after/syntax/css/rails.vim: -------------------------------------------------------------------------------- 1 | if expand('%:p') !~# '[\/]\%(app\|lib\|vendor\)[\/]assets[\/]' 2 | finish 3 | endif 4 | 5 | call rails#sprockets_syntax() 6 | -------------------------------------------------------------------------------- /after/syntax/javascript/rails.vim: -------------------------------------------------------------------------------- 1 | if expand('%:p') !~# '[\/]\%(app\|lib\|vendor\)[\/]assets[\/]' 2 | finish 3 | endif 4 | 5 | call rails#sprockets_syntax() 6 | -------------------------------------------------------------------------------- /after/ftplugin/ruby/rails.vim: -------------------------------------------------------------------------------- 1 | if (!exists('*RailsDetect') || !RailsDetect()) && expand('%:p') !~# '.*\ze[\/]\%(app\|config\|lib\|test\|spec\)[\/]' 2 | finish 3 | endif 4 | 5 | try 6 | call rails#ruby_setup() 7 | catch /^Vim\%((\a\+)\)\=:E117:.*rails#ruby_setup/ 8 | endtry 9 | -------------------------------------------------------------------------------- /after/ftplugin/css/rails.vim: -------------------------------------------------------------------------------- 1 | try 2 | if expand('%:p') =~# '[\/]assets[\/]' 3 | call rails#sprockets_setup('css') 4 | endif 5 | if expand('%:p') =~# '[\/]javascript[\/]packs[\/]' 6 | call rails#webpacker_setup('css') 7 | endif 8 | catch /^Vim\%((\a\+)\)\=:E117:/ 9 | endtry 10 | -------------------------------------------------------------------------------- /after/ftplugin/javascript/rails.vim: -------------------------------------------------------------------------------- 1 | try 2 | if expand('%:p') =~# '[\/]assets[\/]' 3 | call rails#sprockets_setup('js') 4 | endif 5 | if expand('%:p') =~# '[\/]javascript[\/]packs[\/]' 6 | call rails#webpacker_setup('js') 7 | endif 8 | catch /^Vim\%((\a\+)\)\=:E117:/ 9 | endtry 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.markdown: -------------------------------------------------------------------------------- 1 | If your [commit message sucks][suck], I'm not going to accept your pull 2 | request. I've explained very politely dozens of times that [my general 3 | guidelines][guidelines] are absolute rules on my own repositories, so I may 4 | lack the energy to explain it to you yet another time. And please, if I ask 5 | you to change something, `git commit --amend` and `git push -f`. 6 | 7 | If a feature idea is nontrivial, you should probably open an issue to [discuss 8 | it][] before attempting a pull request. One of the biggest challenges in 9 | maintaining rails.vim has been beating back the bloat, so do not assume that 10 | your idea will make the cut. And if I like your idea, I'm generally amenable 11 | to just knocking it out myself, rather than making you familiarize yourself 12 | with a 4 thousand line code base. 13 | 14 | [suck]: http://stopwritingramblingcommitmessages.com/ 15 | [guidelines]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html 16 | [discuss it]: http://www.igvita.com/2011/12/19/dont-push-your-pull-requests/ 17 | -------------------------------------------------------------------------------- /ftplugin/railslog.vim: -------------------------------------------------------------------------------- 1 | if exists('b:did_ftplugin') 2 | finish 3 | endif 4 | let b:did_ftplugin = 1 5 | 6 | function! s:reload_log() abort 7 | if &buftype == 'quickfix' && get(w:, 'quickfix_title') =~ '^:cgetfile' 8 | let cmd = 'cgetfile ' . 9 | \ (exists('*fnameescape') ? fnameescape(w:quickfix_title[10:-1]) : w:quickfix_title[10:-1]) . 10 | \ "|call setpos('.', " . string(getpos('.')) . ")" 11 | else 12 | let cmd = 'checktime' 13 | endif 14 | return cmd . "|if &l:filetype !=# 'railslog'|setfiletype railslog|endif" 15 | endfunction 16 | 17 | if exists('w:quickfix_title') 18 | runtime! ftplugin/qf.vim ftplugin/qf_*.vim ftplugin/qf/*.vim 19 | endif 20 | let b:undo_ftplugin = get(b:, 'undo_ftplugin', 'exe') 21 | nnoremap R :exe reload_log() 22 | nnoremap G :exe reload_log()exe v:count ? v:count : '$' 23 | nnoremap q :bwipe 24 | let b:undo_ftplugin .= '|sil! nunmap R|sil! nunmap G|sil! nunmap q' 25 | setlocal noswapfile autoread 26 | let b:undo_ftplugin .= '|set swapfile< autoread<' 27 | if exists('+concealcursor') 28 | setlocal concealcursor=nc conceallevel=2 29 | let b:undo_ftplugin .= ' concealcursor< conceallevel<' 30 | else 31 | let s:pos = getpos('.') 32 | setlocal modifiable 33 | silent exe '%s/\m\C\%(\e\[[0-9;]*m\|\r$\)//e' . (&gdefault ? '' : 'g') 34 | call setpos('.', s:pos) 35 | endif 36 | setlocal readonly nomodifiable 37 | let b:undo_ftplugin .= ' noreadonly modifiable' 38 | -------------------------------------------------------------------------------- /compiler/rails.vim: -------------------------------------------------------------------------------- 1 | " Vim compiler file 2 | 3 | if exists("current_compiler") 4 | finish 5 | endif 6 | 7 | CompilerSet errorformat=%D(in\ %f), 8 | \%\\s%#from\ %f:%l:%m, 9 | \%\\s%#from\ %f:%l:, 10 | \%\\s%##\ %f:%l:%m, 11 | \%\\s%##\ %f:%l, 12 | \%\\s%#[%f:%l:\ %#%m, 13 | \%\\s%#%f:%l:\ %#%m, 14 | \%\\s%#%f:%l:, 15 | \%m\ [%f:%l]:, 16 | \%+Erake\ aborted!, 17 | \%+EDon't\ know\ how\ to\ build\ task\ %.%#, 18 | \%+Einvalid\ option:%.%#, 19 | \%+Irake\ %\\S%\\+%\\s%\\+#\ %.%# 20 | 21 | runtime! compiler/rake.vim 22 | 23 | let current_compiler = "rails" 24 | 25 | CompilerSet makeprg=rails 26 | " CompilerSet makeprg=ruby\ bin/rails 27 | " CompilerSet makeprg=ruby\ script/rails 28 | 29 | CompilerSet errorformat^= 30 | \%\\S%\\+\ \ %#%[cefi]%[rxod]%[eir]%[a-z]%#%\\x1b[0m\ %\\+%\\S%\\+%$ 31 | \%\\&%\\x1b%\\S%\\+\ \ %#%m%\\>%\\x1b[0m\ \ %#%f, 32 | \%\\s\ %#%[cefi]%[rxod]%[eir]%[a-z]%#\ %\\+%\\S%\\+%$ 33 | \%\\&%\\s\ %#%m%\\>\ \ %#%f, 34 | \\ %#Overwrite%.%#%\\S%\\+\ \ %#%m%\\x1b[0m\ \ %#%f, 35 | \%-G\ %#Overwrite%.%#\"h\"%.%#, 36 | \%+GStarted\ %\\u%\\u%.%#, 37 | \%+GCompleted\ %\\d%\\d%\\d%.%#, 38 | \%+G[ActiveJob]%.%#]\ Perform%.%#, 39 | \%.%#rails\ test\ %f:%l, 40 | \%+GCurrent\ version:%.%#, 41 | \%+G\ %#Status\ %#Migration\ ID%.%#, 42 | \%+G\ The\ fixture\ ID\ for\ %.%#, 43 | \%f:\ %s\ (%m)%$ 44 | \%\\&%.%#/fixtures/%.%#(%\\d%\\+), 45 | \%+G\ %#Prefix\ %#Verb%.%#, 46 | \%+G\ %#Code\ LOC:\ %.%#, 47 | \%+GAbout\ your\ application's\ environment, 48 | \%+Grun\ %\\S%#::Application.routes, 49 | \%+Irails\ %\\S%\\+%\\s%\\+#\ %.%#, 50 | \%+Eruby:%.%#(LoadError), 51 | \%+EUsage:%.%#, 52 | \%+ECould\ not\ find\ generator%.%#, 53 | \%+EType\ 'rails'\ for\ help., 54 | \%\\&completion=rails#complete_rails, 55 | \%\\&start=console, 56 | \%\\&terminal=%\\C%\\%%(console%\\\|dbconsole%\\\|server%\\\|%[cs]%\\\|db%\\)%\\>:%\\@!%\\ze%.%#, 57 | \%\\&force_start=%\\C%\\%%(console%\\\|dbconsole%\\\|server%\\\|%[cs]%\\\|db%\\)%\\>:%\\@!%\\ze%.%#, 58 | \%\\&default=default 59 | 60 | " -complete=customlist,rails#complete_rails 61 | -------------------------------------------------------------------------------- /syntax/railslog.vim: -------------------------------------------------------------------------------- 1 | if exists('b:current_syntax') 2 | finish 3 | endif 4 | 5 | if has('conceal') 6 | syn match railslogEscape '\e\[[0-9;]*m' conceal 7 | syn match railslogEscapeMN '\e\[[0-9;]*m' conceal nextgroup=railslogModelNum,railslogEscapeMN skipwhite contained 8 | else 9 | syn match railslogEscape '\e\[[0-9;]*m' 10 | syn match railslogEscapeMN '\e\[[0-9;]*m' nextgroup=railslogModelNum,railslogEscapeMN skipwhite contained 11 | endif 12 | syn match railslogQfFileName "^[^()|]*|\@=" nextgroup=railslogQfSeparator 13 | syn match railslogQfSeparator "|" nextgroup=railslogQfLineNr contained 14 | syn match railslogQfLineNr "[^|]*" contained contains=railslogQfError 15 | syn match railslogQfError "error" contained 16 | syn match railslogRender '\%(\%(^\||\)\s*\%(\e\[[0-9;]*m\)\=\)\@<=\%(Started\|Processing\|Rendering\|Rendered\|Redirected\|Completed\)\>' 17 | syn match railslogComment '\%(^\|[]|]\)\@<=\s*# .*' 18 | syn match railslogModel '\%(\%(^\|[]|]\)\s*\%(\e\[[0-9;]*m\)*\)\@<=\%(CACHE SQL\|CACHE\|SQL\)\>' skipwhite nextgroup=railslogModelNum,railslogEscapeMN 19 | syn match railslogModel '\%(\%(^\|[]|]\)\s*\%(\e\[[0-9;]*m\)*\)\@<=\%(CACHE \)\=\u\%(\w\|:\)* \%(Load\%( Including Associations\| IDs For Limited Eager Loading\)\=\|Columns\|Exists\|Count\|Create\|Update\|Destroy\|Delete all\)\>' skipwhite nextgroup=railslogModelNum,railslogEscapeMN 20 | syn region railslogModelNum start='(' end=')' contains=railslogNumber contained skipwhite 21 | syn match railslogActiveJob '\[ActiveJob\]'hs=s+1,he=e-1 nextgroup=railslogJobScope skipwhite 22 | syn match railslogJobScope '\[\u\%(\w\|:\)*\]' contains=railslogJobName contained 23 | syn match railslogJob '\%(\%(^\|[\]|]\)\s*\%(\e\[[0-9;]*m\)*\)\@<=\%(Enqueued\|Performing\|Performed\)\>' skipwhite nextgroup=railslogJobName 24 | syn match railslogJobName '\<\u\%(\w\|:\)*\>' contained 25 | syn match railslogNumber '\<\d\+%' 26 | syn match railslogNumber '[ (]\@<=\<\d\+\.\d\+\>\.\@!' 27 | syn match railslogNumber '[ (]\@<=\<\d\+\%(\.\d\+\)\=ms\>' 28 | syn region railslogString start='"' skip='\\"' end='"' oneline contained 29 | syn region railslogHash start='{' end='}' oneline contains=railslogHash,railslogString 30 | syn match railslogIP '\<\d\{1,3\}\%(\.\d\{1,3}\)\{3\}\>' 31 | syn match railslogIP '\<\%(\x\{1,4}:\)\+\%(:\x\{1,4}\)\+\>\|\S\@\|\<\%(\x\{1,4}:\)\+\%(:\S\@!\|\x\{1,4}\>\)' 32 | syn match railslogTimestamp '\<\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\%( [+-]\d\d\d\d\| UTC\)\=\>' 33 | syn match railslogSessionID '\<\x\{32\}\>' 34 | syn match railslogUUID '\<\x\{8\}-\x\{4\}-\x\{4\}-\x\{4\}-\x\{12\}\>' 35 | syn match railslogIdentifier '\%(^\||\)\@<=\s*\%(Session ID\|Parameters\|Unpermitted parameters\)\ze:' 36 | syn match railslogSuccess '\<2\d\d\%( \u\w*\)\+\>' 37 | syn match railslogRedirect '\<3\d\d\%( \u\w*\)\+\>' 38 | syn match railslogError '\<[45]\d\d\%( \u\w*\)\+\>' 39 | syn match railslogDeprecation '\' 40 | syn keyword railslogHTTP OPTIONS GET HEAD POST PUT PATCH DELETE TRACE CONNECT 41 | 42 | hi def link railslogQfFileName Directory 43 | hi def link railslogQfLineNr LineNr 44 | hi def link railslogQfError Error 45 | hi def link railslogEscapeMN railslogEscape 46 | hi def link railslogEscape Ignore 47 | hi def link railslogComment Comment 48 | hi def link railslogRender Keyword 49 | hi def link railslogModel Type 50 | hi def link railslogJob Repeat 51 | hi def link railslogJobName Structure 52 | hi def link railslogNumber Float 53 | hi def link railslogString String 54 | hi def link railslogSessionID Constant 55 | hi def link railslogUUID Constant 56 | hi def link railslogIdentifier Identifier 57 | hi def link railslogRedirect railslogSuccess 58 | hi def link railslogSuccess Special 59 | hi def link railslogDeprecation railslogError 60 | hi def link railslogError Error 61 | hi def link railslogHTTP Special 62 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # rails.vim 2 | 3 | This is a massive (in a good way) Vim plugin for editing Ruby on Rails 4 | applications. 5 | 6 | * Easy navigation of the Rails directory structure. `gf` considers 7 | context and knows about partials, fixtures, and much more. There are 8 | two commands, `:A` (alternate) and `:R` (related) for easy jumping 9 | between files, including favorites like model to schema, template to 10 | helper, and controller to functional test. Commands like `:Emodel`, 11 | `:Eview`, `:Econtroller`, are provided to `:edit` files by type, along 12 | with `S`, `V`, and `T` variants for `:split`, `:vsplit`, and 13 | `:tabedit`. Throw a bang on the end (`:Emodel foo!`) to automatically 14 | create the file with the standard boilerplate if it doesn't exist. 15 | `:help rails-navigation` 16 | 17 | * Enhanced syntax highlighting. From `has_and_belongs_to_many` to 18 | `distance_of_time_in_words`, it's here. 19 | 20 | * Interface to the `rails` command. Generally, use `:Rails console` to 21 | call `rails console`. Many commands have wrappers with additional features: 22 | `:Generate controller Blog` generates a blog controller and loads the 23 | generated files into the quickfix list, and `:Runner` wraps `rails runner` 24 | and doubles as a direct test runner. `:help rails-exec` 25 | 26 | * Default task runner. Use `:Rails` (with no arguments) to run the current 27 | test, spec, or feature. Use `:.Rails` to do a focused run of just the 28 | method, example, or scenario on the current line. `:Rails` can also run 29 | arbitrary migrations, load individual fixtures, and more. 30 | `:help rails-default-task` 31 | 32 | * Partial and concern extraction. In a view, `:Extract {file}` 33 | replaces the desired range (typically selected in visual line mode) 34 | with `render '{file}'`, which is automatically created with your 35 | content. In a model or controller, a concern is created, with the 36 | appropriate `include` declaration left behind. 37 | `:help rails-:Extract` 38 | 39 | * Fully customizable. Define "projections" at the global, app, or gem 40 | level to define navigation commands and override the alternate file, 41 | default rake task, syntax highlighting, and more. 42 | `:help rails-projections`. 43 | 44 | * Integration with other plugins. If [dispatch.vim][] is installed, `:Rails` 45 | and other command wrappers will use it for asynchronous execution. Users of 46 | [dadbod.vim](https://github.com/tpope/vim-dadbod) and 47 | [dbext](http://www.vim.org/script.php?script_id=356) get easy access to 48 | their application's database. Users of 49 | [abolish.vim](https://github.com/tpope/vim-abolish) get pluralize and 50 | tableize coercions, and users of [bundler.vim][] get a smattering of 51 | features. `:help rails-integration` 52 | 53 | ## Installation 54 | 55 | If you don't have a preferred installation method, I recommend 56 | installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and 57 | then simply copy and paste: 58 | 59 | cd ~/.vim/bundle 60 | git clone https://github.com/tpope/vim-rails.git 61 | vim -u NONE -c "helptags vim-rails/doc" -c q 62 | 63 | While not strictly necessary, [bundler.vim][] and [dispatch.vim][] are highly 64 | recommended. 65 | 66 | [bundler.vim]: https://github.com/tpope/vim-bundler 67 | [dispatch.vim]: https://github.com/tpope/vim-dispatch 68 | 69 | ## FAQ 70 | 71 | > I installed the plugin and started Vim. Why does only the `:Rails` 72 | > command exist? 73 | 74 | This plugin cares about the current file, not the current working 75 | directory. Edit a file from a Rails application. 76 | 77 | > I opened a new tab. Why does only the `:Rails` command exist? 78 | 79 | This plugin cares about the current file, not the current working directory. 80 | Edit a file from a Rails application. You can use `:AT` and the `:T` family 81 | of commands to open a new tab and edit a file at the same time. 82 | 83 | > Can I use rails.vim to edit Rails engines? 84 | 85 | It's not supported, but if you `touch config/environment.rb` in the root 86 | of the engine, things should mostly work. 87 | 88 | > Can I use rails.vim to edit other Ruby projects? 89 | 90 | I wrote [rake.vim](https://github.com/tpope/vim-rake) for exactly that 91 | purpose. It activates for any project with a `Rakefile` that's not a 92 | Rails application. 93 | 94 | > What Rails versions are supported? 95 | 96 | All of them, although you may notice a few minor breakages if you dip below 97 | 3.0. A few features like syntax highlighting tend to reflect the latest 98 | version only. 99 | 100 | > Didn't rails.vim used to handle indent settings? 101 | 102 | It got yanked after increasing contention over JavaScript. Check out 103 | [sleuth.vim](https://github.com/tpope/vim-sleuth). 104 | 105 | ## Self-Promotion 106 | 107 | Like rails.vim? Follow the repository on 108 | [GitHub](https://github.com/tpope/vim-rails) and vote for it on 109 | [vim.org](http://www.vim.org/scripts/script.php?script_id=1567). And if 110 | you're feeling especially charitable, follow [tpope](http://tpo.pe/) on 111 | [Twitter](http://twitter.com/tpope) and 112 | [GitHub](https://github.com/tpope). 113 | 114 | ## License 115 | 116 | Copyright (c) Tim Pope. Distributed under the same terms as Vim itself. 117 | See `:help license`. 118 | -------------------------------------------------------------------------------- /plugin/rails.vim: -------------------------------------------------------------------------------- 1 | " rails.vim - Detect a rails application 2 | " Author: Tim Pope 3 | " GetLatestVimScripts: 1567 1 :AutoInstall: rails.vim 4 | 5 | " Install this file as plugin/rails.vim. 6 | 7 | if exists('g:loaded_rails') || &cp || v:version < 800 8 | finish 9 | endif 10 | let g:loaded_rails = 1 11 | 12 | " Utility Functions {{{1 13 | 14 | function! s:error(str) 15 | echohl ErrorMsg 16 | echomsg a:str 17 | echohl None 18 | let v:errmsg = a:str 19 | endfunction 20 | 21 | let s:slash = exists('+shellslash') ? '\' : '/' 22 | function! s:IsAbs(path) abort 23 | return tr(a:path, s:slash, '/') =~# '^/\|^\a\+:' 24 | endfunction 25 | 26 | " }}}1 27 | " Detection {{{1 28 | 29 | function! RailsDetect(...) abort 30 | if exists('b:rails_root') 31 | return 1 32 | endif 33 | if a:0 34 | let path = a:1 35 | elseif &l:buftype =~# '^\%(nowrite\)\=$' && len(@%) || &l:buftype =~# '^\%(nofile\|acwrite\)' && s:IsAbs(@%) 36 | let path = @% 37 | else 38 | return 39 | endif 40 | if !s:IsAbs(path) 41 | let s = exists('+shellslash') && !&shellslash ? '\' : '/' 42 | let path = substitute(getcwd(), '\' . s . '\=$', s, '') . path 43 | endif 44 | let path = substitute(path, '[' . s:slash . '/]$', '', '') 45 | try 46 | if exists('*ExcludeBufferFromDiscovery') && ExcludeBufferFromDiscovery(file, 'projectionist') 47 | return 48 | endif 49 | catch 50 | endtry 51 | 52 | if exists('*ProjectionistHas') 53 | let previous = '' 54 | while path !=# previous && path !~# '^\.\=$\|^[\/][\/][^\/]*$' 55 | if ProjectionistHas('config/environment.rb&app/', path) 56 | let b:rails_root = path 57 | return 1 58 | endif 59 | let previous = path 60 | let path = fnamemodify(path, ':h') 61 | endwhile 62 | return 0 63 | endif 64 | let file = findfile('config/environment.rb', escape(path, ', ').';') 65 | if !empty(file) && isdirectory(fnamemodify(file, ':p:h:h') . '/app') 66 | let b:rails_root = fnamemodify(file, ':p:h:h') 67 | return 1 68 | endif 69 | endfunction 70 | 71 | function! s:LogDetect() abort 72 | let path = matchstr(get(w:, 'quickfix_title'), '\")) && RailsDetect(getcwd()) | 110 | \ call rails#buffer_setup() | 111 | \ call s:doau_user('BufEnterRails') | 112 | \ endif 113 | autocmd FileType netrw 114 | \ if RailsDetect(get(b:, 'netrw_curdir', @%)) | 115 | \ call s:doau_user('BufEnterRails') | 116 | \ endif 117 | autocmd FileType * if RailsDetect() | call rails#buffer_setup() | endif 118 | 119 | autocmd BufNewFile,BufReadPost */config/*.yml{,.example,.sample},*/{test,spec}/fixtures/*.yml 120 | \ if &filetype !=# 'eruby.yaml' && RailsDetect() | 121 | \ set filetype=eruby.yaml | 122 | \ endif 123 | autocmd BufNewFile,BufReadPost *.rjs,*.rxml,*.builder,*.jbuilder,*.ruby 124 | \ if &filetype !=# 'ruby' | set filetype=ruby | endif 125 | autocmd BufNewFile,BufReadPost *.turbo_stream.erb 126 | \ if &filetype !=# 'eruby.html' | set filetype=eruby.html | endif 127 | autocmd BufReadPost *.log if RailsDetect() | set filetype=railslog | endif 128 | 129 | autocmd FileType qf call s:LogDetect() 130 | 131 | autocmd User ProjectionistDetect 132 | \ if RailsDetect(get(g:, 'projectionist_file', '')) | 133 | \ call projectionist#append(b:rails_root, 134 | \ {'*': {"console": rails#app().static_rails_command('console')}}) | 135 | \ endif 136 | augroup END 137 | 138 | command! -bang -bar -nargs=* -range=-1 -complete=customlist,rails#complete_rails Rails execute rails#command(0, '', , ) 139 | 140 | " }}}1 141 | " dadbod.vim support {{{1 142 | 143 | call extend(g:, {'db_adapters': {}}, 'keep') 144 | call extend(g:db_adapters, { 145 | \ 'oracle-enhanced': 'oracle', 146 | \ 'mysql2': 'mysql', 147 | \ 'sqlite3': 'sqlite'}, 'keep') 148 | 149 | let g:db_adapter_rails = 'rails#db_' 150 | 151 | " }}}1 152 | " abolish.vim support {{{1 153 | 154 | function! s:function(name) 155 | return function(substitute(a:name,'^s:',matchstr(expand(''), '\d\+_'),'')) 156 | endfunction 157 | 158 | augroup railsPluginAbolish 159 | autocmd! 160 | autocmd VimEnter * call s:abolish_setup() 161 | augroup END 162 | 163 | function! s:abolish_setup() 164 | if exists('g:Abolish') && has_key(g:Abolish,'Coercions') 165 | if !has_key(g:Abolish.Coercions,'l') 166 | let g:Abolish.Coercions.l = s:function('s:abolish_l') 167 | endif 168 | if !has_key(g:Abolish.Coercions,'t') 169 | let g:Abolish.Coercions.t = s:function('s:abolish_t') 170 | endif 171 | endif 172 | endfunction 173 | 174 | function! s:abolish_l(word) 175 | let singular = rails#singularize(a:word) 176 | return a:word ==? singular ? rails#pluralize(a:word) : singular 177 | endfunction 178 | 179 | function! s:abolish_t(word) 180 | if a:word =~# '\u' 181 | return rails#pluralize(rails#underscore(a:word)) 182 | else 183 | return rails#singularize(rails#camelize(a:word)) 184 | endif 185 | endfunction 186 | 187 | " }}}1 188 | " vim:set sw=2 sts=2: 189 | -------------------------------------------------------------------------------- /after/syntax/ruby/rails.vim: -------------------------------------------------------------------------------- 1 | hi def link rubyEntity rubyMacro 2 | hi def link rubyEntities rubyMacro 3 | hi def link rubyExceptionMacro rubyMacro 4 | hi def link rubyValidation rubyMacro 5 | hi def link rubyCallback rubyMacro 6 | hi def link rubyRakeMacro rubyMacro 7 | hi def link rubyTestMacro rubyMacro 8 | hi def link rubyMacro Macro 9 | hi def link rubyRoute rubyControl 10 | hi def link rubySchema rubyControl 11 | hi def link rubyResponse rubyControl 12 | hi def link rubyAction rubyControl 13 | hi def link rubyUrlHelper rubyHelper 14 | hi def link rubyViewHelper rubyHelper 15 | hi def link rubyTestHelper rubyHelper 16 | hi def link rubyUserAssertion rubyAssertion 17 | hi def link rubyAssertion rubyException 18 | hi def link rubyTestAction rubyControl 19 | hi def link rubyHelper Function 20 | hi def link rubyDebug Debug 21 | 22 | let s:has_app = exists('*RailsDetect') && RailsDetect() 23 | if s:has_app 24 | let s:path = '/' . rails#buffer().relative() 25 | else 26 | let s:path = tr(expand('%:p'), '\', '/') 27 | endif 28 | 29 | if s:path =~# '\v/app/%(channels|controllers|helpers|jobs|mailers|models)/.*\.rb$|/app/views/' 30 | syn match rubyHelper '\v<%(logger)>[!?:]@!' 31 | endif 32 | 33 | if s:path =~# '/app/models/.*_observer\.rb$' 34 | syn match rubyMacro '\v<%(observe)>[!?:]@!' 35 | 36 | elseif s:path =~# '/app/models/.*\.rb$' 37 | syn match rubyMacro '\v<%(accepts_nested_attributes_for|attr_readonly|attribute|enum|serialize|store|store_accessor)>[!?:]@!' 38 | syn match rubyMacro '\v<%(default_scope|scope)>[!?:]@!' 39 | syn match rubyEntity '\v<%(belongs_to|has_one|composed_of)>[!?:]@!' 40 | syn match rubyEntities '\v<%(has_many|has_and_belongs_to_many)>[!?:]@!' 41 | syn match rubyCallback '\v<%(before_validation|after_validation)>[!?:]@!' 42 | syn match rubyCallback '\v<%(before_create|before_destroy|before_save|before_update)>[!?:]@!' 43 | syn match rubyCallback '\v<%(after_create|after_destroy|after_save|after_update)>[!?:]@!' 44 | syn match rubyCallback '\v<%(around_create|around_destroy|around_save|around_update)>[!?:]@!' 45 | syn match rubyCallback '\v<%(after_commit|after_create_commit|after_update_commit|after_save_commit|after_destroy_commit|after_rollback)>[!?:]@!' 46 | syn match rubyCallback '\v<%(after_find|after_initialize|after_touch)>[!?:]@!' 47 | syn match rubyValidation '\v<%(validates|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_absence_of|validates_size_of|validates_with)>[!?:]@!' 48 | syn match rubyValidation '\v<%(validates_associated|validates_uniqueness_of)>[!?:]@!' 49 | syn match rubyMacro '\v<%(validate|has_rich_text|has_secure_password|has_secure_token|has_one_attached|has_many_attached|delegated_type)>[!?:]@!' 50 | endif 51 | 52 | if s:path =~# '/app/jobs/.*\.rb$' 53 | syn match rubyMacro '\v<%(queue_as)>[!?:]@!' 54 | syn match rubyExceptionMacro '\v<%(rescue_from|retry_on|discard_on)>[!?:]@!' 55 | syn match rubyCallback '\v<%(before_enqueue|around_enqueue|after_enqueue|before_perform|around_perform|after_perform)>[!?:]@!' 56 | endif 57 | 58 | if s:path =~# '/app/helpers/.*_helper\.rb$\|/app/views/' 59 | let s:autogenerated_helpers = ' 60 | \ action_name asset_path asset_url atom_feed audio_path audio_tag audio_url auto_discovery_link_tag 61 | \ button_tag button_to 62 | \ cache cache_fragment_name cache_if cache_unless caching? capture cdata_section check_box check_box_tag class_names 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_for? content_tag controller controller_name controller_path convert_to_model cookies csp_meta_tag csrf_meta_tag csrf_meta_tags current_cycle current_page? cycle 63 | \ 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 dom_class dom_id 64 | \ email_field email_field_tag escape_javascript escape_once excerpt 65 | \ favicon_link_tag field_id field_name field_set_tag fields fields_for file_field file_field_tag flash font_path font_url form_for form_tag form_with 66 | \ grouped_collection_select grouped_options_for_select 67 | \ headers hidden_field hidden_field_tag highlight 68 | \ image_path image_submit_tag image_tag image_url 69 | \ j javascript_cdata_section javascript_include_tag javascript_path javascript_tag javascript_url 70 | \ l label label_tag link_to link_to_if link_to_unless link_to_unless_current localize 71 | \ mail_to month_field month_field_tag 72 | \ 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 73 | \ option_groups_from_collection_for_select options_for_select options_from_collection_for_select 74 | \ 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 phone_to pluralize preload_link_tag provide public_compute_asset_path 75 | \ radio_button radio_button_tag range_field range_field_tag raw render request request_forgery_protection_token reset_cycle response 76 | \ safe_concat safe_join sanitize sanitize_css search_field search_field_tag select_date select_datetime select_day select_hour select_minute select_month select_second select_tag select_time select_year session simple_format sms_to strip_links strip_tags stylesheet_link_tag stylesheet_path stylesheet_url submit_tag 77 | \ 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 to_sentence token_list translate truncate 78 | \ uncacheable! 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 79 | \ video_path video_tag video_url 80 | \ week_field week_field_tag weekday_options_for_select weekday_select word_wrap 81 | \'[1:-1] 82 | exe 'syn match rubyViewHelper "\v<%(' . escape(tr(s:autogenerated_helpers, ' ', '|'), '?') . ')[[:keyword:]!?:]@!"' 83 | syn match rubyViewHelper '\v