MPS 2020.3 ヘルプ

エディター


言語のための構造が定義されたら、おそらく行って、開発者がそれを使って便利に AST を構築できるようにするための手段を作成するでしょう。AST を直接操作しても、直感的にも生産的にもなりません。AST を隠してユーザーに快適で直感的な対話を提供することは、言語エディターにとってのロールです。

エディターの概要

ノードのエディターは、そのビューおよびそのコントローラーとして機能します。エディターにノードが表示され、ユーザーはそれを変更、置換、削除などできます。異なる概念のノードは異なるエディターを持ちます。言語デザイナーは、自分の言語のすべての概念に対してエディターを作成する必要があります。

MPS では、エディターはセルで構成されています。セルには、他のセル、テキスト、または UI コンポーネントが含まれています。各エディターには、それが指定されている概念があります。1 つの概念には、複数のエディター宣言を含めることはできません(または、まったく宣言できません)。概念にエディター宣言がない場合、そのインスタンスは、エディター宣言がある概念の最も近い先祖のエディターで編集されます。

特定の概念のエディター(つまり、この概念のノードのエディターに表示する必要のあるセル)を記述するために、言語設計者は、単にエディター言語と呼ばれる専用言語を使用します。ご覧のとおり、MPS は言語指向プログラミングの原則をそれ自体に適用しています。

エディターの説明は、それが保持しているセルの説明で構成されています。このような記述を「セルモデル」と呼びます。たとえば、エディターが変更不可能なテキストを含む一意のセルで構成する場合は、エディターの説明で定数セルモデルを作成し、そのテキストを指定します。エディターを複数のセルで構成する場合は、コレクションセルモデルを作成し、その中にその要素のセルモデルを指定します。

問題が発生した場合のリフレクティブエディターへのフォールバック

実行時の例外のためにエディター定義が初期化に失敗すると、対応するセルにデフォルトのリフレクティブエディターが表示されます。メッセージツールウィンドウに説明的なエラーが表示され、ユーザーは完全なスタックトレースを取得したり、問題のあるセルに移動したりできます。

Editor error

既存のテキストを上書き

既存のテキストを上書きすると、テキストエディターとプロジェクションエディターの区別がさらにぼやけます。テキストセルに入力し、入力した文字がすでにカーソル位置にある場合、カーソルは画面上の既存の文字を上書きしたかのように右に移動します。この機能は、キーストロークを適切に処理できない場合にのみトリガーされ、それ以外の場合は無視されます(たとえば、定数セル内)、またはセルの内容が無効になります。この機能はデフォルトでオンになっていて、設定 / エディター / 全般タブでオフにすることができます。

セルモデルの種類

定数セル

Constant cell このモデルは、常に同じテキストを含むセルを記述します。定数セルは通常、テキストベースのプログラミング言語の「キーワード」を反映しています。

収集セル

他のセルを含むセル。水平 Horizontal collection (コレクション内のセルは一列に配置されています)、垂直にすることができます

Vertical collection
(セルは互いに重なり合っています)またはいわゆる「インデントレイアウト」 Indent collection (セルは水平に配置されますが、行が長すぎる場合はテキストのように次の行に折り返され、次の各行の前にインデントがあります)。
インスペクターでは、結果のセルコレクションで折りたたみを使用するかどうか、および中括弧を使用するかどうかを指定できます。折りたたむと、セルリストを 1 つのセルに縮小(折りたたむ)し、必要に応じてそこから拡張(展開)することができます。大きなルートを編集するときにあなたの言語で書くプログラマーにとっては便利です。彼 / 彼女はいくつかのセルを折りたたんで、現在のタスクに必要のないすべての情報を隠すことができます。たとえば、大きなクラスを編集する場合、現在編集しているメソッドを除くすべてのメソッド本体を折りたたむことができます。
true に設定すると、デフォルトの折りたたみプロパティにより、ユーザーが手動で展開しない限り、コレクションが初めて表示されたときに折りたたまれた状態で表示されます。

コレクションセルはコンテキストアシスタントを指定することもできます。これはユーザーに直感的な視覚アクションを提供します。詳細についてはコンテキストアシスタントのドキュメントをチェックしてください。

プロパティセル

Property cell このセルモデルは、ノードの特定のプロパティの値を表示するセルを表します。プロパティの値はプロパティセルで編集できます。プロパティセルはビューとしてだけでなくコントローラーとしても機能します。インスペクタでは、プロパティセルを読み取り専用にするか、プロパティ値の編集を許可するかを指定できます。

子セル

Child cell このセルモデルには、ノードの概念における特定のリンク宣言への参照が含まれています。結果のセルには、リンクのターゲット用のエディターが含まれます(ほとんどの場合、参照先ではなく子用)。たとえば、2 つの子 "leftOperand" と "rightOperand" を持つ "+" などの二項演算子がある場合、演算子のエディターモデルは次のようになります。左側のオペランドの参照ノードセルを含むインデントコレクションセル、"+" を含む定数セル、右側のオペランドの参照先ノードセル。これは、右側のオペランドのエディターとして、次に "+" の付いたセル、次に左側のオペランドのエディターとしてレンダリングされ、行に配置されます。これまで見てきたように、その名前からわかるように、このタイプのセルモデルは通常子供向けのエディターを表示するために使用されます。

参照先セル

Reference cell 主に参照ターゲットを表示するために使用されます。参照セルと子セルの主な違いは、参照ターゲットのエディター全体を表示する必要がない、または表示したくないということです。例: 特定のノード、たとえばクラスタイプが java クラスへの参照を持っている場合、そのクラスのエディター全体をそのメソッドやフィールドなどとともに表示したくありません。その名前を表示したいだけです。子セルをそのような目的に使用することはできません。参照セルを使用する必要があります。
参照セルを使用すると、ターゲット自体のエディターを使用する代わりに、参照ターゲットに対して別のインラインエディターを表示できます。ほとんどの場合、これは非常に単純です。参照ターゲットのセルは通常、ターゲットの名前を持つプロパティセルのみで構成されます。

子リストセル

