Vim
Vimscript And You!
At Hashrocket we love configuring our development environments to be highly portable and customizeable. Occassionally, that necessitates rolling up our sleeves, busting out our editor, and cranking out some Vimscript. If you've ever implemented a plugin in Vimscript then you have undoubtedly ran into some pain trying to excercise the code. Pathogen gets you a long way by reloading your plugins conveniently, but what if there were a faster way? And wouldn't it be great to be able to test drive it? Well, as luck would have it, we can!
In this post we are going to cover:
- Setting up Vimrunner
- Writing a test using Rspec to exercise Vim
- Writing a plugin to satisfy the test
By the end you should have a solid foothold to start testing your own Vim plugins.
Setting up Vimrunner
[Vimrunner][vimrunner] is a project written by Andrew Radev that let's you leverage the scriptability of Vim. It's documentation is pretty great so if you have questions be sure to refer to the Vimrunner [README][vimrunner_readme].
First start by making a directory structure that looks something like this (simplified for post):
plugin
└── example_plugin.vim
spec
├── plugin
│ └── example_plugin_spec.rb
└── spec_helper.rb
Inside the spec/spec_helper.rb
let's place the Vimrunner config block to get access to its built in vim
helper and support modules.
require 'vimrunner'
require 'vimrunner/rspec'
Vimrunner::RSpec.configure do |config|
config.reuse_server = false
config.start_vim do
vim = Vimrunner.start
vim
end
end
Above we set reuse_server
to false to ensure it uses a new instance for each test. This is slower, but makes everything easier. The start_vim
block gives us access to the vim runner inside our specs.
Now that we have Vimrunner set up for the most part we can open up spec/plugin/example_plugin_spec.rb
and write a test.
Writing a test
This plugin is simply going to strip whitespace for ruby files. So let's start by setting up a file that has trailing whitespace so we can test our expectations.
require 'rspec'
require_relative '../spec_helper'
describe "Trim" do
before do
vim.add_plugin(File.expand_path('../../../',__FILE__), 'plugin/example_plugin.vim')
end
it "strips whitespace" do
sample = "class TestingWhitespaceStripping "
write_file("test.rb", sample)
vim.edit "test.rb"
vim.write
expect(File.read(filename)).to eql(sample.strip + "\n")
end
end
Alright, let's run that and make sure it fails how we expect it to fail.
Making it pass
Now that we are nice and red it is time to go green. Let's actually write the plugin. At this point, you may want to refer to [Learn Vimscript the Hard Way][vimscript_hard_way] by Steve Losh. It's a great way to get up and running in Vimscripting. Our example is naively simple, but it would be trivial to expand it into something more robust.
autocmd BufWritePre *.rb call s:Trim()
function! s:Trim()
%s/\s\+$//e
endfunction
So there you have it, our plugin in all its glory. We are telling it to trim ruby files on BufWritePre
, which means it will execute s:Trim()
right before saving the file. Vioala, no more pesky trailing whitespace. Let's head over to the command line and test it out. Run the following commands
cd path/to/plugin/spec/dir
rspec --color example_plugin_spec.rb
And we've officially arrived at green.
Concerns
Vimrunner requires whichever vim you are using as the server to be compiled with +clientserver
and +xterm-clipboard
if you plan on using GUI vim. Once you have that you're ready to begin testing all your vim plugins. If you would like to see a more robust example refer to [Vim-Spacejam][vim_spacejam], the plugin that inspired this post.
I hope this has inspired you to dive into Vimscript. Thanks for reading.
References
Image by [Zimpenfish][attribution_flickr_profile]
- [Vimrunner][vimrunner]
- [Vim-Spacejam example plugin][vim_spacejam]
- [Learn Vimscript the Hard Way][vimscript_hard_way]
- [Damien Conway's 5 Part Vimscript series][damian_conway_vim] /ty @telemachus
[vimrunner]: https://github.com/AndrewRadev/vimrunner [vimrunner_readme]: https://github.com/AndrewRadev/vimrunner/blob/master/README.md [vim_spacejam]: https://github.com/rondale-sc/vim-spacejam [vimscript_hard_way]: http://learnvimscriptthehardway.stevelosh.com [damian_conway_vim]: http://www.reddit.com/r/vim/comments/15rgqy/50_mins_of_pure_gold_from_drew_neil_a_true_vim/c7pghm4 vim_image: http://i.imgur.com/89lmSby.jpg [attribution_flickr_profile]: http://www.flickr.com/photos/zimpenfish/