Vim で複数の textobj を1つにまとめる textobj つくった

この記事は Vim Advent Calendar 2012 233日目の記事になります。
一昨日からメインのマシンが起動しなくなりましたが、わたしは元気です。


さて、前回は textobj プラグインをまとめてみました。
ご覧の通り textobj プラグインはたくさんあり、これを使い分けるのは大変ですし、使用するマッピングするキーもどんどん枯渇していきます。
そこで複数の textobj を1つにまとめ、抽象的に使用できるような textobj をつくりました。
この textobj を使用する事で設定した複数の textobj から最初にマッチした textobj を使用します。
要は文脈によって使用する textobj が変わるような感じです。
コンセプトとしては textobj-multiblock と似ています。

[インストール]

NeoBundle "osyo-manga/vim-textobj-multitextobj"
NeoBundle "kana/vim-textobj-user"

[使い方]

g:textobj_multitextobj_textobjects_i/a に textobj を設定して使用します。

" 上から順に適用していき、最初にマッチした textobj が使用される
let g:textobj_multitextobj_textobjects_i = [
\   'i"',
\   "i'",
\   "i)",
\]

let g:textobj_multitextobj_textobjects_a = [
\   'a"',
\   "a'",
\   "a)",
\]


omap imb <Plug>(textobj-multitextobj-i)
omap amb <Plug>(textobj-multitextobj-a)
vmap imb <Plug>(textobj-multitextobj-i)
vmap amb <Plug>(textobj-multitextobj-a)


: カーソル位置
: 範囲

" imb
'word'

" amb
"word"

" imb
(word)

" imb
" 一番最初の textobj が使用される
" (word) "

[使い方2]

リストの要素にリストを設定すれば、全ての textobj を適用し、一番内側の textobj が使用されます。

" 上から順に適用していき、最初にマッチした textobj が使用される
let g:textobj_multitextobj_textobjects_i = [
\   "i)",
\   ['i"', "i'"],
\]

let g:textobj_multitextobj_textobjects_a = [
\   "a)",
\   ['a"', "a'"],
\]


omap imb <Plug>(textobj-multitextobj-i)
omap amb <Plug>(textobj-multitextobj-a)
vmap imb <Plug>(textobj-multitextobj-i)
vmap amb <Plug>(textobj-multitextobj-a)


: カーソル位置
: 範囲

" imb
" 'word' "

" amb
' "word" '

" imb
( " word " )

[使い方3]

他の textobj と組み合わせて使う。

" 上から順に適用していき、最初にマッチした textobj が使用される
let g:textobj_multitextobj_textobjects_i = [
\   "\<Plug>(textobj-url-i)",
\   "\<Plug>(textobj-enclosedsyntax-i)",
\   "iw"
\]

omap imw <Plug>(textobj-multitextobj-i)
vmap imw <Plug>(textobj-multitextobj-i)


: カーソル位置
: 範囲

" imw
mado_https://github.com/osyo-manga/vim-textobj-multitextobj"mami

" imw
/homu\/\d+/

" imw
homu-mami-mado

[使い方4]

次のように複数の設定を行うことも出来ます。

" 複数の g:textobj_multitextobj_textobjects_i を設定
" キーには "A""E" が使用出来る
let g:textobj_multitextobj_textobjects_group_i = {
\   "A" : [
\       "i)",
\       ['i"', "i'"],
\   ],
\   "B" : [
\       "\<Plug>(textobj-url-i)",
\       "\<Plug>(textobj-enclosedsyntax-i)",
\       "iw",
\   ],
\}

" <Plug>(textobj-multitextobj-A-i) 〜 <Plug>(textobj-multitextobj-E-i)
" に対応している
map <Plug>(textobj-word-i)    <Plug>(textobj-multitextobj-A-i)
omap imw <Plug>(textobj-word-i)
vmap imw <Plug>(textobj-word-i)

map <Plug>(textobj-bracket-i) <Plug>(textobj-multitextobj-B-i)
omap imb <Plug>(textobj-bracket-i)
vmap imb <Plug>(textobj-bracket-i)


" 更に上記のマッピングを組み合わせて使用することも可
let g:textobj_multitextobj_textobjects_i = [
\   "\<Plug>(textobj-word-i)",
\   "\<Plug>(textobj-bracket-i)",
\   "\<Plug>(textobj-entire-i)"
\]

omap ims <Plug>(textobj-multitextobj-i)
vmap ims <Plug>(textobj-multitextobj-i)


: カーソル位置
: 範囲

" ims
mado_https://github.com/osyo-manga/vim-textobj-multitextobj"mami

" ims
/homu\/\d+/

" ims
homu-mami-mado

" ims
" 'word' "

" ims
' "word" '

" ims
( " word " )


と、いうような感じで使用します。
単純な textobj ですが複数の textobj をいい感じに使いこなす事ができるので個人的にはすごく便利です。
わたし自身もまだそこまで使いこなせていないのでなにか面白い使い方や不具合があれば教えて下さい。