Child list cell このセルは、同じロールのノードの子の複数の子セルを含むコレクションです。たとえば、メソッド呼び出しのエディターには、実際の引数をレンダリングするための子リストセルが含まれます。子リストは、インデント(テキストのような)、水平または垂直にすることができます。
このセルモデルから生成されたセルは、指定されたロールの子の挿入と削除をサポートするため、ビューとコントローラーの両方として機能します。挿入のデフォルトキーは Insert と Enter(それぞれ、選択した子の前または後に子を挿入するため)であり、削除のデフォルトキーは Delete です。
リストの区切り文字を指定することもできます。区切り文字は、子のセル間の定数セルに表示される文字です。セルリスト内でこの文字のキーを押すと、選択した子の後に新しい子が挿入されます。たとえば、メソッド呼び出しの実際のパラメーターを表すリストの区切り文字はコンマです。セパレーターを定義するクエリは、コレクション内のノードの位置に反応する可能性があるため、単一の子コレクション内のセパレーターは、異なる位置で異なる可能性があります。
インスペクターでは、結果のセルリストで折りたたみを使用するかどうか、および中括弧を使用するかどうかを指定できます。折りたたむと、セルリストを 1 つのセルに縮小(折りたたむ)し、必要に応じてそこから拡張(展開)することができます。大きなルートを編集するときにあなたの言語で書くプログラマーにとっては便利です。彼 / 彼女はいくつかのセルを折りたたんで、現在のタスクに現在のタスクに必要ではないすべての情報をエディターで隠すことができます。たとえば、大きなクラスを編集する場合、現在編集しているメソッドを除くすべてのメソッド本体を折りたたむことができます。

インデントセル

Indent cell インデントセルモデルは、空白を含む選択不可能な定数セルに生成されます。インデントセルから生成されたセルと、テキストとして空白を含む定数セルモデルから生成されたセルの主な違いは、インデントセルの幅がユーザー定義のグローバルエディター設定によって変わることです。たとえば、ユーザーがインデントを長さ 4 スペースに定義した場合、すべてのインデントセルは 4 文字のスペースを占有します。2 スペースの長さの場合、各インデントセルは 2 文字になります。

UI コンポーネントセル

Component cell このセルモデルを使用すると、言語設計者はノードのエディター内に任意の UI コンポーネントを挿入できます。言語設計者は、JComponent を返す関数を作成する必要があり、そのコンポーネントは生成されたセルに挿入されます。このようなコンポーネントは、エディターが再構築されるたびに再作成されるため、コンポーネント内の状態を維持しようとしないでください。すべての状態は、ビュー(コンポーネント)ではなく、モデル(つまり、ノード、そのプロパティ、参照)から取得してモデルに書き込む必要があります。
このようなセルモデルの適切な使用例は、プロパティ内のファイルへのパスを保持し、コンポーネントがモーダルファイルチューザーをアクティブにするボタンである場合です。ファイルチューザでデフォルトで選択されたパスが上記のプロパティから読み取られ、ユーザーが選択したファイルパスがそのプロパティに書き込まれます。

モデルアクセス

Model acces モデルアクセスセルモデルは、プロパティセルを一般化したものであるため、より柔軟性があります。プロパティセルは単にプロパティの値を表示し、ユーザーがその値を変更できるようにしますが、モデルアクセスセルはノードの状態に基づいて任意のテキストを表示し、ユーザーが行った変更に基づいてノードを任意の方法で変更できます。セルのテキストに。
プロパティセルを機能させるには、そのセルを介してアクセスするプロパティを指定するだけで済みますが、モデルアクセスセルを機能させるには、言語設計者が「get」、「set」、「validate」の 3 つのメソッドを作成する必要があります。「」後者の 2 つはややオプションです。
「get」メソッドはノードを受け取り、セルのテキストとして表示される文字列を返す必要があります。「set」メソッドは文字列(セルのテキスト)を受け取り、必要に応じてこの文字列に従ってノードを変更する必要があります。「validate」メソッドはセルのテキストを受け取り、それが有効かどうかを返します。ユーザーの変更後にセル内のテキストが無効になった場合、そのテキストは赤でマークされ、「set」メソッドに渡されません。
「validate」メソッドが指定されていない場合、セルは常に有効になります。「set」メソッドが指定されていない場合、セルのテキストを変更してもノード自体には影響しません。

次に該当するエディター

より具体的なエディターは、次に適用可能な新しいエディターエディターセルを介して、同じ概念のあまり具体的でないエディターを再利用できます。次に適用可能なエディターセルがプレースホルダーとして使用されます。プレースホルダーは、特定性の低いエディターを見つけるためのロジックを再適用し、見つかったエディターをその場所に挿入します。例: 特定のコンテキストヒントに 固有のエディターは、次に適用可能なエディターセルの周囲に視覚的なセレモニーを提供する場合があります。次の該当するエディター セルのコンテキストヒントを削除することにより、MPS はエディター検出ロジックを再評価し、見つかったエディターを次の該当するエディターセルに提供します。

Next1

特に、このメカニズムは、汎用コメントアウト機能をカスタマイズするときに、「コメントアウト」ノードのエディターを実装するために頻繁に使用されます。

ツールチップ

ユーザーがエディターの一部にマウスを合わせたときに、役立つメッセージを小さなツールチップポップアップウィンドウに表示できるようにします。ツールチップ言語をエディターモデルにインポートする必要があります。この言語は、mbeddr プロジェクトから MPS に採用されました。

Editor tooltip1

カスタムセル

Custom cell 他のセルモデルでは言語デザイナーが自分の望むエディターを作成するのに十分ではない場合、もう 1 つ選択肢があります。それは、任意のカスタムセルを返すセルプロバイダを作成することです。唯一の制限は、それが "EditorCell" インターフェースを実装しなければならないということです。

エディターコンポーネントとエディターコンポーネントセル

異なる概念のための 2 つ以上のエディター宣言が共通部分を持ち、それがそれらのエディターのそれぞれに重複していることがあります。冗長性を避けるために、エディターコンポーネントと呼ばれるメカニズムがあります。コンセプトエディターの宣言と同じように、エディターコンポーネントを作成するためのコンセプトを指定してセルモデルを作成します。書かれると、そのコンポーネントは指定された概念の子孫のためのエディター宣言で使用される可能性があります。エディター宣言内でエディターコンポーネントを使用するには、特定のセルモデルを作成します。エディターコンポーネントセルモデル、およびエディターコンポーネント宣言をこのセルモデルの参照のターゲットとして設定します。

