階層化マクロメニュー

提供: MeryWiki
移動先: 案内検索

概要[編集]

フォルダ内のマクロファイルを階層化してメニューから呼び出します.

使用上の注意[編集]

マクロライブラリにある includeライブラリ を利用しています.
このマクロの前にそちらを導入してください.

使用例[編集]

メニューの [表示] - [ツール バー] - [マクロ バー] でバーを表示し,マクロを登録するとこのようになります.
下のサンプル画像の My Macros フォルダサンプルです.
ファイル:TreeMacroExecSample.zip

TreeMacroExecSample.png


フォルダ内の文字コード統一[編集]

指定したフォルダ内の文字コードを統一します.
階層化マクロメニューは 1 つの文字コードしか扱えないので, 事前にこのマクロで文字コードを統一します.

注意[編集]

複数回実行しても「× 個のファイルを変換しました」と出る場合がありますが,
日本語が含まれないフィイルは毎回変換される可能性がありますので,正常な動作です.

オプション[編集]

charset マクロファイルの文字コードです.
階層化マクロメニューと同じ文字コードにします.
ext 対象にするファイルの指定です.

コード[編集]

#include "include/IO.js"
#title = "フォルダ内文字コード変換"
 
// =========================================================
// オプション設定
 
// 変換後の文字コード
var charset = "utf-8";
//var charset = "sjis";
 
// 変換対象のファイル拡張子
var ext = "*.js";
// =========================================================
 
if (!Editor.EnableTab) {
  Alert("タブを有効にしてください");
  Quit();
}
 
// 対象のフォルダを指定
var shell = new ActiveXObject("Shell.Application");
var path = shell.BrowseForFolder(0, "文字コードを変換するフォルダを選択してください" , 0x0240 , "");
switch (path){
case null:
case "":
  Quit();
case "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}":
  Alert("「マイコンピュータ」を選択できません");
  Quit();
}
 
// 開いている文書の一覧
var map = {};
for (var i=0; i<Editors.Count; i++) {
  var e = Editors.Item(i);
  for (var j=0; j<e.Documents.Count; j++) {
    var d = e.Documents.Item(j);
    if (d.FullName) {
      map[d.FullName] = d;
    }
  }
}
 
// 文字コードをマクロ定数に変換
switch (charset.toLowerCase()) {
case "utf8":
case "utf-8":   charset = meEncodingUTF8WithoutSignature; break;
case "sjis":
case "shift-jis":
case "shiftjis":  charset = meEncodingShiftJIS; break;
case "euc":
case "euc-jp":    charset = meEncodingEUC;  break;
default:      Alert("不明なエンコーディングです");  Quit();
}
 
// 処理開始
Redraw = false;
var folder = new IO.Folder(String(path));
var count = (function RecursiveConvert(folder){
  var count = 0;
 
  // ファイル処理
  var files = folder.GetFiles(ext);
  for (var i=0; i<files.length; i++) {
    if (!map[files[i].GetPath()]) {
      Editor.NewFile();
      Editor.OpenFile(files[i].GetPath());
      var d = Editor.Documents.Item(Editor.Documents.Count-1);
      if (d.Encoding == charset || (d.Encoding == meEncodingUTF8WithSignature && charset == meEncodingUTF8WithoutSignature)) {
        d.Close();
      } else {
        count++;
        var text = IO.LoadFromFile(d.FullName, d.Encoding);
        d.Close();
        IO.SaveToFile(files[i].GetPath(), text, charset);
      }
    }
  }
 
  // フォルダ処理
  var folders = folder.GetFolders();
  for (var i=0; i<folders.length; i++) {
    count += RecursiveConvert(folders[i]);
  }
 
  return count;
})(folder);
 
Alert(count + " 個のファイルを変換しました");


階層化マクロメニュー[編集]

マクロファイル名と同じフォルダに含まれるフォルダ及びマクロファイルを階層的にメニューで表示し, 選択されたマクロを実行します.

オプション[編集]

charset マクロファイルの文字コードです.
自動判別はできないので,1 つに指定してください.
useCache タイトルの読み込みにキャッシュを利用するかのフラグです.
メニュー表示までに時間がかかる場合は true にしてください.
ignoreFolder
ignoreFile
メニューから除外するファイル・フォルダの定義です.
文字列定義の場合,|で区切られた名前と一致するファイル・フォルダが無視されます.
正規表現で書かれている場合はその正規表現に一致するファイル・フォルダが無視されます.

