†二分探索†で怠惰なカーソル移動をしよう
まえがき
vim のカーソル移動…面倒臭いですよね…
特に縦移動
これを補助するプラグイン等はあるのですが、ラベルを付けてそれを認知する必要があったりと、なかなかしっくり来るものが無い印象です
それもそのはずで、大体のものは明確な行き先があり、それに対して最小のキー数で移動する事を目標としてるんですよね
自分の場合はそういうのではなくて、
ざっくりこの辺りに移動したいなぁ〜ってのがあって、そこへ大雑把に移動してから微調整みたいな感じなのが多いです
マクロとか繰り返しを意識した場合ならまだしも通常時のカーソル移動なんぞ適当でいいし、脳のリソースを使いたくないぜ!のお気持ちです。
特に文字を認識するのが自分にとってコストが高いので、検索をしたり、f/t系の移動で単語の先頭を認識したりといった事はあまりしたくないです。
これは vim を使い初めた頃からそうで、自分のカーソル移動(縦)の変異としては
-
j/k連打 or8jとかの数字付きを繰り返す -
{/}で段落移動してからj/kで微調整 -
H/Lで画面端に移動してから{/}&j/kで微調整
みたいな感じで、徐々に便利なキーマップを覚えつつも、大雑把に移動してから微調整するスタイルは変わっていません。
この大雑把にカーソルを動かす時なのですが、H/M/L以外は大抵の場合空行等のなにかしらのとっかかりが必要になるんですよね。
もうちょいH/M/Lを活用できないかなーと思い、とっかかりが必要無いかわりに、ちょっとキータイプが多くなりやすいプラグインを作ってみました。
えいやで作ったなんちゃって実装もとい、†α†版なので、細かいうんこ挙動は御愛嬌という事でここはひとつ…
もうちょい一般化したいなぁとか思ってたりそうでなかったり…
†二分探索カーソル移動†
さて、ここからが本題ですね
まずは実際の動作例を見たほうが話が早いです

真ん中から徐々に範囲を絞っていって、最終的に目的の行に到達するイメージです
ハイライトがあると、大きなカーソルを徐々に小さくしながら動かしているような感覚になるやもですね。
二分探索って?
さて急に出てきた伝家の宝刀†二分探索†…←これなに
自分が初めて知ったのは競プロやってた時なんですが、ざっくり言うと
ソート済みの配列から探索範囲を半分づつ絞りながら目的の値を探すアルゴリズムです。
†めぐる式二分探索†とかいう名前もどこかしらで聞いた憶えがありますね。
詳しい解説は以下を参考にすると良いかもです。
サブモードって何?
動作例ではMLHH...みたいな感じで入力していましたが、普通のキーバインドに慣れていると違和感があるかもしれないです。
これは巷で噂の†サブモード†とかいうのを利用しています。
これはVim の機能として実装されているわけではなく、キーバンイドの設定を上手くする事で、特定のキーを入力した後に一時的に別のキーバインドセットに切り替えるテクニックだと思っています。
今回の場合だと
-
Mを押すとカーソルを中央に移動して、†二分探索カーソル移動†モードに入る - †二分探索カーソル移動†モードで
Hを押すと探索範囲の上半分に絞る - †二分探索カーソル移動†モードで
Lを押すと探索範囲の下半分に絞る
という感じですね。ちなみに、サブモード中に対応しているキー以外のキーを押すとサブモードが自動解除されて、通常のキーと同様の動作になります。
なので、MLL...を入力している途中でwとかの通常のキーを押せば、サブモードが解除されて通常のwのカーソル移動になります。目的の箇所まで絶対に二分探索する必要はなくて、途中でいつでも抜けられるってのがミソですね。
また、H/Lはサブモード中でのみ二分探索効果があるので、通常時にH/Lを押せば普通に画面端に移動します。
この辺りのサブモードについては色んな記事があるので、貼っておきます。
ちなみに、ハイライトの消去には内部で↓この挙動を利用しています
あとがき
vim におけるカーソル移動はかなりホットな話題なようで、様々なプラグインや設定が存在しています。また定期的に話題にもなりますね。
今回は自分が良く使うH/M/Lや、最近知ったサブモードを利用すれば、簡単に二分探索的なカーソル移動が実現できるんじゃね!?とか思い、ノリで実装してみました。ちょっと使ってみた感じ正直MLとかで全体の1/4移動できるだけで満足で、二分探索である必要が無い気もしますが…
まぁ実際に常用できるかは別として、こういう発想もあるよねって感じで参考になれば幸いです。
Discussion