How I

Andrew Radev

Vim plugin-writer and occasional web developer

Sofia, Bulgaria

Who are you and what do you use Vim for?

My name’s Andrew and I use Vim mostly for Vim plugins. Or at least that’s what most people tell me. Honestly, I probably write a lot more ruby and javascript, but somehow my github profile is overwhelmingly Vim-related stuff.

For me, Vim is just the default go-to for any sort of text editing. Coding, notekeeping, occasional blog-posting. A while back, I used to write my emails with it, but gmail doesn’t use a proper textarea anymore, so it’s been harder. If I could use a Vim-like interface everywhere, I probably would.

Introduce us to your Vim config.

My Vim config is big. Big enough to warrant a README. I realize a lot of people pride themselves on minimalistic vimrcs, and I respect that, but it’s definitely not for me. If I come up with something useful, I code it up and try it out. (That, or forget all about it and delete it years later.)

You wouldn’t guess that if you were to look at my vimrc, mind you. At time of writing, it’s a mere 40 lines, but if you look a bit more closely, you might notice a few lines that include other files into it. At some point, I realized I need separate places for settings, plugin variables, custom mappings, etc. It helps a lot when I’m wondering where to add configuration and new stuff, and, to an extent, when looking for their implementations. Though, for the latter, I often just use ctags. Did you know that ctags understands Vim mappings and commands? It’s priceless.

The startup directory is a pretty small piece of it, though. I use pathogen for plugins, and maintain them in git as submodules, but I still have a plugin directory with old, one-file plugins that don’t really need to be in their own module. I have a ton of things in ftplugin for particular filetypes (just look at the ruby one), but whenever I can, I try to generalize any fancy logic and just leave a few buffer-local variables. I have a “utility” file in autoload I just call lib.vim for various tricks I’d like to reuse. I put everything between not-quite-a-plugin and not-just-one-command either in the personal directory or the wip directory, depending on how complete I feel it is. The naming is not ideal.

And yes, I do have quite a few things around I don’t use, but hey, my Vim still boots in around 170ms, so I’m happy enough. I’ll do a cleanup one of these days. Probably.

What have been the most useful resources for you to learn Vim?

My learning process started off with me trying out vimtutor and then using Vim for a while and then… giving up. I couldn’t understand why anybody would use something this weird. I had to actually witness an expert using it with rails.vim to “get” it. It was a university course in ruby and rails, and for my final project, I used Vim. Two weeks later, and forevermore, this was my editor.

So I guess the first “useful resource” must have been the rails.vim documentation. From that point on, I started my first real job, and realized how incredibly inadequate I was. I was made fun of a lot for my “archaic” text editor, so, with the enthusiasm of a 20-year-old, I resolved to prove them wrong. I googled around for tips and tricks, I searched vim.org for useful PHP and SVN plugins, and I went deep into the help files. That last part was an amazing boost. There was a lot of the “wikipedia effect” of looking at an article, and following a bunch of links for the next half hour, learning cool new stuff. Like, say, hitting :help * and realizing there’s an 'iskeyword' setting. Or even just scrolling down a bit and discovering gd. But my favorite help topic has to be :help magic. I spent a lot of time there.

Later on, I started picking bits and pieces from a lot of places. For instance, Steve Losh had a great twitter account with snippets from his own vimrc. There were blog posts with recommended settings and plugins, and at some point, I just started making new stuff up, so the learning and the creating have bled into each other a bit. As it should be, probably. No better way to learn than to try creating something new, right?

What’s the most recent thing you’ve learned about Vim?

Well, I maintain the VimLinks account, so I try to keep an eye open for new things. Most of the time it’s plugins or blog posts, but following the mailing list lets me learn about new features pretty quickly.

The last thing I’ve learned that’s strictly about Vim core is probably the new jsonencode() and jsondecode() methods. Not a particularly fancy feature for users, but might help plugin authors. Tim Pope had to implement his own json parser for projectionist, for example. It also seems to be the beginning of async jobs! Exciting stuff, but too early to say how it’ll turn out.

The second-most-recent thing I learned is the :smile command :). Though you need a pretty recent Vim version if you want to try it out.

How did you get started writing Vim plugins?

I mentioned my first job and my effort to fight for the glory of my editor. Well, I didn’t start my first plugin then, but I wrote a lot of vimscript that sort of looked like a plugin. It was a PHP shop, and I worked mostly with Symfony. So, missing rails.vim, I figured I’d write a clone of that for symfony.

Believe it or not, I did a pretty good job of it. It was really, really useful to me while working there, but it wasn’t really plugin material. There were a lot of assumptions that worked for the company, but wouldn’t work for a generic project. I wanted to extract it at some point, but I moved on, started working with rails, and realized I’m probably never going to use Symfony again anyway. No point in maintaining the plugin, then. I officially deleted it, with a heavy heart, and it’s deep inside the git history of my Vimfiles, somewhere in this sea of red.

The very first “real” plugin I created was splitjoin. I had quite some Vimscript experience under my belt at the time, and when I came up with the idea, I could see a solution. And I could see it wouldn’t work as just one command in my vimrc or something. It was going to have a lot of moving parts. The idea of “splitting” a line in a different format or “joining” it in a compact representation could work for ruby if-clauses, but also for HTML tags, for javascript objects, or for almost anything, really.

So, I grit my teeth and started on the long road towards making an official plugin. I copied a lot of the documentation structure from Tim Pope, along with quite a few ideas. I also took some inspiration from the NERDTree, which to this day I believe is the most meticulously organized Vim plugin I’ve seen.

