【vim】あたま空っぽでカーソル移動するために

音を置き去りにした

# カーソル移動について考える
N番煎じというか、人類は一生同じこと考えてるなって思いますが
カーソル移動をいかに最適化するかはQOLに直結します（諸説あり）
人生の満足度あげていきましょう

## 移動
~~みなさんのうちにVSCodeユーザなんていないと思いますが~~
VSCodeユーザがもしいれば、基本的にマウス操作か
vimプラグインを入れてjkhlしているでしょう。

世の中には[視線入力](https://www.dinf.ne.jp/d/0/283.html#:~:text=%E8%A6%96%E7%B7%9A%E5%85%A5%E5%8A%9B%E8%A3%85%E7%BD%AE%E3%81%AE%E6%A9%9F%E8%83%BD,%E3%81%93%E3%81%A8%E3%81%8C%E5%8F%AF%E8%83%BD%E3%81%AB%E3%81%AA%E3%82%8B%E3%80%82)なんてものがあるらしいですが、大衆が一般導入するにはまだ早いでしょう。
ここはおとなしくvim操作をベースに考えるしかありませんね。いやぁしかたないなぁ。

まずは縦移動、横移動で分けて考える。
vimにおけるカーソル移動はデフォルトだと

### 縦移動
おおきめの移動 / 細かい移動
|キー|移動先|
|:--|:--|
|H|上のほう|
|M|まんなか|
|L|下のほう|
|{|段落上に|
|}|段落下に|

|キー|移動先|
|:--|:--|
|j|1行上|
|k|1行下|
|gj|表示行で1行上|
|gk|表示行で1行下|

※私は`nnoremap j gj`してます

### 横移動
※他にもありますが、私はだいたいこの辺しか使ってないです

おおざっぱに移動 / 細かい移動
|キー|移動先|
|:--|:--|
|0|いちばん左|
|^|行頭|
|$|行末|
|w|単語ごと移動 先頭文字に|
|e|単語ごと移動 単語末文字に|
|b|単語ごと移動 戻る|
|W E B|単語とみなす文字をおおざっぱに|

|キー|移動先|
|:--|:--|
|h|ひとつ左|
|l|ひとつ右|
|f{char}|カーソルから見て右に、最初の{char}に飛ぶ|
|F{char}|fの左向き|
|tT|fと同じで、{char}の一つ手前に飛ぶ|
|;|fFtT移動の繰り返し用|
|:|;の逆向き|

さて、このようにデフォルトでも十分思考のスピードですが
やはり`今ひとつ細かい移動が足りない`と感じます。このままでは**マウスを使った方が早い**。非常にまずい。

# 改善案
### 縦移動
##### おおきめの移動
`H` `M` `L`はとてもいいが、1ページに表示される行数はだいたい多くても50行。
私は46行です。
ここでHML移動だと、1行目、24行目、46行目に飛べますが
例えば`1-24`行目の間のどこかに飛びたい場合、最大でも12行目まで移動する`11回の縦移動`が必要となる。または
`H`で1行目に飛んだのちに`11j`とする必要があるが、

*数字を数えるくらいならj連打や長押ししたい*。

**プログラミング中に行数数える脳のリソースを割きたくない**。

ここで
```vim
set scrolloff=5
```
この設定を入れることで、`H`とした時1行目でなく、5行目に飛ぶ。
![HML_demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/7ad52bec-f4cd-d791-f512-5e7b990082e8.gif)


ページの上下5行までにしか、カーソルが行かないようになるのだ。
1行目に飛びたい場合こそ`H5k`になるが、12行目に飛びたい場合は`H5j`と、少し幅が狭まった。
そして、`set scrolloff=5`を入れるとだいたい
`H M L`の後に**5行**移動すれば、あと1,2行でゴール、まで行ける。だいたいね。
なので

```vim
nnoremap <Tab> 5j
nnoremap <S-Tab> 5k
```
この設定が活躍する。`<Tab>`キーで5行移動するのだ。
これにより`H M L <Tab> <S-Tab>`で、あたまからっぽでほぼゴールに辿り着ける。

##### 細かい移動
流石に1,2行の移動はjkでいいが、後述する`f移動`によりそれすら不要となるのでご期待ください。

### 横移動
##### おおざっぱに移動
やはり改善すべきは`f移動`。とても強力なジャンプ機能だが、飛びたい文字がカーソルからみて最初に出てきる文字なのかどうかがわからないので
`f{char}`の{char}が何かを見るために一瞬遅れる。非常によろしくない。
ので、

**一撃でf移動できる文字をハイライトする**

ことによりこれを改善する。後述します。

##### 細かい移動
これは不要と断言できる。なぜならvimのテキストオブジェクトは、カーソルが単語に上にさえいれば良いようにできているから。やっぱvimって神なんだなって思います。


# 現存するプラグイン
さて、これらをすでに解決しているプラグインが多数あります。人によって好みが分かれるので、お好きなものをお使いください。

##### vim-easymotion
2次元に移動する。
そもそも縦横でなく、飛びたい場所に一撃で飛ぶもの。
神なので入れてるが、個人的には視差が大きいので、ほんのわずかに集中力途切れるのが好ましくない。神プラグイン機能であることは間違いないしめっちゃ好きな機能ではあります。

https://github.com/easymotion/vim-easymotion

公式デモ
![easykmoton.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/821c517e-0544-2bb0-7fad-d3e03da57638.gif)

##### vim-edgemotion
縦移動の大幅改善。Excelとかで`Ctrl + ↑`とかと同じように、上下に文字がある行まで飛べる。easymotionと同じ作者なので、やはり神プラグイン。
私は主戦力として使ってます。

https://github.com/haya14busa/vim-edgemotion

公式デモ
![vim-edgemotion 2017-11-04 16-18.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/252c1aa2-6cbc-62bb-eb59-cbd62d08d427.gif)

なお、edgemotionをフル活用するために
```vim
set virtualedit=all
```
にすると、文字のない場所にもカーソルをおけるので便利。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/7de03505-015b-ba56-2505-2d335d2908e2.png)

