Episode #056: xmpfilter
By far the most common question I get about RubyTapas is… “how do you get VIM to insert the result of expressions right in the buffer like that?” To which my first answer is “Silence, heathen! Can't you see you are in the presence of Emacs?!” But religious wars aside, how do I accomplish this magical feat?
The answer is that I use the venerable
rcodetools gem. This gem, as its name suggest, contains a number of useful tools for working with Ruby code. The tool that concerns us today is
xmpfilter is a command-line utility which executes Ruby code. As it executes the code, it replaces specially-formatted comments with the value of the previously-executed expression.
For instance, here's a little Ruby file that adds two numbers and tells
xmpfilter to show the result.
2 + 2 # =>
When I run the file through
xmpfilter, it outputs the same code, with the result filled in.
$ xmpfilter math.rb 2 + 2 # => 4
xmpfilter also captures STDOUT and adds what it captures to the end of the output. To demonstrate, I'll add a line that prints some text and then run
xmpfilter on it again.
puts "hello, world" 2 + 2 # =>
$ xmpfilter output.rb puts "hello, world" 2 + 2 # => 4 # >> hello, world
xmpfilter can pretty-print larger datastructures. For instance, here's a Ruby struct with a number of attributes. When I put the special hashrocket comment on the same line, the object is presented all on one line. But when I put it on the next line, it is printed out with newlines and indentation to make it easier to read.
Beer = Struct.new(:brewery, :name, :abv, :ipu) hopback = Beer.new("Troegs", "Hopback Amber Ale", "6.0%", 55) hopback # => #<struct Beer brewery="Troegs", name="Hopback Amber Ale", abv="6.0%", ipu=55>
Beer = Struct.new(:brewery, :name, :abv, :ipu) hopback = Beer.new("Troegs", "Hopback Amber Ale", "6.0%", 55) hopback # => #<struct Beer # brewery="Troegs", # name="Hopback Amber Ale", # abv="6.0%", # ipu=55>
OK, now you know about
xmpfilter, but you're probably still wondering how I integrate it with my editor. As it happens, the
rcodetools gem actually contains an
rcodetools.el file which adds Emacs commands for
rcodetools utilities, including
xmpfilter. I simply bind
C-c C-c in ruby-mode to run the
xmp command. The Emacs extension also modifies the “comment” keybinding so that hitting it twice adds an
Vim users will be happy to hear that
rcodetools also contains a Vim extension. For users of other editors: you'll just need to write a script or macro which feeds the current buffer as
STDIN into the
xmpfilter command, and then replaces the contents of the buffer with the output.
Oh and if you're wondering: The “XMP” in the name is for “example”.
And there you have it! Now you know my trade secrets. Happy hacking!