Vimでoperator-userを使って他のプラグインをoperatorとして使えるようにしてみた
kanaさん作のoperator-userを使うと,簡単にoperatorを定義できる.operatorというのはここでは,Vimのコマンドのうちdwとかc$とかのdとかcとかの,動作を指定するコマンドのこと(こんな説明でいいのか,まぁ詳しくは:h operatorで(^-^;)).で,Vimにははじめから便利なoperatorが定義されていて,新たにoperatorを定義できると言われても,さてどうしたもんかと思っていた.
そんなときに,operator-userとは別に,commentop.vimというコメントアウト/アンコメントするためのoperatorを定義するプラグインを見つけて,あーなるほどこれは便利だと思った.ところが,コメント系のプラグインとしては,NERD Commenterが非常に高機能で便利に使っていたので,そこから機能が落ちるのはちょっとなぁとも思っていた.
というわけで,前置きが長くなったけど,それだったらNERD Commenterとoperator-userを組み合わせて新しいoperatorを作ったらいいんじゃね?ということでやったみた.以下を.vimrcなどに書いておけば,,cや,uなどといったoperatorが定義される.
function! s:SID_PREFIX()
return matchstr(expand('<sfile>'), '<SNR>\d\+_')
endfunction
noremap [Operator] <Nop>
map , [Operator]
" デフォルトのマッピング定義を行わない
let g:NERDCreateDefaultMappings = 0
nmap gA <Plug>NERDCommenterAppend
nmap [Prefix]a <Plug>NERDCommenterAltDelims
" NERDCommenter + operator-user
function! s:setCommentOperator(key, name)
call operator#user#define(
\ 'comment-' . a:name,
\ s:SID_PREFIX() . 'doCommentCommand',
\ 'call ' . s:SID_PREFIX() . 'setCommentCommand("' . a:name . '")')
execute 'map' a:key '<Plug>(operator-comment-' . a:name . ')'
endfunction
function! s:setCommentCommand(command)
let s:comment_command = a:command
endfunction
function! s:doCommentCommand(motion_wiseness)
let v = operator#user#visual_command_from_wise_name(a:motion_wiseness)
execute 'normal! `[' . v . "`]\<Esc>"
call NERDComment(1, s:comment_command)
endfunction
call s:setCommentOperator('[Operator]c', 'norm')
call s:setCommentOperator('[Operator]<Scace>', 'toggle')
call s:setCommentOperator('[Operator]m', 'minimal')
call s:setCommentOperator('[Operator]s', 'sexy')
call s:setCommentOperator('[Operator]i', 'invert')
call s:setCommentOperator('[Operator]y', 'yank')
call s:setCommentOperator('[Operator]l', 'alignLeft')
call s:setCommentOperator('[Operator]b', 'alignBoth')
call s:setCommentOperator('[Operator]n', 'nested')
call s:setCommentOperator('[Operator]u', 'uncomment')
一応ポイントとしては,NERDComment()という関数がNERD Commenterの本体で,第一引数を1にしておくと直前のVisual modeで選択された範囲に対して操作を行うというところ.なので,doCommentCommand()でoperatorの操作範囲を一旦Visual modeで選択してからEscするようにしている.NERD Commenterの各コマンドの意味は:h NERDComFunctionalitySummaryを参照ということで.
また,operatorは,例えばddで一行削除やyyで一行ヤンクというように,2回連続入力でその行全体に対して動作したり,Visual mode中では選択範囲に対して動作したりするのだが,operator-userで定義したoperatorもちゃんとそのように振る舞う.そのため,,c,cで一行コメントアウトやVisual mode中に,uで選択範囲をアンコメントといった動作も同時に定義される.なので,NERD Commenterのデフォルト定義は無効にしてある.
さらに,textobj-commentや textobj-indentといった,text objectとももちろん連携可能なので,使いこなせば光の速さでコメント操作ができるようになる!...はず!
あと,調子にのってAlignプラグインもoperator化してみたけど,さすがにこれはちょっと無理があると思った.自分ではたまに使おうと思うけど(^-^;)
2009/09/19 15:35 | Vim | トラックバック(0) | コメント(0)
コメントの投稿
トラックバック
トラックバックURL
→http://relaxedcolumn.blog8.fc2.com/tb.php/154-d00d36a6
コメント