マクロメニュー

提供:MeryWiki
2020年5月12日 (火) 00:35時点におけるSukemaru (トーク | 投稿記録)による版 (画像を追加)
ナビゲーションに移動 検索に移動

標準メニューバーの「マクロ(M)」には表示されないマクロを含めて、「マクロのカスタマイズ」に登録済みのすべてのマクロをポップアップメニューで表示します。

  • 「マクロのカスタマイズ」で ☑ なし のマクロ(ツールバーのマクロメニューで非表示扱い)は、非表示マクロ」サブメニュー内に表示します。
  • マクロ名は ファイル名 で表示します(各ソースコード内の #title="Hoge" を読みこみません)。
各マクロの実体ファイルの親フォルダ名を表示できます。
ファイル名 「1 マクロA.js」 「2. マクロB.js」 「3_マクロC.js」 「4 - マクロD.js」 などの先頭の連番部分と拡張子をポップアップメニュー上に表示させないように設定できるので、通常のマクロメニューと同じような状態にできます。
  • [選択] や [これを選択] で登録したマクロがメニューに表示されない場合は、 [カスタマイズ] ダイアログを開いて OK ボタンで確定すると表示されるようになります。


  • 追加コマンド [このマクロを実行] は、アクティブなタブのマクロを実行するためのコマンドです。
※ マクロ用と判別できる拡張子で 保存済み のタブでのみ使用できます。
拡張子に対して正規表現 /^(?:jse?|pls?|php|pys?|rbs?|vb[es])$/i でチェックします。


  • 追加コマンド [Macros フォルダを開く] は、Mery インストールフォルダ内の "Macros" フォルダをファイラ(エクスプローラ)で開くためのコマンドです。



  • GetKeyState.exe(キー状態取得実行ファイル)」を導入すると、Ctrl キーを押しながらこのマクロを起動したときに、ポップアップメニュー内のマクロ名を選択(クリック/Enter)したさいの処理を変更できます。
    ⇒ 選択したマクロを Mery で開く(編集する)
Mery インストールフォルダ内の Macros フォルダに実行ファイル GetKeyState.exe を配置してください
(または、設定項目 var gksPath でフルパスを指定)。
※ GetKeyState.exe を導入していないばあいは、選択したマクロをそのまま実行します。
マクロの自作・編集をしない人には設定項目 var gksEnable = false; にすることをおすすめします(ポップアップメニューの表示が高速化するはず)。


スクリーンショット

ソースコード

ダウンロード >> 「ファイル:マクロメニュー.zip(アイコン入り、第2版: 2020/05/02)

#title = "マクロメニュー..."
#tooltip = "全マクロをポップアップメニュー表示"
// #icon = "script_with_lines+.ico"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",318

/**
 * ---------------------------------------------------------
 * マクロメニュー
 * sukemaru, 2019/11/02 - 2020/05/02
 * ---------------------------------------------------------
 * 非表示マクロを含めて全ての登録済みマクロをポップアップメニューで表示する。
 * 
 * Ctrl キーを押しながら「マクロメニュー」マクロを起動して (要 GetKeyState.exe)
 * ポップアップメニュー内のマクロを選択したときは、ソースコードを Mery で開く。
 */

// ---------- ▼ 設定項目 ▼ ---------- //

// ■ ポップアップメニューを表示する位置
var menuPosMouse = true;	// (true: マウス位置 / false: キャレット位置)

// ■ 各マクロの親フォルダ名を表示する
var showParent = false;	// (true: 表示する / false: 表示しない)

// ■ 各マクロの拡張子を表示しない(※ファイル名先頭の連番部分も表示しない)
var trimExt = false;	// (true: 表示しない / false: 表示する)

// ■ GetKeyState.exe による機能拡張を使用する
var gksEnable = true;

// ■ GetKeyState.exe のフルパスを指定する場合
var gksPath = "";
  // 未指定 "" なら、Mery インストールフォルダの Macros\GetKeyState.exe
  // ※ GetKeyState.exe なしのときも "" にする
  // ※ \ 記号はふたつがさね「\\」で記述すること

// ---------- ▲ 設定項目 ▲ ---------- //

var Fso			 = new ActiveXObject( "Scripting.FileSystemObject" );
var WshShell	 = new ActiveXObject( "WScript.Shell" );
var meryPath	 = editor.FullName;
var meryDir		 = meryPath.replace( /[^\\]+$/, "" );
var macroDir	 = meryDir + "Macros\\";
var currentDir	 = WshShell.CurrentDirectory;
var macroPath	 = filePath = editor.ActiveDocument.FullName;

// GetKeyState.exe
var gks   = gksPath || macroDir + "GetKeyState.exe";
var $ctrl = ( gksEnable && Fso.FileExists( gks ) &&
            WshShell.Run( '"' + gks + '" ctrl', 0, true ) != 0 )
          ? true : false;


// ポップアップメニューを表示
var mm = MacroMenu( showParent, trimExt, $ctrl );
var id = mm.menu.Track( menuPosMouse );

// 「このマクロを実行」
if ( id == 1 ) {
  WshShell.Run( '"' + meryPath + '" /mf "' + macroPath + '" "' + filePath + '"' );
}

// 「Macros フォルダを開く」
else if ( id == 2 ) {
  WshShell.Run( '"' + macroDir + '"' );
  Status = " " + macroDir;
}

// Ctrl キーを押しながらマクロメニューを起動したとき
else if ( $ctrl && id >= 6144 && id < 7168 ) {
  WshShell.CurrentDirectory = meryDir;
  macroPath = Fso.GetAbsolutePathName( mm.macros[id - 6144].path ); // 相対パスの解決
  WshShell.CurrentDirectory = currentDir;
  if ( Fso.FileExists( macroPath ) ) {
    // 選択したマクロの実体ファイルを Mery で開く(編集モード)
    WshShell.Run( '"' + meryPath + '" "' + macroPath + '"' );
    Status = " " + macroPath;
  }
}

// マクロまたはコマンドを実行
else if ( id > 2 ) {
  editor.ExecuteCommandByID( id );
}

/**
 * 関数 MacroMenu( [ showParentFolderName: boolean [, trimExtension: boolean [, ctrl ]]] )
 * 戻り値は { menu: objPopupMenu, macros: macroArray }
 * ※ macroArray の各要素は { path: macroPath, visible: int } で
 *    path は Mery.ini に記述されているままの相対パス
 *    visible は 数値 1 または 0
 */
function MacroMenu( showParent, trimExt, $ctrl ) {
  var start = new Date();
  var menu = CreatePopupMenu();
  var b3 = "\u2002\u2002\u2002";	// EN SPACE 「 」(U+2002)
  var d = editor.ActiveDocument;

  // Mery.ini のパスを取得
  var Fso = new ActiveXObject( "Scripting.FileSystemObject" );
  var WshShell = new ActiveXObject( "WScript.Shell" );
  var meryPath = editor.FullName;
  var meryDir = Fso.GetParentFolderName( meryPath ) + "\\";
  var meryName = Fso.GetBaseName( meryPath );
  var meryDirName = Fso.GetBaseName( meryDir );
  var iniPath = meryDir + meryName + ".ini";
  if ( ! Fso.FileExists( iniPath ) ) {
    iniPath = WshShell.SpecialFolders( "APPDATA" )
            + "\\Mery\\" + meryName + ".ini";
  }

  // Mery.ini からデータを取得
  var Adodb = new ActiveXObject( "ADODB.Stream" );
  var adTypeText = 2,  adReadAll = -1;
  Adodb.Type = adTypeText,  Adodb.Charset = "UTF-8";
  Adodb.Open();
  Adodb.LoadFromFile( iniPath );
  var iniText = Adodb.ReadText( adReadAll );
  Adodb.Close();

  // 「このマクロを実行」コマンドの準備
  var ext = d.Name.substr( d.Name.lastIndexOf( "\." ) + 1 );
  var reg2 = /^(?:jse?|pls?|php|pys?|rbs?|vb[es])$/i;
  var macroName = reg2.test( ext ) ? d.Name : "";
  var runFlag = ( macroName && d.Saved ) ? 0 : meMenuGrayed;

  // マクロのパスを抽出
  var reg3 = /\r\n\[Macros\\Macro\d+\]\r\nFileName=[^\r\n]+\r\nVisible=\d/g;
  // \r\n [Macros\Macro##] \r\n FileName=MacroPath \r\n Visible=#
  var macroArray = iniText.match( reg3 ) || [];
  var mcCount = macroArray.length;
  if ( mcCount ) {
    var invisible = false;
    var reg4 = /\r\nFileName=([^\r\n]+)\r\n/;
    for ( var i = 0; i < mcCount; i ++ ) {
      // path: MacroPath, visible: #int		※ path は相対パスの場合がある
      macroArray[i] = {
        path:    reg4.exec( macroArray[i] )[1],
        visible: + macroArray[i].slice( -1 )
      };
      if ( ! invisible && macroArray[i].visible == 0 ) { invisible = true; }
    }

    // マクロのファイル名一覧を作成 (非表示マクロをサブメニュー化)
    if ( invisible ) {
      menu.AddPopup( "非表示マクロ(&H)", subMenu = CreatePopupMenu() );
      menu.Add( "-----", 0, meMenuSeparator );
    }
    var reg5 = /(?:[^\\]+?\\)*?(?:([^\\]+)(?:\\))?([^\\]+)$/;
    var reg6 = /([^\/]*\/ )?(?:\d+[-._ ]+)?([^\/]+)(?:\.[^.]+?)$/;
    var id,  num,  label,  j = 0,  k = 0;
    var mcWidth = ( "" + mcCount ).length;
    for ( var i = 0; i < mcCount; i ++ ) {
      // "親フォルダ名/ ファイル名"
      label = ( showParent )
            ? macroArray[i].path.replace( reg5, "$1/ $2" )
            : /([^\\]+)$/.exec( macroArray[i].path )[1];
      if ( label.charAt( 0 ) == "/" ) {
        label = meryDirName + "/ " + label.slice( 1 );
      }
      // 起動モードでは ファイル名先頭の連番 と 拡張子 を削除
      // 編集モードでは拡張子を大文字に
      label = ( ( trimExt && ! $ctrl ) ? label.replace( reg6, "$1$2" )
              : ( $ctrl ) ? label.replace( /[^.\\]+$/, function( tmp ) {
                                  return tmp.toUpperCase(); } )
              : label
              ).replace( /&/g, "&&" );

      // 可視マクロと不可視マクロの振り分け (Visible= 1 or 0)
      id = i + 6144;
      if ( macroArray[i].visible == 1 ) {
        num = ( b3 + ( ++ j ) ).slice( - mcWidth ).replace( /\d$/, "&$&:\u2002" );
        menu.Add( num + label, id );
      }
      else {
        num = ( b3 + ( ++ k ) ).slice( - mcWidth ).replace( /\d$/, "&$&:\u2002" );
        subMenu.Add( num + label, id );
      }
    }
    menu.Add( "-----", 0, meMenuSeparator );
    if ( invisible ) {
      subMenu.Add( "-----", 0, meMenuSeparator );
      subMenu.Add( "キャンセル\t& ", 0 );
    }
    if ( gksEnable ) {
      menu.Add( b3 + "▲ 選択した"
                + ( $ctrl ? "ソースコードを編集" : "マクロを実行" )
                + " ▲", 0, meMenuGrayed );
      menu.Add( "-----", 0, meMenuSeparator );
    }
  }

  // 標準コマンド
  menu.Add( "編集(&E)  " + ScriptName, 2173 );
  menu.Add( "選択(&L)...", 2174 );
  menu.Add( "これを選択(&T)", 2175, ! d.Name *2 );
  if ( d.FullName != ScriptFullName ) {
    menu.Add( "このマクロを実行(&G)*  " + macroName, 1, runFlag );
  }
  menu.Add( "カスタマイズ(&C)...", 2176 );
  menu.Add( "-----", 0, meMenuSeparator );
  menu.Add( "Macros フォルダを開く(&F)*", 2 );
  menu.Add( "-----", 0, meMenuSeparator );
  menu.Add( "キャンセル\t& ", 0 );

  // ステータスを表示
  Status = " 「マクロメニュー」 "
         + "** " + ( $ctrl ? "編集" : "起動" ) + "モード **  "
         + j + " 件 + " + k + " 件  [ "
         + ( ( new Date() - start ) / 1000 ).toFixed( 3 ).replace( /\./, ". " )
         + " 秒 ]";
  return { menu: menu, macros: macroArray };
}
スポンサーリンク