Vimの様々なカーソル移動のやり方

こんにちは。
ゴリラです。

Vimには`hjkl`以外にも様々のカーソル移動のやり方があります。本日はVim標準機能でカーソル移動のやり方について紹介します。
狙ったところにスパッと行けると気持ちいいし編集も早くなるので、いろいろなやり方を知っておくと吉です。

# 単語単位の移動
## 単語の種類
単語は大きく分けて2種類あります。`word`と`WORD`です。
wordの定義は`:h word`でヘルプを引くと次のようになっています。

```
word はアルファベット、数字、アンダースコア、もしくは他の非空白文字の連続で構
成され、ホワイトスペース(スペース、タブ、<EOL>)で区切られます。これらは
'iskeyword' オプションで変更することができます。空行もwordとみなされます。
```

ここでいうその他の非空白文字は、例えば記号などです。
1例ですが、`hello-1%`はデフォルトでは4wordになります。`hello`と`-`と`1`と`%`ですね。

単語の定義をユーザが自前で追加することができます。
これはヘルプの通り`iskeyword`オプションで単語のパターンを定義できます。
例えば`$name`を1単語として扱うには`set iskeyword+=$`で`$`を追加します。PHPを書くときはこのような設定をしておくと吉です。

もう1つのWORDの定義は`:h WORD`でヘルプを引くと次のようになっています。

```
WORD は非空白文字の連続で構成され、ホワイトスペースで区切られます。空行もまた
1つの WORD と見なされます。
```

`WORD`はシンプルです。例えば`hello-1% &*gorilla`は2`WORD`になります。
`word`と`WORD`は文章だけだと分かりづらいので、gifを一応用意しましたが、ぜひ自分で動かしてみてください。

## wordの移動
|コマンド   |説明                                    |例                                                                                                                       |
|-----------|----------------------------------------|-------------------------------------------------------------------------------------------------------------------------|
|`[count]w` |`[count]` wordの前方に移動              |![vim-w.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/80c1e256-5402-4920-8762-e10b17929f23.gif) |
|`[count]e` |`[count]` wordの前方の単語の終わりに移動|![vim-e.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/13d25c45-de39-e4d8-bf27-30801a96cb31.gif) |
|`[count]b` |`[count]` wordの後方に移動              |![vim-b.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/ba7661fd-a780-6012-be5d-d697ceae7e31.gif) |
|`[count]ge`|`[count]` wordの後方の最後に移動        |![vim-ge.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/3e2a00b8-525f-c05e-5f0c-3c4f72505172.gif)|

## WORDの移動
|コマンド   |説明                                    |例                                                                                                                           |
|-----------|----------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
|`[count]W` |`[count]` WORDの前方に移動              |![vim-big-w.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/daf9a00d-cb00-8868-ffdc-697ac7540ae7.gif) |
|`[count]E` |`[count]` WORDの前方の単語の終わりに移動|![vim-big-e.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/4d671a6a-59b7-76e1-23e1-00b4c1232699.gif) |
|`[count]B` |`[count]` WORDの後方に移動              |![vim-big-b.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/a6d4e543-4925-3696-4ac2-513d39c0e080.gif) |
|`[count]gE`|`[count]` WORDの後方の単語の最後に移動  |![vim-big-ge.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/39fabb25-4bc9-8fd1-61c5-cc46031f23db.gif)|

# `f`と`t`で横移動
## 特定文字に移動
`[count]f{char}`で現在行の右に向かって`[count]`目の`{char}`に移動できます。
個数をぱっと見てわかるならカウントを使うと良いですが、ぱっとみてもわからないことが多いので、
そういうときはカウントを使わず、`;`で対象の`{char}`に移動するとよいと思います。

左に向かって移動したい場合は`F`になります。
次のgifは`f`を使って`o`の文字に移動したあとに、`;`で次のoに移動する例になります。

![vim-f.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/885c4b29-336b-774f-b143-0587360e9903.gif)

ちなみに、`f`、`F`はモーションなので、オペレーターと組み合わせる事ができます。`df{char}`で`{char}`までのテキストを削除できたりします。便利ですね。

## 特定文字の手前に移動
`[count]t{char}`で現在行の右に向かって`[count]`目の`{char}`の1つ左の文字に移動します。
左に向かって移動したい場合は`T`になります。
こちらもモーションです。次のgifはオペレーターと組み合わせた例になります。

![vim-t.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/5fde0eb0-e077-adf2-ab5b-76f9e7870c4d.gif)

# 先頭、末尾に移動
`^`で行頭の非空白文字、`$`で行末に移動できます。行末の非空白文字に移動したい場合は`g_`を使うと吉です。

# 対となる文字に移動
`%`を使うと対象の文字に移動できます。例えば`{"name": "gorilla"}`の場合`{`にカーソルをおいた状態で`%`を使うと`}`に移動します。
デフォルトは`([{}])`ですが、`matchpairs`オプションでカスタマイズすることができます。

