LoginSignup
8
9

More than 5 years have passed since last update.

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

Posted at

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 も OK
let timer_id = timer_start(1000, {-> execute('echo "hoge"', '')})

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

autocmd CursorMoved,CursorMovedI * call s:cursor_moved()

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

function! s:enable_cursorline(timer_id) abort
  setlocal cursorline
endfunction

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

まとめ

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

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9