Using vim in ruby

There’s a trick you see in some command-line apps where you hit a command and you get dropped into your chosen visual editor1 to edit a paragraph or two of text. The one that immediately springs to mind for me is git commit, which drops you into vim if you don’t supply a suitable commit message.

Sometimes you really want the additional feature-set you get with a proper text editor - being able to delete, switch lines, edit non-linearly, and check over your text before giving your program a block of text to wrangle. So this is how I do it in ruby:

1
2
3
4
5
6
7
8
9
10
11
12
13
require "tempfile"

template = "Foo bar" # Insert default text here
file = Tempfile.new("buffer")
path = file.path

file.puts template
file.close

pid = spawn("vim #{path}")
Process.wait(pid)

processed_text = File.read(path)

The main bit of trickiness here is spawning vim and then waiting for it to finish. spawn is a Kernel method that starts a process and doesn’t wait for it to finish, passing back the process ID. The idea is that you either let it do its thing separate from the originating program (using Process.detach'), or at some point you let the ruby program hang until the process itself has finished (usingProcess.wait`). Here we wait for it to finish and, since we save changes to the tempfile we created previously, we can fetch the data from this and proceed as normal.

This particular implementation uses vim regardless of what VISUAL is set to. By inspecting ENV["VISUAL"] it should be pretty easy to check what the user’s preferred text editor is. Different editors may require different command-line arguments (for example, Sublime Text’s command-line implementation needs to be passed the -w flag to keep the terminal open while you edit the file), but the overall method is pretty much the same as above.


  1. On my machine it defaults to vim but presumably if you actually set VISUAL in your .bashrc file it’ll run with that.