Eclipse プラグインの popup メニューの複数 variables の表示条件設定

# 経緯

plugin.xml に popup メニューの表示を追加した時のメモ。

パッケージエクスプローラーやエディタ上で popup メニューを開いた時に、特定のファイルの時だけ表示させるための設定。
一つの variable に対しての設定はネットを検索するといくつも見つかったが、今回は、 selection と adoptEditorInput の二つについての条件を、 popup メニューにつけようという時の情報が見つからなかったのでメモしておく。

基本的な方法についは以下を参考にさせてもらった。

- [Eclipse/プラグイン開発のTIPS集/org.eclipse.ui.menusにvisibleWhenで条件指定する](http://www.masatom.in/pukiwiki/?plugin=related&page=Eclipse%2F%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3%B3%AB%C8%AF%A4%CETIPS%BD%B8%2Forg.eclipse.ui.menus%A4%CBvisibleWhen%A4%C7%BE%F2%B7%EF%BB%D8%C4%EA%A4%B9%A4%EB)

# やりたいことの具体的な内容

1. 自分の作成するツールの入力ファイルの拡張子のファイルが選択されている時のみ popup メニューにそのファイルを処理するメニューを追加したい
1. 選択されている時とは次の二つ
    1. パッケージエクスプローラー等のツリー表示上でファイルを選択した状態
    1. 編集中のエディター画面がアクティブな時

# 実際にやったこと

前提：Eclipse 上のプロジェクトは plugin プロジェクトで、テンプレートに Hello World Command を指定した。このプロジェクトで予め存在している、メインメニューの実行コマンドを popup で起動させる形に機能拡張を施す流れで、自分のやりたいことを確認する。

1. 拡張ポイント org.eclipse.core.expressions.definitions に条件を二つ定義
    1. パッケージエクスプローラー等のツリービューの条件判定用定義
        1. definition を追加
            1. id: org.ironya.tools.training.visibleWhen1
        1. definition に with を追加
            1. variable: selection
        1. with に iterate を追加
            1. ifEmpty: false
        1. iterate に adopt を追加
            1. type: org.eclipse.core.resources.IFile
        1. adopt に or を追加
        1. or に対象とする拡張子を追加(今回は三つ)
            1. property: org.eclipse.core.resources.extension
            1. value: ファイルの拡張子
    1. エディターの条件判定用定義
        1. definition を追加
            1. id: org.ironya.tools.training.visibleWhen2
        1. definition に with を追加
            1. variable: selection
        1. with に adopt を追加
            1. type: org.eclipse.core.resources.IFile
        1. adopt に or を追加
        1. or に対象とする拡張子を追加(今回は三つ)
            1. property: org.eclipse.core.resources.extension
            1. value: ファイルの拡張子
1. 拡張ポイント org.eclipse.ui.menus にポップアップメニューを追加
    1. menuContribution として popup メニューを追加
        1. location: popup:org.eclipse.ui.popup.any?after=additions
    1. 作成した popup の menuContribution にメニュー選択時に実行するコマンドを追加
        1. commandId: org.ironya.tools.training.commands.sampleCommand (既存のid)
        1. label: hello
    1. 追加したコマンドに visibleWhen を追加
        1. checkEnabled: false
    1. 追加した visibleWhen に or を追加
    1. or に最初に作成した条件の参照 (reference) を二つ追加
        1. definitionId: 上で作成した definition に設定した id 

実際の plugin.xml全体

```xml:plugin.xml
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
   <extension
         point="org.eclipse.ui.commands">
      <category
            name="Sample Category"
            id="org.ironya.tools.training.commands.category">
      </category>
      <command
            name="Sample Command"
            categoryId="org.ironya.tools.training.commands.category"
            id="org.ironya.tools.training.commands.sampleCommand">
      </command>
   </extension>
   <extension
         point="org.eclipse.ui.handlers">
      <handler
            commandId="org.ironya.tools.training.commands.sampleCommand"
            class="org.ironya.tools.training.handlers.SampleHandler">
      </handler>
   </extension>
   <extension
         point="org.eclipse.ui.bindings">
      <key
            commandId="org.ironya.tools.training.commands.sampleCommand"
            contextId="org.eclipse.ui.contexts.window"
            sequence="M1+6"
            schemeId="org.eclipse.ui.defaultAcceleratorConfiguration">
      </key>
   </extension>
   <extension
         point="org.eclipse.ui.menus">
      <menuContribution
            locationURI="menu:org.eclipse.ui.main.menu?after=additions">
         <menu
               label="Sample Menu"
               mnemonic="M"
               id="org.ironya.tools.training.menus.sampleMenu">
            <command
                  commandId="org.ironya.tools.training.commands.sampleCommand"
                  mnemonic="S"
                  id="org.ironya.tools.training.menus.sampleCommand">
            </command>
         </menu>
      </menuContribution>
      <menuContribution
            locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
         <toolbar
               id="org.ironya.tools.training.toolbars.sampleToolbar">
            <command
                  commandId="org.ironya.tools.training.commands.sampleCommand"
                  icon="icons/sample.gif"
                  tooltip="Say hello world"
                  id="org.ironya.tools.training.toolbars.sampleCommand">
            </command>
         </toolbar>
      </menuContribution>
      <menuContribution
            allPopups="false"
            locationURI="popup:org.eclipse.ui.popup.any?after=additions">
         <command
               commandId="org.ironya.tools.training.commands.sampleCommand"
               label="hello"
               style="push">
            <visibleWhen
                  checkEnabled="false">
              <or> <!-- ここの二つの reference を囲うような or が可能かどうかについて言及している情報が見つからなかった -->
                <reference
                     definitionId="org.ironya.tools.training.visibleWhen1">
                </reference>
                <reference
                     definitionId="org.ironya.tools.training.visibleWhen2">
                </reference>
              </or>
            </visibleWhen>
         </command>
      </menuContribution>
   </extension>
   <extension
         point="org.eclipse.core.expressions.definitions">
      <definition
            id="org.ironya.tools.training.visibleWhen1">
         <with
               variable="selection">
            <iterate
                  ifEmpty="false">
               <adapt
                     type="org.eclipse.core.resources.IFile">
                  <or>
                    <test
                        property="org.eclipse.core.resources.extension"
                        value="yaml">
                    </test>
                    <test
                        property="org.eclipse.core.resources.extension"
                        value="yml">
                    </test>
                    <test
                        property="org.eclipse.core.resources.extension"
                        value="xml">
                    </test>
                  </or>
               </adapt>
            </iterate>
         </with>
      </definition>
      <definition
            id="org.ironya.tools.training.visibleWhen2">
         <with
               variable="activeEditorInput">
            <adapt
                  type="org.eclipse.core.resources.IFile">
               <or>
                  <test
                        property="org.eclipse.core.resources.extension"
                        value="yaml">
                  </test>
                  <test
                        property="org.eclipse.core.resources.extension"
                        value="yml">
                  </test>
                  <test
                        property="org.eclipse.core.resources.extension"
                        value="xml">
                  </test>
               </or>
            </adapt>
         </with>
      </definition>
   </extension>
</plugin>
```

念のため Eclipse のオンラインドキュメントのページでスキーマを確認。
場所: help.eclipse.org/neon/index.html > Platform Plug-in Developer Guide -> Reference -> Extension Point Reference -> org.eclipse.ui.menus と辿り、ページ内を visibleWhen で検索して見つかったページ内のリンク。

「[visibleWhen](http://help.eclipse.org/neon/topic/org.eclipse.platform.doc.isv/reference/extension-points/org_eclipse_ui_menus.html?cp=2_1_1_177#e.visibleWhen)」

以下の通りの記載があった。

> <!ELEMENT visibleWhen (not | or | and | instanceof | test | systemTest | equals | count | with | resolve | adapt | iterate | reference)?>

で、 or の説明のところは次の通り。

> <!ELEMENT or (not , and , or , instanceof , test , systemTest , equals , count , with , resolve , adapt , iterate , reference)*>

ということで、 or には(最後のアスタリスクが示すように) reference を複数指定できることが仕様として確認できた。