Uma Lição de VIM #15.8: Plugins – SnipMate

(Essa é a parte que automatizamos a digitação de coisas repetidas.))

Para o oitavo plugin, iremos falar sobre SnipMate.

Como de costume, instalando pelo Vundle:

Bundle ‘msanders/snipmate.vim’

SnipMate adiciona a funcionalidade de snippets dentro do VIM. Para quem não sabe, snippets são trechos de código que são adicionados automaticamente (ou com a ação de alguma combinação de teclas) a partir de uma simples palavra.

Por exemplo, um dos snippets que já estão inclusos no pacote do SnipMate, você pode, num arquivo JavaScript, simplesmente digitar:

fun

… e, ao pressionar [Tab], o SnipMate irá adicionar, automaticamente

function function_name (argument) {
  // body…
}

… posicionando o cursor diretamente sobre function_name para que você coloque o nome da função; pressionando [Tab] irá posicionar o cursor sobre argument e pressionando [Tab] de novo, o cursor ficará sobre // body... (depois disso, [Tab] irá funcionar como tabulação, como normalmente é).

Para criar seus próprios snippets, você tem duas opções e ambas devem ficar no diretório $HOME/.vim/snippets:

A primeira forma é através de um único arquivo, com o nome do tipo de arquivo em que os snippets serão válidos (que você pode ver usando :set ft) com a extensão snippets (por exemplo, para snippets para arquivos Python, você teria um arquivo $HOME/.vim/snippets/python.snippets). Neste arquivo você deve iniciar os snippets com a palavra snippet, seguida da palavra que será utilizada para identificar o snippet, seguido pelo snippet em si, com uma tabulação na frente (quando não houver tabulação, SnipMate considera que o snippet terminou). Os pontos onde você quer que o cursor pare devem ser identificados por ${{número}:{texto}} e, se ficou confuso, é porque eu estou usando “coisas que você substituir” com {} e o próprio SnipMate usa {} para blocos, mas deve ficar mais claro com este exemplo:

snippet for
    {% for ${1:record} in ${2:list} %}
        ${3:content}
    {% endfor %}

Este snippet, para Django e Jinja, faz um loop “for”. Ao digitar “for” e pressionar [Tab], o conteúdo será adicionado, o cursor será posicionando onde ${1:record} está permitindo a alteração do mesmo, pressionando [Tab] de novo irá posicionar em ${2:list} e assim por diante.

E, caso você esteja se perguntando “E o que acontece se eu colocar o mesmo número em dois lugares diferentes?”, a resposta é: lugares com o mesmo número são alterados ao mesmo tempo. Por exemplo, o snippet:

snippet block
    {% block ${1:blockname} %}
        ${2:{% content %}}
    {% endblock $1 %}

… tem o número “1” duas vezes (uma depois de “block” e outra depois de “endblock”). Quando você colocar o nome do bloco no primeiro (do lado de “block”), o outro (depois de “endblock”) será preenchido automaticamente.

A segunda forma de adicionar snippets é através de arquivos individuais. Ao invés de ter um arquivo com o tipo de arquivo com todos os snippets dentro, você irá criar um diretório com o tipo de arquivo e cada arquivo dentro deste diretório deve ser {palavra}.snippet. Assim, como no exemplo anterior tínhamos um arquivo $HOME/.vim/snippets/htmldjango.snippets, poderíamos ter, na verdade, um diretório $HOME/.vim/snippets/htmldjango/ e, dentro deste diretório, um arquivo chamando block.snippet com o conteúdo do snippet, sem as tabulações (já que agora o SnipMate sabe exatamente onde termina o snippet: no final do arquivo).

E quando usar um ou outro? Você deve usar arquivos individuais se o SnipMate já tiver um arquivo de snippets para o tipo de arquivo especificado. Assim, se você quiser adicionar novos snippets para Python, que já tem uma série de snippets prontos incluídos no pacote do próprio SnipMate, você deve usar a segunda forma. Caso contrário, fica por preferência pessoal.

