implementing text objects

vim にあって、vi にないものはそりゃたくさんあるわけだけど、今回は vim 界で言うところのテキストオブジェクトを考える。

vi コマンドをオペレーション+モーションの組み合わせて実行する際、vim ではモーションの代わりにテキストオブジェクトを指定することができる。[cci]yaw[/cci] と入力すれば、[cci]aw[/cci] がテキストオブジェクト。これは vi で [cci]yw[/cci] と入力するのと何が違うのかといえば、後者は対象になるのがカーソル以降の単語構成文字だけであるのに対し、前者はカーソル位置から必要なら前方・後方に同時に範囲を拡張する。

つまり

foobar
~

という状態のとき(tilde はカーソル)、[cci]yw[/cci] は “bar” が、一方 [cci]yaw[/cci] では “foobar” がヤンクされる。これだけなら、「ふーん。[cci]byw[/cci] すりゃいいじゃん」ということなのだが、テキストオブジェクトとブラケットを組み合わせると真価を発揮し始める。


function (foo, bar, baz) {
~

という状態のとき、[cci]yi([/cci] と打つ。これは ( ~ ) 内の範囲をヤンクする。これはピュアな vi コマンドだけでは容易に代替できない。

というわけで、これを移植してみたい。ただ、「テキストオブジェクト」という命名はちょっと大げさというか、微妙に分かりづらいと思うんですけど……。テキストオブジェクトというのは本来テキスト中のとある範囲のことであって、コマンド中で指定するのはそれを指す名前でしかない。名前はオブジェクトではない。Range Symbol くらいでいいんじゃないだろうか。うんそうだ。そうしよう。

vim のテキストオブジェクトは、以下の種類がある。これは vim で [cci]:help objects[/cci] すれば出てくる。

|v_aquote| a" ダブルクォートで囲まれた文字列
|v_a'| a' シングルクォートで囲まれた文字列
|v_a(| a( ab と同じ。
|v_a)| a) ab と同じ。
|v_a<| a< "a <>" '<' から '>' までを選択。
|v_a>| a> a< と同じ。 |v_aB| aB "a Block" "[{" から "]}" までを選択(括弧を含む)。 |v_aW| aW "a WORD" (ホワイトスペースを含む) |v_a[| a[ "a []" '[' から ']' までを選択。 |v_a]| a] a[ と同じ。 |v_a`| a` バッククォートで囲まれた文字列 |v_ab| ab "a block" "[(" から "])" までを選択(括弧を含む)。 |v_ap| ap "a paragraph" (ホワイトスペースを含む) |v_as| as "a sentence" (ホワイトスペースを含む) |v_at| at "a tag block" (ホワイトスペースを含む) |v_aw| aw "a word" (ホワイトスペースを含む) |v_a{| a{ aB と同じ。 |v_a}| a} aB と同じ。 |v_iquote| i" ダブルクォートで囲まれた文字列。ダブルクォートは含まない。 |v_i'| i' シングルクォートで囲まれた文字列。シングルクォートは含まない。 |v_i(| i( ib と同じ。 |v_i)| i) ib と同じ。 |v_i<| i< "inner <>" '<' から '>' までを選択。
|v_i>| i> i< と同じ。 |v_iB| iB "inner Block" "[{" から "]}" までを選択。 |v_iW| iW "inner WORD" |v_i[| i[ "inner []" '[' から ']' までを選択。 |v_i]| i] i[ と同じ。 |v_i`| i` バッククォートで囲まれた文字列。バッククォートは含まない。 |v_ib| ib "inner block" "[(" から "])" までを選択。 |v_ip| ip "inner paragraph" |v_is| is "inner sentence" |v_it| it "inner tag block" |v_iw| iw "inner word" |v_i{| i{ iB と同じ。 |v_i}| i} iB と同じ。

つまり、

range_symbol := inclusion_specifier range_specifier
inclusion_specifier := i | a
range_specifier :=
double_quote | single_quote | back_quote
| square_bracket | curly_bracket | angle_bracket | parentheses
| word | big_word
| paragraph | sentence | tag_block
double_quote := "
single_quote := '
back_quote := `
square_bracket := [ | ]
curly_bracket := { | } | B
angle_bracket := < | >
paretheses := ( | ) | b
word := w
big_word := W
paragraph := p
sentence := s
tag_block := t

こんな感じになる。

Leave a Reply

Your email address will not be published. Required fields are marked *