概要
リストで置換マクロの姉妹品です。メニューから置換リストを選ぶ事ができます。無駄に高機能です。
詳しくは、付属の readme.txt をご覧下さい。
ダウンロード
-
version 0.02
listreplace002.zip
- サンプルファイルをつけました。
コメント
- ご意見・ご感想・ご要望 何かあればどぞー -- Nanasiya
-
Dmonkyに移植するのは困難でしょうか? VxEditorで使いたいのですが。 --
コード
/*
* リスト置換マクロ for EmEditor version 0.02
* Created by Nanasiya
*
* 改造・再配布等、ご自由にご利用ください。
*/
/* [Changelog]
*
* version 0.02
* - 置換オプションを書くとエラーが出てしまったのを修正。
* - サンプルファイルを付けた。
*
* version 0.01
* - 公開。
*
*/
/*** 設定ここから ***/
// Windows XP なら 1 それ以前の Windows なら 0
var winxp = 1;
//「置換リストファイル」のリスト
var replaceFileListName = "repfiles.txt";
// 置換オプションデフォルト
var replaceOption =
// eeFindReplaceCase | // 大文字小文字を区別
// eeFindReplaceEscSeq | // エスケープシーケンス使用
eeFindReplaceQuiet | // メッセージ表示なし
// eeFindReplaceOnlyWord | // 単語のみ
eeFindReplaceRegExp | // 正規表現
// eeReplaceSelOnly | // 選択範囲のみ置換
eeReplaceAll | // すべて置換
0;
// フォルダを置換する際のフィルタ関数 (true なら置換する)
var isReplacableFile = function (fileName) {
return true; // 常に置換する
// return fileName.match(/\.txt$/); // 拡張子 .txt のファイルだけ置換
// return fileName.match(/\.(c|h|cpp|hpp)$/); // 拡張子 .c .h .cpp .hpp を置換
}
// サブフォルダも置換対象にするかどうかデフォルト ( 0 = しない / 1 = する )
var searchInSubFolder = 0;
// 置換後、自動的に保存するかどうかデフォルト ( 0 = しない / 1 = する )
var autoSaveAfterReplace = 1;
// バックアップするかどうかデフォルト ( 0 = しない / 1 = する )
var backup = 1;
// バックアップする場合のファイル名生成関数
var backupFileName = function (fileName) {
if (!fileName) return ""; // 無名ならバックアップしない
return fileName + ".bak"; // file.txt.bak
// return fileName.replace(/\..+?$/, ".bak"); // file.bak
// return fileName.replace(/\\(.+?)$/, "\\bak\\$1"); // bak\file.txt
};
/*** 設定ここまで ***/
var FSO = new ActiveXObject("Scripting.FileSystemObject");
var SHELL = new ActiveXObject("WScript.Shell");
SHELL.CurrentDirectory = FSO.GetParentFolderName(ScriptFullName);
var target = document;
var targetIsFile = true;
var replaceFileList = openReplaceFileList();
var replaceFile = "";
var menuItemInfo = { };
//--- メインメニュー ---
var mainMenu;
while(true) {
mainMenu = buildMainMenu();
var result = mainMenu.Track(0);
if (result == 0) break;
if (result == 1) { // 置換リストファイルを選択
var file = openFileDialog();
if (file) {
replaceFile = file;
break;
}
}
else if (result < 1000) { // 置換リスト選択
replaceFile = menuItemInfo["id" + result];
break;
}
else if (result == 1000) { // 置換対象 : このドキュメント
target = document;
targetIsFile = true;
}
else if (result < 1500) { // 置換対象 : 開いているドキュメント
target = menuItemInfo["id" + result];
targetIsFile = true;
}
else if (result == 1500) { // 置換対象 : ファイルを選択
var file = openFileDialog();
if (file) {
target = file;
targetIsFile = true;
}
}
else if (result == 1501) { // 置換対象 : フォルダを選択
var folder = openFolderDialog();
if (folder) {
target = folder;
targetIsFile = false;
}
}
else if (result == 1502) { // 置換対象 : サブフォルダも置換対象にする
searchInSubFolder = !searchInSubFolder;
}
else if (result == 2000) { // 自動保存
autoSaveAfterReplace = !autoSaveAfterReplace;
}
else if (result == 2001) { // バックアップ
backup = !backup;
}
}
if (!target || !replaceFile) { // キャンセルされた
Quit();
}
//--- 置換実行 ---
// 置換リストを読み込み
var replaceList = openReplaceList();
if (!replaceList || replaceList.length == 0) {
alert("置換リストが無効です");
Quit();
}
// 置換を実行
doReplace();
alert("置換が完了しました");
//--- 関数 ---
// 置換ファイルリストを読み込んで返す
function openReplaceFileList() {
if (!FSO.FileExists(replaceFileListName)) return [];
var f = FSO.OpenTextFile(replaceFileListName, 1);
return readReplaceListFile(f);
}
// ファイルから読み込みつつ置換ファイルリストを作成
function readReplaceListFile(f) {
var list = [];
while(!f.AtEndOfStream) {
var line = f.ReadLine();
if (line.match(/^\s*$/)) { // 空行
continue;
}
else if (line.match(/^\s*\[(.*)\s*$/)) { // サブメニュー開始
// 再帰的に自身を呼び出して作成
var caption = RegExp.$1 ? RegExp.$1 : "sub menu";
var item = readReplaceListFile(f);
if (item && item.length > 0) {
list.push({ submenu: true, caption: caption, item: item });
}
}
else if (line.match(/^\s*\]\s*$/)) { // サブメニュー終了
break;
}
else if (line.match(/^\s*-+\s*$/)) { // セパレータ
list.push({ submenu: false, caption: "-", item: "-" });
}
else if (line.match(/^\s*((.+?)\t+)?(.+?)\s*$/)) { // ファイル
// "A\tB" なら A が項目名 B がファイル名
// "A" だけなら A がファイル名 とする
var caption = RegExp.$2 || FSO.GetFileName(RegExp.$3);
list.push({ submenu: false,
caption: caption,
item: RegExp.$3 });
}
}
return list;
}
// 置換リストを読み込む
function openReplaceList() {
var doc = document;
var num = editor.Documents.Count;
editor.OpenFile(replaceFile, 0, eeOpenAllowNewWindow);
document.selection.SelectAll();
var text = document.selection.Text;
var list = [ ];
if (text) {
text = text.split(/\r\n|\r|\n/);
for (var i in text) {
if (text[i].match(/^([^\t]*)\t([^\t]*)(\t([^\t]+))?$/)) {
list.push({
find: RegExp.$1,
replace: RegExp.$2,
option: parseOption(RegExp.$4)
});
}
}
}
if (num < editor.Documents.Count) document.close();
doc.Activate();
return list;
}
// 置換オプションのパース
function parseOption(opt) {
var option = replaceOption;
if (!opt) return option;
var p = true;
for(var i = 0; i < opt.length; i++) {
switch(opt.charAt(i).toLowerCase()) {
case '+': p = true; break;
case '-': p = false; break;
case 'i': setSwitch(option, eeFindReplaceCase, p); break;
case 'e': setSwitch(option, eeFindReplaceEscSeq, p); break;
case 'q': setSwitch(option, eeFindReplaceQuiet, p); break;
case 'w': setSwitch(option, eeFindReplaceOnlyWord, p); break;
case 'x': setSwitch(option, eeFindReplaceRegExp, p); break;
case 's': setSwitch(option, eeReplaceSelOnly, p); break;
case 'a': setSwitch(option, eeReplaceAll, p); break;
}
}
return option;
}
// オプションスイッチのON/OFF
function setSwitch(option, sw, swon) {
if (swon) {
return option | sw;
} else {
return option & (~sw);
}
}
// 置換を実行
function doReplace() {
var lastDocument = document;
if (targetIsFile) {
if (typeof(target) == "string") {
// ファイルパスの場合
doReplaceInFile(target);
} else {
// ドキュメントオブジェクトの場合
doReplaceInDocument(target);
}
} else {
// フォルダの場合
doReplaceInFolder(target);
}
lastDocument.Activate();
}
// ファイルを開いてから置換を実行
function doReplaceInFile(path) {
var num = editor.Documents.Count;
editor.OpenFile(path, 0, eeOpenAllowNewWindow);
doReplaceInDocument(document);
if (num < editor.Documents.Count) document.close();
}
// フォルダ置換を実行
function doReplaceInFolder(path) {
var folder = FSO.GetFolder(path);
var files = new Enumerator(folder.Files);
for ( ; !files.atEnd(); files.moveNext()) {
var fileName = files.item().Path;
if (isReplacableFile(fileName)) {
// 置換対象なら
doReplaceInFile(fileName);
}
}
if (searchInSubFolder) {
// サブフォルダも置換対象にする場合
var subs = new Enumerator(folder.SubFolders);
for ( ; !subs.atEnd(); subs.moveNext()) {
doReplaceInFolder(subs.item().Path);
}
}
}
// ドキュメントを置換
function doReplaceInDocument(doc) {
doc.Activate();
if (backup) backupDocument(doc);
for (var i in replaceList) {
var item = replaceList[i];
doc.selection.Replace(item.find, item.replace, item.option);
}
doc.HighlightFind = false;
if (autoSaveAfterReplace) {
doc.Save(doc.FullName);
}
}
// ドキュメントのバックアップを作成
function backupDocument(doc) {
var fileName = backupFileName(doc.FullName);
if (!fileName) return;
// 親フォルダが存在しなければ作成する
var folderName = FSO.GetParentFolderName(fileName);
if (!FSO.FolderExists(folderName)) {
SHELL.Run("cmd /c md \"" + folderName + "\"", 0, true);
}
var sel = saveSelection(doc.selection);
doc.selection.SelectAll();
var text = doc.selection.Text;
editor.NewFile();
document.ConfigName = doc.ConfigName;
document.Encoding = doc.Encoding;
document.UnicodeSignature = doc.UnicodeSignature;
document.writeln(text);
document.Save(fileName);
document.close();
restoreSelection(doc.selection, sel);
doc.Activate();
}
// 選択範囲をオブジェクトとして保存する
function saveSelection(selection) {
if (!selection || selection.isEmpty) return null;
return {
mode: selection.Mode,
topX: selection.GetTopPointX(eePosLogical),
topY: selection.GetTopPointY(eePosLogical),
bottomX: selection.GetBottomPointX(eePosLogical),
bottomY: selection.GetBottomPointY(eePosLogical)
};
}
// 選択範囲をオブジェクトから復元する
function restoreSelection(selection, obj) {
if (!selection || !obj) return;
selection.Mode = obj.Mode;
selection.SetActivePoint(eePosLogical, obj.topX, obj.topY, false);
selection.SetActivePoint(eePosLogical, obj.bottomX, obj.bottomY, true);
}
// メインメニューを作成
function buildMainMenu() {
var mainMenu = CreatePopupMenu();
menuItemInfo = { };
addReplaceFilesMenu(mainMenu);
mainMenu.Add("", 0, eeMenuSeparator);
addTargetSubMenu(mainMenu);
mainMenu.Add("自動保存(&S)", 2000, (autoSaveAfterReplace ? eeMenuChecked : 0));
mainMenu.Add("バックアップ(&B)", 2001, (backup ? eeMenuChecked : 0));
return mainMenu;
}
// 置換リスト選択メニューを追加
function addReplaceFilesMenu(menu) {
menu.Add("置換リストファイルを選択(&R)...", 1);
// 置換リストが読み込まれていればメニューに追加
if (replaceFileList && replaceFileList.length > 0) {
menu.Add("", 0, eeMenuSeparator);
addReplaceFileList(menu, replaceFileList, 2);
}
}
// 置換リストを追加
// id は開始メニューアイテムID
function addReplaceFileList(menu, list, id) {
for(var i in list) {
var item = list[i];
if (item.submenu) {
// サブメニューを再帰的に追加
var m = CreatePopupMenu();
id = addReplaceFileList(m, item.item, id);
menu.AddPopup(item.caption, m);
}
else if (item.caption == "-") {
menu.Add("", 0, eeMenuSeparator);
}
else {
// アイテム情報(ファイルパス)を覚えておく
menuItemInfo["id" + id] = item.item;
menu.Add(item.caption, id++);
}
}
return id;
}
// 置換対象のサブメニューを追加
function addTargetSubMenu(menu) {
var targetSubMenu = CreatePopupMenu();
var targetChecked = false;
var targetCaption = "選択されていません";
// メニューアイテムを追加する
// caption = 項目のキャプション
// acc = アクセラレータ
// id = メニューアイテムID
// checked = チェックされているかどうか
// captionAfter = アクセラレータの後ろに表示するキャプション
var addMenu = function(caption, acc, id, checked, captionAfter) {
var after = checked && captionAfter ? captionAfter : "";
var menuCaption = caption + acc + after;
if (checked) {
targetChecked = true;
targetCaption = caption + after;
targetSubMenu.Add(menuCaption, id, eeMenuChecked);
} else {
targetSubMenu.Add(menuCaption, id);
}
}
// セパレータを追加する
var addSeparator = function() {
targetSubMenu.Add("", 0, eeMenuSeparator);
}
menuItemInfo["id1000"] = document;
addMenu("このドキュメント", "(&A)", 1000,
typeof(target) == "object" && target == document);
addSeparator();
var docs = new Enumerator(editor.Documents);
for(var i = 0; !docs.atEnd(); docs.moveNext(), i++) {
var doc = docs.item();
if (doc == document) continue;
menuItemInfo["id" + (1001 + i)] = doc;
addMenu(doc.Name, generateAcc(i), 1001 + i,
typeof(target) == "object" && target == doc);
}
addSeparator();
addMenu("ファイルを選択", "(&F)...", 1500,
!targetChecked && targetIsFile, " : " + target);
addMenu("フォルダを選択", "(&D)...", 1501,
!targetChecked && !targetIsFile, " : " + target);
addSeparator();
addMenu("サブフォルダも対象にする", "(&R)", 1502, searchInSubFolder);
menu.AddPopup("置換の対象(&T) : " + targetCaption, targetSubMenu);
return targetSubMenu;
}
// アクセラレータを作成する
function generateAcc(c) {
c = c.toString();
if (c.length != 1) return "";
else return "(&" + c + ")";
}
// ファイルを開くダイアログ
function openFileDialog() {
var doc = document;
var num = editor.Documents.Count;
editor.ExecuteCommandByID(4097);
if (doc == document) { return ""; }
var fileName = document.FullName;
if (num < editor.Documents.Count) document.close();
doc.Activate();
return fileName;
}
// フォルダを開くダイアログ
function openFolderDialog() {
var shapp = new ActiveXObject("Shell.Application");
var folder = shapp.BrowseForFolder(0, "フォルダを選択してください", 0x50, "");
if (folder) {
return winxp ? folder.Self.Path : folder.Items.Item(0).Path;
} else {
return "";
}
}
添付ファイル