セルレイアウト

各コレクションセルは、子ノードがどのように配置されるかを記述するプロパティ " セルレイアウト " を持ちます。いくつかのレイアウトがあります。

  • インデントレイアウト - テキストのようにセルを配置します。

  • 水平レイアウト - セルを水平に並べて配置します。

  • 垂直レイアウト - セルを垂直に配置します。

インデントレイアウトセルには、レイアウトをカスタマイズするためのいくつかのプロパティがあります。一部はレイアウトセル自体に適用でき、一部はレイアウトセル内のセルに適用できます。

  • indent-layout-indent- このセルは、行の最初に表示された場合、インデントが先頭に追加されます

  • indent-layout-new-line - このセルは行の最後になります

  • 新しい行のインデントレイアウト - このセルは次の行の先頭になります

  • indent-layout-new-line-children - このコレクションセルのすべての子セルは別々の行に表示されます

  • indent-layout-wrap-anchor - このコレクションセルの子セルが画面の幅を超えると、それらはこのコレクションと垂直方向に揃うように折り返されます。

  • indent-layout-indent-anchor - 後続のすべてのインデントは、現在のコレクションセルのインデントを基準にして計算されます。

  • indent-layout-no-wrap - セルは、新しい行で最初に終わるようにラップすることはできません。

スタイル

エディターセルをスタイリングすると、言語設計者はコードの読みやすさを向上させるための非常に強力な方法を手に入れることができます。キーワード、定数、呼び出し、定義、式、コメント、その他の言語要素をそれぞれ異なる色またはフォントで表示することで、開発者はより簡単に構文を理解することができます。開発者が編集できないように、スタイリングを使用してエディターの領域を読み取り専用としてマスクすることもできます。

各セルモデルには、セルの表示を決定するいくつかの外観設定があります。たとえば、フォントの色フォントのスタイル、セルを選択できるかどうかなどです。これらの設定は、スタイルシートと呼ばれるエンティティに結合されます。スタイルシート は、インラインにすることも、特定のセルモデルと一緒に記述することも、個別に宣言して多くのセルモデルで使用することもできます。インスペクタービューの 各セルには、インラインスタイルシートスタイル参照の両方が指定されています。

Style2

Style1

設定を単一の値で指定する必要はありません。クエリオプションもすべての設定で使用できます。この場合、開発者はコンセプト関数を実装する必要があります。これにより、目的の値が返されます。

Image2017 10 19 18 2 53

さまざまな目的のためにいくつかのスタイルシートを宣言することをお勧めします。もう 1 つの良い習慣は、言語のエディターを開発するとき、および言語の拡張機能を開発するときに、スタイルガイドラインを念頭に置くことです。例: BaseLanguage には、キーワード(Java のキーワードに対応する BaseLanguage エディターの定数セルに適用される)、静的フィールド(静的フィールド宣言および静的フィールド参照に適用される)、インスタンスフィールド、数値リテラル、文字列リテラルなどのスタイルがあります。BaseLanguage の拡張機能を開発するときは、キーワードスタイルを新しいキーワードに適用したり、フィールドスタイルを新しいタイプのフィールドに適用したりする必要があります。

スタイルシートは CSS スタイルシートと非常によく似ています。これは、いくつかのスタイルプロパティの値が指定されているスタイルクラスのリストで構成されています。MPS はさらに、スタイルを拡張するためのメカニズムと、プロパティ値をオーバーライドするためのメカニズムを提供します。

スタイルのプロパティ

ブールスタイルプロパティ

  • selectable- セルを選択できるかどうか。デフォルトでは True。

  • 読み取り専用 - セルとネストされたセルを変更できるかどうか。デフォルトでは False です。セルツリーの断片を凍結するために設計されています。

  • 編集可能 - セル内のテキストを変更できるかどうか。デフォルトでは、定数セルモデルの場合は false、他のセルモデルの場合は true です。

  • draw-border- セルの周囲に境界線を描画するかどうか

  • ドローブラケット - 括弧がセルの周囲に描画されるかどうか

  • first-position-allowed / last-position-allowed- テキストを含むセルの場合、キャレットが最初 / 最後の位置にあることを許可するかどうかを指定します (つまり、セルのテキスト全体の前後)

補完メニューからプロパティ値を選択するか、クエリ、つまりブール値を返す関数を指定できます。

Style3

パディングプロパティ

  • padding-left/right/top/bottom- 浮動小数点数。テキストセルのパディング、つまりセルのテキストとセルの左側と右側の間にそれぞれどのくらいのスペースがあるかを指定します。

句読点のプロパティ

コレクション内のすべてのセルは、デフォルトでは 1 つのスペースで区切られています。時々私達は一緒に置かれるセルを必要とします。

  • 句読点 - 左 - このプロパティが true の場合、セルの左側からのスペースが削除され、セルの最初の位置が許可されなくなります。

  • 句読点 - 右 - このプロパティが true の場合、セルの右側からのスペースが削除され、セルの最後の位置が許可されなくなります。

  • 水平ギャップ - コレクション内のセル間のギャップサイズを指定します。デフォルト値は 1 スペースです。

たとえばコード

(1 + 1)

「(」と「1」の間、および「1」と「)」の間にスペースは必要ありません。プロパティの句読点をセル "("、およびプロパティに追加する必要があります
句読点 - セル ")" に残されます。

カラースタイルプロパティ

  • テキストの前景色 - セルテキストの色 (テキストセルのみに影響する)

  • テキストの背景色 - セルテキストの背景色 (テキストセルのみに影響します)

  • 背景色 - セルの背景色。すべてのセルに影響します。テキストセルにゼロ以外のパディングとテキストの背景色がある場合、セルの背景色は余白の色になります。
    完了メニューから色を選択するか、クエリ、つまり色を返す関数を指定できます。

インデントレイアウトプロパティ

  • indent-layout-indent- すべての行がインデント付きで配置されます。このプロパティは、コードブロックのインデントに使用できます。

Block statement editor

  • indent-layout-new-line- このセルの後に新しいラインマーカーがあります。

Switch case editor

  • indent-layout-on-new-line- このセルは新しい行に配置されます

  • indent-layout-new-line-children- コレクションのすべての子が新しい行に配置されます

