Navigating Ruby Projects in VIM
Effectively navigating Ruby code in VIM
When I made the switch to VIM as my editor/IDE of choice for Ruby projects, the hardest part was learning how to effectively navigate projects that are not my own. It's not really something that comes in the manual. The following is what I use to move around Ruby projects in VIM.
Installing Pathogen, Ctags, NERDTree, Rails.vim, & Taglist
The first step before installing anything else in VIM is to install pathogen.vim.
Next, install and learn how to use ctags. Fortunately this one is in the manual. See ":help ctags." Like most things in Linux/Unix, there are a lot of ways to install ctags. Under Ubuntu I use:
apt-get install exuberant-ctags
There is more on this below.
Finally, install the following VIM plugins through pathogen using the pathogen documentation as a general guide:
- rails.vim - tons of Ruby and Ruby on Rails features
- The NERD Tree - directory browser
- taglist.vim - high level file browser exposing classes, methods, etc...
Navigating Ctags
Ctags generates an index composed of tags (language objects) and their locations in relevant files. When the cursor is on a tag, use one of the commands below to navigate through related locations.
The most important keys are:
- CTRL-] - use the word under the cursor as the tag to search for
- CTRL-T - go back
- :ts - list the tags that match the last search (interactive select)
- :tn - go to the next matching tag
- :tp - go to the previous matching tag
To learn about ctags in VIM, see ":help ctags."
Tag Current Ruby and Ruby Gems
I use the following script to set up tags for both the current version of Ruby and all of the Ruby gems that are relevant to my working environment. It should be rerun after important gem installations. Note that I use rvm and this script does as well. You should be using it too, but if you don't you need to make changes accordingly. The custom configuration in this guide will look to the file generated by this script for definitions inside Ruby Gems and Ruby itself.
1 #! /bin/sh
2 # tags default ruby and associated gems
3
4 SRC="${rvm_path}/rubies/default"
5 echo "SRC: ${SRC}"
6
7 GEMS=`rvm gemdir`/gems
8 echo "GEMS: ${GEMS}"
9
10 DEST=~/.vim/tags/ruby_and_gems
11 echo "DEST: ${DEST}"
12 mkdir -p $(dirname $DEST)
13 rm $DEST
14
15 ctags \
16 --exclude=.git \
17 --exclude=tags \
18 --exclude=logs \
19 --exclude=doc \
20 -R -f $DEST $SRC $GEMS
Custom Configuration
I use the following customizations in .vimrc for navigation:
1 set tags+=./tags
2 set foldlevel=1
3
4 let mapleader=','
5 map <leader>fi :setlocal foldmethod=indent<cr>
6 map <leader>fs :setlocal foldmethod=syntax<cr>
7 map <leader>e :TNERDTreeToggle<CR>
8 map <leader>t :TlistToggle<CR>
9 map <C-F12> :!ctags -R --exclude=.git --exclude=logs --exclude=doc .<CR>
10
11 au BufRead,BufNewFile *.rb setlocal tags+=~/.vim/tags/ruby_and_gems
The above works as follows:
- 1: make the ./tags file available - the local tags generated by control-f12 above
- 2: set the default fold level
- 4: make ',' a control key (like ctrl, shift, super, etc...)
- 5: make ',fi' set the fold method to indent - fold wherever indentation changes
- 6: make ',fs' set the fold method based on language specific syntax
- 7: make ',e' toggle the NERD Tree plugin
- 8: make ',t' toggle the taglist plugin
- 9: make control-f12 tag the current working directory and everything beneath it
- 11: when a ruby file is loaded add all ruby and ruby gems tags to the list of tags that are available/relevant
When you are in a project/folder and you want to use tags that are relevant to that project/folder type "control-f12" (per the configuration above). If you have run the script above, the ruby and gems tags will already be available when in a Ruby file.
Rails.vim
This is probably the most useful plugin that I use in VIM. It does a lot. It's worth reading the help documentation with ":help rails." The features I use most are:
- syntax highlighting
- gf - go to the definition of the thing under the cursor
- :R[model|controller|migration|view] [ident] - go to the thing named [ident].
- :AV - go to the alternate file (often the matching test or spec or the subject of the test).
- :RV - go to the related file (i.e. if in a controller method will go to the related view; this varies by subject)
Folding
Folding is important for getting a high level view of a file. This is another subject where you should really read the help documentation (see ":help folding"). I tend to use the following commands the most:
- zo - open fold
- zc - close fold
- zr - reduce folds
- zm - more folds
You can alter folding behavior for a particular file with the custom configuration above by typing ",fi" or ",fs". Adding folds will do things like reducing methods to signatures, classes and modules to single lines, etc...
NerdTree
Use this plugin to browse projects.
- o - open dir (expand) or file (open)
- s - open file in split view
- normal movement controls (h,j,k,l)
- normal search (/)
- ctrl-^ - go back when in opened file
- ,e - toggle this plugin (per custom configuration above)
Note that after you install this plugin running VIM [directory] on the command line will launch a window to this plugin.
Taglist plugin
This is the closest thing to the classes/methods list that you would find in an IDE. I don't use it very often. I prefer folding instead.
- activate the plugin with ',t' (per custom config above)
- press enter to go to location
- be sure you understand how to move between windows (:help window-move-cursor)
- :help taglist
What? When?
I've presented a lot of options. Which one is relevant to getting where you want to go depends on what you are doing. If you're in a rails project you probably want something that the rails plugin provides. If you're looking to see what files are in a project or gem and to move between them you want NerdTree. If you want to pretend you're in an IDE and hop around between methods in a specific file you want folding or the taglist plugin. If you want to jump to declarations or the use of a method look to the rails plugin or ctags. With great power comes a lot of reading... I found it to be worth the investment.