Python-backed Vim super snippets with UltiSnips
I spent some of my day on Sunday converting my old snippets from my SnipMate, to the format expected by UltiSnips (a slighlty more robust snippet plugin). UltiSnips supports SnipMate out of the box, but I wanted my snippets in the UltiSnips form to make writing more advanced snippets a little bit easier.
This involved moving snippets from ~/.vim/snippets/
to ~/.vim/UltiSnips/
,
and converting them to a style that doesn't rely on significant whitespace.
" SnipMate format
snippet hm
has_many :${0}
" UltiSnips format
snippet hm
has_many :${0}
endsnippet
Writing more advanced snippets with Python
UltiSnips supports Python interpolation which allows you to execute python code to transform inputs as you type them. To demonstrate what I mean here, let's take a look at the following snippet I patched up on Sunday:
snippet set
def set_${1:model}
$1 = `!p snip.rv = ''.join([x.capitalize() for x in t[1].split('_')])`.find_by(params[:id])
end
endsnippet
And lets see it in action:
Note: new
should really be show
here. Oops.
Pretty great stuff. What's going on here:
!p
houses an interpolated python expressionsnip.rv
assigns the value to be returned to vim from the snippet''.join([x.capitalize() for x in t[1].split('_')])
— convertsadvanced_charm
toAdvancedCharm
as I type.
Let's take a look at one more example. Quite often, I need to write a new
feature spec using capybara/RSpec. I tend to name the files like so
user_creates_an_article_spec.rb
, and then end up adding the feature spec
boilerplate:
require "rails_helper"
feature "User creates an article" do
scenario "some text that varies here" do
# Add expectation here
end
end
Let's see how we can write a snippet that automate some of that process using python.
snippet feat
require "rails_helper"
feature "`!p snip.rv = snip.basename.replace("_", " ").replace(" spec", "").capitalize()`" do
scenario "${0}" do
end
end
endsnippet
Let's check this one out in action:
This is pretty similar to the snippet before. All we are doing differently here
is returning a different value via snip.rv
. This time around we access the
filename without the extension via snip.basename
and perform some python
functions to convert the filename into a capitalized description.
I've only scratched the surface here, but I hope you try out some python powered snippets too. Cheers!