概要
リストで置換マクロの姉妹品です。メニューから置換リストを選ぶ事ができます。無駄に高機能です。
詳しくは、付属の 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 ""; } }
添付ファイル