MPS 2019.2ヘルプ

エディター


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

エディターの概要

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

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

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

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

セルモデルの種類

定数セル

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

収集セル

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

VerticalCollection
(セルは上下に重なっています)またはいわゆる「インデントレイアウト」 IndentCollection (セルは水平に配置されていますが、行が長すぎる場合は、次の行までテキストのように折り返されます)。
Inspectorでは、結果として得られるセルコレクションが折りたたみを使用するかどうか、およびブレースを使用するかどうかを指定できます。折りたたみを使用すると、セルリストを1つのセルに折りたたみ(折りたたみ)、必要に応じてそこから展開(展開)することができます。大きなルートを編集するときあなたの言語で書いているプログラマーにとって有用です:彼/彼女はいくつかのセルを折りたたみそして現在のタスクに必要でないすべての情報を隠すことができます。たとえば、大きなクラスを編集するときは、現在編集しているメソッド以外のすべてのメソッド本体を折りたたむことができます。
trueに設定されたときのデフォルトプロパティーによる折りたたみは、ユーザが手動で展開しない限り、コレクションが最初に表示されたときに折りたたまれて表示されることを保証します。

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

プロパティーセル

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

子セル

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

参照先セル

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

子リストセル

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

インデントセル

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

UIコンポーネントセル

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

モデルアクセス

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

次に該当するエディター

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

next1(英語)

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

カスタムセル

CustomCell 他のセルモデルでは言語デザイナーが自分の望むエディターを作成するのに十分ではない場合、もう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(英語)

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

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

スタイルのプロパティー

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

  • 選択可能 - セルを選択できるかどうか。デフォルトでは真です。

  • 読み取り専用 - セルと入れ子になったセルを変更できるかどうかデフォルトではです。セルの木の断片を凍結するために設計されています。

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

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

  • draw-brackets - 括弧がセルの周囲に描かれるかどうか

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

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

Style3

パディングプロパティー

  • 左/右/上/下のパディング - テキストセルの余白、つまりセルのテキストとセルの左右の間のスペースを指定する浮動小数点数。

句読点のプロパティー

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

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

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

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

たとえばコード

(1 + 1)

"("と "1"の間、および "1"と ")"の間にスペースは必要ありません。そのため、セル "("にproperty句読点権を追加し、propertyを追加する必要があります。
句読点 - セル ")"の左。

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

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

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

  • 背景色 - セルの背景色。どのセルにも影響します。テキストセルに0以外の余白とテキストの背景色がある場合、セルの背景色は余白の色になります。
    補完メニューから色を選択するか、色を返す関数などのクエリを指定できます。

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

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

BlockStatementEditor

  • indent-layout-new-line - このセルの後に改行マーカーが表示されます。

SwitchCaseEditor

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

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

StatementListEditor

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

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

  • フォントファミリー
  • フォントサイズ
  • フォントスタイル - プレーン、ボールド、イタリック、ボールドイタリックのいずれかです。

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

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

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

  • 下線を引く - 下線を引く、下線を引かない、またはそのままの形で使用できます(「そのまま」は、囲んでいるセルコレクションのプロパティーによって異なります)。

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

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

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

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

styles500

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

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

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

エディター定義でstyle属性を使用するには、あなたの言語はその属性を定義している言語をインポートしなければならず、エディターのアスペクトは使用されている言語の中で定義言語をリストしなければなりません。
BaseLanguageコード内からカスタム属性を参照するには、jetbrains.mps.lang.editorをインポートしてStyleAttributeReferenceExpressionの概念にアクセスする必要があります。

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

スタイル継承

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

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

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

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

style4

そしてreadOnlyスタイルクラスはcommandHolderセルには適用されません

style5

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

style30

スタイルの優先順位

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

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

  2. スタイルクラスを支配するように宣言しますが、(何のスタイルクラスが指定されていないが、言葉は存在を支配 )を支配スタイルクラスを指定しない場合は、スタイルクラスは、以上のすべての低レベルのスタイルクラスを支配したと見なされます。

  3. 支配関係推移的でありサイクルは許されない。

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

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

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

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

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

style7

「優位性を追加」 インテンションを使用して、dominates over句をスタイルに追加します。

style31

セルアクション

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

キー・マップ

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

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

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

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

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

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

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

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

アクションマップ

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

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

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

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

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

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

エディターの内容全体を選択し、Control/Cmd + 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 <Type> nodeType = node。タイプ; if(nodeType!= null){result = MyUtil.splitByCamels(nodeType。getPresentation()); } else {result = new list <String> {empty}; }結果を返す; }

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

一次置換子メニュー

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

参照メニューを選択する

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

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

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

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

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

ノードを置き換える(カスタムノードの概念): バイナリ操作

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

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

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

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

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

一般メニュー項目

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

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

