この記事は Vim Advent Calendar 2013 73日目の記事になります。
普段何気なくvimrcに書いているset hlsearch
や:nohlsearch
。実はこれ、結構ややこしいです。
まずはhelp!
- :h ‘hlsearch’ <- オプション
- :h :nohlsearch <- コマンド
- :h v:hlsearch <- 新たなる変数(最近入った)
そして他に注意すべきものとして
set nohlsearch
<-set hlsearch
の逆。:nohlsearch
とは違う&hlsearch
<- オプションhlsearchの値の変数。set hlsearch
なら1,set nohlsearchなら0
ややこしいですね。
v:hlsearchを解説しながら全体的に説明するよ
最近縁があったのでv:hlsearchの日本語訳を書かせて頂きましたが、ぶっちゃけ元の英語の説明もわかりづらいのでここで解説します。
まず仕様ですが、この変数は実際に現在検索によるハイライトが行われているかどうかを判定、決定できます。
判定
echo v:hlsearch
- ハイライトが行われている -> 1
- ハイライトが行われていない -> 0
決定(ハイライトをON or OFFにする)
この変数を0に設定することは、 |:nohlsearch| コマンドを実行することと同様に働き、 1に設定することは以下と同様に働く let &hlsearch = &hlsearch
わかりずらい!!!
let v:hlsearch = 0
これは、helpによると:nohlsearch
コマンドを実行することと同様に働きます。
|:nohlsearch| コマンドを使うと、一時的に強調表示をやめさせることができます。
一時的に というのがミソです。この:nohlsearch
コマンドはhlsearch
オプションの変数である、&hlsearch
を変更しないのです。つまりset hlsearch
している場合&hlsearch
変数の値は1ですが、:nohlsearch
を実行しても&hlsearch
の値は1のままでハイライトを一時的にオフにします。
let v:hlsearch = 1
helpによると1に設定することは
let &hlsearch = &hlsearch
をすることと同様に働くようです。ここがかなりわかりずらい。
前提として、
- 基本的に
v:hlsearch
は実際にハイライトを行っているかどうかを決定するのですがset nohlsearch
が設定されていた場合はset nohlsearch
が優先されます。 - コマンド
:nohlsearch
によって一時的にハイライトをオフにした場合、再び検索するなどしたときにハイライトが有効になるのですが、set hlsearch
,つまりはlet &hlsearch = 1
を設定した場合も同様にトリガーとなってハイライトが有効になります(実装は見ていないので予測含む。動作確認はしています)
よって、もしset nohlsearch
が設定されていれば&hlsearch
の値は0なのでlet &hlsearch = 0
と同様の動作となり何も起こりません。
反対に、set hlsearch
が設定されていれば&hlsearch
の値は1で、let &hlsearch = 1
と同様になり、前提の2からこの動作がトリガーとなって再びハイライトがONになります。
はぁ、ややこしかった。わからなかった方は直接@haya14busaまで質問とかしてください。また間違ってたらご指摘よろしくおねがいします。
ここからv:hlsearch
から得られたTipsを2つ紹介します
Reloadableなvimrcの設定
一般的には下記のような設定をしている方が多いと思います
が、リローダブルなvimrcを目指している方はこの問題に少なからず気づいているかもしれません。
つまり、set hlsearch
を記述しているとリロード時に問答無用でハイライトされてしまうのです。(ウザイ
これを改善しましょう
1. 簡単かつv:hlsearchがなくてもOK
上記のようにすると&hlsearch
の値は1で検索のハイライトは有効になっていますが、:nohlsearch
コマンドによりそれを一時的にOFFにします。
欠点: ハイライトしている状態でリロードするとハイライトが消えてしまう。
2. v:hlsearchを使って1の欠点をなくす
欠点: 書き方が悪いということを除いてもわざわざそこまでしたくない…
スクリプトから扱う
ハイライトを確認する
v:hlsearch
が登場する以前では&hlsearch
の値を見ることしかできず、ハイライトの設定がされているかどうかは分かるけれども、実際にハイライトされているかどうかがわかりませんでした。(:nohlsearch
で一時的にハイライトしていなくてもset hlsearch
していれば一貫して&hlsearch
の値は1です)
v:hlsearch
の登場によって改善されたのはほぼこの一点といってもいいでしょう。
実際に関数からハイライトさせる
上記の記事の問題はv:hlsearch
でも同じなようで、関数内でlet v:hlsearch = 1
にしても実行が終わると勝手に元の値に戻されてしまいます。これを回避するには記事にあるように:h feedkeys()を使うしかないようです。残念…
ちょっと改善
上記の記事の関数だとset nohlsearch
のオプションを無視してしまうので下記のように:let &hlsearch=&hlsearch\<CR>
を使うとよりお行儀よくハイライトさせることができます。
最後に
最新への追従 #84: https://github.com/vim-jp/vimdoc-ja/issues/84
Vimの日本語訳がオリジナルのヘルプに追従しきれていないようです。実際v:hlsearch
を訳して、レビューしてもらったりしましたが、結構新鮮で面白かったしこれからも暇があれば、僕も日本語訳に参加して貢献できればいいなと思います。人手は足りていないようなので、気になった方は簡単な/分かるところからでもいいから訳して、vim-jpに投げてみるといいのではないでしょうか。きっとみんな優しくしてくれると思います。