Python Backed Snippets with UltiSnips

December 04, 2017

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:

UltiSnips snippet

Pretty great stuff. What’s going on here:

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:

UltiSnips snippet 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!