VimのText Objects を正しく理解する

Windows, Linux, MacOSどのOSでも利用できるエディタということで個人的にVimを愛用しています。私たちの会社では、エンジニアはエディタは各々好きなものを利用することにしているので、社内では他にもEmacsEclipseやメモ帳などが使われています。メモ帳Hacksは別の人に任せるとして、今回はVim派を代表して、Vimの便利な機能の中でも意外と活用されていないText Objectsについて紹介したいと思います。

基本となるText Objects

Vimには3種類の基本となるText Objectsが存在します。単語、文章、段落の3種類です。まずは単語から見てみましょう。

aw
前後の空白を含む単語(a word)
iw
前後の空白を含まない単語(inner word)

aが冠詞のaを表し、iがinnerを表し、wは単語を表しています。同じように文章と段落は以下の様に表現されます。

as
前後の空白を含む文章(a sentence)
is
前後の空白を含む文章(inner sentence)
ap
前後の空白を含む段落(a paragraph)
ip
前後の空白を含む段落(inner paragraph)

sが文章を表し、pが段落を表しているのは説明するまでもないですね。ただ、これだけでは何を言っているのかわかりませんよね?awとタイプしてもwと追記されるだけですし、もう少し見ていきましょう。

Text Objectsの操作

VimはこれらのText Objectsを対象として様々な操作を行うことができます。操作をする時のコマンドの形式は以下の様になります。

<回数><操作><Text Objects>

Vimを使っている人であれば、いつものやつね。という感じかもしれませんが、6ddとタイプして6行削除する様な操作と同じ形式です。
例えば以下のような文章を例に見てみましょう(カーソルはproductsのdにあたっている前提)。

It's really hard to design pro"d"ucts by focus groups. 

単語を前後の空白も含めて消したい場合、daw(delete a word)とタイプすると以下のようになります。前後の空白を含めて消去と言いましたが、正確には削除後にdesignとbyの間に空白が1つ残っている点に注意してください。

It's really hard to design by focus groups.

またdiwとタイプすると以下のようになります。わかりにくいですが、designの後にスペースが2つ続いています。

It's really hard to design  by focus groups.

ではdwと何が違うのでしょうか?dwとタイプすると以下のようになります。

It's really hard to design proby focus groups.

dwはそのカーソルの位置からそれ以降の単語を削除するため、単語を丸ごと消したい場合bなどを利用して単語の先頭へカーソルを移動させる必要がありましたが、Text Objectsを利用するとカーソル移動を省略できます。bdwとdawでタイプ数変わらないじゃん、という冷静な突っ込みは無視します。この例ではd(削除)を行いましたが、その他にもc(変更), y(ヤンク/コピー)もできます。同様に文章や段落も、das, dis, dap, dipでそれぞれ削除できます。
尚、2dawとタイプすると以下のように2単語が削除されます。

It's really hard to design focus groups.

ちなみに2diwとタイプすると以下のように1単語しか削除されていないように見えますが、iwは1つ以上連続したスペースを1つのinner wordとして見なすため、2diwとタイプするとproductという単語とスペース1つが削除されているというわけです。

It's really hard to design by focus groups.

また日本語の場合はどうなるのでしょうか?以下の文を例に見てみましょう(カーソルはフォーカスグループのスにあたっている前提)。

フォーカ"ス"グループによって製品をデザインするのはとても難しい。

単語を削除するためにdawとタイプすると

によって製品をデザインするのはとても難しい。

このように意図した通りにフォーカスグループという単語全体が削除されます。実はdiwとタイプしても同様に単語全体が削除されます。

によって製品をデザインするのはとても難しい。

このように日本語は単語間にスペースが無いため、dawとdiwの結果は同じになるようです。

プログラミング/マークアップに利用できるText Objects

w(単語)、s(文章)、p(段落)に対する操作を見てきましたが、プログラミングやマークアップでは以下のText Objectsの方が利用できます。個人的にもプログラミングをする際には、こちらの方が利用頻度は高いのでよく使うものから覚えて慣れておくとよいと思います。

a]
前後のを含むで囲まれたブロック
i]
前後のを含まないで囲まれたブロック
a)
前後の()lを含む()で囲まれたブロック
i)
前後の()を含まない()で囲まれたブロック
a>
前後の<>を含む<>で囲まれたブロック
i>
前後の<>を含まない<>で囲まれたブロック
a}
前後の{}を含む{}で囲まれたブロック
i}
前後の{}を含まない{}で囲まれたブロック
a"
前後の""を含む""で囲まれたブロック
i"
前後の""を含まない""で囲まれたブロック
a'
前後の''を含む''で囲まれたブロック
i'
前後の''を含まない''で囲まれたブロック
at
前後のタグ(htmlやxmlタグなど)を含むタグで囲まれたブロック
it
前後のタグ(htmlやxmlタグなど)を含まないタグで囲まれたブロック

コマンドを忘れた場合も:help text-objectsで調べられるので併せてそちらも活用してください。