Quantcast
Channel: Vimタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 5608

【Vim】必要な時だけカーソル行をハイライトする

$
0
0

Vim には 'cursorline'という機能があります。これは名前の通り、カーソルのある行を強調し、目立たせてくれるものです。

便利な機能なのですが、常時有効にしていると以下のような問題がありました。

  • 有効のまま画面をスクロールすると動作が重い。
  • (カラースキームによっては)文字が背景と同化して見づらい。

そもそもこれはカーソルの位置を見失わないようにするための機能ですから、必要な時だけ有効になってくれると便利です。具体的には、以下のように切り替わって欲しいです。

  • カーソルを動かすと無効にする。
  • ウィンドウを開いたり、移動したりした時に有効にする。
  • しばらくカーソルが止まっている時も有効にする。

……と、ここまでは以下のエントリーに書いてあることの要約です。

エントリー内のスクリプトでまさにこれが実現できるのですが、後述の理由により一つのプラグインとしてまとめました。

インストール方法などは README を読んでみてください。以下は、どうしてこのプラグインを作ったのかについて書いています。

CursorHoldイベントの功罪

従来の Vim では、他の言語にはよくある「タイマー機能」というものがありませんでした。例えば JavaScript の setTimeout()のような、「一定時間が経ったら〇〇を実行する」ということができなかったのです。

その不便をある程度解消するために使われていたのが CursorHoldイベントです。

これはカーソルを移動させた後、'updatetime'に指定した時間が過ぎた時に発動するイベントです。おそらくユーザーはカーソルを留めて何か考え中のはずですから、多少重たい動作をさせても構わないだろう、というわけです。このため、なるべくユーザーの操作をブロックしたくないプラグインは、みんなこの CursorHoldイベントで関数を呼び出していました。

ただこの 'updatetime'の値は、Vim 全体で一つしか設定できません。例えば vim-gitgutterのようなプラグインではこの値を小さく(100ms)設定することが推奨されています

しかし今回の要件のためには 100ms という時間は短すぎます。上述の thinca 氏のエントリー内のスクリプトでは CursorHoldを使っているのですが、vim-gitgutter のために、頻繁に cursorline が on/off されるのが悩みのタネでした。

CursorHoldの代わりにタイマー機能を使う

Vim8.0 ではまさにこのために、タイマー機能が実装されました。

使い方は簡単で、timer_start()の引数に時間と関数を指定するだけです。

function! EchoHoge(timer_id) abort
  echo 'hoge'endfunction" 1秒後に hoge と表示するlet timer_id = timer_start(1000,'EchoHoge')" 関数リファレンスも使えるlet timer_id = timer_start(1000,function('EchoHoge'))" Lambda も OKlet timer_id = timer_start(1000,{-> execute('echo "hoge"','')})

今回はこれを使って、以下のような処理を実装しています。

autocmd CursorMoved,CursorMovedI * calls:cursor_moved()function!s:cursor_moved() abort
  " cursorline を消すsetlocal nocursorline
  " すでに起動しているタイマーを止めるcall timer_stop(s:timer_id)" 新しいタイマーを起動lets:timer_id= timer_start(1000,function('s:enable_cursorline'))endfunctionfunction!s:enable_cursorline(timer_id) abort
  setlocal cursorline
endfunction

基本的にはこれだけです。ただ、このままだとカーソルを動かすたびに setlocal nocursorlineしていて無駄ですし、他にもいろんなエッジケースがあったのでもう少し複雑なことをやっています。詳しくはソースを読んでみてください。

まとめ

これからは CursorHoldじゃなくてタイマー機能を使おうぜ!という話でした。


Viewing all articles
Browse latest Browse all 5608

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>