rcmdnk's blog

SNIPPETS:: overheard conversations and other short short fiction pieces (English Edition)

Vimの Neosnippet というプラグインを入れたまままともに使ってなかったので 使えるようにしてみたら思った以上に便利だったので ちゃんと使っていこうと思ったのでメモ。

Neosnippet

もともと Neocomplcache という補完強化プラグイン 1 を使っている時に、スニペット部分が分離されて なんとなく指示通りに入れていた、と言うもの。

これまでまともにスニペットを使えてなかったので 今回使い始めるに当たってのメモです。

インストールするプラグイン

NeoBundleで管理してるなら

1
2
3
4
5
6
7
8
9
if has('lua') && (( v:version == 703 && has('patch885')) || (v:version >= 704))
  NeoBundle 'Shougo/neocomplete'
else
  NeoBundle 'Shougo/neocomplcache'
fi
NeoBundle "Shougo/neosnippet"
NeoBundle "Shougo/neosnippet-snippets"
NeoBundle "honza/vim-snippets"
NeoBundle "rcmdnk/vim-octopress-snippets"

こんな感じ。

スニペットの構造

各スニペットは次のような構造をしています。

1
2
3
4
5
6
7
8
snippet function
alias func
abbr function(...) {...}
options head
  ${1:#:function} (${2:#:arguments}) {
    ${3:#:content}
  }
  ${0}

まず、スニペット名をsnippetで指定し、 必要な場合aliasも設定できます。

abbrは補完するときに表示される文字列の指定。(無ければスニペットそのものが表示されます。)

optionsにはwordheadindentが指定できそれぞれ

  • word: 通常は空白の後にスニペット名が記入された時のみ展開出来る様になるが、このオプションを指定すると数字、アルファベット、”_“以外文字列の直後ならどこでもスニペットを展開出来る様になる。 e.g. (funcと記入しても展開できる。
  • head: 行の最初にあるときのみ有効。
  • indent: スニペット展開後にインデントを適用する。

の効果を与えます。

その下から、インデントして始まっているのがスニペット部分。 ここでは${N:XXXX}となってる部分がplacefolderで 書き換えを行う部分です。

数字は1から順番に移動することが出来るようにするための数値です。 0は一番最後に飛ぶことになるので上の様に最後にスニペットの外側に 置く感じになることが多いかと。(無くても良い。)

また、上の例では${1:#:function}と、#:が挟まれて名前、みたいになってますが、 #:が入っている場合、この文字列はジャンプ後に必ず消えます。

逆に#:が入ってない名前を付けると、そこへジャンプして編集せずに 次へ行くとその名前がその場に残ります。(デフォルト値的な扱いにも出来る。)

また、もし必ず同じワードを入れる箇所があるなら、 $3の様に書いておくと、${3:#:content}へ書き込んだ内容と同じものが $3へも展開される様になります。

もう一つ、特殊な${1:TARGET}(数値は何でも良いけど後ろは必ず:TARGET#:もなし) というplacefolderがあり、 これを書いておくと、ビジュアルモードで選択したものを ここへ入れる事が出来ます。 (普通にスニペット展開した時は通常のplacefolderと一緒。)

1
2
3
4
5
snippet comment
abbr /*...*/
  /*
  ${1:TARGET}
  */

として設定があるとき、ビジュアルモードで選択した部分を簡単に /*~*/で囲むことが出来る様になります。

Neosnippetの設定

現在使っている設定がこんな感じ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if s:neobundle_enabled && ! empty(neobundle#get("neosnippet"))
  imap <C-s> <Plug>(neosnippet_expand_or_jump)
  smap <C-s> <Plug>(neosnippet_expand_or_jump)
  xmap <C-s> <Plug>(neosnippet_expand_target)
  let g:neosnippet#enable_snipmate_compatibility = 1
  let g:neosnippet#disable_runtime_snippets = {'_' : 1}
  let g:neosnippet#snippets_directory = []
  if ! empty(neobundle#get("vim-octopress-snippets"))
    let g:neosnippet#snippets_directory += ['~/.vim/bundle/vim-octopress-snippets/neosnippets')]
  endif
  let g:neosnippet#snippets_directory += ['~/bundle/neosnippet-snippets/neosnippets')]
  if ! empty(neobundle#get("vim-snippets"))
    let g:neosnippet#snippets_directory += ['~/bundle/vim-snippets/snippets')]
  endif
endif

取り敢えず最低限必要なのが

1
2
imap <C-s> <Plug>(neosnippet_expand_or_jump)
smap <C-s> <Plug>(neosnippet_expand_or_jump)

の部分 2

これで、スニペット名を入力した状態でCtrl-sを押すと スニペットを展開してくれます。

また、展開後にはまず一番数の少ないplacefolder上へセレクトモードで移動するので、 すぐに書き込める様になっています。 その後はインサートモードかセレクトモードに居る限り Ctrl-sによって次のplacefolderへ移動出来ます。 一度ノーマルモードに戻ってももう一度インサートモードに入ると placefolderが残ってる限りCtrl-sで飛べます。

1
  xmap <C-s> <Plug>(neosnippet_expand_target)

の設定は上の${1:TARGET}への挿入するための設定。

ビジュアルモードで範囲を選択した後、 Ctrl-sを押すと、

Please input snippet trigger:

と聞かれるので、上の例に在るcommentのようなTARGETを含むスニペット名を入力すると TARGET部分を選択部分で置換した状態で展開してくれます。

それ以下の部分はneosnippet-snippets以外のスニペットを読み込むための設定です。 neosnippet-snippetsだけ使うのであればこれらは必要ありません。

1
let g:neosnippet#enable_snipmate_compatibility = 1

honza/vim-snippets 等、元々snipmate用等に作られた物との互換性を上げるための設定。

その後、

1
let g:neosnippet#disable_runtime_snippets = {'_' : 1}

で、一旦 Shougo/neosnippet-snippets を無効にしています。

その後の、 g:neosnippet#snippets_directoryにスニペットのディレクトリを指定することで スニペットを追加していくことが出来るのですが、 スニペットは同じ名前のものがあったりすると先に定義されてたものが優先されるので、 自作の物を優先させるために一度 Shougo/neosnippet-snippets を無効にし、 後からユーザー定義のものと同様に g:neosnippet#snippets_directoryに入れる事で読み込んでいます。

優先順として

の順。

vim-octopress-snippets

Octopressで自分でよく使う物を入れたものです。

honza/vim-snippets の中にあるmarkdown.snippetsにもOctopressのcodeblockgist等、一部のスニペットが入っていますが、 それに付け加える形でLiquidのコメント等や、 追加プラグイン用のスニペットなどを加えてあります。

またcodeblとして

1
2
3
4
5
6
7
snippet codebl
abbr {% codeblock <title> lang:<language> %}~{% endcodeblock %}
options head
  {% codeblock ${1:#:title} lang:${2:#:language} %}
  ${3:#:code_snippet}
  {% endcodeblock %}
  ${0}

の様に codeblockの定義 を作っています。

元々、 Shougo/neosnippet-snippets の中にはcodeblockというスニペット名で三点バックチックのコードブロック、 また、 honza/vim-snippets の中には codeblock-shortcodeblock-fullという名前で Octopressのra{% codeblock %} なコードブロックの タイトルとか何もない物とtitle/lang/url/textのplacefolder付きの物が入っています。

よく使うのはtitleとlangだけなのでちょっと毎回消すだけに移動するのも面倒なので 別途上のcodeblを作っています。

最初、これをcodeblockという名前で登録したくて上に書いたような スニペットの読み込み順の変更等をしてみたんですが、 一応三点バックチックとかぶらない様につくろう、ということで名前を変えてあります。 (なので設定ファイルでわざわざ上の様にする必要も無いのですが、いずれ必要になるかもしれないので 取り敢えずそのままに。)

Sponsored Links
  1. 現在はこれの後継の Neocomplete を使っています。

  2. Neosnippetの例とかだと良く<C-k>へマッピングしてます。 <C-s>も特に使ってないので今回はそちらに設定。

Sponsored Links

« Vimでシェルスクリプトを書く時の'w'の挙動 Google Chromeの右上のユーザー表示を名前から元の画像表示に戻す »

}