はわわーっ

はわわわわっ

Vimで突然の死に備える

この記事はVim Advent Calendar 2012 : ATNDの66日目の記事になります。
65日目はおしょーさんのそうだ Vim で画像を表示させよう - C++でゲームプログラミングでした。

さて、Vimで突然の死というと

こんな感じにいろんな人が作っています。たくさんありますね。

ちなみに突然の死ってのは

_人人人人人_
> 突然の死 <
 ̄^Y^Y^Y^Y^Y ̄

こんなやつです。

この記事ではこの枠を作るオペレータを作りましょう。
完成品はyomi322/vim-operator-suddendeath · GitHubにあります。
kana/vim-operator-user · GitHubに依存しています。

まず、plugin/ 以下のファイルでオペレータの定義をします。

" plugin/operator/suddendeath.vim

call operator#user#define('suddendeath', 'operator#suddendeath#do')

これでoperator-userが <Plug>(operator-suddendeath) というマッピングを定義して、
それが operator#suddendeath#do() という関数を呼び出すことになります。

あとはこの関数の中で枠をつけましょう。

" autoload/operator/suddendeath.vim

function! operator#suddendeath#do(motion_wise)
  if a:motion_wise !=# 'line'
    echoerr 'operator-suddendeath supports linewise only'
    return
  endif
  let put = getpos("']")[1] == line('$') ? 'p' : 'P'
  normal! `[V`]d
  let str = split(@", '\n')
  let @" = s:to_suddendeath(str)
  execute 'normal!' put
endfunction


function! s:to_suddendeath(str)
  let width = max(map(copy(a:str), 'strwidth(v:val)'))
  let mb_width = width / 2 + 1
  let suddendeath = '_' . repeat('人', mb_width) . '_' . "\n"
  for s in a:str
    let w = strwidth(s)
    let suddendeath .= '> ' . s . repeat(' ', width - w) . ' <' . "\n"
  endfor
  let suddendeath .= ' ̄' . repeat('^Y', mb_width) . ' ̄' . "\n"
  return suddendeath
endfunction

この関数には引数として charactorwise, linewise, blockwiseのどれでオペレータが呼ばれたかを示す文字列が渡されます。
ここではlinewise以外のときにエラーを出して終了するようにしてます。
選択された部分は

normal! `[V`]d

で取得しています。(:help `[ や :help `] が参考になります。)
これで無名レジスタに文字列が入るので
それを s:to_suddendeath() で枠を付けた文字列にします。
無名レジスタには @" でアクセスできます。
レジスタについては :help registers や :help @ や :help let-@
あたりが参考になります。
最後に

execute 'normal!' put

で張り付けてます。

使い方は

map X <Plug>(operator-suddendeath)

みたいに適当なキーにマッピングすればよいです。
それから

突然の死

とか書いて XX すると

_人人人人人_
> 突然の死 <
 ̄^Y^Y^Y^Y^Y ̄

こうなります。
複数行にも対応しているので

突
然
の
死

これで Xip すると

_人人_
> 突 <
> 然 <
> の <
> 死 <
 ̄^Y^Y ̄

こうなります。
さらに . で繰り返しすると

_人人人人人_
> _人人_ <
> > 突 < <
> > 然 < <
> > の < <
> > 死 < <
>  ̄^Y^Y ̄ <
 ̄^Y^Y^Y^Y^Y ̄

こうなります。便利ですね。

ちなみに、余分に空行が入ることがありますが
どうすればいいかよくわからないので放置してます。

これで突然の死に備えることができましたね。

明日は@supermomongaさんです。
(いつまで続くんだろう……)