呼び出したマクロがうまく動かない場合[編集]

・文字コードは一致しているか?
 ⇒オプションで指定している文字コードと一致している必要があります

・マクロとは別に必要なファイル(include ファイルや exe など)はあるか?
 ⇒マクロとの相対位置は維持した方が確実です(include は補正かけてますが)

・スクリプト内で「ScriptName」「ScriptFullName」を利用しているか?
 ⇒大文字小文字の書き方によっては正しく動きません.呼び出されるマクロ側の変数名を上のように直してください.

コード[編集]

#include "include/StringEx.js"
#include "include/IO.js"
#title = "階層化マクロメニュー"
 
// =========================================================
// オプション設定
 
// マクロの文字コード
var charset = "utf-8";
//var charset = "sjis";
 
// タイトル表示にキャッシュを使うか
var useCache = false;
 
// 無視するファイル・フォルダの定義
var ignoreFolder = "include|MacroSettings"; // 無視するフォルダ
var ignoreFile = "";  // 無視するファイル
// =========================================================
 
 
// タイトルのロードとキャッシュ
var load = {};
load = IO.Deserialize(load);
var map = {};
function LoadTitle(fullpath, isReload){
  var path = fullpath.substring(IO.Path.GetParent(ScriptFullName).length+1);
  // キャッシュから取得
  if (useCache && !isReload && load[path] != null) {
    map[path] = load[path];
    return load[path];
  }
  // ファイルから取得
  var texts = IO.LoadFromFile(fullpath, charset).split("\n");
  for (var i=0; i<texts.length; i++) {
    var text = texts[i].trim();
    if (text.startsWith("#title", true)) {
      var title = text.match(/".*"/)[0];
      title = title.substring(1, title.length-1)
      map[path] = title;
      return title;
    }
    if (!text.startsWith("#") && text.length > 0) {
      break;
    }
  }
  map[path] = "";
  return "";
}
 
// 自分と同じ名前のフォルダを取得
var basePath = IO.Path.Add(IO.Path.GetParent(ScriptFullName), IO.Path.GetBase(ScriptName));
if (!IO.Path.IsFolder(basePath)) {
  Alert("同じ名前のフォルダがありません");
  Quit();
}
var base = new IO.Folder(basePath);
 
// フォルダ・ファイルの無視判定
var ignoreFile = ignoreFile || "";
var ignoreFolder = ignoreFolder || "";
function IsIgnoreName(name, isFile){
  var def = isFile ? ignoreFile : ignoreFolder;
  if (!def) {
    return false;
  }
 
  if (typeof def == 'string') {
    var a = def.split("|");
    for (var i=0; i<a.length; i++) {
      if (name.equalsIgnoreCase(a[i])) {
        return true;
      }
    }
  } else if (def instanceof RegExp) {
    if (name.search(def) >= 0) {
      return true;
    }
  }
  return false;
}
 
// 配下のフォルダを辿っていきながら、メニューに追加する
var menu = CreatePopupMenu();
var list = [null];
(function RecursiveInsert(folder, menu, list, nest){
  // フォルダ処理
  var folders = folder.GetFolders();
  for (var i=0; i<folders.length; i++) {
    if (!IsIgnoreName(folders[i].GetName(), false)) {
      var subMenu = CreatePopupMenu();
      RecursiveInsert(folders[i], subMenu, list, nest+1);
      menu.AddPopup(folders[i].GetName(), subMenu);
    }
  }
  // ファイル処理
  var files = folder.GetFiles("*.js");
  for (var i=0; i<files.length; i++) {
    if (!IsIgnoreName(files[i].GetName(), true)) {
      var title = LoadTitle(files[i].GetPath(), false);
      if (!title) {
        title = files[i].GetName();
      }
 
      menu.Add(title, list.length);
      list.push(files[i].GetPath());
    }
  }
})(base, menu, list, 1);
var track = menu.Track(mePosMouse);
 
// 選択結果の実行とキャッシュの保存
if (track > 0) {
  (function(path){
    LoadTitle(path, true);
    IO.Serialize(map);
    var ScriptFullName, ScriptFullname, scriptfullname, ScriptName, Scriptname, scriptname;
    ScriptFullName = ScriptFullname = scriptfullname = path;
    ScriptName = Scriptname = scriptname = IO.Path.GetFileName(path);
    eval(IO.Include(path, charset));
  })(list[track]);
} else {
  IO.Serialize(map);
}