🎨

vim-colortemplateプラグインでVimのカラースキームを作る

2021/11/17に公開

はじめに

この記事ではvim-colortemplateプラグインを使った、Vimのカラースキームの作り方を説明します。さらに、vim-airlineのカラーテーマの作り方も説明します。最低限利用できるカラースキームを作ることを目的とするため、vim-colortemplateプラグインの一部の機能しか紹介しません。vim-airlineのカラーテーマに関しては詳細なことまでは調べられていないので、設定すべき項目に漏れがあるかもしれません。ご容赦ください。
https://github.com/lifepillar/vim-colortemplate

情報源

主な情報源は:help colortemplateで読むことができるvim-colortemplateのヘルプです。vim-airlineのカラーテーマに関しては、:help airlineやvim-airlineといくつかのカラーテーマのソースコードを斜め読みして得た情報をもとにこの記事を書きました。

カラースキームの作成

カラースキームを作成していきます。適当なディレクトリの下にtemplatesという名前のディレクトリを作成します。テンプレートは、例えばtemplates/dark.colortemplateという名前で作成します。拡張子は必ずcolortemplateにします。

カラースキームを生成するために、テンプレートに記述する必要が要素は以下の通りです。これらの要素の書き方を説明していきます。

  1. メタデータ
  2. BackgroundVariantディレクティブ
  3. ColorTerm Colorsの定義
  4. ハイライトグループの設定

メタデータにはカラースキームや作者の名前、ライセンスなどと記述します。Backroundディレクティブは背景がdarklightであるかを設定します。Variantディレクティブは使用する色の数を設定します。

Colorで色とその名前の対応関係を記述します。Term Colorsは変数g:terminal_ansi_colorsに設定する16色のカラーパレットを設定します。最後に、ハイライトグループにColorで定義した名前で色を指定していきます。

メタデータの設定

カラースキームの名前と作成者を設定する必要があります。作成したcolortemplateファイルの冒頭に以下の記述を加えます。

Full name: カラースキームの名前
Short name: カラースキームの短い名前(スネークケース)
Author: 作者 <メールアドレス>

これらの情報は生成されたカラースキームではコメントとして書き込まれます。生成されるカラースキームには上記のメタデータ以外にもライセンスに関する記述が書き込まれます。デフォルトで使用されるライセンスはVim Licenseです。他のライセンスを適用する場合は以下の記述をテンプレートに加えます。

License: ライセンス名

他にも設定できるメタデータはありますが、ここでは割愛します。詳しくは:help colortemplate-metaで確認できます。

BackgroundVariantディレクティブ

Backgroundディレクティブで背景がdarkあるいはlightかを記述します。VariantディレクティブではGUI colors, 256 colors, 16 colorsのいずれかをサポートするかを記述します。

例えば以下の例では、背景をdarkにして、GUI colorsと256 colorsをサポートすることを宣言します。

Background: dark
Variant: gui 256

Colorの定義

テンプレートでの記述方法

この記事では、GUI colorsと256色で設定する場合で説明します。以下に例を示します。

Color: darkblack	rgb(22,24,33)		234
Color: darkred		rgb(178,108,108)	131

行頭のColor:に続いて色の名前を記述します。名前の後にGUIでの色をRGB値で指定します。その次に、256色での色を番号で指定します。256色で指定する番号は256 Colors Cheat Sheetを参照してください。

なお、番号の代わりに~を書くことでGUIの色に近い色を自動で選択することができますが、思った通りの色が出ないことがあるので、個人的にはあまり使い勝手は良くないと思っています。

色の選び方

次節で説明しますが、ANSIで規定された16色の代わりに使う色をTerm colorsで設定するので、これらの色を選ばなければなりません。選ばなければならない色は256 Colors Cheat Sheetにあるように、黒・赤・緑・黄・青・マゼンタ・シアン・白の暗いものと明るいものの合わせて16色は最低限選ばなければなりません。

vim-colortemplateはカラーピッカーを提供しています。このカラーピッカーはノーマルモードでgsを入力することで起動できます。カラーピッカーではRGB値で色をプレビューしながら指定できます。しかし、TrueColor対応の端末でないと256色に変換された色しか表示されないため多くの環境ではあまり役に立たないかもしれません。

私がカラースキームを作成したときは、Illustratorで色を並べて16色の配色を調整してからテンプレートに色を記述しました。

Term colorsの設定

Term colorsの設定は以下のように16色の色をColorで設定した名前を使って指定します。順番は256 Colors Cheat Sheetの0から15までの色の順に従ってください。

Term colors: darkblack darkred darkgreen darkyellow
Term colors: darkblue darkpurple darkcyan darkwhite
Term colors: brightblack brightred brightgreen brightyellow
Term colors: brightblue brightpurple brightcyan brightwhite

ハイライトグループの設定

ハイライトグループの設定は、ハイライトグループ名の後に前景色、背景色をColorで指定した名前で記述します。以下に例を示します。

Normal		darkwhite	darkblack
Cursor		darkwhite	brightblack

太字にするためには、次の例のように背景色の後にboldを記述してください。下線をつける場合はunderlineを記述します。

StatusLineTerm  darkblack       brightgreen     bold
Underlined      brightcyan      omit            underline

背景色をomitで指定することで、そのとき使われていた背景色をそのまま使うように指定できます。例えば、ハイライトグループPmenuでは通常の背景とは異なる色を背景色に設定することが多いと思います。

vim-lspやcoc.nvimのホバー表示はPmenuの背景色を使ってポップアップウインドウにソースコードを表示することがあります。このとき、シンタックスハイライト用のハイライトグループは背景色をomitにすることで、読みやすいポップアップ表示を実現できます。(逆に言えばomitにしないとかなり読みにづらくなります。)

