シンタックスカラーリング
カラーリングはやり方が2つあるようです。
- package.json の grammars で指定したシンタックスファイル(TextMate文法など)で定義
- LanguageServerでカラーリング情報を与える(?)
方法2. はパーサーを書くとかなり自由度が高い正確なカラーを与えられますが、私の場合はパーサーを書く前にカラーリングを作ったので1.しかやっていません。
方法1. は使えるシンタックス形式がいくつかあるようです。
今回はTextMate形式の文法定義ファイルを使います。この定義は正規表現を使って単語のマッチをし、結果にscope(タグのようなもの)付けするものでjsonベースです。
文法定義ファイル(*.tm)
"keywords": {
"patterns": [
{
"match": "`(include|define|undef|ifdef|ifndef|else|endif|timescale|default_nettype)",
"name": "keyword.preprocessor.sv"
},
{
"match": "\\b(package|endpackage)\\b",
"name": "keyword.decl.sv"
},
こんな感じ。
`include にマッチすると、keyword.preprocessor.sv というscopeが付くイメージです。
これをpackage.jsonで指定すると有効になります。
"grammars": [
{
"language": "sv",
"scopeName": "source.sv",
"path": "./syntaxes/sv.tmLanguage.json"
}
],
ところで今更ですが、個人的にjson系は読み書きしにくいと思います。
VSCodeは文法定義にplistを受け付けるようなので、ここに書かれているように、YAMLを使って文法を書いてからplistに変換したほうがスッキリしたと思います。
YAMLはSublimeの文法定義に使われており、とても読み書きしやすいです。
テーマファイル(*.theme)
このscopeに対して実際に色を与えるのがテーマファイルとなっておりまして、標準テーマを使いたい場合は標準テーマが定義しているscopeを文法定義ファイルで与えると、標準テーマのカラーが紐付きます。
例えば、標準の dark_vs.json だと
{
"scope": "keyword.operator",
"settings": {
"foreground": "#d4d4d4"
}
},
みたいにして、keyword.operator などが定義されています。
なお、この定義はそれ以下のscope、すなわちkeyword.operator.svやkeyword.operator.hoge.hogeなどを包含していることに注意。
私の場合は標準テーマとは別のカラーリングを実現したかったので、独自のテーマを作っています。
この際、別のテーマをincludeでき、
{
"name": "SystemVerilog",
"include": "./dark_plus.json",
"tokenColors": [
{
差分だけを定義できてとても便利です。
また、差分を定義する時は、より具体的なscopeを定義してやることで元のカラーリングを保持したまま拡張テーマを定義できます。
例えば、
keyword.operator が標準テーマで定義されており、keyword.operator.sv が拡張テーマで定義された場合、文法ファイルで keyword.operator.sv を定義すると拡張テーマ側のカラーが適用されます。また、*.sv 以外のスコープを使う別の文法では標準テーマのkeyword.operatorが適用されます。
VSCodeに限らないのですが、このテーマ、という概念は言語文法とは独立しているため、こういった仕組みが必要なのだと思われます(言語ごとにカラーテーマを勝手に切り替えられない)。良いようにも、悪いようにも感じる仕様だと思います。
作成したテーマはpackage.jsonに
"themes": [
{
"label": "SystemVerilog",
"uiTheme": "vs-dark",
"path": "./themes/SystemVerilog-color-theme.json"
}
],
とすることで有効になります。
ただし、テーマなので拡張機能をインストール後に自身で適用してやらなければいけません。