aceエディター用のシンタックスハイライトファイルを作成する


需要はない?が備忘録用。

予備知識

  • VSCodeなどのシンタックスハイライトはTextMateシンタックスで書かれている。詳細は以下を参照。

  • TextMateシンタックスはjsonやyamlで書きたりする。勿論変換も可能。

  • そしてtmLanugageファイルはace用のjsファイルに変換できる。

  • またVSCode用のシンタックスハイライト拡張機能は数多く開発されている(むしろない場合のほうが稀に思える)。

つまりVSCode用の拡張機能からシンタックスハイライト用のファイルだけお借りして変換すればace(ブラウザーエディター)で使える(かも)。

実際にやってみる

今回はyaml。まずyamlファイルを取ってきてtmLanguageファイルに変換する。

カスタムタグの編集

ただ変換しようにもいくつか問題があった。まずyamlにカスタムタグが設定されている場合、yaml.loadするとエラーになる。
これを回避するには新たなスキーマをjs-yamlに登録する必要がある。

const yaml = require('js-yaml')

let schema = yaml.Schema.create([
    new yaml.Type("<custom tag>", {kind: "<data type>", construct: function (data) {return <process data>}})
])
<...>
let datas = yamlTexts.map((t) => {
    return yaml.load(t, {schema: schema}) // set the schema
})

js-yamlのバージョンは3.8.3。4以上だとyaml.Schema.createメソッドが変わってるらしくよくそれにあたるメソッドがわからなかった。

カスタムタグは以下みたいなやつ。

key: !hoge value

データ型はscalar, sequence, mappingのどれか。返したいデータ型に合わせる。constructで引数に取ったデータを加工して値を返す。

tmLanugageファイルの編集

tmLanugageを生成したら次は下のリポジトリのtmlanguage.jsでace用のjsに変換する。

tmLanguageはxmlを拡張したやつで主にplistタグの中にdict, array, key, stringタグで構成されている。
こっからもう一加工必要で、まずplistの中のデータが返されるのでこいつがちゃんとtmlanguage.jsの意図したものになっていないといけない。
jsonで表現すると下のようになってる必要がある。

{
  "name": "hoge",
  "patterns": [{}]
}

ポイントは一番外がオブジェクト(dict)でその中にnameが必要。私が生成したtmLanugageは下のようになっていた。

[
  {
    "patterns": [{}]
  }
]

一番外が配列でその中のオブジェクトにnameがない。ので上のように加工して

$ node tmlanguage.js hoge.tmLanguage

でaceようのシンタックスハイライトをつくれた。

ビルド

最後にビルドする。

  • add your language to \$ACE_ROOT/lib/ace/ext/modelist.js. In my case I inserted a new line like Mealy: ["mealy"],.
  • (optional) you may now test your Ace editor by running node static.js --allow-save in $ACE_ROOT and going to http://localhost:8888/tool/mode_creator.html and http://localhost:8888/build/kitchen-sink.html.
  • run npm install in \$ACE_ROOT
  • run node ./Makefile.dryice.js full in \$ACE_ROOT. This should create \$ACE_ROOT/build/src. You should even see there your syntax \$ACE_ROOT/build/src/mode-\$NAME.js.
  • Copy \$ACE_ROOT/build/src to your project directory. In my case I added it to code/ace/build/src, which you can even see on GitHub.
  • Finally embed ace in your HTML file like in this example. Notice that $ACE_ROOT/build/src contains ace.js.

あとは生成したbuild/src-hogeをコピーして使うだけ。