この記事は、Vim駅伝の2024年5月29日の記事です。
22日の記事でH/LとPageUp/PageDownを共存させる設定の紹介がありました。
HとLは通常では、表示領域内の最初の行や最後の行にカーソルを移動させるコマンドです。
連打しやすい割に、連打する意味がない、惜しい存在ですが、スクロール機能も持たせるのは良いアイデアですね。
というわけで、似たようなことを、疑似サブモードを利用して実現してみました。
以下のマッピングを定義すると、H単発でウィンドウ上端へのカーソル移動、連打で<PageUp>に変身します。
難読な気もしますが、たった4行で実現できるのが凄いですね。
nnoremap H H<Plug>(H)
nnoremap L L<Plug>(L)
nnoremap <Plug>(H)H <PageUp><Plug>(H)
nnoremap <Plug>(L)L <PageDown><Plug>(L)
挙動としては以下のような流れ。
Hを入力すると、オリジナルのHとして動作した後、<Plug>(H)を入力した状態になる- Vimは、
<Plug>(H)をprefixに持つマッピングがくるのを一定時間待機する - 待機中に
Hを入力すると、<Plug>(H)H扱いになり、<PageUp>した後、もう一度<Plug>(H)をprefixとした待機状態になる
なお、<PageUp>の直後にHを、<PageDown>の直後にLzbを仕込んでおくと、カーソル位置が良い感じに調整されると思います。
nnoremap H H<Plug>(H)
nnoremap L L<Plug>(L)
nnoremap <Plug>(H)H <PageUp>H<Plug>(H)
nnoremap <Plug>(L)L <PageDown>Lzb<Plug>(L)
<PageUp>Hや<PageDown>Lをすると、連打中のカーソル位置が常にウィンドウの上端か下端に固定されます。
また、バッファ最終行で<PageDown>すると、ウィンドウに表示される内容が最終行だけになってしまいスクロールし過ぎな感じになります。<PageDown>Lzbのようにzbを含めると、カーソル位置をウィンドウの下端に寄せることができ、情報量が多くて良い感じになります。
2024-05-30追記
上記のマッピングの場合、belloffオプション次第でサブモードの待機時間経過後にベルが鳴るそうです。
Neovimではset belloff=allが既定値なので問題ありませんが、Vimはset belloff=が既定値なので、うるさいかもしれません。
自前でbelloffを設定するか、以下のようにサブモード離脱時の挙動を<Nop>に設定しておくといいです。
情報提供頂いたthincaさんに感謝。
nnoremap <Plug>(H) <Nop>
nnoremap <Plug>(L) <Nop>
それから、サブモードの待機時間はtimeoutlenオプションに依存します。
使い勝手に合わせて調整してみてもいいかもしれません。
ENJOY
Atusy's blog