VimRubySupport

Josh Greenwood edited this page Apr 28, 2016 · 19 revisions

Introduction

NOTE: The latest version of these runtime files for Vim can be found packaged together as part of the the Vim-Ruby Configuration Files project

If you install Vim 7.x, the following Ruby support is enabled out of the box:

  • syntax highlighting for Ruby and eRuby
  • automatic, smart indenting for Ruby and eRuby
  • compiler plugins for running Ruby, eRuby, Test::Unit and RSpec files
  • IntelliSense-like autocompletion (when compiled with the Ruby interface)

These files are maintained by @segfault, @dkearns, @tpope, @AndrewRadev, and @now.

The purpose of this article is to describe what these features are, how they work, and how you can add other Ruby features. The target readership is those who use Ruby and Vim, but are not sure how to get the most out of the combination.

Special files that come with Vim

When you install Vim 7.3 (please don’t use 6.x if you can help it!), the following important files are created ($VIMRUNTIME is the directory where the Vim runtime files are installed, like /usr/share/vim/vim70 or C:\Program Files\vim\vim70):

  • $VIMRUNTIME/autoload/rubycomplete.vim
  • $VIMRUNTIME/compiler/eruby.vim
  • $VIMRUNTIME/compiler/rspec.vim
  • $VIMRUNTIME/compiler/rubyunit.vim
  • $VIMRUNTIME/compiler/ruby.vim
  • $VIMRUNTIME/ftdetect/ruby.vim
  • $VIMRUNTIME/ftplugin/eruby.vim
  • $VIMRUNTIME/ftplugin/ruby.vim
  • $VIMRUNTIME/indent/eruby.vim
  • $VIMRUNTIME/indent/ruby.vim
  • $VIMRUNTIME/syntax/eruby.vim
  • $VIMRUNTIME/syntax/ruby.vim

Since Vim 6.x, a lot of configuration and extensions have been placed in plugins. For instance, from VimOnline you can download plugins for a calendar or tetris. These are global plugins. The files we are concerned with are filetype-specific plugins.

Filetypes

The notion of filetype is central to Vim. When you load a file, Vim decides (based on either the filename extension or the file contents) the type of file you are editing. It then loads the specific runtime files for that filetype, in order to highlight it, indent it, and apply whatever other settings are deemed appropriate for files of that type.

