H/LとPageUp/PageDownを共存させる設定 (submode編)

by
カテゴリ:

この記事は、Vim駅伝の2024年5月29日の記事です。

22日の記事でH/LとPageUp/PageDownを共存させる設定の紹介がありました。

https://zenn.dev/vim_jp/articles/20240522_ekiden_better_hl

HLは通常では、表示領域内の最初の行や最後の行にカーソルを移動させるコマンドです。
連打しやすい割に、連打する意味がない、惜しい存在ですが、スクロール機能も持たせるのは良いアイデアですね。

というわけで、似たようなことを、疑似サブモードを利用して実現してみました。

以下のマッピングを定義すると、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)

挙動としては以下のような流れ。

なお、<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