##### clever-f.vim
横移動の`f移動`の連打`;`をより頭空っぽにするためのもの。
`;`とか`:`ってちょっと打ちにくいじゃないですか。。
f連打で繰り返しできるようになる上、**行をまたいでf移動できます**。

https://github.com/rhysd/clever-f.vim

公式デモ
![cleverf_main.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/aeeee25f-e113-a96e-2bee-bcc785be694c.gif)

##### quick-scope
f移動先の、`一撃で行ける文字を剪定`してハイライトしてくれるもの。
ただ単語の先頭文字をハイライトしてるだけじゃないです。何も考えずに
色ついてる文字に対して`f{char}`すればいいだけになる。
clever-fもあれば、本当に頭使わずに瞬間移動できる。

https://github.com/unblevable/quick-scope

公式デモ
![6ecbed28-158b-11e5-9474-89e846e7682c.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/196df591-6294-7f0a-2e89-ac7690d6a7e1.gif)

ほかにも多数ありますが、いったんここまでとします。

# より、あたまを空っぽに
さて、実はこれでもまだ弱いです。
横移動において、**その行までいかないと移動できない**のです。
当たり前かと思いますが、`だいたい近い行`まで来たらそのまま移動しきりたい。

これは
- quick-scopeが現在行しかハイライトしないこと
- それに対しclever-fが行をまたいでf移動できること

の噛み合わせの悪さにあります。
いくらclever-fで行をまたいで移動できようと、移動先の行にいかなければハイライトされないので
行跨ぎ機能 がいまいち生きていない。そこで

`前後n行のfな文字をハイライトする機能`および冒頭で紹介した`タブで5行移動`のプラグインを作成しました。

### vim-anchor5

https://github.com/serna37/vim-anchor5

![vim-anchor-demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/5871aa3a-23aa-ff15-f82f-bc4c2908155f.gif)

これあ5行移動するだけでなく、前後5行にマークをつけてくれるので
行きたい行まで行けてるのかどうかがぱっと見でわかります。


### vim-fscope-around
そして、マークのアンカーがある行内で、現在行の前後5行にquick-scopeをする。
さすがに全部の行で文字に色がつくと目がしんどいので
現在行以外は下線が引かれます。
もちろんハイライトを即座にオンオフできます。

https://github.com/serna37/vim-fscope-around

![fscope_anchor5_edgemotion.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/58f8488a-57d5-0b25-8b23-84c5e71d446c.gif)

↑のgifは
[vim-anchor5](https://github.com/serna37/vim-anchor5), [fscope-around](https://github.com/serna37/vim-fscope-around)に加えて
[edgemotion](https://github.com/haya14busa/vim-edgemotion), [clever-f](https://github.com/rhysd/clever-f.vim)
の組み合わせなどで実現できます。
`HML`や`}{`やタブ、`edgemotion`でだいたい縦に移動し、行きたい場所にハイライトがついたら`f{char}`し、たどり着くまでf連打するだけ。

これらによりあたま空っぽで光速移動できるようになりました。