Files with either a filename extension of .rb or a ruby shebang line (#!/usr/bin/ruby) will be set to filetype “ruby” and files with a filename extension of .rhtml will be set to filetype “eruby”.

Filetype Plugins

The filetype plugin files (ftplugin/*) are a place for miscellaneous configuration when editing Ruby and eRuby code: mappings, options, matchit configuration etc.

See :help matchit-activate for an explanation of how to enable the matchit global plugin. There is also a summary at the end of the ftplugin/ruby.vim file.

Syntax Files

The syntax files contain instructions for Vim to highlight Ruby and eRuby code.

See :help ft-ruby-syntax for more details, including configuration options.

Indent Files

The indent files contain instructions for Vim to automatically indent Ruby and eRuby code.

Compiler Plugins

The compiler plugins contain instructions which allow Vim to run the specified source file with an appropriate executable, parse any errors, and jump to the corresponding error location if required.

  • the ruby compiler will run the specified Ruby file with ruby
  • the eruby compiler will run the specified eRuby file with eruby
  • the rubyunit compiler will run the specified Test::Unit file with testrb

To set a compiler, you can put the following line in your own ftplugin extension (for example, ~/.vim/ftplugin/ruby_custom.vim):

compiler ruby

If you prefer to set it from your .vimrc, you can use this instead:

autocmd FileType ruby compiler ruby

Omni Completion Functions

The omni completion function (autoload/rubycomplete.vim) file offers context sensitive (IntelliSense-like) completion similar to that available in irb.

NOTE: This functionality is new for Vim 7 and requires a version of Vim compiled with the Ruby interface – see :help ruby

IMPORTANT: There is a bug in the Ruby interface for Vim 7.3 on Windows that can cause Vim to crash. This was fixed in version 7.3.088.

To activate the completion menu type CTRL-X CTRL-O while in insert mode.

See :help ft-ruby-omni and :help i_CTRL-X_CTRL-O for more details.

Installing the latest version

While these files are included as part of the standard Vim distribution they tend to be updated more frequently than Vim itself. To install the latest version, your favorite method works. Here are some options.

With pathogen.vim

Install pathogen.vim, then copy and paste:

git clone git://github.com/vim-ruby/vim-ruby.git ~/.vim/bundle/vim-ruby

With Vundle

Install Vundle, then add the following to your vimrc:

Bundle 'vim-ruby/vim-ruby'

Manually

Download an archive and extract the relevant files to ~/.vim (or $HOME/vimfiles on Windows).

Enabling Ruby Extensions

Unfortunately, although Vim has all this power, it is not enabled by default, primarily for “backward compatibility”, I suppose. So make sure these lines are contained within your $HOME/.vimrc file:


set nocompatible      " We're running Vim, not Vi!
syntax on             " Enable syntax highlighting
filetype on           " Enable filetype detection
filetype indent on    " Enable filetype-specific indenting
filetype plugin on    " Enable filetype-specific plugins

filetype plugin indent on can replace the filetype statements above (see :h :filetype-overview) – felixhummel

Verifying Installation

You should verify that your installation of vim-ruby is correct.

A simple way to do this in Vim 7, which will test that the syntax, filetype, indent and omni completion scripts are working properly, is to:

1. Open a new Ruby source file. This file should have either a filename extension of ‘.rb’ or the appropriate shebang line (eg. #!/usr/bin/ruby)

2. Edit the buffer and insert the string:


1.upto(5) do |i| puts "#{i}. Infinity, the star that would not die" end

The fragment should be highlighted and automatically indented as you type.

3. Add the ‘dot’ operator after the string and while in insert mode type CTRL-X CTRL-O:


        puts "#{i}. Infinity, the star that would not die".<CTRL-X><CTRL-O>

A list of string methods should be offered in a pop-up window. You can navigate this list with CTRL-N and CTRL-P and use CTRL-Y to accept a match. NOTE: this step assumes you have Vim compiled with the Ruby interface (the output of :help version should include +ruby)

4. Happy hacking!

Customising

You can complement the system-wide settings with plugins placed within your home directory.

Inside the directories $HOME/.vim and $HOME/.vim/after (Unix), or $HOME/vimfiles and $HOME/vimfiles/after (Windows), exists the same directory structure as found in $VIMRUNTIME: in particular, the subdirectories ftplugin, indent, and syntax. If you put a file ruby.vim in any of these directories, you can tailor the way Vim treats Ruby files to your own needs. Files placed in the $HOME/.vim/after directory hierarchy can be used to override or add to the default settings in $VIMRUNTIME and files placed in the $HOME/.vim will replace the default settings. See :help runtimepath for more details.

I see no need to tamper with syntax highlighting or indenting, but being able to have Vim load up a special configuration file whenever a Ruby file is loaded is a great benefit. In fact, it can load more than one file. Here are the three important files that Vim loads whenever I edit a Ruby program:

  • vimfiles/ftplugin/ruby.vim
  • vimfiles/ftplugin/ruby_structure.vim

You can see the pattern there. When the filetype is “ruby”, Vim will load any files like those above.

In my directory, ruby.vim sets textwidth, softtabstop, and shiftwidth. That’s it. (These are inappropriate for the system-wide ftplugin, because they reflect user preferences.)

ruby_structure contains a set of insert-mode mappings that make editing Ruby code much easier. My favourite one is the following:


imap <S-CR>    <CR><CR>end<Esc>-cc

This enables the following shortcut. Say I’m writing an if-statement. Having typed:


if name == "John"[<--cursor]

I can hit Shift-Enter and will get:


if name == "John"
  [<--cursor]
end

This saves typing and enables me to keep the program balanced. Of course it applies to def, do, class, while, unless as well, and probably others.

I will provide all the details of my personal Vim/Ruby configuration in an appendix in the near future. (Well, that hasn’t happened because I haven’t actually written any significant Ruby code for a while.)

Maybe it will be useful to adopt the 2 spaces indent Ruby rule. In case use this


        set expandtab
        set tabstop=2 shiftwidth=2 softtabstop=2
        set autoindent

The following extension works with braces, too. Having typed:


ary.map { |elem|[<--cursor]

I can hit Shift-Enter and will get:


ary.map { |elem|
  [<--cursor]
}

Here’s the code:


if !exists( "*EndToken" )
  function EndToken()
    let current_line = getline( '.' )
    let braces_at_end = '{\s*\(|\(,\|\s\|\w\)*|\s*\)\?$'
    if match( current_line, braces_at_end ) >= 0
      return '}'
    else
      return 'end'
    endif
  endfunction
endif

imap <S-CR> <ESC>:execute 'normal o' . EndToken()<CR>O

— PitCapitain?

<S-CR> didn’t work for me, so I hacked this function to “do the right thing”™ when you press return. http://pmade.com/articles/2006/06/02/vim_mapping_for_ruby/

In addition to above, I have found this quite helpful:


imap <<-    <<-QUOTE<CR><Tab><CR>QUOTE<Esc>-A

— AnonymousRubyist

previous link don’t works anymore, so here is the code:


if !exists( "*RubyEndToken" )

  function RubyEndToken()
    let current_line = getline( '.' )
    let braces_at_end = '{\s*\(|\(,\|\s\|\w\)*|\s*\)\?$'
    let stuff_without_do = '^\s*\(class\|if\|unless\|begin\|case\|for\|module\|while\|until\|def\)'
      let with_do = 'do\s*\(|\(,\|\s\|\w\)*|\s*\)\?$'

      if match(current_line, braces_at_end) >= 0
        return "\<CR>}\<C-O>O"
      elseif match(current_line, stuff_without_do) >= 0
        return "\<CR>end\<C-O>O"
      elseif match(current_line, with_do) >= 0
        return "\<CR>end\<C-O>O"
      else
        return "\<CR>"
      endif
    endfunction

endif

imap <buffer> <CR> <C-R>=RubyEndToken()<CR>

Postscript

For more information

Get the latest released vim-ruby files from Vim-Ruby Configuration Files project

Created: 23 Oct 2002 Last Updated: 12 Apr 2006 (DougKearns)

Questions

Some questions Ruby Vimmers may be able to answer (put here as they may help others)[should these move to a /discuss page, or would that make editing this page more painful?]:

Is there a way to debug ruby code running inside vim (like printing the backtrace, etc) ?

With matchit you can jump to the balancing word def…end, if…else…end, but is there a way to jump to the enclosing syntactical structure, such as the def…end, or from def…end to the enclosing class…end structure? Can this be done without creating maps (which are harder to look up/remember and in vim there’s less namespace for them than in vi)?

There’s no way I know of to achieve this. It could be done imperfectly with search patterns.

Is there a way to jump to a method of a given class in the file, for example if there are many similar named methods in different classes in the said file? I think this is equivalent to asking if there is tags support for ruby, but I’ve not done much with tags.

Exuberant ctags does support Ruby (see bottom of page for more), but I doubt it would be able to resolve names in the face of many options. Good for basic navigation, though, and Vim’s support for ctags is excellent.

[Gnu Global] [Irish mirror] may help with this, though it doesn’t support Ruby at the time of writing (04-APR-2003). It does support vim though.

What about [taglist] ? It works wonders for me (except the fact that it only does the current file) SimonVandemoortele

External Pages on using Vim for Ruby development