変換メニュー言語
概要
変換メニュー言語は、エディターのさまざまな場所に表示されるサブメニューとアクションの階層構造を説明する変換メニューを定義するために使用されます。現在、変換メニューが表示される可能性のある場所はいくつかあります: サイド変換メニュー、代替メニュー、コンテキストアシスタント、およびコンテキストアクションツール。変換メニュー言語の拡張に記載されているように、言語設計者とプラグイン作成者は追加の場所を定義し、場所ごとに必須またはオプションの機能 (アイコンやツールチップなど) を指定できます。
メニューを理解する
代替メニューは、現在のノードを別のノードに置き換えるオプションを提供します。提供されるノードは、ノードが最終的に挿入される位置と互換性がある必要があります。代替メニュー定義が検索されるとき、検索アルゴリズムへの入力は、既存のノードの概念ではなく、その包含リンクです。重要なのは AST 内の「場所」であり、現在その場所を占めているノードではありません。
例として、BaseLanguage の ExpressionStatement コンセプトのインスタンスを考えてみましょう。これには、Expression のコンセプトを期待する「expression」子ロールがあります。それが AssignmentExpression (`a = 5;`)を保持していると仮定しましょう。ユーザーが ExpressionStatement 内の AssignmentExpression を別のノードに置き換える(置き換える)場合は、ExpressionStatement.expression 包含リンクのターゲットコンセプトであるため、任意の式が機能します。現在のノードは、関連する代替メニュー定義を見つける目的には関係ありません。
ほとんどの概念は、以下を含む代替メニュー定義を暗黙的に使用します。
抽象的でない限り、この概念のノードを作成するためのアクション
この概念のすべてのサブコンセプトのデフォルトメニュー定義を含めるための指示
その結果、Expression のメニューを作成するときに、MPS はそのサブコンセプトをトラバースし、それらもメニューに含めます。ただし、スーパーコンセプトは考慮されていないことに注意してください。ExpressionStatement.expression の補完メニューには、BaseConcept のインスタンスを置換することはできず、式 のみを置換できるため、BaseConcept の置換メニュー定義からのエントリは含まれません。
変換メニュー定義は、代替メニュー定義とは逆の方法で構成されます。既存のノードを変換したいという考えなので、その概念を調べて、その変換メニューを調べます。その特定の概念に対してメニューが定義されていない場合、MPS はスーパーコンセプトのデフォルトメニューにフォールバックします(コンセプトのインスタンスは、リスコフの置換原則に従って、そのスーパーコンセプトのインスタンスと見なすこともできるため)。デフォルトの変換メニュー定義を作成する場合、フォールバック動作は適用されず、明示的に指定する必要があることに注意してください(`superconceptsmenu` 命令を使用)。BaseConcept_TransformationMenu と呼ばれる BaseConcept のデフォルトの変換メニューを見ると、現在のリンクのデフォルトの代替メニューが含まれていることがわかります。
代替メニュー定義をエディターセルに直接添付することはできません。まず、変換メニューに含める必要があります。デフォルトの代替メニュー定義は、BaseConcept のデフォルトの変換メニュー定義にすでに含まれているため、デフォルトのメニュー定義のみを使用する場合は、これを行う必要がない場合があります。補完メニューは、変換メニュー定義から構築されます。定義に「この代替メニュー定義を含める」と記載されている場合は含まれますが、記載されていない場合は含まれません。
メニューを定義する
変換メニューは、さまざまな場所に表示される UI アクションを定義します。設計時に、メニューはセクションのリストとして指定され、各セクションには特定の場所のセットのメニューパーツのリストが含まれます。実行時には、メニュー部分と場所を使用してメニューの内容(メニュー項目)が生成されます。
メニュー定義には、デフォルトと名前付きの 2 つの種類があります。メニュー定義はメニューの貢献によっても拡張できます。
デフォルトメニュー
各概念には、デフォルトの変換メニューが関連付けられています。言語設計者が明示的に提供しない場合は、最も近いスーパーコンセプト用に定義された変換メニューが想定されます。どのスーパーコンセプトにも何も指定されていない場合は、BaseConcept で定義されているものが使用されます。これには、その位置に適した代替アクションが含まれます(以下の代替アクションのセクションを参照)。
デフォルトメニューは、言語設計者が表示するメニューを指定していない場合に使用されます。
名前付きメニュー
名前付きメニューは、概念の追加メニューです。デフォルトメニューのようにそれはまた適当な概念を指定しそしてセクションのリストを含んでいる。その用語が示すように、名前付きメニューは明示的に設定された名前を持ちます。名前付きメニューは、セルの変換メニューとして設定すること、またはメニューメニューを含めるを介して別のメニューに含めることを意味します。
名前付きメニューをエディターセルに添付する:
注: デフォルトの変換メニューは、メニューと同じ方法で個々のセルに添付することもできます。
メニューのコントリビューション
メニューコントリビューションは、追加のメニューパーツをコントリビューションすることにより、特定のメニューを拡張します。これは、拡張言語が拡張言語で定義されたメニューにエントリを追加する必要がある場合に特に役立ちます。貢献は、実際には、貢献されているメニューがある言語以外の言語でのみ定義できます。
実行時にメニューが要求されると、元の定義とすべてのコントリビューションがマージされ、結合された定義を使用してメニューが作成されます。貢献に関するいくつかの重要な注意事項:
個々の定義がマージされる順序は、現在のところ不明です。
寄付は、寄付するメニューからメニュー部分を削除することはできません。
概念の暗黙のデフォルトメニューへのコントリビュートを定義することは可能です。
セクションの場所
メニュー内のセクションの場所を指定することで、UI のどの部分にアクションを挿入するかを指定します。
補完 - 補完メニュー
コンテキストアクションツール - コンテキストアクションツール (jetbrains.mps.editor.contextActionsTool.lang.menus 言語のインポートが必要です)
コンテキストアシスタント - コンテキストアシスタント
サイド変換 - 左右の変換
メニューパーツ
以下の標準メニューパーツが利用可能です。
action - 実行するアクション、それに対応するメニューテキスト、適用範囲を指定する単純なメニュー項目。
グループ - メニュー項目のコレクション。これらの項目を超えて、グループは 1 つ以上の変数を定義して、繰り返し計算を回避するためにグループ内のすべてのアクションによって共有される場合があります。さらに、グループは、グループ内のアクションをユーザーが使用できるようにする必要があるときを示す条件を保持します。
include- 特定のデフォルトまたは名前付きメニューを(もしあれば、その貢献とともに)含めます。包含サイクルは実行時に検出され、エラーメッセージが生成されます。
代替メニューを含める - このメニューの一部として使用するデフォルトまたは名前付きの代替メニューを含めます。
parametrized - 複数の値でパラメーター化されているアクション。
サブメニュー - さらなる部分を含むサブメニュー。
superconcepts menu - デフォルトでは含まれないため、該当する概念のスーパーコンセプトのデフォルトメニューが含まれます。
代用メニューの折り返し - 提供されたハンドラーを使用して指定された概念を折り返します。
言語 jetbrains.mps.lang.editor.menus.extras
には、変換メニューからさまざまなアクションに似たエンティティを含めるためのアダプターが含まれています。
インテンション - インテンション(
jetbrains.mps.lang.intentions
からBaseIntentionDeclaration
のサブコンセプト)をラップします。リファクタリング -
jetbrains.mps.lang.refactoring
からリファクタリングRefactoring
をラップします。plugin Action – プラグインアクション
ActionDeclaration
をjetbrains.mps.lang.plugin
からラップします。
追加の方法
下部にある追加のメソッドセクションでは、繰り返しを避けるためにメニュー内から呼び出すことができるユーティリティメソッドを定義できます。通常、追加のメソッドは、計算を実行したり、メニュー定義の複数の場所で必要なタスクを実行したりします。追加のメソッドは、含まれているノード内からのみ表示されるようにプライベートにする必要があります。
サイド変換
テキストエディターでコードを編集するときは、左から右のいずれかに入力できます。
または右から左へ
この振る舞いをエミュレートするために、MPS には左右の変換という側面の変換アクションがあります。セルの左または右部分を入力したときに利用できるようになるアクションを作成できます。例: MPS では次のことができます。
また
最初のケースは右変換と呼ばれます。2 番目のケースは左変換と呼ばれます。
セクションのサイド変換位置を選択して、変換メニューでサイド変換を定義します。
この言語では、言語設計者が特定のセルの補完メニューにサイド変換メニューの項目を含めることもできます。これを行うには、補完セクションを含む変換メニューを目的のセルに添付します。その補完セクションには、インクルードメニュー部分が保持され、サイド変換の場所が指定されます。サイド変換メニューの項目が補完に含まれます。
含まれるメニューの場所は、インテンションの「場所の指定」を使用して指定できます。
代替メニュー
代用アクションは、モデルの一部に対してユーザーが呼び出した変換を定義し、その間に 1 つのノードが別のノードに置き換えられます。これらの代替アクションのビジュアル UI 要素(補完メニューなど)への実際のマッピングは、変換メニューを介して行われます(上記のセクションを参照)。
通常、代替アクションは、エディターで Ctrl + スペースを押すことによってトリガーされます。表示される完了メニューには、ユーザーが選択すると、キャレットのノードを置き換えるオプションが含まれています。side-transformations、コンテキストアシスタント、またはコンテキストアクションツールとは異なり、置換にはデフォルトの動作があり、言語の作成者が別の方法で定義しない限り、これが有効になります。
コード補完のデフォルトの動作
言語作成者によって明示的に実装されたメニューがなくても、MPS は現在のノードの代わりとなる補完メニューを提供します。
キャレットは単一セルエディターの前面に配置されます
ユーザがノードのエディター全体を選択しました
このような場合、Control + Space を押すと、特定のコンテキストに適用可能なインポートされた言語のすべての概念を含むメニューが表示され、モデル内の現在のノードを置き換えることができます。
MPS は次の手順でデフォルトの補完メニューを作成します。
選択が概念 A を許す位置の内側にあるなら、A のすべての可能にされた副概念は完了メニューで利用可能になるでしょう。
すべての抽象的な概念は除外されます
「子になることができる」という制約が false を返すすべての概念は除外されます
親ノードの「親になることができる」制約が false を返すすべての概念が除外されます
概念に 1:1 の参照が含まれている場合は、完了メニュー自体には追加されません。代わりに、その参照のスコープ内の各要素にアイテムが追加されます。そのようなアイテムには名前スマート参照を使用します。
ノード置換をカスタマイズするには、代替メニューが使用されます。
代替メニュー (デフォルト)
コンセプトのデフォルトの代替メニューを定義することにより、ユーザーが Control + Space を押したときに表示される完了メニューの内容をカスタマイズできます。また、これらのサブコンセプトが独自のデフォルトの代替メニューを定義していない限り、コンセプトのサブコンセプトにも影響を及ぼします。
ただし、代替メニューをエディターの特定のセルに割り当てる場合は、変換メニューにしか追加できないため、代替メニューを変換メニューに含める必要があります。
代替メニュー (名前)
名前付き代替メニューを使用すると、複数の代替メニューを作成してさまざまなコンテキストで使用することができます。名前を付けた代替メニューを有効にするには、最初に別の代替メニューまたは変換メニューに含める必要があります。
代替メニュー投稿
トランスフォームメニューと同様に、代替メニューの貢献は、新しい言語で定義された代替メニューへの新しいエントリを提供します。
オプション
概念の追加 - メニューに単一の概念を追加します
概念リスト - 概念のコレクションを追加します
グループ - 条件が満たされた場合、エントリのグループを追加します
包含 - 指定されたメニューを含みます
パラメーター化 - パラメーター化された代替アクションを追加します
参照アクション - 参照の可能なターゲットの外観を含めてカスタマイズします
サブコンセプトメニュー - コンセプトのすべてのサブコンセプトを含む
代替アクション - 単一の代替アクションを追加します
代用メニューの折り返し - 提供されたハンドラーを使用して指定された概念を折り返します
セルメニューとセル固有の変換メニューの相互作用
セルに "menu" と "transformation menu" の両方が指定されている場合は、両方のメニューから該当するエントリが結合されます。一部のセルメニューパーツ(CellMenuPart_PropertyPostfixHints
などの CellMenuPart_Abstract
の子孫)には、同等の変換 / 置換メニューパーツがまだありません。
プロパティ / 参照用の変換メニューを含める
プロパティ / 参照セルのメニューのカスタマイズはプロパティ / 参照変換メニューパーツで行うことができます。参照 / プロパティセルの補完メニューをカスタマイズしたいとします。以前は、インスペクタで「インラインメニュー」を定義することによって行われていました。今それは変換メニューによってもすることができます。プロパティと参照変換メニュー部分を導入しました。参照変換メニュー部分には、ターゲットノードを特定の参照に設定するアクションが含まれています。ターゲットノードはその参照のスコープから来ます。プロパティメニュー部分にも同じことが言えます。プロパティタイプの値を取り、値を特定のプロパティに設定するアクションを含みます。
参照例
参照セルの補完メニューを作成したいとします。メニューには、スコープ内にある参照の通常のターゲットとその他のカスタムアクションが含まれているはずです。これは、次の名前付き変換メニューを参照セルにアタッチすることによって実行できます。
それで、すべての標準的な参照アクションと私たちのカスタムアクションを完成時に受け取るでしょう:
見ることができるように参照メニュー部分は「インラインメニュー」の「一次選択参照メニュー」部分の類似物です、しかしさらにカスタマイズ可能です。また、セルにメニューが添付されていない場合は、その参照メニューがデフォルトで使用されます。
プロパティの例
もう 1 つの例として、キャレットがそのプロパティセルの隣のラベルセル上にあるときに、コンテキストアシスタントで特定のプロパティの可能な値をすべて表示したいとします。Kaja 言語のコードを見てみましょう。
探しているセルにキャレットを置くときに、見る方向のすべてのバリエーションを確認したいと考えています。そこで、このラベルセルに次のメニューをアタッチします。
そして結果を得る:
「インラインメニュー」に対するこれらのメニュー部分の利点は次のとおりです。
これらは、参照 / プロパティセルだけでなく、任意のセルにアタッチできます。
補完だけでなく、あらゆるメニューの場所(コンテキストアシスタント、コンテキストメニュー)で使用できます。
参照メニューはよりカスタマイズ可能です(プロパティメニューも間もなくカスタマイズ可能になるでしょう)。
メニュー発見アルゴリズム
MPS がどのように変換メニューを選択するかのプロセスを理解すると、メニューをより自信を持ってデザインできます。
デフォルトでは、MPS は、<CurrentConcept> _TransformationMenu という名前の現在の概念の変換を探し、次にその上位概念のメニューを探し、BaseConcept_TransformationMenu まで探すことになります。
代替メニューは変換メニューに似ていますが、その発見は反対方向に働きます。ここで、概念 A の変換メニューはそのスーパーコンセプトのメニュー(BaseConcept まで)を含みます。なぜなら、サブ概念だけがモデル内の A を安全に置き換えることができるからです。代替メニューは、既存のノードの概念に基づいて検索されるのではなく、リンクのターゲットの概念に基づいて検索されるため、変換メニューとは少し異なります。
アイテムトレースを表示する
どの変換または代替メニューが完了メニューまたはコンテキストアシスタントに特定のアクションを提供したかを追跡するには、ユーザーは完了メニューエントリで Control/Cmd + Alt + B を押すだけで、対話的なトレースレポートが表示されます。
多数の代替メニューや変換メニューが互いに関連しているため、補完またはコンテキストアシスタントでアクションがどのように表示されたかを追跡するのが難しい場合があります。そこで、補完 (矢印を使用) またはコンテキストアシスタント (cmd/ctrl+alt+Enter を押す) でアクションを選択し、cmd/ctrl+alt+B を押します。プロジェクトツールにトレースが表示されます。これは、最上位メニューからアクション宣言まで相互に含まれるメニューとメニューパーツ宣言のトレースです。メニューまたはメニューパーツ宣言が明示的でプロジェクト内にある場合、ツールでは太字で表示され、クリックして宣言に移動できます。
キャレットをステートメントに置き、変数参照の補完を表示してから、「アイテムトレースの表示」を呼び出すと、次のようになります。
完成したものが、BaseConcept である superconcept のメニューを含む Statement のデフォルトの変換メニューであることがわかります。それは今度はステートメントの代わりのメニューを含み、今度は式のメニューをラップします。それから、Expression のサブコンセプトになります。その 1 つが VariableReference です。VariableReference は「スマートリファレンス」の概念であるため、Variable 概念の目に見えるすべてのターゲットを見つけようとします。そのため、ステートメントのメニューに変数参照が表示されます。
関連ページ:
エディターのアクション
MPS エディターには、完了アクション、ノード作成ポリシーにかなり実用的なデフォルトがあります。しかし、カスタマイズしたい場合は、アクション言語を使用しなければなりません。ノードファクトリ:あるノードが別のノードと交換されるとき、交換されるノードによって保持される値で交換するノードの作成プロセスをパラメーター化すること、またはおそらくモデル内の交換するノードの将来の位置を反映することも役に立つでしょう。ノードファクトリはあなたにまさにそれを与えます。新しいノードを代入アクションで、または新しい...
コンテキストアシスタント
概要:MPS はコンテクストの中でアクションを実行するためのいくつかのメカニズムを提供します: 完了、インテンション、リファクタリング、他の様々なポップアップメニュー。これらのメカニズムには、経験の浅い新規ユーザーにはすぐには見えないという共通点があります。彼らはまた、多くの可能な選択肢を提供し、利用可能な機能全体を明らかにします。これは上級ユーザーを手助けしますが初心者を圧倒するかもしれません。DSL でスクリプトを作成するプロセスを通じて新しいユーザーをより適切にガイドするために、コンテキ...
コンテキストアクションツール
コンテキストアクションツールは一部の DSL ユーザーのマウスナビゲーションへの好みに対応しています。指定されたコンテキストで適用可能なアクションが、階層的に整理されたサイドバーに一覧表示されます。一般的な動作は、キャレットの位置で何かを実行し、シングルクリックでアクティブ化することです。コンテキストアクションツールは、このコンテキストでどのようなことが実行できるかを明確に伝えるため、探索的な作業を発見するのに最適です。ツールウィンドウでオプションを選択することによって、ユーザーは関連するアクシ...