E, para concluir: Ao escrever este post, descobri que existe um fork da versão apresentada aqui. A versão do “msanders” não é atualizada a 4 anos — mas funciona perfeitamente e tenho usado sem problemas a bastante tempo. Se você quiser algo mais recente (por algum motivo), o fork está em github.com/garbas/vim-snipmate (e requer mais dependências que a versão original).

My list of VIM Bundles

Not that anybody asked me, but I recently ditched Sublime Text 2 for VIM… again.

But here is the thing: I just ditched it ’cause I’m using a lot of bundles to change VIM default behaviour, adding more feature and that fuss. The ones I’m using:

Vundle
Vundle is the plugin I’m currenctly using to manage all the other plugins. Vundle is a really simple way to keep your other plugins up-to-date. All the other plugins listed here were installed using Vundle.

vundle

Powerline
Powerline changes the default “last status” line to provide a lot more information. The cool thing about Powerline is that it comes not only with a VIM plugin, but also with a Bash prompt and an iPython prompt, so everything have (almost) the same look.

powerline

Vim-Fugitive
I got Vim-Fugitive to display the current branch in the old Powerline plugin (the current one does that already). One of the things I still try to use is :Gstatus, which display the current changes in the index. The problem here is that the display, although pretty familiar, it’s a mess when you’re dealing with a single file (it shows “Changes not staged for commit” and then, when you add it to the index, it just change that to “Changes staged for commit”, which is pretty easy to miss in the list of things that are shown).

fugitive

Vim-Commentary
Vim-Commentary lets you comment a block of text pretty quickly, which is useful. The only issue with it is that it follows the current file type (as VIM does not have a “block type” or “region type” support), so trying to comment a few lines of JavaScript in an HTML file will produce HTML comments, not JavaScript/C++ comments. Still pretty useful to quickly comment that one line in your Python code.
Tabular
Tabular is a hard plugin to master, but really useful. With it, you can realign your code on custom characters (for example, align your variable definition on the “=” character). Or make all your HTML/XML properties align on “=”. And so on.
Auto Pairs
Auto-pairs does exactly what it says: It complete pairs of characters, adding a second " after your first ", the closing bracket and so on.
Vim-Flake8
On our Python project, we have a strictly “follow PEP8” policy. With Vim-Flake8, PEP8 errors are displayed in the error window for easy access (and fix).

flake8

SnipMate
SnipMate is a TextMate-like snippet plugin, but really easy to use. Type the snippet name, press [Tab] and it will complete the snippet, positioning the cursor on the marker areas.

snipmate

CtrlP
Again, a plugin inspired on TextMate/Sublime Text: Fuzzy file search. It allows faster file switching by doing fuzzy search on filenames and directories, to the point that I barely use the open command/dialog these days. Also, you can chose to open the file in the current buffer, new split window or new tab.

ctrlp

Vim Multiple Cursors
Again, a feature based on TextMate/Sublime Text: Selection of multiple elements and change in those selected. It is a more visual way of doing :s/<original>/<replacement>.

multiple-cursors

After seeing this, you’re probably asking yourself: But with all those features based on Sublime Text, why not use Sublime Text directly? Well, for one, I’m a fan of the VIM movement/selection way of doing things; second, I use “jump to mark” pretty often (including “jump to last changed area in this file” and “jump to the previous jump place”) and Sublime does not have that; third, I prefer the way VIM colorizes the code, even if I try to use the same colorscheme in both editors (the difference here is the syntax file, so…); fourth, even if Sublime have a Vintage mode, most of the things I use (like smart jumps) do not exists.

Also, some bugs in plugins/Sublime let me down from time to time: Ctrl+R, sometimes, start in visual mode when Vintage is on (in other words, as soon as you find the definition you’re looking for, you start selecting text); Flake8 for Sublime manages, from time to time, to move the cursor to focus nothing, so you’re forced to move your hand to the mouse and click on the text again to be able to do anything.