例えば`set mps+=ウ:ホ`を設定すると`ウ`で`%`を使うと`ホ`に移動できます。次のgifはその一例になります。

![vim-match.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/c9a00f04-8a75-e287-11d9-9788313bccd9.gif)

# 指定行に移動
`[count]G`もしくは`[count]gg`で`[count]`行目の最初の非空白文字に移動できます。
`gg`と`G`はジャンプモーションと呼ばれていて、ジャンプリストという履歴に残ります。

これの何が便利かというと、`[count]Ctrl-o`で`[count]`だけ古いカーソルの位置、`[count]Ctrl-i`で`[count]`だけ新しいカーソル位置に移動できます。
ジャンプリストは`:jumps`で確認できます。

ジャンプモーションは他にもいくつかあります。`:h jump-motions`で参照してください。

ちなみに、指定した行に移動する方法として`:10`というように行数を指定することで、その行数に移動できます。
ただ、これはジャンプリストには履歴として残らないので、筆者は`gg`もしくは`G`をおすすめします。

## 指定行分を移動
`[count]j`/`[count]k`で現在行から`[count]`行分移動できます。例えば`2j`なら2行下の行に移動できます。
こういった移動の仕方をよく使う時は`:set relativenumber`を設定しておくと便利です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/a3f6ae24-f777-1518-b889-99e378cd7d2e.png)

設定すると画像のように、現在行との差分の行数が表示されます。こうすれば計算しなくて済むので楽です。

## 段落の移動
`{`段落の後方に、`}`で段落の前方に移動します。
段落の定義は`:h paragraph`でヘルプを引くと次のようになっています。

```
段落はそれぞれ空行の後から始まり、そしてまた段落マクロのセットからそれぞれ始ま
ります。段落マクロは 'paragraphs' オプションで指定されている文字のペアです。デ
フォルトで "IPLPPPQPP TPHPLIPpLpItpplpipbp" で、".IP", ".LP", などのマクロに一
致します(これらは nroff のマクロです。ですのでドットは1桁目になければなりませ
ん)。セクションの境界は段落の境界でもあります。空行(ホワイトスペースのみを含む
行)は、段落の境界ではないということに注意してください。
これは '{' か '}' を1桁目には含んでいないということにも注意してください。
'cpoptions' にフラグ "{" が入っていると1桁目の "{" が段落の境界とみなされるよ
うになります。|posix|
```

難しいこと書いてありますが、`段落は空白の行のあとから始まる`というのを理解していれば良いと思います。
つまり、段落の間の空白に移動するということです。

# 検索による移動
これはあまり知られていないかもしれませんが、`/`の検索もモーションの1つです。
例えば`v`で選択したあとに`n`や`N`で移動すると選択は選択範囲が移動したカーソルまで広がります。
次のgifはその一例です。

![vim-search.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/c98cc478-704e-5ce1-80a0-1a158da9fbb9.gif)

モーションなので、もちろんオペレーターと組み合わせることもできます。
例えば`d`のあとに`/\/`で`/`を検索してEnterを押すと現在のカーソル位置から`/`までのテキストを削除します。
次のgifがその一例です。

![vim-d-search.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/af37b66b-ee29-6c69-18fb-1dca00f57988.gif)

他に`*`によるカーソル下の単語検索もとても便利です。


個人的にこの検索によるカーソル移動は一番汎用性があると思っています。
これまでに紹介してきた移動方法は縦か横のみですが、検索はそういった制限はなく自由度も高いです。

![vim-search-asta.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/a682424e-55f6-24dd-1dc9-dfe674c2f20b.gif)

# マークによる移動
Vimにはマークと言う機能があり、`m{a-zA-z0-9}`でカーソル位置をマークすることができます。これはブックマークのような機能になります。
小文字はファイル内のみ使用可能なマーク、大文字と数字はファイル間の移動ができるマークになります。
マークした場所にジャンプしたい場合は`` `{mark}``というように`` ` ``に続けてマークを入力します。

次のgifがマークの一例です。

![vim-mark.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/9a59aa45-f6eb-1d36-bd51-aecbb28333a8.gif)

`:marks`で現在のマークを確認する事ができます。
ちなみに、マークもモーションの1つなので、オペレーターと組み合わせて使うことも可能です。

マークについてより詳しく知りたい方は`:h mark-motions`を参照してください。

# まとめ
筆者が普段使っている移動方法について一通り紹介しました。本記事を読んで、編集の効率が上がったら嬉しいです。
実は、まだまだ他にもたくさんの移動法があります。筆者も全てを把握していません。
興味ある方は`:h motions`でヘルプを読むと吉です。

ではよいVimライフを〜