Vim で非空白行の行末スペースをハイライトする正しいやり方
問題
Vim + quickrun で例えばなんかの api からの response を受け取るとする.しばしば改行が入っていなくてかなり長い一行のファイルになる.
それを読み込んだ時に,例えば 1行 5万文字のものを読み込んだ時に,— Vim が, Vim が死んでしまう.
Vim は一行があまりに長いのは得意でない,という噂があったのでちょっと遅くなるのはあまり気にしていなかったのだが,それでもあまりにひどい.
Vim だぜ? Vim で 5万文字の text file を読み込んで $ kill -KILL
する羽目になるなんて屈辱ではないか.絶対に何とかなるはず.
試しにこれでやってみる.
$ vim -u NONE -U NONE foo.txt
起動は一瞬,その後の動きも軽快なものだ.そうだ.これが Vim だ.
半ば闇の道に堕ちてしまった自分を省みつつ .vimrc
を削ってゆく.git で管理しているから好き放題できてやりやすい.
まず疑わしいのはどうせ neocomplete
とかそのへん……削っても効果はない(そう言えば txt
とかではそもそも動いていない),
ならばマッチ系が怪しいか,rainbow parentheses, 多分関係ないけど quickhl …. とうとう plugin をすべてなくしてしまった.
まだ Vim は死んだままだ.どうして,どうして…….synmaxcol
は 200
で問題ないはず,cursorline
でも削ってみるか,うーん,……
虱潰しにオプションを削ってゆく,怪しそうなものから順に,ザクザク.ひょっとして .vimrc
なんて空にしとくべきなんじゃないか.
解決
…としばらくやっていると,三番目くらいに目をつけたここを削ると一気に動作が改善した.
augroup highlightSpaces
autocmd!
autocmd ColorScheme * hi ExtraWhiteSpace ctermbg=darkgrey guibg=lightgreen
autocmd ColorScheme * hi ZenkakuSpace ctermbg=white guibg=white
autocmd VimEnter,WinEnter,Bufread * call s:syntax_additional()
augroup END
ご覧の通りこれは全角空白と行末スペースをハイライトする設定.s:syntax_additional
に飛んでやってみると,なんと問題になっていたのは次の一行.
matchadd('ExtraWhiteSpace', '\(\S\+\)\@<=\s\+$',0)
これは「空白行ではないところにある,行末の半角スペースをハイライト」する部分. この需要があるのは僕がインデントがあるべき空白行には行頭にインデントを入れるからで,例えば python だとこんな感じで書いている(* がスペース).
class FOO(object):
****
****def __init__(self):
これを設定したのはしばらく前で,どこかで解説されていた方法に従ったのだが……
…
あれ?っていうかこれ明らかに重そうでは?????
前半部分囲われてる意味ないんじゃないですかね………………
この設定を書いた時よりはかなりVim正規表現力が向上しているので書き換えてみる.
matchadd('ExtraWhiteSpace', '\S\+\zs\s\+\ze$',0)
—> あ,呆気無く速くなったーーーー!!!!!
(後ろの \ze
要らないかもしれないがまあ.)
\@<= Matches with zero width if the preceding atom matches just before what
follows. |/zero-width| {not in Vi}
Like "(?<=pattern)" in Perl, but Vim allows non-fixed-width patterns.
Example matches ~
\(an\_s\+\)\@<=file "file" after "an" and white space or an
end-of-line
For speed it's often much better to avoid this multi. Try using "\zs"
instead |/\zs|. To match the same as the above example:
ヘルプにも遅いから \zs
使えって書いてありますね.あっけねえ.
ありがとうございました.