I even wrote tests, but that came a bit later. In fact, I wrote my Vimrunner project, which I use for testing, specifically because I was tired of testing splitjoin manually. This was a plugin that had a lot of different use cases for different filetypes, and quite a few edge cases. If I hadn’t automated, development would have ground to a halt. Not that it’s moving too fast right now, but I’ve made a lot of test-backed changes.

splitjoin.vim feels like a natural addition to Vim’s editing language. What can you tell us about the story of its development?

Well, I guess I said most of that in my previous answer. Though, I really, really like its description as “a natural addition to Vim’s editing language”. It’s actually something I’ve been told by a few people, and I’m very proud of it.

A few of my other plugins try to achieve a similar thing, I think, switch, sideways, whitespaste, and maybe undoquit. I’m not sure how well they succeed, but I’m pretty happy with how comfortable they are to me at least. I rarely have to think about them at all.

It’s never been an explicit design goal, or at least, I’ve never thought about it much. I feel like it’s more a matter of the problem it tries to solve. There’s a whole category of plugins that implements a very specific action, like a small change to a few characters, or a tiny adjustment to the built-in way that Vim works. Like, say surround, or smartword. Just a tiny boost, but it tends to add up and change your workflow a lot.

Are you involved in a local Vim community?

I lived in Berlin for a few years, and I went to Vimberlin all the time. That was really nice, but I’m based in Sofia, Bulgaria now, and we don’t really have anything like it. I’ve considered starting a VimSofia (or should it be Sofia.vim?), but I’m not sure where I’d even start. Not to mention I have no idea if there’d be enough people in attendance. Maybe some day in the future.

I do give quite a few Vim talks, so much so that it’s become a running gag for everybody that knows me. Every time I do a talk for a conference, it’s sort of automatically considered to be a Vim talk. Which is why I’ve been doing different talks for the last few years, just for the heck of it :). Mind you, most of the talk usually consists of showing code in Vim… What can I say, it’s a lot easier than copying it in slides.

Share a snippet of Vim script you’ve written and talk about what it does.

I have a lot to pick from, and the big problem is, I tend to be quite verbose. Which means it’s difficult to find one that’s short enough to be readable.

One thing I wanted to do at some point was “delete a surrounding function call”. I’ve got a gist of it here, but let me try to explain in more detail.

The first iteration of this was something like:

nmap dsf F(bdt(ds(

So, breaking it down, if I type dsf,

This worked great for simple cases. If you have a function_call(something) and you hit dsf while between the brackets, you’ll be left with something. This can be useful if the invocation of the function_call moved elsewhere, so you don’t need it anymore, or something like that.

Unfortunately, this doesn’t work for method calls, or really, any invocation that involves a few words and connecting symbols. So, I had to delete this elegant mapping and expand it into this monstrocity:

" First, we do the mapping again, but this time we invoke a special function created for the task
nnoremap <silent> dsf :call <SID>DeleteSurroundingFunctionCall()<cr>

" (The s: of this function is the <SID> upstairs)
function! s:DeleteSurroundingFunctionCall()
  " most of the real work is done by the s:FindFunctionCallStart function.
  let [success, opening_bracket] = s:FindFunctionCallStart('b')
  if !success
    return
  endif

  " if it succeeded, it moved us to the right place to just delete everything to the opening bracket...
  exe 'normal! dt'.opening_bracket
  " ...and then delete the brackets themselves
  exe 'normal ds'.opening_bracket
  " and let's get repeat.vim support, so we can do this again with a simple `.`
  silent! call repeat#set('dsf')
endfunction

function! s:FindFunctionCallStart(flags)
  " first, look for something that looks like a keyword, followed by a ( or a [
  if search('\k\+\zs[([]', a:flags, line('.')) <= 0
    return [0, '']
  endif

  " what's the opening bracket?
  let opener = getline('.')[col('.') - 1]

  " go back one word to get to the beginning of the function call
  normal! b

  " now we're on the function's name, see if we should move back some more
  let prefix = strpart(getline('.'), 0, col('.') - 1)
  while prefix =~ '\k\(\.\|::\|:\|#\)$'
    if search('\k\+', 'b', line('.')) <= 0
      break
    endif
    let prefix = strpart(getline('.'), 0, col('.') - 1)
  endwhile

  return [1, opener]
endfunction

I’ve put some comments in between the code, but if you’re not familiar with vimscript, I’m sure there’s a lot of it that looks like black magic. My advice would be to hit the :help if you want to learn more :).

The end result? Type dsf within the brackets in Module::Foo.new("bar") and you’re left with just the "bar". It’s not something I use every day, but when I do, it saves me from a lot of unnecessary thinking.

What have you been working on recently in Vim?

Well, I’ve been working with ember.js recently, which made me think of editor optimizations, as usual. For now, I have a set of projections for projectionist and a small project file, but I’m definitely thinking of building some rails.vim-like tools. Maybe an override of gf? We’ll see.

As for Vim plugins, I recently had an idea for a plugin that I’m pretty excited about. The basic idea is that, after searching for something, say Foo, I’d be able to call :Modsearch word to modify the search by wrapping the pattern in word-limits – turn it into \<Foo\>. Which isn’t particularly impressive, but led me to think about other modifications. Like, say, searching for a variable and then excluding strings and/or comments from the search. Now this is something I could use.

I’ve put modsearch.vim up on github, and it actually works, but there’s still some work to do on documentation. And configuration, like creating your own “modifiers” to searches. And searching for camelcased/underscored versions of the word? And maybe an :Unmodsearch command to reset it? Though there’s a question of, should it reset it or keep a history, and how do I even tell when the modifications begin…

Well, there’s some work to do, but I’ll be sure to tweet about it when I feel it’s ready :).