Vimのcwとciwの違い 単語の途中にカーソルがあるときに差が出る
cwで単語を書き換えたつもりが、単語の後半だけ残ってしまったことがあります。単語の頭で試したときはうまくいったのに、途中のカーソル位置だと結果が変わります。ciwとの違いを理解していないと、この不一致にいつまでも振り回されることになります。
目次(8項目)
| キー | これだけ覚える |
|---|---|
| cw | カーソル位置から単語末尾までを変更(前半は残る) |
| ciw | カーソル位置に関係なく単語全体を変更 |
| w | モーション:次の単語の先頭までの相対範囲 |
| iw | テキストオブジェクト:単語そのものの絶対範囲 |
どちらも「変更」+「単語」だが範囲指定が違う
cwは変更のオペレータcとモーションwの組み合わせ、ciwは同じcとテキストオブジェクトiwの組み合わせです。両方とも「単語を変更する」という見た目ですが、対象範囲の決め方が異なります。
| 対象範囲 | |
|---|---|
| w(モーション) | カーソル位置から次の単語の頭まで |
| iw(テキストオブジェクト) | カーソルがどこにあっても、その単語全体 |
単語の先頭にカーソルがあるときは、この2つはたまたま同じ範囲になるので違いに気づきにくくなります。差が出るのは単語の途中にカーソルがあるときです。cwはそこから後ろだけを対象にするため、単語の前半が変更されずに残ります。ciwはカーソル位置に関わらず単語全体を対象にするので、常に単語まるごとを書き換えられます。
具体例で見る違い
test sentenceで、sentenceの3文字目(n、単語の途中)にカーソルを置いて実行すると差がはっきり分かります。
test sentence ^ カーソル
test seNEW
test sentence ^ カーソル
test NEW
同じカーソル位置から始めても、cwはそこから後ろのntenceだけを対象にするのに対し、ciwはカーソル位置に関係なくsentence全体を対象にします。
attempt の途中にカーソルがある状態で ciw を押し、counter と打ったところ実務ではciwを使う場面のほうが多い
カーソルを単語の先頭に正確に合わせてからcwを打つより、単語のどこにカーソルがあってもciwを打てば済むほうが速く済みます。移動の精度を気にしなくていい分、ciwのほうが実用上のミスが少なくなります。単語の一部だけを変更したい、という明確な意図があるとき以外はciwを選んでおけば安全です。
cwだけ覚えていた時期は、単語の途中にカーソルがあるたびに変更範囲がズレて、結局uで取り消してカーソルを単語頭に移動し直すという二度手間をやっていました。ciwを覚えてからはカーソル移動の精度を気にしなくてよくなり、単純に手数が減りました。今ではcwをあえて使う場面のほうが少なく、単語頭だと分かっている場合でもciwを打つ癖がついています。
cw が dw と違う範囲になる理由
単語の先頭にいるときでも、cw と dw は消える範囲が違います。dw は次の単語の先頭までなので後ろの空白まで消えるのに対し、cw は単語の末尾までしか消しません。つまり ce と同じ動きです。
これはVimがこのときだけ設けている例外です。単語を差し替えるときに後ろの空白まで消えてしまうと、入力し終わったあとに空白を打ち直すことになるためで、実際の使われ方に合わせた特例になっています。
この例外があるおかげで cw は使いやすい一方、dw との対称性が崩れています。ciw を覚えてしまえば、この例外を意識する場面自体がほとんど無くなります。
iw と aw の使い分け
テキストオブジェクトには iw のほかに aw があります。iw が単語そのものなのに対し、aw は単語と後ろの空白です。後ろに空白が無ければ、代わりに前の空白が含まれます。
使い分けは単純で、書き換えるときは iw、消すときは aw です。ciw なら空白が残るので打ち直した語がきれいに収まり、daw なら区切りの空白ごと消えるので、消したあとに空白が2つ並びません。
ciw " 単語を書き換える(空白は残る)
daw " 単語を空白ごと消す
diw " 単語だけ消す(空白が2つ並ぶ)
繰り返すなら ciw を選ぶ
同じ書き換えを何か所かで行うときは、ciw のほうが確実です。. で繰り返したとき、cw はそのときのカーソル位置によって範囲が変わりますが、ciw は単語のどこにいても同じ結果になります。
「カーソル位置に結果が左右されない操作を選ぶ」という考え方は、マクロを組むときにも同じように効きます。位置合わせに l を何度も使うような手順は再生時に壊れるので、内容を頼りに範囲が決まるテキストオブジェクトを使うほど、繰り返しに強くなります。詳しくはドットコマンドの記事にまとめています。
まとめ
cwとciwの違いは、モーション(相対的な範囲指定)とテキストオブジェクト(絶対的な範囲指定)の違いそのものです。この考え方はdwとdiw、ywとyiwなど他のオペレータでもそのまま成り立つので、1組覚えれば残りにも応用できます。似た系統の違いとして、cwとdwの間にも見た目以上に独自の癖があります。詳しくはcwとdwの違いのほうで扱っています。テキストオブジェクトは単語だけのものではありません。括弧や引用符の中身を指すi(やi"も同じ形で、ci(のように組み合わせて使えます。
ここで扱ったキーは、ブラウザ上で動くVim道場の中身をまとめて狙うでそのまま試せます。インストールもログインも要りません。