設定すべきハイライトグループの一覧は:highlightあるいは:hiで確認できます。ハイライトグループの一覧は例えば以下のスクリーンショットのようになります。:hiで表示されるハイライトグループは種々のプラグインが定義したものも含まれるので、それらは定義しなくても問題ありません。また、:so $VIMRUNTIME/syntax/hitest.vimでもハイライトグループを確認できます。
vim-highlightgroup-1
vim-highlightgroup-2
vim-highlightgroup-3
vim-highlightgroup-4

カラースキームの生成と適用

ハイライトグループを定義し終わったらカラースキームを生成して実際に適用してみましょう。カラースキームの生成は:Colortemplate!で生成できます。カレントディレクトリにcolor/カラースキーム名.vimという名前のファイルが生成されます。このファイルはVimスクリプトになっています。

そのまま:colo カラースキーム名を実行することで実行中のVimに生成されたカラースキームを適用できます。適当なソースコードを開くなどしてカラースキームの出来映えを確認してみましょう。

vim-airlineのカラーテーマの作成

ここからは、先ほど作成したcolortemplateファイルにvim-airlineのカラーテーマを記述していきます。vim-airlineのカラーテーマはいくつかの変数を設定するVimスクリプトとして記述されます。vim-colortemplateのAuxialiary filesという機能を使うことで、カラースキームとは別のファイルを生成することができます。colortemplateファイルで定義した色を参照して、vim-airline用の変数を定義していきます。最後に、カラーテーマを生成してVimに適用します。

Verbatim blocksとAuxialiary files

Verbatim blocksに記述した内容はテンプレートとして解釈されず@で始まる文字列を除いてそのまま出力されます。Auxialiary filesもそのようなVerbatim blocksの一種です。

Auxialiary fileは以下のように記述します。auxfileで始まる行以降がauxialiary fileの内容となります。auxfileの後に出力先のパスを記述します。endauxfileがauxialiary fileの内容の終わりになります。この例では、vim-airlineのカラーテーマを格納するディレクトリにファイルを出力します。@shortnameでカラースキームのshortnameを参照できます。

auxfile autoload/airline/themes/@shortname.vim
endauxfile

設定すべき変数

設定しなければならない変数の概要は.vim/plugged/vim-airline/autoload/airline/themes/dark.vimのコメントに記述されています。

まずはスクリプトのエンコーディングを設定してから、vim-airlineのパレットを格納する変数に空の辞書を束縛します。

auxfile autoload/airline/themes/@shortname.vim
scriptencoding utf-8

let g:airline#themes#@shortname#palette = {}

ステータスラインの色の設定

ここでvim-airlineで色を設定できる部分を確認しておきましょう。Vimの画面下部のステータスラインは左側から

  • airline_a
  • airline_b
  • airline_c
  • airline_x
  • airline_y
  • airline_z

と呼ばれる部分に分かれています。下のスクリーンショットでは、左から順に緑、灰、黒、黒、灰、緑という色付けになっています。

vim-airline-parts

ステータスラインの各部分の色を、

  • normal
  • insert
  • replace
  • visual
  • inactive
  • terminal
  • commandline

の各モードについて定義していきます。

airline_a/b/cとairline_x/y/zを対称的に設定するairline#themes#generate_color_mapという関数が提供されています。この関数にはステータスラインの各部分の色を[guifg, guibg, ctermfg, ctermbg]の順で格納した配列を受け取ります。以下の例ではnormalモードでのステータスラインの色を設定します。@guiの後にColorで定義した名前を続けた文字列は、そのRGB値に置き換えられます。同様に@term256の後にColorで定義した名前を続けた文字列は、256色での色の番号に置き換えられます。

let s:airline_a_normal   = ['@guidarkblack', '@guidarkgreen', '@term256darkblack', '@term256darkgreen']
let s:airline_b_normal   = ['@guidarkwhite', '@guibrightblack', '@term256darkwhite', '@term256brightblack']
let s:airline_c_normal   = ['@guidarkwhite', '@guidarkblack', '@term256darkwhite', '@term256darkblack']
let g:airline#themes#@shortname#palette.normal = airline#themes#generate_color_map(s:airline_a_normal, s:airline_b_normal, s:airline_c_normal)

その他の設定

先ほどお見せしたスクリーンショットのステータスラインには右端に黄色の部分と赤色の部分があったことにお気づきでしょうか。この部分はcoc.nvimなどが警告やエラーを表示します。これらの領域はそれぞれairline_warningとairline_errorと呼ばれています。以下の例ではnormalモードでのairline_warningの色を設定しています。各モードに対して設定が必要になります。

let g:airline#themes#@shortname#palette.normal.airline_warning = ['@guidarkblack', '@guidarkyellow', '@term256darkblack', '@term256darkyellow']

また、ステータスラインにはairline_termと呼ばれる部分もあります。これはterminalモードで実行したコマンドが表示されます。

カラーテーマの生成と適用

カラーテーマの生成はカラースキームと同様に:Colortemplate!で実行できます。vim-airlineのカラーテーマの適用は、:AirlineTheme カラーテーマ名で実行できます。

おわりに

駆け足で説明しましたがこれで一通りのカラースキームを書けるはずです。完成したテンプレートを参考にしたい人は、以下のリポジトリに私が作成したカラースキームがあるのでコードを読んでみてください。(ただし、Vim Licenseです。)
https://github.com/ShotaroTsuji/Kaninchenhaus.vim

Discussion