Vim のカラースキームが微妙に気に食わないときの対処法
この記事は Vim Advent Calendar の 253 日目の記事です。昨日は id:tyru さんの Alt-Spaceでウインドウのメニューを表示、あとウインドウの最大化 でした。
はじめに
Vim にはたくさんのカラースキームがありますね。きっとみなさんは、たくさんあるカラースキームの中からお気に入りを見つけて設定をしていることでしょう。
しかし中には 99% 気に入って入るけれど、1% だけ微妙に気に食わないという場合もあるかと思います。今日はそんなときにカラースキームの一部だけをちょこっと改造する方法を紹介します。
:highlight を vimrc に書く (基本編)
色を変えたい部分は highlight コマンドをちょろっと vimrc に書けば OK です。
" 以下のコマンドは :colorscheme の前に設定します " コメントを濃い緑にする autocmd ColorScheme * highlight Comment ctermfg=22 guifg=#008800 " ... colorscheme molokai
まず、:highlight
コマンドは autocmd ColorScheme
で囲むようにします。こうすることにより、気が変わって途中でカラースキームを変えたとしても再度設定し直されるようになります。
Comment というのがコメントを表しています。他にどういうのがあるかは :help group-name
:help highlight-groups
して調べてみましょう。ソースコードの要素だけでなく行番号やビジュアルモードの選択範囲なども設定出来ます。
ctermfg はターミナルの、guifg は GUI 版の Vim の前景色を表します。GUI 版の場合は CSS などでお馴染みの RGB を 16 進数で記述しますが、ターミナルの場合は色を表す番号で指定します。どの番号がどの色かを調べる Perl スクリプトがあるのでそれを利用すればよいでしょう。
ほかにも太字にしたい場合は cterm=BOLD
gui=BOLD
などのように設定出来ます。
蛇足 syntax と highlight
ここからは応用編です。
Vim の色を決定しているのは主に syntax と highlight という仕組みです。syntax は構文とその構文が属するハイライトグループを決定するもので、例えば "hoge"
は文字列、int
はキーワードなどのように各言語ごとに用意された構文用のファイルに従って決定されます。highlight は各ハイライトグループどのように色付けするかを設定するものです。文字列は緑、キーワードは青などのように設定します。
どのハイライトグループがどのように highlight されているかは :highlight
コマンドを引数なしで起動することで確認できます。
この出力を眺めていると、ハイライトの仕方ではなく link to
となっているものがあることに気づきます。実はハイライトグループは他のハイライトグループにリンクさせることができます。
例えば、Vim script の文字列は vimString、Ruby の文字列は rubyString というハイライトグループになっていますが、どちらも String というハイライトグループにリンクされています。これにより、String というハイライトグループだけ変更すればほとんどの言語での文字列の色を帰ることができます。また、逆に特定の言語の文字列の色だけを変えるということもできます。(デフォルトでちゃんと設定されていれば)
カーソル下の syntax 情報を取得する
例として以下の Ruby ファイルを見てください。
これは、molokai というカラースキームで Ruby ファイルを表示したものですが、module
class
といったキーワードと実際のモジュール名、クラス名が同じ色になってしまっています。これを改善するために module
class
というキーワードの色を変えたいとして、これらがどのハイライトグループに属するかが予めわかっていないといけません。
そこで、Vim script の synID
synIDattr
synIDtrans
という組み込みの関数を使って構文情報とそのハイライト情報を取得してみましょう。
以下の様な Vim script を書いてみます。
function! s:get_syn_id(transparent) let synid = synID(line("."), col("."), 1) if a:transparent return synIDtrans(synid) else return synid endif endfunction function! s:get_syn_attr(synid) let name = synIDattr(a:synid, "name") let ctermfg = synIDattr(a:synid, "fg", "cterm") let ctermbg = synIDattr(a:synid, "bg", "cterm") let guifg = synIDattr(a:synid, "fg", "gui") let guibg = synIDattr(a:synid, "bg", "gui") return { \ "name": name, \ "ctermfg": ctermfg, \ "ctermbg": ctermbg, \ "guifg": guifg, \ "guibg": guibg} endfunction function! s:get_syn_info() let baseSyn = s:get_syn_attr(s:get_syn_id(0)) echo "name: " . baseSyn.name . \ " ctermfg: " . baseSyn.ctermfg . \ " ctermbg: " . baseSyn.ctermbg . \ " guifg: " . baseSyn.guifg . \ " guibg: " . baseSyn.guibg let linkedSyn = s:get_syn_attr(s:get_syn_id(1)) echo "link to" echo "name: " . linkedSyn.name . \ " ctermfg: " . linkedSyn.ctermfg . \ " ctermbg: " . linkedSyn.ctermbg . \ " guifg: " . linkedSyn.guifg . \ " guibg: " . linkedSyn.guibg endfunction command! SyntaxInfo call s:get_syn_info()
これで :SyntaxInfo
というコマンドによりカーソル下の構文情報(ハイライト情報)を取得できるようになりました。
調べてみると、module
は rubyModule で Define というハイライトグループにリンクしており、モジュール名(Hoge) は rubyConstant でType というハイライトグループにリンクしていることが分かります。
この情報を使って色を変えてみましょう。
autocmd ColorScheme * highlight rubyModule guifg=#88ff88
これで Ruby の時だけ module というキーワードの色を変えることができました。
カラースキームを自作してみる
いろいろ改造していると、たくさんの :highlight
コマンドが vimrc に増えてきます。そこまで来たらむしろカラースキームを作ってしまったほうが良いでしょう。
乱暴に言ってしまうとカラースキームの実態はここで説明した highlight コマンドの集合体です。なので、既存のカラースキームを改造するだけの場合は結構簡単に作れます。
カラースキームの作り方については下記の id:thinca さんの記事がとても参考になるでしょう。 *1
まとめ
:highlight
を vimrc に書けば色付けを変更できるsynID
などの関数により構文情報を取得できるのでハイライトの設定に便利- カラースキームの自作は難しくない
明日は @ujihisa さんです。
*1:書いている途中でネタかぶりに気づきました