本記事ではEclipse Photon以降のEclipseで、TM4Eを使った場合のシンタックスハイライト、インデントの実装について解説する。 TM4EはEclipse Photonで追加されたRustなどにも使われている。
本記事ではContents Assist(補完機能)については触れないが、Eclipse Photon以降であれば、LSP4E(Language Server Protocol for Eclipse)を用いるのが良いだろう。
目次
- 下準備:開発する言語の内容
- TM4E(TextMate support in Eclipse IDE)
- Dependencies
- Content Type
- Generic Editor
- .tmLanguageを作成
- language-configuration.json
- まとめ
- 参考
下準備:開発する言語の内容
今回はサンプルなので、非常に単純な仮想言語HOGEの実装をする。ファイルの拡張子は.hogeである。
仮想言語HOGEはサンプルなので厳密な定義をする気はないが、こんな感じの構文とする。
// コメント fn name int:value{ string piyo = "piyopiyo" if value == 1 { piyo = "moge" }else if value == 2{ piyo = "hoge\!" } return piyo } name 10
ざっくりしたルール
- {}でブロックを生成する
- 複数行にわたる構文はサポートしない
- fn [a-z]+[ type:name]*で関数定義
- キーワードはif,else,=
,
,return - 型はintとstringのみ
- ""でstring。
- 数値は10進数整数のみ
- 関数呼び出しは name 引数
- if,fnの後は必ず{}によるブロックが必要
- //で文末までコメントアウト
TM4E(TextMate support in Eclipse IDE)
Eclipse Photonからシンタックスハイライト等を実装するのに、TextMateの構文(.tmLanguage)を使うことが出来るプラグインTM4Eが、公式で提供される様になった。 .tmLanguageはVisual Studio Codeもサポートしており、汎用的な定義と言える。というか、TM4Eがそもそも、VS Codeのvscode-textmateから作られている。
Eclipse専用に開発するよりずっとエコで、Eclipseの謎仕様を追いかける精神的苦痛からも解放される。
現段階ではややバギーではある(執筆時はv0.2)が、おおよそは動くので、TM4Eを使うという選択肢は十分にありだろう。
デフォルトの状態ではTM4Eはインストールされていないので、開発を開始する前に、インストールをしておく。
Menu:Help→New Install Software…を開き、公式アップデートサイトを選択し、TextMateをチェックする。検索ボックスにTextMateと打ち込むと、探しやすい。
選択したら、Nextを押す。次の画面でもNextを押す。
ライセンスに同意して、インストールを開始する。インストール完了後、再起動をする。
Dependencies
plugin.xmlを開き、依存関係に、以下を追加する。(※流石にプラグインプロジェクトの作り方等の説明は省略させていただく)
- org.eclipse.ui
- org.eclipse.core.runtime
- org.eclipse.ui.genericeditor
- org.eclipse.tm4e.core
- org.eclipse.tm4e.languageconfiguration
- org.eclipse.tm4e.registory
- org.eclipse.tm4e.ui
Content Type
まずは.hogeファイルをEclipseに認識させる為に、Content Typeを定義する必要がある。
- plugin.xmlのExtensions(拡張)タブを開く
- Add(追加)ボタンを押して、org.eclipse.core.contenttype.contentTypesを追加する。
- org.eclipse.core.contenttype.contentTypesを右クリックし、ポップアップからNew→content-typeを選択し、content-typeを追加する。
- 以下の表の内容を設定する
項目 | 内容 | 説明 |
---|---|---|
id | editor.sample.hoge | ID. 全てのプラグインを含めて、ユニークな名前である必要がある。 |
name | HOGE Language File | 人が読める名前 |
base-type | org.eclipse.core.runtime.text | このファイル情報の継承元。特にない場合はorg.eclipse.core.runtime.textにする |
file-extensions | hoge | ファイル拡張子 |
この段階で、このプラグインを導入したEclipseを起動し(図の赤く囲ったボタンで起動可能)、.hogeファイルを適当に生成し、プロパティを見てみよう。 TypeのところがFile (HOGE Language File)となっていて、上記の設定が認識されている。
Generic Editor
次に、.hogeを開いた時に使用するエディタを設定する。 かつては自分でエディタを作成し、エディタを登録し、そのエディタを使う様に設定するという面倒くさい作業が必要だったが、 TM4Eを使う場合は単にGenericEditorでよい。素晴らしい。
- plugin.xmlのExtensions(拡張)タブを開く
- Add(追加)ボタンを押してorg.eclipse.ui.editorsを追加する。
- org.eclipse.ui.editorsを右クリックし、ポップアップからNew→editorContentTypeBindingを選択し、追加する。
- 以下の表の内容を設定する。書くのが面倒なら、右のBrowse…から検索すると良い。
項目 | 内容 | 説明 |
---|---|---|
contentTypeId | editor.sample.hoge | Content Typeで設定したidを指定する。 |
editorId | org.eclipse.ui.genericeditor.GenericEditor | どのエディタで開くか指定する。 |
.tmLanguageを作成
.tmLanguageを実際に作成していく。
最初に、プラグインを配布する際のバイナリに、構文ファイルが追加される様にしておこう。
- grammar/hoge.tmLanguage.jsonを作成する
- build.propertiesを開く
- 「Binary Build」に「grammar」ディレクトリにチェックを入れる
grammarディレクトリが不都合なら、別なディレクトリ名にしても良い。 なお、今回はjsonにしたが、tmLanguage形式が良い場合やexsdで書きたい場合は、それに変更する。 どの形式が良いのかは正直よく分からないが、jsonにしておけば、何処でも使えそうな雰囲気はある。後ブログでシンタックスハイライトしやすい。
次に、.hogeファイルと、grammar/hoge.tmLanguage.jsonを結びつける設定をする。
- plugin.xmlを開き、Extensionsタブに移動する
- Addボタンを押し、org.eclipse.tm4e.registry.grammarsを追加する
- org.eclipse.tm4e.registry.grammarsを右クリックし、ポップアップメニューからNew→grammarを選択し、追加する。
- 同じくポップアップメニューからNew→scopeNameContentTypeを選択し、追加する。
- grammarとscopeNameContentTypeを以下の内容で設定する
grammar:
項目 | 内容 | 説明 |
---|---|---|
scopeName | source.hoge | スコープ名。source.言語名にしとけばいいのかな |
path | grammar/hoge.tmLanguage.json | 構文ファイルのパス |
scopeNameContentType:
項目 | 内容 | 説明 |
---|---|---|
scopeName | source.hoge | grammarのscopeNameを指定する |
contentTypeId | editor.sample.hoge | Content Typeを指定する。 |
これでgrammar/hoge.tmLanguage.jsonがhogeファイルを開いた時に取りこまれる様になる。
最後に、TM4Eが提供するPresentation Reconcilerを.hogeファイルに登録すればお終いだ。 Presentation Reconcilerはドキュメントが変更された時の領域分割や色の設定をするクラスで、EclipseのAPIを叩いてプログラムするとかなり面倒くさい。泣きたくなる。
- plugin.xmlを開き、Extensionsタブに移動する
- Addボタンを押し、org.eclipse.ui.genericeditor.presentationReconcilersを追加する
- presentationReconcilerを以下の内容で設定する。
項目 | 内容 | 説明 |
---|---|---|
class | org.eclipse.tm4e.ui.text.TMPresentationReconciler | IPresentationReconcilerの実装 |
contentType | editor.sample.hoge | Content Type |
tmLanguageの書き方はTextMate Language Grammarsを参照せよ。JSONで書く場合は、単にJSONに直すだけである。
{ "scopeName" : "source.hoge", "name" : "HOGE Language", "fileTypes":[".hoge"], "uuid" : "a75f98cf-a3d0-4606-b1e5-1067590c0618", "patterns" : [ { "name" : "string.quoted.double.hoge", "begin" : "\"", "end" : "\"", "patterns" : [ { "name" : "constant.character.escape.hoge", "match" : "\\." } ] }, { "name" : "storage.type.hoge", "match" : "\\b(int|string)\\b" }, { "name" : "keyword.control.hoge", "match" : "\\b(return|if|else|fn)\\b" }, { "name" : "comment.line.double-slash.hoge", "begin" : "//", "end" : "(?=$)" }, { "name": "keyword.operator.hoge", "match" : "==|!=" }, { "name" : "constant.numeric.hoge", "match" : "-?[0-9]+" } ] }
UUIDはWELLHATで生成した。
これでsample.hogeに冒頭のサンプルコードを打ち込んでみよう。(起動時にファイルを開いてしまっている場合は、一旦閉じてから、再度開く)
簡単にシンタックスハイライトをすることができた。
ところで、たまに何故か「// コメント」が文字化けするという現象にぶち当たった。
これ、毎回じゃなくて、なったりならなかったりだ。しかも、// aコメントとかすると直る。(aを外すと化ける)。 どうやら、フォントのエラーっぽい。Eclipseでコメントだけ文字化けした場合は、フォントを確認しよう。
language-configuration.json
VS CodeのLanguage Configuration(の一部)を使うことが出来る。 これによって、{を書くと自動的に閉じたり、インデントをさせたりといったことが可能になる。 随分楽だ。
language-configurations/language-configuration.jsonに以下を記述する。
{ "comments": { "lineComment": "//" }, "brackets": [ ["{", "}"] ], "autoClosingPairs": [ { "open": "{", "close": "}", "notIn": ["string"] }, { "open": "\"", "close": "\"", "notIn": ["string"] } ], "surroundingPairs": [ ["{", "}"], ["\"", "\""] ] }
括弧{}のインデントと、{や"を入力すると自動で閉じる、対応するペアを選択する機能が、これだけで実装された。
後は、これをTM4Eが認識できるようにする。
- build.propertiesを開く
- Binary Buildのlanguage-configurationsにチェックを入れる
- plugin.xmlを開き、Extensionsタブに移動する
- Addボタンを押し、org.eclipse.tm4e.languageconfiguration.languageConfigurationsを追加する
- languageConfigurationを以下の内容で設定する。
項目 | 内容 | 説明 |
---|---|---|
path | language-configurations/language-configuration.json | 設定ファイルのpath |
contentTypeId | editor.sample.hoge | Content Type |
たしかにこれで、何か良い感じには動くのだが、割とBuggyである。 例えば、文字列の閉じ"で、次の文字列の開始"が選択されたり、文字列の中でも"や{の自動クローズされたり、 インデントが揃ってないところで{の後に改行すると}の位置が変だったりする。(インデント計算がn*4でしか発生してないっぽい)
まぁ、執筆時はv0.2だし、まだまだこれから。たぶん。
まとめ
Eclipseのエディタ開発をするのは、かなりの重労働だった。しかし、TM4Eを用いれば、非常に簡単にハイライト機能、インデント機能などを実装することが出来る。 今回は全くJavaによるプログラミングをせずに済んだ。
LSP4Eと組み合わせれば、VS Code対応すれば、Eclipse対応も大してコストがかからなくなる。いずれ、実装が面倒くさいというEclipseの欠点は、間違いなく解消されるだろう。
でも、まだまだBuggyである点は注意する必要がある。