プログラムdeタマゴ

nodamushiの著作物は、文章、画像、プログラムにかかわらず全てUnlicenseです

Eclipse プラグイン開発:TM4Eによるエディタ開発

Eclipse プラグイン開発 目次


 本記事ではEclipse Photon以降のEclipseで、TM4Eを使った場合のシンタックスハイライト、インデントの実装について解説する。 TM4EはEclipse Photonで追加されたRustなどにも使われている。

 本記事ではContents Assist(補完機能)については触れないが、Eclipse Photon以降であれば、LSP4E(Language Server Protocol for Eclipse)を用いるのが良いだろう。

目次

下準備:開発する言語の内容

 今回はサンプルなので、非常に単純な仮想言語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

ざっくりしたルール

  1. {}でブロックを生成する
  2. 複数行にわたる構文はサポートしない
  3. fn [a-z]+[ type:name]*で関数定義
  4. キーワードはif,else,=,,return
  5. 型はintとstringのみ
  6. ""でstring。
  7. 数値は10進数整数のみ
  8. 関数呼び出しは name 引数
  9. if,fnの後は必ず{}によるブロックが必要
  10. //で文末までコメントアウト

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を定義する必要がある。

 

  1. plugin.xmlのExtensions(拡張)タブを開く
  2. Add(追加)ボタンを押して、org.eclipse.core.contenttype.contentTypesを追加する。
  3. org.eclipse.core.contenttype.contentTypesを右クリックし、ポップアップからNew→content-typeを選択し、content-typeを追加する。
  4. 以下の表の内容を設定する

 

項目 内容 説明
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でよい。素晴らしい。

 

  1. plugin.xmlのExtensions(拡張)タブを開く
  2. Add(追加)ボタンを押してorg.eclipse.ui.editorsを追加する。
  3. org.eclipse.ui.editorsを右クリックし、ポップアップからNew→editorContentTypeBindingを選択し、追加する。
  4. 以下の表の内容を設定する。書くのが面倒なら、右のBrowse…から検索すると良い。

 

項目 内容 説明
contentTypeId editor.sample.hoge Content Typeで設定したidを指定する。
editorId org.eclipse.ui.genericeditor.GenericEditor どのエディタで開くか指定する。

.tmLanguageを作成

 .tmLanguageを実際に作成していく。

 最初に、プラグインを配布する際のバイナリに、構文ファイルが追加される様にしておこう。

  1. grammar/hoge.tmLanguage.jsonを作成する
  2. build.propertiesを開く
  3. 「Binary Build」に「grammar」ディレクトリにチェックを入れる

 grammarディレクトリが不都合なら、別なディレクトリ名にしても良い。 なお、今回はjsonにしたが、tmLanguage形式が良い場合やexsdで書きたい場合は、それに変更する。 どの形式が良いのかは正直よく分からないが、jsonにしておけば、何処でも使えそうな雰囲気はある。後ブログでシンタックスハイライトしやすい。

 

 次に、.hogeファイルと、grammar/hoge.tmLanguage.jsonを結びつける設定をする。

  1. plugin.xmlを開き、Extensionsタブに移動する
  2. Addボタンを押し、org.eclipse.tm4e.registry.grammarsを追加する
  3. org.eclipse.tm4e.registry.grammarsを右クリックし、ポップアップメニューからNew→grammarを選択し、追加する。
  4. 同じくポップアップメニューからNew→scopeNameContentTypeを選択し、追加する。
  5. 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を叩いてプログラムするとかなり面倒くさい。泣きたくなる。

 

  1. plugin.xmlを開き、Extensionsタブに移動する
  2. Addボタンを押し、org.eclipse.ui.genericeditor.presentationReconcilersを追加する
  3. 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に冒頭のサンプルコードを打ち込んでみよう。(起動時にファイルを開いてしまっている場合は、一旦閉じてから、再度開く)

f:id:nodamushi:20181008200728p:plain

 簡単にシンタックスハイライトをすることができた。

 ところで、たまに何故か「// コメント」が文字化けするという現象にぶち当たった。

f:id:nodamushi:20181008223652p:plain

 これ、毎回じゃなくて、なったりならなかったりだ。しかも、// 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が認識できるようにする。

  1. build.propertiesを開く
  2. Binary Buildのlanguage-configurationsにチェックを入れる
  3. plugin.xmlを開き、Extensionsタブに移動する
  4. Addボタンを押し、org.eclipse.tm4e.languageconfiguration.languageConfigurationsを追加する
  5. languageConfigurationを以下の内容で設定する。

 

項目 内容 説明
path language-configurations/language-configuration.json 設定ファイルのpath
contentTypeId editor.sample.hoge Content Type

 

 たしかにこれで、何か良い感じには動くのだが、割とBuggyである。 例えば、文字列の閉じ"で、次の文字列の開始"が選択されたり、文字列の中でも"や{の自動クローズされたり、 インデントが揃ってないところで{の後に改行すると}の位置が変だったりする。(インデント計算がn*4でしか発生してないっぽい)

f:id:nodamushi:20181008211527p:plain

 まぁ、執筆時はv0.2だし、まだまだこれから。たぶん。

まとめ

 Eclipseのエディタ開発をするのは、かなりの重労働だった。しかし、TM4Eを用いれば、非常に簡単にハイライト機能、インデント機能などを実装することが出来る。  今回は全くJavaによるプログラミングをせずに済んだ。

 LSP4Eと組み合わせれば、VS Code対応すれば、Eclipse対応も大してコストがかからなくなる。いずれ、実装が面倒くさいというEclipseの欠点は、間違いなく解消されるだろう。

 でも、まだまだBuggyである点は注意する必要がある。

参考