Statement list editor

  • indent-layout-no-wrap- このセルの前に行が折り返されることはありません

その他のスタイルプロパティ

  • フォントファミリー

  • フォントサイズ

  • フォントスタイル - プレーン、ボールド、イタリック、またはボールドイタリックのいずれかです。

  • レイアウトの制約 -
    • フローレイアウト用
      • なし - デフォルトの動作

      • 句読点 - フローレイアウトの前の項目は常に、この制約が割り当てられている項目と同じ行に配置する必要があることを意味します。

      • noflow - フローレイアウトからセルを除外します。現在の行は終了し、アイテムはそに配置されます。この項目の後に新しい行が開始され、通常のフローレイアウトが適用されます。このスタイルは写真をテキストの中に埋め込むのに使うことができます。

  • 下線付き - 下線付き、下線なし、またはそのままのいずれかになります(「現状のまま」とは、囲んでいるセルコレクションのプロパティに依存することを意味します)。

スタイルプロパティの伝播

一部のスタイルプロパティは、それらが適用されるセルにのみ影響しますが、他のプロパティの値は、セルサブツリー(ネストされたセル)にプッシュされ、子セルの一部がプロパティに独自の値を指定するまで適用されます。セル階層にプッシュされるこのような継承可能なプロパティには、text-foreground-colortext-background-colorbackground-colorfont-stylefont-size などがあります。

ユーザー設定のスタイル...

言語設計者はスタイルシートで独自のスタイル属性を定義してからエディターで使用できます。これにより、言語エディターの定義の柔軟性が高まります。属性は異なるタイプの値を保持することができ、オプションでデフォルト値を提供できます。

Styles500

カスタムスタイル属性には 2 種類あります。

  • 単純な - 単一のエディターセルにのみ適用されます

  • 継承 - セルとそのすべての子孫セルに再帰的に適用される

エディター定義で style 属性を使用するには、言語が属性を定義する言語をインポートする必要があり、エディターアスペクトは使用される言語の中で定義言語をリストする必要があります。
BaseLanguage コード内からカスタム属性を参照するには、次の StyleAttributeReferenceExpression コンセプトへのアクセスを得るために jetbrains.mps.lang.editor をインポートする必要があります。

EditorCell cell = ... cell.getStyle().get(styleAttribute/myValue/);

スタイル継承

本当に使用できるようにするには、特定のスタイルクラスが明示的にオーバーライドされないすべてのスタイルプロパティの値を継承することを説明するために、スタイルクラスに拡張メカニズムが必要です。特別なスタイルプロパティ apply を使用して、親スタイルクラスで指定されたすべてのプロパティの値をスタイルクラスにコピーできます。apply プロパティを使用することは、親スタイルクラスからすべてのプロパティをコピーして貼り付けることと意味的に同等です。条件付きでスタイルプロパティ値を適用するために、apply-if バリアントも使用できます。従来のスタイル拡張とは異なり、適用メカニズムでは複数のクラスを継承できます。

unapply プロパティを使用すると、スタイルクラスは選択した継承プロパティの効果を停止できます。例: コメントアウトされたコードのスタイルクラスは、コード要素をすべて灰色に見えるようにするスタイルをプッシュダウンします。ただし、ユーザーがリンクを見つけてクリックできるように、リンクを通常の色でレンダリングする必要がある場合があります。

親スタイルで指定されたプロパティと継承しているセルで明示的に定義されたプロパティとの間の潜在的な競合は順序に基づいて解決されます。最後に指定された値は、同じスタイルプロパティの以前のすべての値をオーバーライドします。

例: ConsoleRoot の概念は、編集が許可される単一のポイント(commandHolder セル)のみを備えた読み取り専用エディターを提供します。まず、readOnly スタイルクラスがエディターで設定されます。

Style4

次に、readOnly スタイルクラスが commandHolder セルに適用されません。

Style5

readOnly スタイルクラスは次のように定義されています。

Style30

スタイルの優先順位

スタイルクラスは、他のスタイルクラスまたは複数のクラスよりも優先されるように宣言できます。

  1. スタイルクラスが何よりも優位ではない場合、低レベルスタイルクラスです。

  2. スタイルクラスを支配するように宣言しますが、オーバー支配するスタイルクラスを指定しない場合は、すべての低レベルのスタイルクラス上支配し、スタイルクラスが考慮される(何のスタイルクラスを指定しますが、本を支配する言葉ではありません)。

  3. 支配関係推移的でありサイクルは許可されていません。

支配関係は、継承可能な属性を持つスタイルに対してのみ意味があります。あるスタイルプロパティの一方の値が親からプッシュダウンされ、現在のセルに適用されているスタイルクラスに同じプロパティの別の値が指定されている場合、結果として生じる動作は 2 つのスタイルクラス間の関係によって異なります。

  1. 両方のスタイルクラスが low-level の場合、parent からプッシュされた値は無視され、現在のセルのスタイルクラスからの値に置き換えられます。

  2. 一方のスタイルクラスが他方を支配する場合、両方の値が保持されてプッシュダウンられますが、スタイルクラスの値が支配的であるため、他方のスタイルクラスの値は隠されます。

  3. ただし、一部の子セルで、支配的なスタイルクラスが適用されていない場合(特別なスタイルプロパティが適用されていない場合)、他のスタイルクラスの値がこのプロパティの結果の値になります。

例: TODO という単語を含むコメントは、プレーンコメントよりも目立つようにスタイル設定する必要があります。コメントを表す言語の概念は、TODO 対応スタイル( TODO_Style)を適用する必要があります。これは、プレーンな Comment_Style に対する優位性を宣言します。ただし、実際のスタイリングプロパティは、コメントに TODO テキスト(isToDo())が実際に含まれている場合にのみ適用されます。それ以外の場合は、プレーンな Comment_Style プロパティが使用されます。

Style7

「ドミナンスの追加」インテンションを使用して、ドミナンスオーバー句をスタイルに追加します。

Style31

セルアクション

すべてのセルモデルには、それに関連付けられたいくつかのアクションがあります。このようなアクションは編集の使いやすさを向上させるためのものです。任意のセルモデルのインスペクタで指定できます。

キーマップ

