vimでsnippetのインデント深くするときはハードタブじゃないとダメ

問題

vimのneosnippetを使っているときに,インデントが上手く動作しない場合があった.

snippet     initial
options     head
    #include <iostream>
    int main(int argc, char const* argv[])
    {
      ${1}
      ${2}

      ${3}
      return 0;
    }

のように書いて,snippetを起動させると以下のように,

cpp-snip-wrong-result

一つ目のplaceholderより下のインデントでおかしくなる部分が出てしまう.

解決策

ググってみたところ,docsのここを見ろという内容のissue1を発見した.

If you use hard-tab for indentation inside a snippet file, neosnippet will use ‘shiftwidth’ instead of Vim indent plugin. This feature is useful while some languages’ indent files do not work very well (e.g.: PHP, Python).

ハードタブのインデントをスニペットの登録側ですると,呼び出しの際には対応するfiletypeのshiftwidthの値分だけインデントされるように変換されて展開されるようだ.
というわけで以下のように先程のスニペット内のスペースをタブに変換して,

snippet     initial
options     head
	#include <iostream>
	int main(int argc, char const* argv[])
	{
		${1}
		${2}

		${3}
		return 0;
	}

再度snippetを起動させる.

cpp-snip-correct-result

今度は正しくインデントされて展開された!

今後の対策としては,ftplugin/snippet.vimに以下の記述を書いてsnippetファイルを編集するときだけハードタブが挿入されるように変更する2

setl noexpandtab

感想

vimを使い始めて1年半くらいになるが,まだ時々Emacsが恋しくなる.Emacs時代は毎日エディタの設定をしていたから最終的にかなり使いやすくなったが,小指痛めてvimに移ってからあまりいじらなくなったからなぁ..もう少し頑張って軽くVim scriptを触れるくらいにはならなければ.