「Eclipse風コメントアウト(改)」の版間の差分
ナビゲーションに移動
検索に移動
プロパティ名の修正(マクロリファレンス:3:Document オブジェクト#Tag プロパティを参照) |
|||
| (3人の利用者による、間の22版が非表示) | |||
| 1行目: | 1行目: | ||
= 概要 = | == 概要 == | ||
Eclipse風なコメントアウト <=> コメントの除去を行います。 | Eclipse風なコメントアウト <=> コメントの除去を行います。 | ||
| 8行目: | 8行目: | ||
オリジナルを作成されたksさんに感謝するとともに、せっかく作成したので改造版をここに公開します。 | オリジナルを作成されたksさんに感謝するとともに、せっかく作成したので改造版をここに公開します。 | ||
== 注意事項 == | |||
Mery Ver 3.7.2未満のソースコードでは、Shiftキーの状態を取得するために、[[GetKeyState.exe(キー状態取得実行ファイル)]]を使用しています。本体マクロと併せて上記実行ファイルも必要になります。 | |||
なお、Mery Ver 3.7.2以降のソースコードでは[[マクロリファレンス:3:Shell オブジェクト#GetKeyState メソッド|shell.GetKeyStateメソッド]]を使用しているため、GetKeyState.exeは必要ありません。 | |||
== 変更履歴 == | |||
* 1.0.2 (2020-03-15) | |||
** Mery 3.0.0以降対応版の追加(document.Tagプロパティを使用) | |||
* 1.0.1 (2019-04-12) | |||
** window.Quit() メソッドの使用排除 | |||
* 1.0.0 (2019-03-04) | |||
** 新規作成 | |||
== ソースコード == | |||
=== Ver 3.7.2以降 === | |||
このスクリプトはMery Ver 3.7.2以降対応版です。Mery Ver 3.7.2未満の環境では、Ver 3.0.0以降またはVer 3.0.0未満対応のスクリプトを利用してください。 | |||
<syntaxhighlight lang="javascript" copy> | |||
#icon = "_Comment.ico" | |||
#title = "選択行コメントアウト" | |||
// このスクリプトはMery Ver 3.7.2以降対応版です | |||
// Ver 3.7.2以前の環境では動作しません | |||
= | // ----------------------------------------------------------------------------- | ||
< | // Eclipse風なコメントアウト | ||
// 複数行一括コメントアウト、復帰マクロ | |||
// 1) 対象は行全体(行途中の選択も行全体とみなす) | |||
// 2) 空白行はコメントアウトしない | |||
// 3) インデントは選択行の範囲で一番左(タブ幅単位)に合わせる | |||
// 4) 選択範囲全体がコメントアウトされている場合は復帰 | |||
// | |||
// Copyright (c) ks. All Rights Reserved. | |||
// www: http://merysmacro.seesaa.net/ | |||
// ----------------------------------------------------------------------------- | |||
// a) 最終行の先頭までの選択状態では、最終行は処理範囲外にする(行選択対応) | |||
// b) コメント文字の種類を追加(Mery標準で単一行コメント可能な編集モード全て対応) | |||
// c) スペースが含まれるコメント文字に対応 | |||
// d) コメント文字が正規表現文字でも正しく動作するようにした | |||
// e) コメント文字不明時、SHIFTキー押下起動時はコメント文字を入力できるようにした | |||
// f) 選択方向を維持するようにした(下から上への選択対応) | |||
// g) 空白行で実行するとUndoされてしまう問題に対処 | |||
// h) OutputBarにフォーカスがある場合に処理できない問題に対処 | |||
// | |||
// Improved by pizz | |||
// ----------------------------------------------------------------------------- | |||
var doc = editor.ActiveDocument; | |||
var COM = ""; // 単一行コメント | |||
var TAGKEY = "pizzComment"; | |||
switch (doc.Mode.toLowerCase()) { | |||
case "bat": | |||
COM = "rem "; | |||
break; | |||
case "c#": | |||
case "c++": | |||
case "coldfusion": | |||
case "delphi": | |||
case "java": | |||
case "javascript": | |||
case "jsp": | |||
case "php": | |||
case "uwsc": | |||
COM = "// "; | |||
break; | |||
case "hsp": | |||
case "ini": | |||
case "x86 assembler": | |||
COM = "; "; | |||
break; | |||
case "perl": | |||
case "perlscript": | |||
case "powershell": | |||
case "python": | |||
case "rhtml": | |||
case "ruby": | |||
COM = "# "; | |||
break; | |||
case "sql": | |||
COM = "-- "; | |||
break; | |||
case "tex": | |||
COM = "% "; | |||
break; | |||
case "vbscript": | |||
case "visualbasic": | |||
COM = "'"; | |||
break; | |||
} | |||
// タグ設定を取得 | |||
var comSelected = ""; | |||
if (document.Tag.exists(TAGKEY)) { | |||
comSelected = document.Tag(TAGKEY); | |||
} | |||
if (comSelected == "") { | |||
comSelected = COM; | |||
} | |||
var comTrim = comSelected.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字 | |||
// SHIFTキー状態を取得 | |||
var shift = shell.GetKeyState(0x10); | |||
// コメント文字の入力を受ける | |||
if (comTrim == "" || shift < 0) { | |||
var comInput = "// "; | |||
if (comTrim != "") { | |||
comInput = comSelected; | |||
} | |||
comInput = prompt("コメント文字を指定してください", comInput); | |||
comTrim = comInput.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字 | |||
if (comTrim != "") { | |||
comSelected = comInput; | |||
document.Tag(TAGKEY) = comSelected; | |||
} | |||
} | |||
if (comTrim != "") { | |||
var meGetLineLogical = 0; | |||
var regOrg = new RegExp("^[ \\t]*" + comSelected.replace(/\W/g, "\\$&")); | |||
var regTrim = new RegExp("^[ \\t]*" + comTrim.replace(/\W/g, "\\$&")); | |||
var scrollY = window.ScrollY; | |||
var sel = doc.Selection; | |||
var st = sel.GetTopPointY(mePosLogical); | |||
var ed = sel.GetBottomPointY(mePosLogical); | |||
var ac = sel.GetActivePointY(mePosLogical); | |||
if (st != ed && sel.GetBottomPointX(mePosLogical) == 1) { | |||
// 複数行選択、最下行選択位置が行頭の場合は、最終行は除外 | |||
ed--; | |||
} | |||
var tab = GetTabSpace(); | |||
sel.SetActivePoint(mePosLogical, doc.GetLine(ed, meGetLineLogical).length + 1, ed); | |||
sel.SetAnchorPoint(mePosLogical, 1, st); | |||
var lines = sel.Text.split("\n"); | |||
if (sel.Text.length > 0) { | |||
sel.Untabify(); | |||
} | |||
var linesWithoutTab = sel.Text.split("\n"); | |||
if (sel.Text.length > 0) { | |||
doc.Undo(); | |||
} | |||
// インデント取得 | |||
var indent = -1; | |||
var existNotCommentLine = false; // 空白・コメント行でない行が存在するか | |||
for (var i = 0, len = linesWithoutTab.length; i < len; i++) { | |||
var line = linesWithoutTab[i]; | |||
var left = line.search(/[^ ]/); | |||
if (left >= 0 && (indent < 0 || left < indent)) { | |||
// インデントはタブ幅単位(左寄せ) | |||
indent = Math.floor(left / tab) * tab; | |||
} | |||
if (left >= 0) { | |||
// コメント行判定 | |||
if (!existNotCommentLine && line.search(regTrim) == -1) { | |||
existNotCommentLine = true; | |||
} | |||
} | |||
} | |||
var txt = ""; | |||
var changed = false; | |||
if (existNotCommentLine) { | |||
// コメントアウト | |||
for (var i = 0, len = lines.length; i < len; i++) { | |||
var line = lines[i] + "\n"; | |||
// 空白行はコメントアウトしない | |||
if (line.search(/[^ \t\n]/) == -1) { | |||
txt += line; | |||
continue; | |||
} | |||
// 挿入位置をタブと空白を考慮して決定 | |||
var index = 0, j; | |||
for (j = 0; index < indent; j++) { | |||
// indent の範囲には半角スペースかタブしかない | |||
if (line.charAt(j) == " ") { | |||
index += 1; | |||
} else { | |||
index += tab - (index % tab); | |||
} | |||
} | |||
txt += line.substring(0, j) + comSelected + line.substring(j); | |||
changed = true; | |||
} | |||
} else { | |||
// コメントから復帰 | |||
for (var i = 0, len = lines.length; i < len; i++) { | |||
var line = lines[i] + "\n"; | |||
if (line.match(regTrim)) { | |||
if (line.match(regOrg)) { | |||
txt += line.replace(comSelected, ""); // 先頭のコメント(空白付き)の削除 | |||
} else { | |||
txt += line.replace(comTrim, ""); // 先頭のコメント(空白なし)の削除 | |||
} | |||
changed = true; | |||
} else { | |||
txt += line; | |||
} | |||
} | |||
} | |||
// コメントアウト部分を書き換えて、全体を選択 | |||
if (doc.GetLine(ed + 1, meGetLineWithNewLines) == "") { | |||
txt = txt.substring(0, txt.length - 1); // 最後の改行は除去 | |||
} | |||
if (ac == st) { | |||
// 下から上への選択状態 | |||
sel.SetActivePoint(mePosLogical, 1, st); | |||
sel.SetAnchorPoint(mePosLogical, 1, ed + 1); | |||
if (changed) { | |||
sel.Text = txt; | |||
} | |||
sel.SetActivePoint(mePosLogical, 1, st); | |||
sel.SetAnchorPoint(mePosLogical, 1, ed + 1); | |||
} else { | |||
// 上から下への選択状態 | |||
sel.SetActivePoint(mePosLogical, 1, ed + 1); | |||
sel.SetAnchorPoint(mePosLogical, 1, st); | |||
if (changed) { | |||
sel.Text = txt; | |||
} | |||
sel.SetAnchorPoint(mePosLogical, 1, st); | |||
} | |||
window.ScrollY = scrollY; | |||
} | |||
//======================================== | |||
// 関数 | |||
//======================================== | |||
// タブ幅を取得 | |||
function GetTabSpace() { | |||
var doc = editor.ActiveDocument; | |||
var sel = doc.Selection; | |||
var saved = doc.Saved; | |||
sel.EndOfDocument(); | |||
doc.Write("\n\t"); | |||
sel.SetAnchorPoint(mePosLogical, sel.GetActivePointX(mePosLogical) - 1, sel.GetActivePointY(mePosLogical)); | |||
sel.Untabify(); | |||
var n = sel.Text.length; | |||
doc.Undo(); | |||
doc.Undo(); | |||
doc.Saved = saved; | |||
return n; | |||
} | |||
</syntaxhighlight> | |||
=== Ver 3.0.0以降 === | |||
このスクリプトはMery Ver 3.0.0以降対応版です。Mery Ver 3.0.0未満の環境では、Ver 3.0.0未満対応のスクリプトを利用してください。 | |||
<syntaxhighlight lang="javascript" copy> | |||
#icon = "_Comment.ico" | #icon = "_Comment.ico" | ||
#title = "選択行コメントアウト" | #title = "選択行コメントアウト" | ||
// このスクリプトはMery Ver 3.0.0以降対応版です | |||
// Ver 3.0.0以前の環境では動作しません | |||
// ----------------------------------------------------------------------------- | // ----------------------------------------------------------------------------- | ||
// Eclipse風なコメントアウト | // Eclipse風なコメントアウト | ||
// | // 複数行一括コメントアウト、復帰マクロ | ||
// 1) 対象は行全体(行途中の選択も行全体とみなす) | |||
// 2) 空白行はコメントアウトしない | |||
// 3) インデントは選択行の範囲で一番左(タブ幅単位)に合わせる | |||
// 4) 選択範囲全体がコメントアウトされている場合は復帰 | |||
// | |||
// Copyright (c) ks. All Rights Reserved. | |||
// www: http://merysmacro.seesaa.net/ | |||
// ----------------------------------------------------------------------------- | |||
// a) 最終行の先頭までの選択状態では、最終行は処理範囲外にする(行選択対応) | |||
// b) コメント文字の種類を追加(Mery標準で単一行コメント可能な編集モード全て対応) | |||
// c) スペースが含まれるコメント文字に対応 | |||
// d) コメント文字が正規表現文字でも正しく動作するようにした | |||
// e) コメント文字不明時、SHIFTキー押下起動時はコメント文字を入力できるようにした | |||
// f) 選択方向を維持するようにした(下から上への選択対応) | |||
// g) 空白行で実行するとUndoされてしまう問題に対処 | |||
// h) OutputBarにフォーカスがある場合に処理できない問題に対処 | |||
// | |||
// SHIFTキー状態取得のために、"GetKeyState.exe"が必要です | |||
// | |||
// Improved by pizz | |||
// ----------------------------------------------------------------------------- | |||
var doc = editor.ActiveDocument; | |||
var COM = ""; // 単一行コメント | |||
var TAGKEY = "pizzComment"; | |||
switch (doc.Mode.toLowerCase()) { | |||
case "bat": | |||
COM = "rem "; | |||
break; | |||
case "c#": | |||
case "c++": | |||
case "coldfusion": | |||
case "delphi": | |||
case "java": | |||
case "javascript": | |||
case "jsp": | |||
case "php": | |||
case "uwsc": | |||
COM = "// "; | |||
break; | |||
case "hsp": | |||
case "ini": | |||
case "x86 assembler": | |||
COM = "; "; | |||
break; | |||
case "perl": | |||
case "perlscript": | |||
case "powershell": | |||
case "python": | |||
case "rhtml": | |||
case "ruby": | |||
COM = "# "; | |||
break; | |||
case "sql": | |||
COM = "-- "; | |||
break; | |||
case "tex": | |||
COM = "% "; | |||
break; | |||
case "vbscript": | |||
case "visualbasic": | |||
COM = "'"; | |||
break; | |||
} | |||
var wshShell = new ActiveXObject("WScript.Shell"); | |||
// カレントディレクトリをマクロディレクトリに変更 | |||
wshShell.CurrentDirectory = editor.FullName.match(/^.*\\/)[0] + 'Macros'; | |||
// タグ設定を取得 | |||
var comSelected = ""; | |||
if (document.Tag.exists(TAGKEY)) { | |||
comSelected = document.Tag(TAGKEY); | |||
} | |||
if (comSelected == "") { | |||
comSelected = COM; | |||
} | |||
var comTrim = comSelected.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字 | |||
// SHIFTキー状態を取得 | |||
var shift = wshShell.Run("GetKeyState.exe shift", 0, true); | |||
if (shift != -1) { | |||
// コメント文字の入力を受ける | |||
if (comTrim == "" || shift == 1) { | |||
var comInput = "// "; | |||
if (comTrim != "") { | |||
comInput = comSelected; | |||
} | |||
comInput = prompt("コメント文字を指定してください", comInput); | |||
comTrim = comInput.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字 | |||
if (comTrim != "") { | |||
comSelected = comInput; | |||
document.Tag(TAGKEY) = comSelected; | |||
} | |||
} | |||
if (comTrim != "") { | |||
var meGetLineLogical = 0; | |||
var regOrg = new RegExp("^[ \\t]*" + comSelected.replace(/\W/g, "\\$&")); | |||
var regTrim = new RegExp("^[ \\t]*" + comTrim.replace(/\W/g, "\\$&")); | |||
var scrollY = window.ScrollY; | |||
var sel = doc.Selection; | |||
var st = sel.GetTopPointY(mePosLogical); | |||
var ed = sel.GetBottomPointY(mePosLogical); | |||
var ac = sel.GetActivePointY(mePosLogical); | |||
if (st != ed && sel.GetBottomPointX(mePosLogical) == 1) { | |||
// 複数行選択、最下行選択位置が行頭の場合は、最終行は除外 | |||
ed--; | |||
} | |||
var tab = GetTabSpace(); | |||
sel.SetActivePoint(mePosLogical, doc.GetLine(ed, meGetLineLogical).length + 1, ed); | |||
sel.SetAnchorPoint(mePosLogical, 1, st); | |||
var lines = sel.Text.split("\n"); | |||
if (sel.Text.length > 0) { | |||
sel.Untabify(); | |||
} | |||
var linesWithoutTab = sel.Text.split("\n"); | |||
if (sel.Text.length > 0) { | |||
doc.Undo(); | |||
} | |||
// インデント取得 | |||
var indent = -1; | |||
var existNotCommentLine = false; // 空白・コメント行でない行が存在するか | |||
for (var i = 0, len = linesWithoutTab.length; i < len; i++) { | |||
var line = linesWithoutTab[i]; | |||
var left = line.search(/[^ ]/); | |||
if (left >= 0 && (indent < 0 || left < indent)) { | |||
// インデントはタブ幅単位(左寄せ) | |||
indent = Math.floor(left / tab) * tab; | |||
} | |||
if (left >= 0) { | |||
// コメント行判定 | |||
if (!existNotCommentLine && line.search(regTrim) == -1) { | |||
existNotCommentLine = true; | |||
} | |||
} | |||
} | |||
var txt = ""; | |||
var changed = false; | |||
if (existNotCommentLine) { | |||
// コメントアウト | |||
for (var i = 0, len = lines.length; i < len; i++) { | |||
var line = lines[i] + "\n"; | |||
// 空白行はコメントアウトしない | |||
if (line.search(/[^ \t\n]/) == -1) { | |||
txt += line; | |||
continue; | |||
} | |||
// 挿入位置をタブと空白を考慮して決定 | |||
var index = 0, j; | |||
for (j = 0; index < indent; j++) { | |||
// indent の範囲には半角スペースかタブしかない | |||
if (line.charAt(j) == " ") { | |||
index += 1; | |||
} else { | |||
index += tab - (index % tab); | |||
} | |||
} | |||
txt += line.substring(0, j) + comSelected + line.substring(j); | |||
changed = true; | |||
} | |||
} else { | |||
// コメントから復帰 | |||
for (var i = 0, len = lines.length; i < len; i++) { | |||
var line = lines[i] + "\n"; | |||
if (line.match(regTrim)) { | |||
if (line.match(regOrg)) { | |||
txt += line.replace(comSelected, ""); // 先頭のコメント(空白付き)の削除 | |||
} else { | |||
txt += line.replace(comTrim, ""); // 先頭のコメント(空白なし)の削除 | |||
} | |||
changed = true; | |||
} else { | |||
txt += line; | |||
} | |||
} | |||
} | |||
// コメントアウト部分を書き換えて、全体を選択 | |||
if (doc.GetLine(ed + 1, meGetLineWithNewLines) == "") { | |||
txt = txt.substring(0, txt.length - 1); // 最後の改行は除去 | |||
} | |||
if (ac == st) { | |||
// 下から上への選択状態 | |||
sel.SetActivePoint(mePosLogical, 1, st); | |||
sel.SetAnchorPoint(mePosLogical, 1, ed + 1); | |||
if (changed) { | |||
sel.Text = txt; | |||
} | |||
sel.SetActivePoint(mePosLogical, 1, st); | |||
sel.SetAnchorPoint(mePosLogical, 1, ed + 1); | |||
} else { | |||
// 上から下への選択状態 | |||
sel.SetActivePoint(mePosLogical, 1, ed + 1); | |||
sel.SetAnchorPoint(mePosLogical, 1, st); | |||
if (changed) { | |||
sel.Text = txt; | |||
} | |||
sel.SetAnchorPoint(mePosLogical, 1, st); | |||
} | |||
window.ScrollY = scrollY; | |||
} | |||
} | |||
//======================================== | |||
// 関数 | |||
//======================================== | |||
// タブ幅を取得 | |||
function GetTabSpace() { | |||
var doc = editor.ActiveDocument; | |||
var sel = doc.Selection; | |||
var saved = doc.Saved; | |||
sel.EndOfDocument(); | |||
doc.Write("\n\t"); | |||
sel.SetAnchorPoint(mePosLogical, sel.GetActivePointX(mePosLogical) - 1, sel.GetActivePointY(mePosLogical)); | |||
sel.Untabify(); | |||
var n = sel.Text.length; | |||
doc.Undo(); | |||
doc.Undo(); | |||
doc.Saved = saved; | |||
return n; | |||
} | |||
</syntaxhighlight> | |||
=== Ver 3.0.0未満 === | |||
以下は、Mery Ver 3.0.0未満の環境でも利用できます(3.0.0以降でも動作しますが、上のバージョンの利用をお勧めします)。 | |||
<syntaxhighlight lang="javascript" copy> | |||
#icon = "_Comment.ico" | |||
#title = "選択行コメントアウト" | |||
// ----------------------------------------------------------------------------- | |||
// Eclipse風なコメントアウト | |||
// 複数行一括コメントアウト、復帰マクロ | |||
// 1) 対象は行全体(行途中の選択も行全体とみなす) | // 1) 対象は行全体(行途中の選択も行全体とみなす) | ||
// 2) 空白行はコメントアウトしない | // 2) 空白行はコメントアウトしない | ||
| 57行目: | 544行目: | ||
var settingFilename = "_CommentMacro.ini"; | var settingFilename = "_CommentMacro.ini"; | ||
switch(doc.Mode.toLowerCase()){ | switch (doc.Mode.toLowerCase()) { | ||
case "bat": | case "bat": | ||
COM = "rem "; | |||
break; | |||
case "c#": | case "c#": | ||
case "c++": | case "c++": | ||
case "coldfusion": | case "coldfusion": | ||
case "delphi": | case "delphi": | ||
case "java": | case "java": | ||
case "javascript": | case "javascript": | ||
case "jsp": | case "jsp": | ||
case "php": | case "php": | ||
case "uwsc": | case "uwsc": | ||
COM = "// "; | |||
break; | |||
case "hsp": | case "hsp": | ||
case "ini": | case "ini": | ||
case "x86 assembler": | case "x86 assembler": | ||
COM = "; "; | |||
break; | |||
case "perl": | case "perl": | ||
case "perlscript": | case "perlscript": | ||
case "powershell": | case "powershell": | ||
case "python": | case "python": | ||
case "rhtml": | case "rhtml": | ||
case "ruby": | case "ruby": | ||
COM = "# "; | |||
break; | |||
case "sql": | case "sql": | ||
COM = "-- "; | |||
break; | |||
case "tex": | case "tex": | ||
COM = "% "; | |||
break; | |||
case "vbscript": | case "vbscript": | ||
case "visualbasic": | case "visualbasic": | ||
COM = "'"; | |||
break; | |||
} | } | ||
| 105行目: | 592行目: | ||
// 設定ファイルからコメント文字を読み込む | // 設定ファイルからコメント文字を読み込む | ||
var comSelected = LoadDocSetting(); | var comSelected = LoadDocSetting(); | ||
if(comSelected != null){ | if (comSelected != null) { | ||
if (comSelected == "") { | |||
comSelected = COM; | |||
} | |||
var comTrim = comSelected.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字 | |||
// SHIFTキー状態を取得 | |||
var shift = wshShell.Run("GetKeyState.exe shift", 0, true); | |||
if (shift != -1) { | |||
// コメント文字の入力を受ける | |||
if (comTrim == "" || shift == 1) { | |||
var comInput = "// "; | |||
if (comTrim != "") { | |||
comInput = comSelected; | |||
} | |||
comInput = prompt("コメント文字を指定してください", comInput); | |||
comTrim = comInput.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字 | |||
if (comTrim != "") { | |||
if (comInput != comSelected) { | |||
SaveDocSetting(comInput); | |||
comSelected = comInput; | |||
} | |||
} | |||
} | |||
if (comTrim != "") { | |||
var meGetLineLogical = 0; | |||
var regOrg = new RegExp("^[ \\t]*" + comSelected.replace(/\W/g, "\\$&")); | |||
var regTrim = new RegExp("^[ \\t]*" + comTrim.replace(/\W/g, "\\$&")); | |||
var scrollY = window.ScrollY; | |||
var sel = doc.Selection; | |||
var st = sel.GetTopPointY(mePosLogical); | |||
var ed = sel.GetBottomPointY(mePosLogical); | |||
var ac = sel.GetActivePointY(mePosLogical); | |||
if (st != ed && sel.GetBottomPointX(mePosLogical) == 1) { | |||
// 複数行選択、最下行選択位置が行頭の場合は、最終行は除外 | |||
ed--; | |||
} | |||
var tab = GetTabSpace(); | |||
sel.SetActivePoint(mePosLogical, doc.GetLine(ed, meGetLineLogical).length + 1, ed); | |||
sel.SetAnchorPoint(mePosLogical, 1, st); | |||
var lines = sel.Text.split("\n"); | |||
if (sel.Text.length > 0) { | |||
sel.Untabify(); | |||
} | |||
var linesWithoutTab = sel.Text.split("\n"); | |||
if (sel.Text.length > 0) { | |||
doc.Undo(); | |||
} | |||
// インデント取得 | |||
var indent = -1; | |||
var existNotCommentLine = false; // 空白・コメント行でない行が存在するか | |||
for (var i = 0, len = linesWithoutTab.length; i < len; i++) { | |||
var line = linesWithoutTab[i]; | |||
var left = line.search(/[^ ]/); | |||
if (left >= 0 && (indent < 0 || left < indent)) { | |||
// インデントはタブ幅単位(左寄せ) | |||
indent = Math.floor(left / tab) * tab; | |||
} | |||
if (left >= 0) { | |||
// コメント行判定 | |||
if (!existNotCommentLine && line.search(regTrim) == -1) { | |||
existNotCommentLine = true; | |||
} | |||
} | |||
} | |||
var txt = ""; | |||
var changed = false; | |||
if (existNotCommentLine) { | |||
// コメントアウト | |||
for (var i = 0, len = lines.length; i < len; i++) { | |||
var line = lines[i] + "\n"; | |||
// 空白行はコメントアウトしない | |||
if (line.search(/[^ \t\n]/) == -1) { | |||
txt += line; | |||
continue; | |||
} | |||
// 挿入位置をタブと空白を考慮して決定 | |||
var index = 0, j; | |||
for (j = 0; index < indent; j++) { | |||
// indent の範囲には半角スペースかタブしかない | |||
if (line.charAt(j) == " ") { | |||
index += 1; | |||
} else { | |||
index += tab - (index % tab); | |||
} | |||
} | |||
txt += line.substring(0, j) + comSelected + line.substring(j); | |||
changed = true; | |||
} | |||
} else { | |||
// コメントから復帰 | |||
for (var i = 0, len = lines.length; i < len; i++) { | |||
var line = lines[i] + "\n"; | |||
if (line.match(regTrim)) { | |||
if (line.match(regOrg)) { | |||
txt += line.replace(comSelected, ""); // 先頭のコメント(空白付き)の削除 | |||
} else { | |||
txt += line.replace(comTrim, ""); // 先頭のコメント(空白なし)の削除 | |||
} | |||
changed = true; | |||
} else { | |||
txt += line; | |||
} | |||
} | |||
} | |||
// コメントアウト部分を書き換えて、全体を選択 | |||
if (doc.GetLine(ed + 1, meGetLineWithNewLines) == "") { | |||
txt = txt.substring(0, txt.length - 1); // 最後の改行は除去 | |||
} | |||
if (ac == st) { | |||
// 下から上への選択状態 | |||
sel.SetActivePoint(mePosLogical, 1, st); | |||
sel.SetAnchorPoint(mePosLogical, 1, ed + 1); | |||
if (changed) { | |||
sel.Text = txt; | |||
} | |||
sel.SetActivePoint(mePosLogical, 1, st); | |||
sel.SetAnchorPoint(mePosLogical, 1, ed + 1); | |||
} else { | |||
// 上から下への選択状態 | |||
sel.SetActivePoint(mePosLogical, 1, ed + 1); | |||
sel.SetAnchorPoint(mePosLogical, 1, st); | |||
if (changed) { | |||
sel.Text = txt; | |||
} | |||
sel.SetAnchorPoint(mePosLogical, 1, st); | |||
} | |||
window.ScrollY = scrollY; | |||
} | |||
} | |||
} | } | ||
| 238行目: | 738行目: | ||
//======================================== | //======================================== | ||
// タブ幅を取得 | // タブ幅を取得 | ||
function GetTabSpace() | function GetTabSpace() { | ||
{ | var doc = editor.ActiveDocument; | ||
var sel = doc.Selection; | |||
var saved = doc.Saved; | |||
sel.EndOfDocument(); | |||
doc.Write("\n\t"); | |||
sel.SetAnchorPoint(mePosLogical, sel.GetActivePointX(mePosLogical) - 1, sel.GetActivePointY(mePosLogical)); | |||
sel.Untabify(); | |||
var n = sel.Text.length; | |||
doc.Undo(); | |||
doc.Undo(); | |||
doc.Saved = saved; | |||
return n; | |||
} | } | ||
// コメント文字設定をファイルから読み込み | // コメント文字設定をファイルから読み込み | ||
function LoadDocSetting() | function LoadDocSetting() { | ||
{ | var dic = LoadDocSettingDataListWithOpend(); | ||
if (dic == null) { | |||
return null; | |||
} | |||
var ret = ""; | |||
for (var key in dic) { | |||
if (key.toLowerCase() == window.document.FullName.toLowerCase()) { | |||
ret = dic[window.document.FullName.toLowerCase()]; | |||
} | |||
} | |||
return ret; | |||
} | } | ||
// コメント文字設定をファイルに書き込み | // コメント文字設定をファイルに書き込み | ||
function SaveDocSetting(comStr) | function SaveDocSetting(comStr) { | ||
{ | var dic = LoadDocSettingDataListWithOpend(); | ||
if (dic != null) { | |||
dic[window.document.FullName.toLowerCase()] = comStr; | |||
SaveDocSettingDataListWithOpend(dic); | |||
} | |||
} | } | ||
// 設定ファイルから全ての設定値を取得 | // 設定ファイルから全ての設定値を取得 | ||
function LoadDocSettingDataListWithOpend() | function LoadDocSettingDataListWithOpend() { | ||
{ | var settingPath = GetSettingFilePath(); | ||
if (settingPath == "") { | |||
return null; | |||
} | |||
var dic = {}; | |||
var deleted = false; | |||
if (fso.FileExists(settingPath)) { | |||
var tso = fso.OpenTextFile(settingPath, 1, false, -1); | |||
while (tso.AtEndOfStream == false) { | |||
var setting = tso.ReadLine().split("\t", 2); | |||
var detect = false; | |||
for (var i = 0; i < window.Editors.Count; i++) { | |||
for (var j = 0; j < window.Editors.Item(i).Documents.Count; j++) { | |||
if (window.Editors.Item(i).Documents.Item(j).FullName.toLowerCase() == | |||
setting[0].toLowerCase()) { | |||
dic[setting[0].toLowerCase()] = setting[1]; | |||
detect = true; | |||
break; | |||
} | |||
} | |||
if (detect) { | |||
break; | |||
} | |||
} | |||
if (detect == false) { | |||
deleted = true; | |||
} | |||
} | |||
tso.Close(); | |||
} | |||
if (deleted) { | |||
SaveDocSettingDataListWithOpend(dic); | |||
} | |||
return dic; | |||
} | } | ||
// 設定ファイルを全て書き換え | // 設定ファイルを全て書き換え | ||
function SaveDocSettingDataListWithOpend(dic) | function SaveDocSettingDataListWithOpend(dic) { | ||
{ | var settingPath = GetSettingFilePath(); | ||
if (settingPath != "") { | |||
var tso = fso.OpenTextFile(settingPath, 2, true, -1); | |||
for (var key in dic) { | |||
tso.WriteLine(key + "\t" + dic[key]); | |||
} | |||
tso.Close(); | |||
} | |||
} | } | ||
// コメント文字設定ファイルの場所を取得する | // コメント文字設定ファイルの場所を取得する | ||
function GetSettingFilePath() | function GetSettingFilePath() { | ||
{ | var meryDir = fso.GetParentFolderName(editor.FullName); | ||
var settingPath = ""; | |||
if (fso.FileExists(fso.BuildPath(meryDir, "Mery.ini"))) { | |||
settingPath = fso.BuildPath(meryDir, settingFilename); | |||
} else { | |||
var appDataPath = fso.BuildPath(wshShell.SpecialFolders('Appdata'), 'Mery'); | |||
if (fso.FileExists(fso.BuildPath(appDataPath, "Mery.ini"))) { | |||
settingPath = fso.BuildPath(appDataPath, settingFilename); | |||
} | |||
} | |||
if (settingPath == "") { | |||
window.Alert("Mery.ini ファイルが見つかりません"); | |||
} | |||
return settingPath; | |||
} | } | ||
</syntaxhighlight> | |||
</ | |||
2025年11月26日 (水) 15:52時点における最新版
概要[編集]
Eclipse風なコメントアウト <=> コメントの除去を行います。
ksさんの作成された、Eclipse風コメントアウトは、私にとって欠かせないツールです。
便利に使わせていただく一方、細かい挙動が気になって変更したり、機能を追加しているうちに、すっかり別物になってしまいました。
オリジナルを作成されたksさんに感謝するとともに、せっかく作成したので改造版をここに公開します。
注意事項[編集]
Mery Ver 3.7.2未満のソースコードでは、Shiftキーの状態を取得するために、GetKeyState.exe(キー状態取得実行ファイル)を使用しています。本体マクロと併せて上記実行ファイルも必要になります。
なお、Mery Ver 3.7.2以降のソースコードではshell.GetKeyStateメソッドを使用しているため、GetKeyState.exeは必要ありません。
変更履歴[編集]
- 1.0.2 (2020-03-15)
- Mery 3.0.0以降対応版の追加(document.Tagプロパティを使用)
- 1.0.1 (2019-04-12)
- window.Quit() メソッドの使用排除
- 1.0.0 (2019-03-04)
- 新規作成
ソースコード[編集]
Ver 3.7.2以降[編集]
このスクリプトはMery Ver 3.7.2以降対応版です。Mery Ver 3.7.2未満の環境では、Ver 3.0.0以降またはVer 3.0.0未満対応のスクリプトを利用してください。
#icon = "_Comment.ico"
#title = "選択行コメントアウト"
// このスクリプトはMery Ver 3.7.2以降対応版です
// Ver 3.7.2以前の環境では動作しません
// -----------------------------------------------------------------------------
// Eclipse風なコメントアウト
// 複数行一括コメントアウト、復帰マクロ
// 1) 対象は行全体(行途中の選択も行全体とみなす)
// 2) 空白行はコメントアウトしない
// 3) インデントは選択行の範囲で一番左(タブ幅単位)に合わせる
// 4) 選択範囲全体がコメントアウトされている場合は復帰
//
// Copyright (c) ks. All Rights Reserved.
// www: http://merysmacro.seesaa.net/
// -----------------------------------------------------------------------------
// a) 最終行の先頭までの選択状態では、最終行は処理範囲外にする(行選択対応)
// b) コメント文字の種類を追加(Mery標準で単一行コメント可能な編集モード全て対応)
// c) スペースが含まれるコメント文字に対応
// d) コメント文字が正規表現文字でも正しく動作するようにした
// e) コメント文字不明時、SHIFTキー押下起動時はコメント文字を入力できるようにした
// f) 選択方向を維持するようにした(下から上への選択対応)
// g) 空白行で実行するとUndoされてしまう問題に対処
// h) OutputBarにフォーカスがある場合に処理できない問題に対処
//
// Improved by pizz
// -----------------------------------------------------------------------------
var doc = editor.ActiveDocument;
var COM = ""; // 単一行コメント
var TAGKEY = "pizzComment";
switch (doc.Mode.toLowerCase()) {
case "bat":
COM = "rem ";
break;
case "c#":
case "c++":
case "coldfusion":
case "delphi":
case "java":
case "javascript":
case "jsp":
case "php":
case "uwsc":
COM = "// ";
break;
case "hsp":
case "ini":
case "x86 assembler":
COM = "; ";
break;
case "perl":
case "perlscript":
case "powershell":
case "python":
case "rhtml":
case "ruby":
COM = "# ";
break;
case "sql":
COM = "-- ";
break;
case "tex":
COM = "% ";
break;
case "vbscript":
case "visualbasic":
COM = "'";
break;
}
// タグ設定を取得
var comSelected = "";
if (document.Tag.exists(TAGKEY)) {
comSelected = document.Tag(TAGKEY);
}
if (comSelected == "") {
comSelected = COM;
}
var comTrim = comSelected.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字
// SHIFTキー状態を取得
var shift = shell.GetKeyState(0x10);
// コメント文字の入力を受ける
if (comTrim == "" || shift < 0) {
var comInput = "// ";
if (comTrim != "") {
comInput = comSelected;
}
comInput = prompt("コメント文字を指定してください", comInput);
comTrim = comInput.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字
if (comTrim != "") {
comSelected = comInput;
document.Tag(TAGKEY) = comSelected;
}
}
if (comTrim != "") {
var meGetLineLogical = 0;
var regOrg = new RegExp("^[ \\t]*" + comSelected.replace(/\W/g, "\\$&"));
var regTrim = new RegExp("^[ \\t]*" + comTrim.replace(/\W/g, "\\$&"));
var scrollY = window.ScrollY;
var sel = doc.Selection;
var st = sel.GetTopPointY(mePosLogical);
var ed = sel.GetBottomPointY(mePosLogical);
var ac = sel.GetActivePointY(mePosLogical);
if (st != ed && sel.GetBottomPointX(mePosLogical) == 1) {
// 複数行選択、最下行選択位置が行頭の場合は、最終行は除外
ed--;
}
var tab = GetTabSpace();
sel.SetActivePoint(mePosLogical, doc.GetLine(ed, meGetLineLogical).length + 1, ed);
sel.SetAnchorPoint(mePosLogical, 1, st);
var lines = sel.Text.split("\n");
if (sel.Text.length > 0) {
sel.Untabify();
}
var linesWithoutTab = sel.Text.split("\n");
if (sel.Text.length > 0) {
doc.Undo();
}
// インデント取得
var indent = -1;
var existNotCommentLine = false; // 空白・コメント行でない行が存在するか
for (var i = 0, len = linesWithoutTab.length; i < len; i++) {
var line = linesWithoutTab[i];
var left = line.search(/[^ ]/);
if (left >= 0 && (indent < 0 || left < indent)) {
// インデントはタブ幅単位(左寄せ)
indent = Math.floor(left / tab) * tab;
}
if (left >= 0) {
// コメント行判定
if (!existNotCommentLine && line.search(regTrim) == -1) {
existNotCommentLine = true;
}
}
}
var txt = "";
var changed = false;
if (existNotCommentLine) {
// コメントアウト
for (var i = 0, len = lines.length; i < len; i++) {
var line = lines[i] + "\n";
// 空白行はコメントアウトしない
if (line.search(/[^ \t\n]/) == -1) {
txt += line;
continue;
}
// 挿入位置をタブと空白を考慮して決定
var index = 0, j;
for (j = 0; index < indent; j++) {
// indent の範囲には半角スペースかタブしかない
if (line.charAt(j) == " ") {
index += 1;
} else {
index += tab - (index % tab);
}
}
txt += line.substring(0, j) + comSelected + line.substring(j);
changed = true;
}
} else {
// コメントから復帰
for (var i = 0, len = lines.length; i < len; i++) {
var line = lines[i] + "\n";
if (line.match(regTrim)) {
if (line.match(regOrg)) {
txt += line.replace(comSelected, ""); // 先頭のコメント(空白付き)の削除
} else {
txt += line.replace(comTrim, ""); // 先頭のコメント(空白なし)の削除
}
changed = true;
} else {
txt += line;
}
}
}
// コメントアウト部分を書き換えて、全体を選択
if (doc.GetLine(ed + 1, meGetLineWithNewLines) == "") {
txt = txt.substring(0, txt.length - 1); // 最後の改行は除去
}
if (ac == st) {
// 下から上への選択状態
sel.SetActivePoint(mePosLogical, 1, st);
sel.SetAnchorPoint(mePosLogical, 1, ed + 1);
if (changed) {
sel.Text = txt;
}
sel.SetActivePoint(mePosLogical, 1, st);
sel.SetAnchorPoint(mePosLogical, 1, ed + 1);
} else {
// 上から下への選択状態
sel.SetActivePoint(mePosLogical, 1, ed + 1);
sel.SetAnchorPoint(mePosLogical, 1, st);
if (changed) {
sel.Text = txt;
}
sel.SetAnchorPoint(mePosLogical, 1, st);
}
window.ScrollY = scrollY;
}
//========================================
// 関数
//========================================
// タブ幅を取得
function GetTabSpace() {
var doc = editor.ActiveDocument;
var sel = doc.Selection;
var saved = doc.Saved;
sel.EndOfDocument();
doc.Write("\n\t");
sel.SetAnchorPoint(mePosLogical, sel.GetActivePointX(mePosLogical) - 1, sel.GetActivePointY(mePosLogical));
sel.Untabify();
var n = sel.Text.length;
doc.Undo();
doc.Undo();
doc.Saved = saved;
return n;
}
Ver 3.0.0以降[編集]
このスクリプトはMery Ver 3.0.0以降対応版です。Mery Ver 3.0.0未満の環境では、Ver 3.0.0未満対応のスクリプトを利用してください。
#icon = "_Comment.ico"
#title = "選択行コメントアウト"
// このスクリプトはMery Ver 3.0.0以降対応版です
// Ver 3.0.0以前の環境では動作しません
// -----------------------------------------------------------------------------
// Eclipse風なコメントアウト
// 複数行一括コメントアウト、復帰マクロ
// 1) 対象は行全体(行途中の選択も行全体とみなす)
// 2) 空白行はコメントアウトしない
// 3) インデントは選択行の範囲で一番左(タブ幅単位)に合わせる
// 4) 選択範囲全体がコメントアウトされている場合は復帰
//
// Copyright (c) ks. All Rights Reserved.
// www: http://merysmacro.seesaa.net/
// -----------------------------------------------------------------------------
// a) 最終行の先頭までの選択状態では、最終行は処理範囲外にする(行選択対応)
// b) コメント文字の種類を追加(Mery標準で単一行コメント可能な編集モード全て対応)
// c) スペースが含まれるコメント文字に対応
// d) コメント文字が正規表現文字でも正しく動作するようにした
// e) コメント文字不明時、SHIFTキー押下起動時はコメント文字を入力できるようにした
// f) 選択方向を維持するようにした(下から上への選択対応)
// g) 空白行で実行するとUndoされてしまう問題に対処
// h) OutputBarにフォーカスがある場合に処理できない問題に対処
//
// SHIFTキー状態取得のために、"GetKeyState.exe"が必要です
//
// Improved by pizz
// -----------------------------------------------------------------------------
var doc = editor.ActiveDocument;
var COM = ""; // 単一行コメント
var TAGKEY = "pizzComment";
switch (doc.Mode.toLowerCase()) {
case "bat":
COM = "rem ";
break;
case "c#":
case "c++":
case "coldfusion":
case "delphi":
case "java":
case "javascript":
case "jsp":
case "php":
case "uwsc":
COM = "// ";
break;
case "hsp":
case "ini":
case "x86 assembler":
COM = "; ";
break;
case "perl":
case "perlscript":
case "powershell":
case "python":
case "rhtml":
case "ruby":
COM = "# ";
break;
case "sql":
COM = "-- ";
break;
case "tex":
COM = "% ";
break;
case "vbscript":
case "visualbasic":
COM = "'";
break;
}
var wshShell = new ActiveXObject("WScript.Shell");
// カレントディレクトリをマクロディレクトリに変更
wshShell.CurrentDirectory = editor.FullName.match(/^.*\\/)[0] + 'Macros';
// タグ設定を取得
var comSelected = "";
if (document.Tag.exists(TAGKEY)) {
comSelected = document.Tag(TAGKEY);
}
if (comSelected == "") {
comSelected = COM;
}
var comTrim = comSelected.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字
// SHIFTキー状態を取得
var shift = wshShell.Run("GetKeyState.exe shift", 0, true);
if (shift != -1) {
// コメント文字の入力を受ける
if (comTrim == "" || shift == 1) {
var comInput = "// ";
if (comTrim != "") {
comInput = comSelected;
}
comInput = prompt("コメント文字を指定してください", comInput);
comTrim = comInput.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字
if (comTrim != "") {
comSelected = comInput;
document.Tag(TAGKEY) = comSelected;
}
}
if (comTrim != "") {
var meGetLineLogical = 0;
var regOrg = new RegExp("^[ \\t]*" + comSelected.replace(/\W/g, "\\$&"));
var regTrim = new RegExp("^[ \\t]*" + comTrim.replace(/\W/g, "\\$&"));
var scrollY = window.ScrollY;
var sel = doc.Selection;
var st = sel.GetTopPointY(mePosLogical);
var ed = sel.GetBottomPointY(mePosLogical);
var ac = sel.GetActivePointY(mePosLogical);
if (st != ed && sel.GetBottomPointX(mePosLogical) == 1) {
// 複数行選択、最下行選択位置が行頭の場合は、最終行は除外
ed--;
}
var tab = GetTabSpace();
sel.SetActivePoint(mePosLogical, doc.GetLine(ed, meGetLineLogical).length + 1, ed);
sel.SetAnchorPoint(mePosLogical, 1, st);
var lines = sel.Text.split("\n");
if (sel.Text.length > 0) {
sel.Untabify();
}
var linesWithoutTab = sel.Text.split("\n");
if (sel.Text.length > 0) {
doc.Undo();
}
// インデント取得
var indent = -1;
var existNotCommentLine = false; // 空白・コメント行でない行が存在するか
for (var i = 0, len = linesWithoutTab.length; i < len; i++) {
var line = linesWithoutTab[i];
var left = line.search(/[^ ]/);
if (left >= 0 && (indent < 0 || left < indent)) {
// インデントはタブ幅単位(左寄せ)
indent = Math.floor(left / tab) * tab;
}
if (left >= 0) {
// コメント行判定
if (!existNotCommentLine && line.search(regTrim) == -1) {
existNotCommentLine = true;
}
}
}
var txt = "";
var changed = false;
if (existNotCommentLine) {
// コメントアウト
for (var i = 0, len = lines.length; i < len; i++) {
var line = lines[i] + "\n";
// 空白行はコメントアウトしない
if (line.search(/[^ \t\n]/) == -1) {
txt += line;
continue;
}
// 挿入位置をタブと空白を考慮して決定
var index = 0, j;
for (j = 0; index < indent; j++) {
// indent の範囲には半角スペースかタブしかない
if (line.charAt(j) == " ") {
index += 1;
} else {
index += tab - (index % tab);
}
}
txt += line.substring(0, j) + comSelected + line.substring(j);
changed = true;
}
} else {
// コメントから復帰
for (var i = 0, len = lines.length; i < len; i++) {
var line = lines[i] + "\n";
if (line.match(regTrim)) {
if (line.match(regOrg)) {
txt += line.replace(comSelected, ""); // 先頭のコメント(空白付き)の削除
} else {
txt += line.replace(comTrim, ""); // 先頭のコメント(空白なし)の削除
}
changed = true;
} else {
txt += line;
}
}
}
// コメントアウト部分を書き換えて、全体を選択
if (doc.GetLine(ed + 1, meGetLineWithNewLines) == "") {
txt = txt.substring(0, txt.length - 1); // 最後の改行は除去
}
if (ac == st) {
// 下から上への選択状態
sel.SetActivePoint(mePosLogical, 1, st);
sel.SetAnchorPoint(mePosLogical, 1, ed + 1);
if (changed) {
sel.Text = txt;
}
sel.SetActivePoint(mePosLogical, 1, st);
sel.SetAnchorPoint(mePosLogical, 1, ed + 1);
} else {
// 上から下への選択状態
sel.SetActivePoint(mePosLogical, 1, ed + 1);
sel.SetAnchorPoint(mePosLogical, 1, st);
if (changed) {
sel.Text = txt;
}
sel.SetAnchorPoint(mePosLogical, 1, st);
}
window.ScrollY = scrollY;
}
}
//========================================
// 関数
//========================================
// タブ幅を取得
function GetTabSpace() {
var doc = editor.ActiveDocument;
var sel = doc.Selection;
var saved = doc.Saved;
sel.EndOfDocument();
doc.Write("\n\t");
sel.SetAnchorPoint(mePosLogical, sel.GetActivePointX(mePosLogical) - 1, sel.GetActivePointY(mePosLogical));
sel.Untabify();
var n = sel.Text.length;
doc.Undo();
doc.Undo();
doc.Saved = saved;
return n;
}
Ver 3.0.0未満[編集]
以下は、Mery Ver 3.0.0未満の環境でも利用できます(3.0.0以降でも動作しますが、上のバージョンの利用をお勧めします)。
#icon = "_Comment.ico"
#title = "選択行コメントアウト"
// -----------------------------------------------------------------------------
// Eclipse風なコメントアウト
// 複数行一括コメントアウト、復帰マクロ
// 1) 対象は行全体(行途中の選択も行全体とみなす)
// 2) 空白行はコメントアウトしない
// 3) インデントは選択行の範囲で一番左(タブ幅単位)に合わせる
// 4) 選択範囲全体がコメントアウトされている場合は復帰
//
// Copyright (c) ks. All Rights Reserved.
// www: http://merysmacro.seesaa.net/
// -----------------------------------------------------------------------------
// a) 最終行の先頭までの選択状態では、最終行は処理範囲外にする(行選択対応)
// b) コメント文字の種類を追加(Mery標準で単一行コメント可能な編集モード全て対応)
// c) スペースが含まれるコメント文字に対応
// d) コメント文字が正規表現文字でも正しく動作するようにした
// e) コメント文字不明時、SHIFTキー押下起動時はコメント文字を入力できるようにした
// (Mery.iniと同じ場所に設定ファイルとして一時記憶)
// f) 選択方向を維持するようにした(下から上への選択対応)
// g) 空白行で実行するとUndoされてしまう問題に対処
// h) OutputBarにフォーカスがある場合に処理できない問題に対処
//
// SHIFTキー状態取得のために、"GetKeyState.exe"が必要です
//
// Improved by pizz
// -----------------------------------------------------------------------------
var doc = editor.ActiveDocument;
var COM = ""; // 単一行コメント
var settingFilename = "_CommentMacro.ini";
switch (doc.Mode.toLowerCase()) {
case "bat":
COM = "rem ";
break;
case "c#":
case "c++":
case "coldfusion":
case "delphi":
case "java":
case "javascript":
case "jsp":
case "php":
case "uwsc":
COM = "// ";
break;
case "hsp":
case "ini":
case "x86 assembler":
COM = "; ";
break;
case "perl":
case "perlscript":
case "powershell":
case "python":
case "rhtml":
case "ruby":
COM = "# ";
break;
case "sql":
COM = "-- ";
break;
case "tex":
COM = "% ";
break;
case "vbscript":
case "visualbasic":
COM = "'";
break;
}
var wshShell = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");
// カレントディレクトリをマクロディレクトリに変更
wshShell.CurrentDirectory = editor.FullName.match(/^.*\\/)[0] + 'Macros';
// 設定ファイルからコメント文字を読み込む
var comSelected = LoadDocSetting();
if (comSelected != null) {
if (comSelected == "") {
comSelected = COM;
}
var comTrim = comSelected.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字
// SHIFTキー状態を取得
var shift = wshShell.Run("GetKeyState.exe shift", 0, true);
if (shift != -1) {
// コメント文字の入力を受ける
if (comTrim == "" || shift == 1) {
var comInput = "// ";
if (comTrim != "") {
comInput = comSelected;
}
comInput = prompt("コメント文字を指定してください", comInput);
comTrim = comInput.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字
if (comTrim != "") {
if (comInput != comSelected) {
SaveDocSetting(comInput);
comSelected = comInput;
}
}
}
if (comTrim != "") {
var meGetLineLogical = 0;
var regOrg = new RegExp("^[ \\t]*" + comSelected.replace(/\W/g, "\\$&"));
var regTrim = new RegExp("^[ \\t]*" + comTrim.replace(/\W/g, "\\$&"));
var scrollY = window.ScrollY;
var sel = doc.Selection;
var st = sel.GetTopPointY(mePosLogical);
var ed = sel.GetBottomPointY(mePosLogical);
var ac = sel.GetActivePointY(mePosLogical);
if (st != ed && sel.GetBottomPointX(mePosLogical) == 1) {
// 複数行選択、最下行選択位置が行頭の場合は、最終行は除外
ed--;
}
var tab = GetTabSpace();
sel.SetActivePoint(mePosLogical, doc.GetLine(ed, meGetLineLogical).length + 1, ed);
sel.SetAnchorPoint(mePosLogical, 1, st);
var lines = sel.Text.split("\n");
if (sel.Text.length > 0) {
sel.Untabify();
}
var linesWithoutTab = sel.Text.split("\n");
if (sel.Text.length > 0) {
doc.Undo();
}
// インデント取得
var indent = -1;
var existNotCommentLine = false; // 空白・コメント行でない行が存在するか
for (var i = 0, len = linesWithoutTab.length; i < len; i++) {
var line = linesWithoutTab[i];
var left = line.search(/[^ ]/);
if (left >= 0 && (indent < 0 || left < indent)) {
// インデントはタブ幅単位(左寄せ)
indent = Math.floor(left / tab) * tab;
}
if (left >= 0) {
// コメント行判定
if (!existNotCommentLine && line.search(regTrim) == -1) {
existNotCommentLine = true;
}
}
}
var txt = "";
var changed = false;
if (existNotCommentLine) {
// コメントアウト
for (var i = 0, len = lines.length; i < len; i++) {
var line = lines[i] + "\n";
// 空白行はコメントアウトしない
if (line.search(/[^ \t\n]/) == -1) {
txt += line;
continue;
}
// 挿入位置をタブと空白を考慮して決定
var index = 0, j;
for (j = 0; index < indent; j++) {
// indent の範囲には半角スペースかタブしかない
if (line.charAt(j) == " ") {
index += 1;
} else {
index += tab - (index % tab);
}
}
txt += line.substring(0, j) + comSelected + line.substring(j);
changed = true;
}
} else {
// コメントから復帰
for (var i = 0, len = lines.length; i < len; i++) {
var line = lines[i] + "\n";
if (line.match(regTrim)) {
if (line.match(regOrg)) {
txt += line.replace(comSelected, ""); // 先頭のコメント(空白付き)の削除
} else {
txt += line.replace(comTrim, ""); // 先頭のコメント(空白なし)の削除
}
changed = true;
} else {
txt += line;
}
}
}
// コメントアウト部分を書き換えて、全体を選択
if (doc.GetLine(ed + 1, meGetLineWithNewLines) == "") {
txt = txt.substring(0, txt.length - 1); // 最後の改行は除去
}
if (ac == st) {
// 下から上への選択状態
sel.SetActivePoint(mePosLogical, 1, st);
sel.SetAnchorPoint(mePosLogical, 1, ed + 1);
if (changed) {
sel.Text = txt;
}
sel.SetActivePoint(mePosLogical, 1, st);
sel.SetAnchorPoint(mePosLogical, 1, ed + 1);
} else {
// 上から下への選択状態
sel.SetActivePoint(mePosLogical, 1, ed + 1);
sel.SetAnchorPoint(mePosLogical, 1, st);
if (changed) {
sel.Text = txt;
}
sel.SetAnchorPoint(mePosLogical, 1, st);
}
window.ScrollY = scrollY;
}
}
}
//========================================
// 関数
//========================================
// タブ幅を取得
function GetTabSpace() {
var doc = editor.ActiveDocument;
var sel = doc.Selection;
var saved = doc.Saved;
sel.EndOfDocument();
doc.Write("\n\t");
sel.SetAnchorPoint(mePosLogical, sel.GetActivePointX(mePosLogical) - 1, sel.GetActivePointY(mePosLogical));
sel.Untabify();
var n = sel.Text.length;
doc.Undo();
doc.Undo();
doc.Saved = saved;
return n;
}
// コメント文字設定をファイルから読み込み
function LoadDocSetting() {
var dic = LoadDocSettingDataListWithOpend();
if (dic == null) {
return null;
}
var ret = "";
for (var key in dic) {
if (key.toLowerCase() == window.document.FullName.toLowerCase()) {
ret = dic[window.document.FullName.toLowerCase()];
}
}
return ret;
}
// コメント文字設定をファイルに書き込み
function SaveDocSetting(comStr) {
var dic = LoadDocSettingDataListWithOpend();
if (dic != null) {
dic[window.document.FullName.toLowerCase()] = comStr;
SaveDocSettingDataListWithOpend(dic);
}
}
// 設定ファイルから全ての設定値を取得
function LoadDocSettingDataListWithOpend() {
var settingPath = GetSettingFilePath();
if (settingPath == "") {
return null;
}
var dic = {};
var deleted = false;
if (fso.FileExists(settingPath)) {
var tso = fso.OpenTextFile(settingPath, 1, false, -1);
while (tso.AtEndOfStream == false) {
var setting = tso.ReadLine().split("\t", 2);
var detect = false;
for (var i = 0; i < window.Editors.Count; i++) {
for (var j = 0; j < window.Editors.Item(i).Documents.Count; j++) {
if (window.Editors.Item(i).Documents.Item(j).FullName.toLowerCase() ==
setting[0].toLowerCase()) {
dic[setting[0].toLowerCase()] = setting[1];
detect = true;
break;
}
}
if (detect) {
break;
}
}
if (detect == false) {
deleted = true;
}
}
tso.Close();
}
if (deleted) {
SaveDocSettingDataListWithOpend(dic);
}
return dic;
}
// 設定ファイルを全て書き換え
function SaveDocSettingDataListWithOpend(dic) {
var settingPath = GetSettingFilePath();
if (settingPath != "") {
var tso = fso.OpenTextFile(settingPath, 2, true, -1);
for (var key in dic) {
tso.WriteLine(key + "\t" + dic[key]);
}
tso.Close();
}
}
// コメント文字設定ファイルの場所を取得する
function GetSettingFilePath() {
var meryDir = fso.GetParentFolderName(editor.FullName);
var settingPath = "";
if (fso.FileExists(fso.BuildPath(meryDir, "Mery.ini"))) {
settingPath = fso.BuildPath(meryDir, settingFilename);
} else {
var appDataPath = fso.BuildPath(wshShell.SpecialFolders('Appdata'), 'Mery');
if (fso.FileExists(fso.BuildPath(appDataPath, "Mery.ini"))) {
settingPath = fso.BuildPath(appDataPath, settingFilename);
}
}
if (settingPath == "") {
window.Alert("Mery.ini ファイルが見つかりません");
}
return settingPath;
}
スポンサーリンク