僕のYak Shavingは終わらない

車輪の再発明をやめたらそこには壮大なYakの群れが

Vimのsnippetについてあまり知らなかったので設定してみたら便利過ぎてつらい

今までこれを使いこなせてなかったなんて、今までの人生をなかったことにしたくてつらい・・・

vimでneocomplecacheを使用していて、スニペットの候補が来た時にCtrl-kと打つとスニペットが展開されることは知っていましたが、いまいち意識して使えていない状態が続いていました。

とりあえずスニペット使ってみる

追記
一応下のようにプラグインが入っている前提です。

NeoBundle 'Shougo/neocomplcache'
NeoBundle 'Shougo/neosnippet'

追記終わり

追記 2013/01/19
現時点でのおすすめ設定も書いているのでそちらも参照
今しているneocomplcache + neosnippetの設定の自分的おすすめ - 僕の車輪の再発明
追記終わり


例えば「PerlVim」で言うと、この記事がかなりの良記事になっていて、そこでもスニペット補完の話が出てきます。
VimでPerl(に限らないけど)を書くときにこれだけはやってほしい設定 #Perl #Vim - Qiita

neocomplecacheのスニペットの設定は以下のようになっています。

" for snippets
imap <expr><C-k> neocomplcache#sources#snippets_complete#expandable() ? "\<Plug>(neocomplcache_snippets_expand)" : pumvisible() ? "\<C-n>" : "\<TAB>"
smap <C-k> <Plug>(neocomplcache_snippets_expand)


例えばスニペットファイルに以下の用に記述されていた場合、

snippet u
    #!/usr/bin/env perl
    use 5.10.0;
    use strict;
    use warnings;

インサートモード時に「u」と入力後、続けざまにC-kと入力すると上のスニペットがその場に展開されます。

また下のようにマーカ(${1:code}の部分)が設定してあるスニペットの場合は

snippet n
    sub new {
        my $class = shift;
        my $args = ref $_[0] ? $_[0] : +{@_};

        ${1:code}

        bless $args, $class;
    }

まず「n」を入力。
f:id:kazuph1986:20121128100135j:plain

そしてCtrl+kと入力すると、
f:id:kazuph1986:20121128100159j:plain
こんな感じで展開されますがそれだけじゃありません。

おもむろに入力。
f:id:kazuph1986:20121128100230j:plain
実はインサートモードにすでになっていて、「code」と書かれた場所にすぐさま入力できます。

便利ですね!

複数のマーカーの利用

上記の例だとメソッド名(subの隣の名前)が「new」になっています。

とりあえずcodeを関数内に書きたいだけならいいんですが、結局newって名前は変更しますよね。
またnewの部分を最初に書くほうが普通な気もします。

ですのでスニペットを以下のように修正してみます。

snippet n
    sub ${1:fnc} {
        my $class = shift;
        my $args = ref $_[0] ? $_[0] : +{@_};

        ${2:code}

        bless $args, $class;
    }

newの部分を${1:fnc}と置き換えてみました。

じゃあ補完してみます。
f:id:kazuph1986:20121128103344j:plain
オプス!newだった部分は入力できましたが${2:code}の部分によくわからないものがでましたね。

と、ここで天下り的に以下の設定に変更してみます。
ちなみにneosnippetのドキュメントと同じ設定です。

" 2013/01/19 19:20最新のREADMEのものを反映
" Plugin key-mappings.
imap <C-k>     <Plug>(neosnippet_expand_or_jump)
smap <C-k>     <Plug>(neosnippet_expand_or_jump)

" SuperTab like snippets behavior.
imap <expr><TAB> neosnippet#expandable() <Bar><bar> neosnippet#jumpable() ? "\<Plug>(neosnippet_expand_or_jump)" : pumvisible() ? "\<C-n>" : "\<TAB>"
smap <expr><TAB> neosnippet#expandable() <Bar><bar> neosnippet#jumpable() ? "\<Plug>(neosnippet_expand_or_jump)" : "\<TAB>"

" For snippet_complete marker.
if has('conceal')
  set conceallevel=2 concealcursor=i
endif

追記 2013/01/11
なんだかneosnippet#expandable()の使い方が変わっているようで、しかもREADMEも書き換わってないようなので、以下の内容を見て設定を修正してください。
http://d.hatena.ne.jp/thinca/20130110/1357790456
追記終わり

もう一度同じことをしてみます。
f:id:kazuph1986:20121128104016j:plain
今度は単純に「code」と表示されているのがわかります。
この状態でカーソルは「fnc」の場所にあるので、そのまま関数名を入力します。
そしておもむろにTABを押して下さい。
f:id:kazuph1986:20121128104119j:plain
そうするとカーソルが今度はcodeに移動しました!
そのまま文字を入力してみます。
f:id:kazuph1986:20121128104159j:plain
入力できました!

多くのプログラミング言語に対するsnippetを設定してみる。

これもneosnippetのドキュメントに書いてあるのですが、

If you want to use a different collection of snippets than the built-in ones, then you can set a path to the snippets with the g:neosnippet#snippets_directory variable (e.g Honza's Snippets)

" Tell Neosnippet about the other snippets
let g:neosnippet#snippets_directory='~/.vim/bundle/snipmate-snippets/snippets'

はい、ということでHonzaさんのスニペットというものがあるようです。
honza/snipmate-snippets · GitHub
Neobundleでインストールして、上記の「snippets_directory」の値を上記の用にします。

これをするとなんと以下のすべての言語に対してスニペットが設定されます!

actionscript apache autoit c chef clojure cmake coffee cpp cs css dart diff django erlang eruby falcon go haml haskell html htmldjango htmltornado java javascript-jquery javascript jsp ledger lua make mako markdown objc perl php plsql po processing progress puppet python r rst ruby sh snippets sql tcl tex textile vim xslt yii-chtml yii zsh

スニペットの内容はいつでも上記のディレクトリの中身を見ればわかるので一度目を通しておくといいと思います。
(ところでlet g:neosnippet#snippets_directoryの部分で複数ディレクトリを指定したい場合はどうすればいいのだろう?)

追記
はてブコメントで

hide_o_55
g:neosnippet#snippets_directoryに複数ディレクトリを指定する場合はカンマ区切りで指定すればOKです

と回答を頂きました!
hide_o_55さんありがとうございます!

追記終わり

おわりに

スニペットは超便利ですので、めちゃくちゃ有効活用しましょう。
また自分なりのスニペットをどんどん増やしていくといいと思います。

ちなみに僕のvimrcはここにあります。なにかわからないことがあったら参照して下さい。
https://github.com/kazuph/dotfiles.git

追記
snippetで検索してたら以下のサイトでUnite.vimと連携する方法も書かれていました。
さらに便利になると思うので試してみるといいと思います。
Ning Ning ~ :h! don't panic!: [Vim] SnipMateでなくneocomplcache snippet completeを使うわけ

あとたくさんはてブがついて驚いていますが、今回の記事は、VimっていうかShogo」さんまじすごいって記事ですw
ほんとVimならどこにでも登場しますよね、もはや。。
追記終わり

Enjoy Vim Life!