セルモデルのキーマップへの参照を指定できます。キーマップは根本的な概念、つまりキーストロークと実行するアクションからなる一連のキーマップ項目です。特定のキーマップを参照してセルモデルから生成されたセルは、キーストロークに対して適切なアクションを実行します。

キーマップでは、キーマップが適用可能な概念を指定する必要があります。たとえば、式を使ってアクションを実行したい場合は、Expression を適切な概念として指定する必要があります。その場合は、Expression の子孫のエディター宣言内に含まれているセルモデルに対してのみこのようなキーマップを指定できます。それ以外の場合は型エラーです。

キーマッププロパティ "everyModel" が "true" の場合、このキーマップはエディターのすべてのセルに指定されているかのように動作します。それは多くの異なるエディターを持っている特定の概念の多くの子孫を持っていて、あなたのキーマップがそれらの先祖に適用可能であるときに役に立ちます。「すべてのモデル」のキーマップとしてマークするのであれば、すべてのエディターでそのようなキーマップを指定する必要はありません。

キーマップアイテムは、次の機能で構成されています。

  • キーマップアイテムがトリガーされたときに実行される関数 (何も返さない)

  • このキーマップアイテムをトリガーする一連のキーストローク

  • キーマップ項目がここで適用可能かどうかを判断するブール関数(指定されていない場合は常に適用可能)。キーマップアイテムがトリガーされた瞬間に適用できない場合は、アクションは実行されません。

  • キーマップアイテムにキャレットポリシーを指定できます。キャレットポリシーは、このキーマップアイテムを有効にするためにセル内のどこにキャレットを配置するかを指定します。キャレットポリシーは、最初のポジション、最後のポジション、中間のポジション、または任意のポジションのいずれかです。デフォルトでは、キャレットポリシーは「任意のポジション」です。セル内のキャレットが、起動された瞬間にキーマップアイテムのキャレットポリシーと一致しない場合、このキーマップアイテムはアクションを実行しません。

アクションマップ

セルモデルには、アクションマップへの参照を含めることができます。アクションマップは、特定の概念に対するデフォルトのセルアクションをオーバーライドします。アクションマップは、いくつかのアクションマップ項目で構成されています。アクションマップでは、そのアクションマップが適用可能な概念を指定する必要があります。

アクションマップ項目には、次のものが含まれます。

  • 文字列であるアクションの説明

  • アクションを実行する(何も返さない)関数。

アクションマップ項目は、デフォルトのアクションの 1 つをオーバーライドすることがあります(アクションを参照)。たとえば、エディターにアクションマップのない return ステートメントがあり、キーワード "return" を持つセルに対して Delete キーを押すと、ステートメント全体が削除されます。ただし、delete アクションマップ項目を含むアクションマップを指定することもできます。これは、return ステートメントを単に削除する代わりに、削除された return ステートメントと同じ式を含む式ステートメントで置き換えます。

アクション DELETE の説明: <description なし> 実行: (ノード、editorContext)-> void { ノード <ExpressionStatement> expressionStatement = node。new(ExpressionStatement)に置き換えます。; expressionStatement。式。set(node .expression); }

エディターのコンテンツ全体を選択し、Ctrl+A によってトリガーされる SELECT_ALL アクションは、アクションマップを介してカスタマイズすることもできます。 executeWhile メソッドを使用する jetbrains.mps.nodeEditor.selection.SelectUpUtil クラスを利用して、このアクションの選択の上限を指定できます。

Mps selectall

既存のアクションマップのアクションマップアイテムは、インポートを介して新しいアクションマップで再利用できます。ユーザーには 2 つのオプションがあります。

  • アクションマップからすべての項目をインポートする

  • 特定のアクション ID を持つアイテムのみをインポートします

Image2018 9 14 13 23 37

インポートアクションは次の規則に従います。

  • インポート作業は推移的に行われます。

  • 現在のセルのアクションマップで定義されているアクションは、インポートされたセルのアクションマップで定義されているアクションよりも優先されます。

  • 複数のマップが同じ種類のアクションを定義している場合は、最後にインポートされたマップが優先されます。

  • 循環インポートは許可されていません。

  • インポートされたセルアクションマップの適用可能な概念は、このマップの適用可能な概念の同じ概念または上位概念である必要があります。

  • アクションマップは言語間の作業をインポートします。ある言語のエディターアスペクトのアクションマップは、別の言語のエディターアスペクトからアクションマップをインポートできます。

DELETE および BACKSPACE アクションハンドラーには特定のセマンティクスがあります。アクションマップの定義やインポート DELETE ハンドラー場合と BACKSPACE ハンドラーを定義またはインポートしません、DELETE のためのものと同じデフォルトの BACKSPACE ハンドラーが自動的に登録されています。

インポートされたアクションハンドラーの解決は動的です(実行時に行われます)。アクションマップ A がアクションマップ B から項目をインポートすると、登録される正確なアクションハンドラーはアクションマップ A の生成時に解決されません。その結果、アクションマップ B が変更されたときにアクションマップ A を再生成する必要がなくなります。

セルメニュー

特定のセルに対してカスタム補完メニューを指定することができます。セル宣言のインスペクタを開き、Common という名前のテーブルを見つけ、menu という名前の行を見つけ、新しいセルメニュー記述子を作成します。セルメニュー記述子はメニュー部分で構成されています。メニュー部分はさまざまな種類のもので、以下で説明します。

プロパティ値メニュー部分

このメニュー部分はプロパティセルで利用可能です。あなたのプロパティのために完成で示されるプロパティ値のリストを指定します。list <String> 型の値を返す関数を書くべきです。

プロパティ後置ヒントメニュー部分

このメニュー部分はプロパティセルで利用可能です。あなたのプロパティ値のための「良い」後置文字列として役立つ文字列のリストを指定します。そのようなメニュー部分では、list <String> 型の値を返す関数を書くべきです。このようなメニューは、MPS にプロパティの適切な値を「推測」させたい場合に便利です。たとえば、変数型名であるが最初の文字が小文字になっている、またはその型名で終わる良い変数名になると決めることができます。型 "Foo" の変数の場合、良い名前は "foo" になります。"," aFoo "," firstFoo "," goodFoo " などです。変数宣言用のエディターで、変数名のプロパティセルのメニューに次のようなメニュー部分を記述する必要があります。