アクショングループ

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

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

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

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

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

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

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

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

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

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

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

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

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

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

参照表示のカスタマイズ

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

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

RefCust1(英語)

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

RefCust2(英語)

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

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

制約の側面における参照表示部分の設計は、その時代を見せてきたため、上記の新しい機能に置き換えられました。ほとんどのコードは自動的に移行されます。マイグレーションで生成されたコードの中には単純化できるものもあるため、それを検討してください。

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

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

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

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

言語が他の誰かによって他のプロジェクトで拡張されるかもしれないと期待しているなら、非推奨のプレゼンテーション部分を削除しないでください。そうでない場合は、拡張言語は不適切に移行されるかもしれません。

二段階削除

プロジェクションエディターでは、削除またはバックスペースを押したときにコードのどの部分が削除されるのかを予測するのが難しい場合があります。例:キャレットがbaseLanguageステートメントのセミコロンの上にあり、バックスペースを押すと、ステートメント全体が削除されます。2段階削除では、コードのどの部分が削除されるのかを確認できます。
削除またはバックスペースを押すと、削除されるコード部分が強調表示されます。それがあなたに合っているなら、もう一度削除またはバックスペースを押すとコードは削除されます。強調表示した後にこのコードを削除したくない場合は、エスケープを押すかキャレットを移動するだけで強調表示が消えます。

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

Semicolon

バックスペースを押します。文全体が強調表示されています。つまり、もう一度バックスペースを押すと、そのステートメントは削除されます。

Semicolon highlighted

もう一度バックスペースを押します。文が削除されます。

Deleted

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

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

コードからの2段階削除

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

appr del

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

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

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

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

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

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

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

dotE

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

より複雑なケース

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

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

非表示にする前にfinalキーワードを強調表示する場合( finalプロパティーをfalseに設定することによって)、この方法で削除を承認します。

final

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

CompletionStylingConceptFunc

言語デザイナーは、完成メニューの項目のスタイルと優先順位を設定できます。そうするためには、言語設計者は言語のエディター面で完成スタイリングルートを作成するべきです。補完メニュー項目のスタイルを指定するために、言語設計者はまずその項目を指定する必要があります。
現在、完成品の2つの可能なセレクターを提供しています:

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

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

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

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

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

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

それで可能な限り最も特定的なセレクターを好むべきです。例:BaseConceptのインスタンスを変更するセレクターまたはアクションは、最も特定性の低いセレクターであり、すべての補完メニュー項目に影響します。

CompletionStylingStrike

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

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

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

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

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

  • アイテムを隠す

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

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

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

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

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

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

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

情報パラメータ:

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

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

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

  • outputConcept - 代替アクションが新しいノードを作成するようないくつかのアクションは、出力の概念は新しいノードの概念です。

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

  • 現在のステートメントリストの最後にある場合は、リターンアイテムを太字にして優先順位をゼロ以外に設定するReturnStatementStyling

    CompletionStylingReturn

  • 項目が変数宣言を参照している場合、項目の優先順位をゼロ以外に設定するVariableReferencePriority

    CompletionStylingVarRef

重要な注意点:

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

最終更新日: 2019年8月30日

関連ページ:

エディタークックブック

このドキュメントは、上級言語設計者を対象としており、MPSエディターに関する最も一般的な質問に対する回答を提供します。エディターのドキュメントを読むのを好むかもしれません。それは主題に関する徹底的な情報を含みます。MPSにバンドルされているRobotKajaサンプルプロジェクトは、流暢なテキストのよ...

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

概要:概要、説明、コンテキストアシスタントUIを使用する、コンテキストアシスタントフレームワークを使用する、プレースホルダセル、メニュー検索、プレースホルダ検索、MPSはコンテクストの中でアクションを実行するためのいくつかのメカニズムを提供します:完了、インテンション、リファクタリング、他の様々なポ...

エディター・アクション

MPSエディターには、完了アクション、ノード作成ポリシーにかなり賢明なデフォルトがあります。しかし、カスタマイズしたい場合は、アクション言語を使用しなければなりません。サイド変換アクションとノード代替アクションはMPS 3.4で非推奨になり、新しい変換メニュー言語に置き換えられました。ノードファクト...

SModel言語

SModel言語の目的はMPSモデルを問い合わせて修正することです。次のことができます。はあなたのモデルのノード、属性、プロパティー、リンクそして他の多くの本質的な性質を調査します。言語はあなたの言語のいくつかの異なる側面をコード化するために必要とされます - 最も顕著なものを挙げるために、行動、リ...

構造

MPSはあなたの意図した言語のための文法を定義することからあなたを解放するため、明らかにあなたの言語の構造を指定するための異なる方法を必要とします。これは構造言語が便利になるところです。それはあなたに言語構造を定義するためのすべての手段を与えます。前に説明したように、MPSでコーディングするときは、...