dcsimg

Extending Vim with Ruby

Vim is a fascinating editor. You could spend a lifetime learning the intricacies of its strange but powerful interface without knowing everything it can do. One thing you might not know is that you can write scripts to control Vim in another language.

Vim is a fascinating editor. You could spend a lifetime learning the intricacies of its strange but powerful interface without knowing everything it can do. One thing you might not know is that you can write scripts to control Vim in another language.

Like vi, Vim contains the command language of their common predecessor ex (for more information on the ex editor, see the March 2001 issue online at http://www.linux-mag.com/2001-03/newbies_01.html). However, the ex language is not a good way to programmatically control Vim. There are few variables, little in the way of control structures, and no subroutines.

Fortunately, there are other scripting languages that have access to Vim’s internal API. These include Tcl, Perl, Python, and Ruby. You can write scripts in these languages that can be called from within Vim to control what it does.

This month we’ll explore the Ruby API for Vim, which was implemented by Shugo Maeda and is included in Vim starting with version 6.0. We’ll provide you with a brief overview of what parts of Vim’s functionality Ruby has control over.

First, you have to make sure that Ruby was compiled with the option –enable-ruby-interp . If you’re running Debian Linux, you can use the apt-get program to install the vim- ruby and vim-rt packages. You can also find out more about Ruby in this month’s issue (See “Write Ruby Be Happy”).

Ways of Invoking Ruby

There are three ways to access the Ruby interpreter from within Vim. The method to use will depend on whether you’re working interactively within Vim or writing an extension for it.

:rubydo: This is a range command that sets $_ to each line within the range and performs the Ruby command you specify on each line of the range. If you don’t specify a range, it will default to the entire file. Here’s an example that replaces all occurrences of the word “proprietary” with the word “free”:


:rubydo $_.gsub!(
‘proprietary’,
‘free’)

:rubyfile: This command allows you to specify a Ruby script to execute with the interpreter. It’s useful when you want to perform complex operations or to define a method in the file that you can use later in the session. An example appears in Figure One.




Figure One: example.rb


b = VIM::Buffer.current
b.append(0, “# Be as careful in the beginning…”)
b.append(b.length, “# …as you are in the end.”)
 
def h(n)
win = VIM::Window.current
win.height = n
end

From Vim’s command mode, you can type :rubyfile example.rb to execute this script. It starts by adding a line to the beginning and end of the current buffer by using the append method of VIM::Buffer. Then it defines (but does not call) a method named h, which will resize the current window’s height to n.

:ruby: This command can be used in two ways. The first lets you execute a line of Ruby code. This is useful during debugging when you want to inspect a variable’s value. For instance, you can use this command to display the third line in the current buffer:


:ruby VIM::message($curbuf[3])

The second way to use the :ruby command is to invoke methods defined earlier in the session. To maximize the height of a window, type [Ctrl-W]99+ or invoke the h method defined earlier by typing :ruby h(99) instead.

If you have a very long command to pass to the Ruby interpreter via the :ruby command, you can build it as a “here document” (as in Figure Two). This lets you build a long string that ends only when the value after the << is seen on a line by itself.




Figure Two: Entering a Multiple-Line Ruby Command in Vim


:ruby <<EOF
$curbuf.append(
0,
“a contrived example of using ” +
["more", "than", "one", "line"].join(” “)
)
EOF

This multi-line form is very useful when writing non-trivial extensions to Vim using Ruby. When writing a Vim function, you can embed Ruby commands in it by using the multi-line form of :ruby (shown in Figure Three).




Figure Three: Calling Ruby from a Vim Function


function! DrawCircle()
ruby <<EOF
$curbuf.append(0, “o”);
EOF
endfunction

It’s Time to Be Creative

With the information presented here, you should have a good idea of how Ruby can manipulate Vim. To see some more Vim stuff, check out http://vim.sourceforge.net. Among the impressive scripts is one that adds IDE-like functionality to Vim. There’s another that allows you to control GDB from within Vim. Most of these scripts are implemented in Vim Script, which is not nearly as powerful as Ruby. If this much can be done with Vim Script, imagine what you could do with Ruby.




Ruby’s Interface to Vim


The VIM module in Ruby contains all you need to know. In this namespace, there are four functions and two classes, each of which has a handful of attributes and methods.

Functions in the VIM module

VIM::message(msg)


This displays the string msg on the bottom line (where you usually type ex commands).

VIM::set_option(arg)


This sets a Vim option just as :set would.

VIM::command(cmd)


This executes an ex command.

VIM::evaluate(expr)


This evaluates expr using Vim’s internal expression evaluator (see :help expression ) and returns the result as a string.

Classes in the VIM module

VIM::Buffer: This class represents a buffer, which is the data structure that text is stored in during the editing process. A global variable, $curbuf, represents the current buffer, also accessible as VIM::Buffer.current.






Class Methods
current Returns the current buffer object
count Returns the number of buffers
self[n] Returns buffer object n (the first buffer is numbered 0)











Methods
name Returns the name of the buffer
number Returns the number of the buffer
count Returns the number of lines
length Returns the number of lines
self[n] Returns line n from the buffer (the first line is numbered 1)
self[n] = str Sets line n in the buffer to str
delete(n) Deletes line n from the buffer
append(n, str) Appends a line containing str after line n

VIM::Window: This class represents a window, which is your view into a buffer. A global variable, $curwin, represents the current window, also accessible as VIM::Window.current.






Class Methods
current Returns the current window object
count Returns the number of windows
self[n ] Returns window object n (the first window is numbered 0)








Methods
buffer Returns the buffer object displayed in the window
height Returns the height of the window
height = n Sets the window height to n
cursor Returns a [row, col] array for the cursor position
cursor = [row, col]Sets the cursor position to row and col



John Beppu encourages you to use your computer skillfully and creatively. He can be reached at beppu@cpan.org.

Fatal error: Call to undefined function aa_author_bios() in /opt/apache/dms/b2b/linux-mag.com/site/www/htdocs/wp-content/themes/linuxmag/single.php on line 62