プロパティの接尾辞のヒント接尾辞: (scope、operationContext、node)-> list <String> {list <String> result; node <タイプ> nodeType = ノード。タイプ ; if(nodeType!= null){result = MyUtil.splitByCamels(nodeType。getPresentation()); } else { 結果 = 新しいリスト <文字列> { 空 }; } 結果を返す ; }

ここで、splitByCamels() は、大文字で始まる文字列の接尾辞のリストを返す関数です(たとえば、MyFooBar-> MyFooBar、FooBar、Bar)。

一次置換子メニュー

これはセルメニューの一部で、子供のための主要なアクションを返します(デフォルトでは、セルメニューが存在しない場合と同様)。

参照メニューを選択する

これはセルメニューの一部で、参照先の主なアクションを返します(デフォルトでは、セルメニューが存在しない場合と同様)。

ノードメニューの置換 (カスタムノードの概念)

この種のセルメニュー部分は、編集されたノード(たとえば、完了メニューが呼び出されるノード)を特定の指定された概念およびそのサブコンセプトのインスタンスと置き換えることを可能にします。このようなセルメニュー部分は、たとえば、ノードのエディターの特定のセルにノード全体の置き換えを担当させる場合に便利です。たとえば、二項演算用のエディターを考えてみましょう。左オペランド用のセル、概念プロパティ "alias" 用のセルである演算符号用のセル、および右オペランド用のセルで構成されるすべてのバイナリ演算用の共通エディターがあります。

[>%leftExpression%^ {{alias}}%rightExpression%<]

操作記号付きのセルのセルメニューを作成するのは当然です。これにより、操作記号を別の記号に置き換えることができます(もちろんノード全体を置き換えることによって)。そのような目的のために、操作記号のためのセルにノード置換メニュー部分を書くでしょう:

ノードを置き換える(カスタムノードの概念): BinaryOperation

BinaryOperation 概念のノードファクトリに従って、前の左子と右子が新しく作成された BinaryOperation に追加されます。

子メニューを置き換える (カスタム子供の概念)

そのようなセルメニュー部分は、ある子供のためのセルに適用可能であり、そのどのサブコンセプトが完成メニューに表示される(そして選択されたときインスタンス化されそしてインスタンスが子供として設定される)特定の概念を指定します。その概念を指定するために、ノード <ConceptDeclaration> 型の値を返す関数を書くべきです。

子メニューを置き換えます(カスタムアクション)。

この種のセルメニューパーツは、特定の子のセルに適用でき、子の概念だけでなく子の置換アクション全体をカスタマイズすることもできます。マッチングテキスト(補完メニューに表示されるテキスト)、説明テキスト(説明)補完メニューの右部分に表示されるアクション、および補完メニューからアクションが選択されたときに子ノードを作成する関数です。そのようなメニューを書くには、一致するテキスト、説明のテキストを指定し、ノードを返す関数を書く必要があります(このノードは、それぞれの子リンクで指定されたターゲット概念のインスタンスである必要があります)。

一般メニュー項目

この種のセルメニュー部分では、補完メニューでそれぞれのメニュー項目が選択されるときに MPS に任意のアクションを実行させることができます。メニュー項目にマッチするテキストを指定して、欲しいことをする関数を書くべきです。たとえば、クラスフィールドが存在しない場合、クラスフィールドの子リストセルを表示したくない場合があります。そのため、デフォルトのアクションを使用して新しいフィールドを作成することはできません。代わりに、クラスの新しいフィールドを作成するテキスト「create field」が一致する一般的なメニュー項目をクラスのエディターのどこかに作成できます。

テキストに一致する一般的なアイテム: フィールドハンドラーを追加: (ノード、モデル、スコープ、operationContext)-> void { ノード。フィールド。新規追加(<デフォルト>); }

アクショングループ

アクショングループは、カスタムアクションのグループを返すセルメニューパーツです。実行時には、メニュー構築中に、パラメーターオブジェクトと呼ばれる特定の型のオブジェクトがいくつか収集または作成されます。そのパラメーターには、アクショングループの関数オブジェクト型が対応するテキストと説明テキストを返すように指定されています。パラメーターオブジェクトを持つメニュー項目が選択されたときにトリガーされる機能も指定されています。

アクショングループの説明は次のもので構成されます。

  • パラメーターオブジェクト型。

  • 指定された型のパラメーターオブジェクトのリストを返す関数(編集されたノード、スコープ、オペレーションコンテキストを取ります)。

  • 指定された型のパラメーターオブジェクトを受け取り、一致するテキスト(補完メニューに表示されるテキスト)を返す関数。

  • 指定された型のパラメーターオブジェクトを受け取り、パラメーターオブジェクトの説明テキストを返す関数。

  • 完了メニューでパラメーターオブジェクトが選択されたときにアクションを実行する関数。

アクションを実行する関数は種類が異なる場合があるため、セルアクショングループのメニュー部分には 3 つの異なる種類があります。

  • 一般的な行動グループ。パラメーターオブジェクトが与えられると、そのアクション関数は任意のアクションを実行します。パラメーターオブジェクトの他に、この関数には編集されたノード、そのモデル、スコープ、操作コンテキストが提供されています。

  • 子グループを置き換えます。それは子セルに適用可能であり、パラメーターオブジェクトが与えられるとそのアクション関数は新しい子を返します。それはそれぞれの子リンク宣言で指定された型を持たなければなりません。パラメーターオブジェクトの他に、機能には編集されたノード、そのモデル、現在の子(たとえば置き換えられる子)、スコープおよび操作コンテキストが提供されます。

  • ノードグループを置き換えます。パラメーターオブジェクトが与えられると、そのアクション関数はノードを返します。通常、編集されたノード(つまり、完了メニューが呼び出されるノード)の一部です。パラメーターオブジェクトの他に、この関数には編集されたノード、そのモデル、スコープ、操作コンテキストが提供されています。

セルメニューコンポーネント

