読者です 読者をやめる 読者になる 読者になる

特定の列まで指定した文字を連続入力するVim pluginを作った

この記事はVim Advent Calendar 2012の172日目の記事です。
171日目はmanga_osyoさんによるunite-source を作成する流れをまとめてみたでした。

整形のために、スペースをたくさん入力するのが億劫だったので題記のプラグインを作りました。 本記事はこのプラグインについての紹介記事です。

目的

コーディング規約にもよると思いますが、上の行とxxの文字と揃えるために insert modeでスペースをたくさん入力するようなケースがたまにあります。

例えば、以下の様なケース

  // ケース1
  int hogehogehoge = 0;
  int hoge         = 0;
  //      ^^^^^^^^^
  //      ここの部分のスペース

  // ケース2
  callfuncion("hoge"
             ,"hige");
//^^^^^^^^^^^
//ここの部分のスペース

ケース1は、aligntaというVim pluginで整形可能で、 ケース2は、言語によってはset indentexprが設定されていて自動で入力されたりします。

でもたまに、言語が対応してなかったり、思うようにスペース入れてくれなくて <Space><Space><Space>...とか、<Tab><Tab><Tab>...とかしてて悲しくなることがあります。 Vim使ってて、繰り返し同じキー打ってる時ほど悲しい気分になることはないので 改善することにしました。

使い方

目的の例のケース2について使い方を載せます。 なお、本プラグインはinsert modeで使うことを意図したプラグインです。

以下のアニメーションGIFをご覧ください。

f:id:deris:20130522003802g:plain

ちょっとわかりづらいかもしれませんが、insert modeで、callfunctionの下の行に カーソルがある状態で、<C-k>(デフォルトキーマッピングの場合)をタイプすると Insert above column:というメッセージが表示されるので、(とタイプし、 Insert insert column:というメッセージが表示されるので、スペースをタイプすると、 callfunctionの行の(の列までスペースが入力されます。
((が複数ある場合は、直近の(まで入力されます。)

Insert above column:で入力する文字、Insert insert column:で入力する文字は あらかじめキーマッピングで指定することができるので、例えば必ずスペースを 入力するのであれば、Insert insert column:を出さないことも可能です。

また、上の行ではなく、下の行を見たい場合は<C-j>(デフォルトキーマッピング) を使えますし、入力する位置の終端が気に食わなければオプションで調整出来ます。

インストール方法

プラグイン名はfit-columnという名前で、githubにあげてます。
(helpは、間に合わなかったので明日くらいには上げる予定です。)

なので、NeoBundleを入れていれば.vimrcに以下を書いておけばインストール出来ます。

NeoBundle 'deris/vim-fitcolumn'

もちろん、.vim配下に突っ込んでも構いません。

設定方法

デフォルトキーマッピングが以下のように割り当てているため、これで良ければそのまま使えます。

" デフォルトキーマッピング
imap <C-k>  <Plug>(fitcolumn-abovecolumn)
imap <C-j>  <Plug>(fitcolumn-belowcolumn)

デフォルトキーマッピングが気に入らなければ以下のように.vimrcに書けば変更できます。

" デフォルトキーマッピングを変更
let g:fitcolumn_no_default_key_mappings = 1
imap <C-h>  <Plug>(fitcolumn-abovecolumn)
imap <C-l>  <Plug>(fitcolumn-belowcolumn)

さらにデフォルト動作が気に入らなければ、関数にマッピングすることで設定出来ます。 例えば、入力する文字を手動入力でなく、固定でスペースに割り当ててしまいたい場合、 以下のように設定することで割り当てられます。

" 入力文字をスペースにする
let g:fitcolumn_no_default_key_mappings = 1
inoremap <expr> <C-k>  fitcolumn#fitabovecolumn({
  \ 'insertchar': ' ',
  \ })
inoremap <expr> <C-j>  fitcolumn#fitbelowcolumn({
  \ 'insertchar': ' ',
  \ })

他にも、searchcharrightwardというオプションがあります。
searchcharは、使い方の章で紹介したInsert above char:で 入力する文字を指定することができます。
rightwardは、スペースを入力する終端を数値で微調整できます。 例えば、1を指定すると1文字多めに文字を入力します。 マイナスも指定出来ますが、入力する文字がなくなった場合は 何も入力されません。

例えば、以下のように設定出来ます。

" 上(下)の行の、'('と同じ位置まで、スペースを入力する
let g:fitcolumn_no_default_key_mappings = 1
inoremap <expr> <C-k>  fitcolumn#fitabovecolumn({
  \ 'insertchar': ' ',
  \ 'searchchar': '(',
  \ 'rightward': 1,
  \ })
inoremap <expr> <C-j>  fitcolumn#fitbelowcolumn({
  \ 'insertchar': ' ',
  \ 'insertchar': '(',
  \ 'rightward': 1,
  \ })

おまけ(考察)

使い方のケース2で挙げたケースの場合は、set indentexpr用の関数書いて設定するのが正解な 気もするんですが(lingrvim部屋でご指摘頂きました。)、 別解を思いついて作ってしまったのでVACに書いて公開することにしました。

作ってみたものの、使い道は限られるかもしれません。

まとめ

以上が、自作Vim pluginのご紹介でした。

あと、本題とは関係ありませんが、Vimレベルが上がるのでvimrc読書会に参加することをおすすめします。毎週土曜日23時からやってます。

それではVim Advent Calendar 2012の172日目を終わります。

明日のVim Advent Calendar 2012はthincaさんです。

追記(2013/5/22)

記載を忘れていたので追記します。

  • 今のところタブは対応していません。要望があれば対応するかも