Vim の map でコマンドを展開させた場合に任意の位置にカーソルを持ってくる

この記事は Vim Advent Calendar 2012 145日目の記事になります。


さて、先日 vimrc読書会でとある vimrc を読んでいると次のような感じに を多用しているマッピングがありました。

nnoremap <A-p> :%s//hoge/g<Left><Left><Left><Left><Left><Left><Left>


これは何をやっているのかというと :%s//hoge/g を展開した後にカーソル位置を左にずらしています。
つまり を呼び出すと

のようにカーソル位置がいい感じの位置に移動します。


これは便利そう、と思ったのですがいちいちカーソル位置の文字数を数えて を書くのはめんどくさいので簡単なラッパーを書いてみました。

function! s:move_cursor_pos_mapping(str, ...)
    let left = get(a:, 1, "<Left>")
    let lefts = join(map(split(matchstr(a:str, '.*<Cursor>\zs.*\ze'), '.\zs'), 'left'), "")
    return substitute(a:str, '<Cursor>', '', '') . lefts
endfunction

function! _(str)
    return s:move_cursor_pos_mapping(a:str, "\<Left>")
endfunction


" 展開後 <Cursor> 位置にカーソルが移動する
nnoremap <expr> <A-p> _(":%s/<Cursor>/ほむ/g")
" nnoremap <expr> <A-p> ":%s//ほむ/g\<Left>\<Left>\<Left>\<Left>\<Left>\<Left>\<Left>"
" と等価


" コマンド版
command! -nargs=* MoveCursorPosMap execute <SID>move_cursor_pos_mapping(<q-args>)
command! -nargs=* Nnoremap MoveCursorPosMap nnoremap <args>

Nnoremap <A-o> :%s/<Cursor>/マミ/g


とりあえず、 版とコマンド版の2つを書いてみました。
どちらも 位置にカーソルが移動するように map を展開します。