異なるセルのいくつかのメニュー部分が等しい場合は、重複を避けるために別々の固有のエンティティに抽出することをお勧めします。そのような目的のためにセルメニューコンポーネントが意図されています。セルメニューコンポーネントは、セルメニュー記述子(セルメニュー部分のコンテナー)と適用可能な機能の指定から構成されています。適用可能な機能の仕様は、メニューが適用可能である機能への参照(たとえば、子リンク宣言、参照リンク宣言またはプロパティ宣言)を含みます。たとえば、あなたのメニューコンポーネントがある子を置き換えるために使われるなら、その子リンク宣言はここで指定されるべきです。等

セルメニューコンポーネントが作成されると、セルメニューコンポーネントメニュー部分を介してセルメニューで使用できます。セルメニューコンポーネントメニュー部分は、特定のメニューコンポーネントへの参照を含むセルメニュー部分です。SModel 言語

参照表示のカスタマイズ

一致するテキストの指定および参照用のエディター内テキスト表現は、エディターの側面で直接行うことができます。

参照。プレゼンテーションセルでは、表示されるテキストをカスタマイズできます。

Ref cust1

セルメニューでは、完了メニューに表示されるテキストをカスタマイズできます。

Ref cust2

この機能は、以前は制約によって実現されていました。

参照制約におけるプレゼンテーションクエリの移行

制約の側面での参照プレゼンテーション部分の設計はその時代を示しているため、上記の新しい機能に置き換えられました。ほとんどのコードは自動的に移行されます。移行で生成された一部のコードは簡略化できるため、確認することを検討してください。

プレゼンテーションクエリを移行できない場合があります。参照リンクのあるコンセプトのエディターがあり、そのサブコンセプトの 1 つで参照用に定義されたプレゼンテーションパーツのある参照制約があるとします。エディターコンポーネントがサブコンセプトでオーバーライドされない場合、MPS はこのプレゼンテーション部分をインライン化する場所を認識しません。この場合、ユーザーコードでの未修正の参照プレゼンテーションを防ぐために、プレゼンテーションパーツの使用箇所を手動で移行する必要があります。それを行うにはいくつかの選択肢があります。

  • サブコンセプトでエディターを上書きするだけです。表示部分から適切な参照セルにコードを移動します。

  • 参照セルを別のコンポーネントに抽出し、そのサブコンポーネントのコンポーネントをオーバーライドします。

  • 参照用のプレゼンテーションを提供する新しい動作メソッドを作成します。作成したメソッドに参照セルデリゲートを作成します。このメソッドを subconcept でオーバーライドします。

自分の言語が他の誰かによって別のプロジェクトで拡張される可能性があると予想される場合は 、非推奨のプレゼンテーション部分を削除しないでください。そうしないと、拡張言語が不適切に移行される可能性があります。

二段階削除

プロジェクティブエディターでは、Delete キーまたは Backspace キーを押したときにコードのどの部分が削除されるかを予測するのが難しい場合があります。例: キャレットが baseLanguage ステートメントのセミコロン上にあり、Backspace キーを押すと、ステートメント全体が削除されます。2 段階の削除により、コードのどの部分が削除されるかを確認できます。
ここではどのように動作します: ハイライト表示されますが削除または Backspace キーを押すと、削除されるコードの一部は、になります。必要に応じて、 もう一度 Delete キーまたは Backspace キーを押すと、コードが削除されます。ハイライトした後、このコードを削除したくないことに気付いた場合は、エスケープを押すか、キャレットを動かすだけでハイライトが消えます。

例を見てみましょう:
ステートメントのセミコロンにキャレットを置きます。

Semicolon

Backspace キーを押します。ステートメント全体がハイライトされます。これは、Backspace キーをもう一度押すと、ステートメントが削除されることを意味します。

Semicolon highlighted

もう一度 Backspace キーを押します。ステートメントが削除されます。

Deleted

他のノードでも同じことがデフォルトで機能します。

2 段階削除を有効にするには、設定> エディター> 一般の 2 段階削除チェックボックスをオンにします。

コードからの 2 段階削除

言語設計者は、カスタム削除アクションに 2 段階の削除シナリオを含めることができます。jetbrains.mps.lang.editor の ApproveDelete_Operation は、その目的のために導入されます。この操作はノードに適用されます。

Appr del

この操作は、それが成功し、そのノードが以前に削除を承認されていない場合に true を返します。より正式には、以下のすべての条件を満たす必要があります。

1)2 段階の削除設定オプションがチェックされています。

2)ノードが完全に選択されていません。

3)ノードはすでに削除承認されていません。

これらの条件がすべて満たされると、削除が承認されたノードがハイライトされ、カスタム削除アクションがこの時点で停止することがあります。

削除を承認した直後に同じカスタム削除アクションが呼び出された場合、approveDelete 操作は false を返し(ノードがすでに承認されているため)、アクションは削除を続行します。

baseLanguage の典型的なシナリオを見てみましょう。

Dot e

これは、ドット式操作の削除アクションの一部です。このアクションは、最初に削除の操作を承認しようとし、成功するとアクションが停止します。ir が成功しない場合、ノードの操作がすでに承認されている(= ハイライトされている)か、ユーザーがノードを選択したか、「2 ステップ削除」設定オプションがオフになります。この場合、操作を削除し、抽象概念のノードに置き換えます。

より複雑なケース

カスタマイズされた削除アクションは、現在のノードを削除するよりも複雑な場合があります。

シナリオの例を見てみましょう。IncompleteMemberDeclaration の「final」キーワードで delete を押します。最終プロパティを false に設定するカスタムアクションがあります。 エディターには、ノードの最終プロパティが true の場合にのみ表示されるセルがあるため、アクションの後、セルは表示されません。

(final プロパティを false に設定して)非表示にする前に final キーワードをハイライトする場合は、次の方法で削除を承認します。

Final

完成品のカスタムスタイルと優先順位 (実験用)

Completion styling concept func

言語設計者は、完了メニューの項目のスタイルと優先順位を設定できます。そのためには、言語設計者は、言語のエディターの側面で Completion Styling ルートを作成する必要があります。補完メニュー項目のスタイルを指定するには、言語設計者は最初に項目を指定する必要があります。
現在、完了アイテムの 2 つの可能なセレクターを提供しています。

  • 特定の概念のインスタンスを変更するアイテム。このセレクターは、ユーザーがコンセプトのノード(またはそのプロパティ、参照、または子)にキャレットを置き、Control + Space を押すと、完了メニューに表示される項目を選択します。

  • 特定の概念のインスタンスを作成するアイテム。これらは主に代替アクションです。例: ユーザーが StatementList に ある ReturnStatement選択し、Control + Space を押すと、完了メニューの項目が Statement のインスタンスを作成し、ReturnStatement をそれらのインスタンスに置き換えます。したがって、Statement のインスタンスを作成するアクションのセレクターは、それらの項目を選択します。

1 つの項目を複数のセレクターによって選択できることが重要です。例: 上記の状況では、複数のセレクターが 1 つの補完項目に一致します。

  • ステートメントのインスタンスを作成するアクションの場合 (アイテムが現在のノードを別のステートメントに置き換えるため )

  • ステートメントのインスタンスを変更するアクションの場合 (現在のノードは ReturnStatement であり、これはステートメントでもあるためです。)

  • StatementList:statement のインスタンスを変更するアクションの場合 (メニュー項目は新しいノードを親 StatementList のステートメントロールに貼り付けるためです )

可能な限り最も具体的なセレクターを選択する必要があります。例: BaseConcept のインスタンスを変更するセレクターまたはアクションは、最も具体性の低いセレクターであり、すべての補完メニュー項目に影響します

Completion styling strike

セレクターがメニュー項目と一致すると、言語デザイナーはそのスタイルをカスタマイズできます。スタイルオブジェクトはこの目的を果たします。
現在、次のことが可能です。

  • アイテムのフォントを太字にする

  • アイテムのフォントを斜体にする

  • アイテムのテキストを削除する (概念を廃止できます)

  • アイテムの背景とテキストの色を設定します

  • アイテムを隠す

  • アイテムの優先順位を設定します

すべてのスタイルが累積することに注意してください。

  • 少なくとも 1 つのスタイラーが太字 / 斜体 / 非表示スタイルのいずれかを設定している場合、項目は太字 / 斜体 / 非表示になります。

  • 背景色またはテキストの色が矛盾する場合は、最初に指定された色が使用されます。

  • 優先順位は項目をソートするために使用されます。スタイルによってアイテムの優先順位として設定された最大値が使用されます。

  • アイテムはまず優先度順にソートされ、次にユーザーのテキストと一致するレベル順にソートされます。現在、このレベルを上書きする方法はありません。

言語設計者が使用できるいくつかのパラメーターがあります。それらはアイテムに格納されています。

情報パラメーター:

  • matchingText- アイテムの左側に表示されるテキスト。このテキストは、ユーザーが完了メニューにテキストを入力したときにアイテムをフィルタリングするために使用されます。

  • descriptionText- アイテムの右側に表示されるテキスト。

  • parameterObject- 一部のアイテムはオブジェクトでパラメーター化できます。例: ノードの参照を変更するアイテムは、実行時に設定される参照のターゲットでパラメーター化されます。

  • outputConcept- 代替アクションなどの一部のアクションは新しいノードを作成します。出力の概念は新しいノードの概念です。

baseLanguage のスタイルのいくつかの注目すべき例:

  • ReturnStatementStyling は、戻り項目を太字にし、現在のステートメントリストの最後にある場合、その優先度をゼロ以外に設定します。

    Completion styling return

  • アイテムが変数宣言を参照する場合、アイテムの優先度をゼロ以外に設定する VariableReferencePriority。

    Completion styling var ref

重要な注意点:

この機能は実験的なものであり、その設計は将来大幅に変更される機能があります。この機能に関するフィードバックは非常に高く評価されており、それを改善できます。この機能をオフにする可能性があります: 設定 - > エディター - > 一般 - > Use completion styling

関連ページ:

エディタークックブック

このドキュメントは、上級言語設計者を対象としており、MPS エディターに関する最も一般的な質問に対する回答を提供します。エディターのドキュメントを読むのを好むかもしれません。それはサブジェクトに関する徹底的な情報を含みます。エディター定義を作成する方法:MPS がエディターをデザインするために言語デザイナーに提供する DSL は、セルの概念に基づいて構築されています。言語設計者は、エディターセルを組み合わせて、表記法の望ましい最終レイアウトを反映するように画面上に配置します。画面の右下隅にある...

コンテキストアシスタント

MPS は、コンテキストでアクションを実行するためのいくつかのメカニズムを提供する: 完了、インテンション、リファクタリング、その他のさまざまなポップアップメニュー: これらのメカニズムには、経験の浅い新しいユーザーにはすぐには表示されないという共通点があります。また、通常、多くの可能な選択肢を提供し、利用可能な機能全体を明らかにします。これは、上級ユーザーには役立ちますが、初心者を圧倒する可能性があります。DSL でスクリプトを作成するプロセスを通じて新しいユーザーをより適切にガイドするために...

エディターのアクション

MPS エディターには、完了アクション、ノード作成ポリシーにかなり実用的なデフォルトがあります。しかし、カスタマイズしたい場合は、アクション言語を使用しなければなりません。ノードファクトリノードが別のノードに置き換えられる場合、置き換えられるノードが保持する値を使用して、置き換えノードの作成プロセスをパラメーター化するか、モデル内の置き換えノードの将来の位置を反映することも役立つ場合があります。ノードファクトリはまさにそれを提供します。置換アクションで、または新しい初期化ノード <>...

テスト言語

テスト言語:導入:テストは言語設計者の作業の重要な部分です。MPS が優れているためには、BaseLanguage コードと言語の両方のテスト機能を提供する必要があります。jetbrains.mps.baselanguage.unitTest 言語を使用すると、JUnit-like ユニットテストで BaseLanguage コードをテストできますが、言語テスト言語の jetbrains.mps.lang.test は、言語テストを作成するための便利なインターフェースを提供します。クイックナビゲーション...

構造

MPS を使用すると、目的の言語の文法を定義する必要がなくなるため、言語の構造を指定するためのさまざまな方法が明らかに必要になります。ここで構造言語が役に立ちます。それはあなたに言語構造を定義するためのすべての手段を与えます。前に説明したように、MPS でコーディングする場合、AST を直接効果的に構築しているため、言語の構造では、AST の構築に使用する要素であるブリックを指定する必要があります。プロパティ、参照、および子供: レンガをコンセプトと構造言語が公開の概念と概念インターフェースだけ...