「Eclipse風コメントアウト(改)」の版間の差分

提供:MeryWiki
ナビゲーションに移動 検索に移動
編集の要約なし
(2人の利用者による、間の5版が非表示)
20行目: 20行目:
= 更新履歴 =
= 更新履歴 =
2019/3/4 新規作成
2019/3/4 新規作成
2019/4/12 window.Quit() メソッドの使用排除
2020/3/15 Mery 3.0.0以降対応版の追加(document.tagプロパティを使用)


= コード =
= コード =
このスクリプトはMery Ver.3.0.0以降対応版です
Mery Ver.3.0.0未満の環境では、後半のスクリプトを利用してください
<source lang="javascript">
<source lang="javascript">
#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;
}
</source>
以下は、Mery Ver.3.0.0未満の環境でも利用できます
(3.0.0以降でも動作しますが、上のバージョンの利用をお勧めします)
<source lang="javascript">
#icon = "_Comment.ico"
#title = "選択行コメントアウト"
#title = "選択行コメントアウト"


53行目: 294行目:
var doc = editor.ActiveDocument;
var doc = editor.ActiveDocument;
var COM = ""; // 単一行コメント
var COM = ""; // 単一行コメント
var settingFilename = "CommentMacro.ini";
var settingFilename = "_CommentMacro.ini";


switch(doc.Mode.toLowerCase()){
switch(doc.Mode.toLowerCase()){
103行目: 344行目:
// 設定ファイルからコメント文字を読み込む
// 設定ファイルからコメント文字を読み込む
var comSelected = LoadDocSetting();
var comSelected = LoadDocSetting();
if(comSelected == "") comSelected = COM;
if(comSelected != null){
  if(comSelected == "") comSelected = COM;


var comTrim = comSelected.replace(/(^\s+)|(\s+$)/g, "");  // スペースなしのコメント文字
  var comTrim = comSelected.replace(/(^\s+)|(\s+$)/g, "");  // スペースなしのコメント文字


// SHIFTキー状態を取得
  // SHIFTキー状態を取得
var shift = wshShell.Run("GetKeyState.exe shift", 0, true);
  var shift = wshShell.Run("GetKeyState.exe shift", 0, true);
if(shift == -1) window.Quit();


// コメント文字の入力を受ける
  if(shift != -1){
if(comTrim == "" || shift == 1){
    // コメント文字の入力を受ける
  var comInput = "// ";
    if(comTrim == "" || shift == 1){
  if(comTrim != "") comInput = comSelected;
      var comInput = "// ";
      if(comTrim != "") comInput = comSelected;


  comInput = prompt("コメント文字を指定してください", comInput);
      comInput = prompt("コメント文字を指定してください", comInput);


  comTrim = comInput.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字
      comTrim = comInput.replace(/(^\s+)|(\s+$)/g, ""); // スペースなしのコメント文字
  if(comTrim == "") window.Quit();
      if(comTrim != ""){
        if(comInput != comSelected){
          SaveDocSetting(comInput);
          comSelected = comInput;
        }
      }
    }


  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 meGetLineLogical = 0;
      // インデント取得
var regOrg = new RegExp("^[ \\t]*" + comSelected.replace(/\W/g, "\\$&"));
      var indent = -1;
var regTrim = new RegExp("^[ \\t]*" + comTrim.replace(/\W/g, "\\$&"));
      var existNotCommentLine = false;  // 空白・コメント行でない行が存在するか
var scrollY = window.ScrollY;
      for(var i=0, len = linesWithoutTab.length; i < len; i++){
var sel = doc.Selection;
        var line = linesWithoutTab[i];
var st = sel.GetTopPointY(mePosLogical);
        var left = line.search(/[^ ]/);
var ed = sel.GetBottomPointY(mePosLogical);
        if(left >= 0 && (indent < 0 || left < indent)){
var ac = sel.GetActivePointY(mePosLogical);
          // インデントはタブ幅単位(左寄せ)
if(st != ed && sel.GetBottomPointX(mePosLogical) == 1){
          indent = Math.floor(left / tab) * tab;
  // 複数行選択、最下行選択位置が行頭の場合は、最終行は除外
        }
  ed--;
        if(left >= 0){
}
          // コメント行判定
var tab = GetTabSpace();
          if(!existNotCommentLine && line.search(regTrim) == -1){
            existNotCommentLine = true;
          }
        }
      }


sel.SetActivePoint(mePosLogical, doc.GetLine(ed, meGetLineLogical).length + 1, ed);
      var txt = "";
sel.SetAnchorPoint(mePosLogical, 1, st);
      var changed = false;
var lines = sel.Text.split("\n")
      if(existNotCommentLine){
if(sel.Text.length > 0) sel.Untabify();
        // コメントアウト
var linesWithoutTab = sel.Text.split("\n");
        for(var i = 0, len = lines.length; i < len; i++){
if(sel.Text.length > 0) doc.Undo();
          var line = lines[i] + "\n";
          // 空白行はコメントアウトしない
          if(line.search(/[^ \t\n]/) == -1){
            txt += line;
            continue;
          }


// インデント取得
          // 挿入位置をタブと空白を考慮して決定
var indent = -1;
          var index = 0, j;
var existNotCommentLine = false;  // 空白・コメント行でない行が存在するか
          for(j = 0; index < indent; j++){
for(var i=0, len = linesWithoutTab.length; i < len; i++){
            // indent の範囲には半角スペースかタブしかない
  var line = linesWithoutTab[i];
            if(line.charAt(j) == " "){
  var left = line.search(/[^ ]/);
              index += 1;
  if(left >= 0 && (indent < 0 || left < indent)){
            }else{
    // インデントはタブ幅単位(左寄せ)
              index += tab - (index % tab);
    indent = Math.floor(left / tab) * tab;
            }
  }
          }
  if(left >= 0){
          txt += line.substring(0, j) + comSelected + line.substring(j);
    // コメント行判定
          changed = true;
    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{
       }else{
         index += tab - (index % tab);
         // コメントから復帰
        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;
          }
        }
       }
       }
    }
 
    txt += line.substring(0, j) + comSelected + line.substring(j);
      // コメントアウト部分を書き換えて,全体を選択
    changed = true;
      if(doc.GetLine(ed + 1, meGetLineWithNewLines) == "") txt = txt.substring(0, txt.length - 1); // 最後の改行は除去
  }
      if(ac == st){
}else{
        // 下から上への選択状態
  // コメントから復帰
        sel.SetActivePoint(mePosLogical, 1, st);
  for(var i = 0, len = lines.length; i < len; i++){
        sel.SetAnchorPoint(mePosLogical, 1, ed + 1);
    var line = lines[i] + "\n";
        if(changed) sel.Text = txt;
    if(line.match(regTrim)){
        sel.SetActivePoint(mePosLogical, 1, st);
      if(line.match(regOrg)){
         sel.SetAnchorPoint(mePosLogical, 1, ed + 1);
         txt += line.replace(comSelected, ""); // 先頭のコメント(空白付き)の削除
       }else{
       }else{
         txt += line.replace(comTrim, ""); // 先頭のコメント(空白なし)の削除
         // 上から下への選択状態
        sel.SetActivePoint(mePosLogical, 1, ed + 1);
        sel.SetAnchorPoint(mePosLogical, 1, st);
        if(changed) sel.Text = txt;
        sel.SetAnchorPoint(mePosLogical, 1, st);
       }
       }
       changed = true;
       window.ScrollY = scrollY;
    }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;


//========================================
//========================================
254行目: 497行目:
{
{
   var dic = LoadDocSettingDataListWithOpend();
   var dic = LoadDocSettingDataListWithOpend();
  if(dic == null) return null;
   var ret = "";
   var ret = "";
   for(var key in dic){
   for(var key in dic){
267行目: 511行目:
{
{
   var dic = LoadDocSettingDataListWithOpend();
   var dic = LoadDocSettingDataListWithOpend();
   dic[window.document.FullName.toLowerCase()] = comStr;
   if(dic != null){
  SaveDocSettingDataListWithOpend(dic);
    dic[window.document.FullName.toLowerCase()] = comStr;
    SaveDocSettingDataListWithOpend(dic);
  }
}
}


275行目: 521行目:
{
{
   var settingPath = GetSettingFilePath();
   var settingPath = GetSettingFilePath();
  if(settingPath == "") return null;
   var dic = {};
   var dic = {};
   var deleted = false;
   var deleted = false;
   if(fso.FileExists(settingPath)){
   if(fso.FileExists(settingPath)){
305行目: 552行目:
{
{
   var settingPath = GetSettingFilePath();
   var settingPath = GetSettingFilePath();
   var tso = fso.OpenTextFile(settingPath, 2, true, -1);
   if(settingPath != ""){
  for(var key in dic){
    var tso = fso.OpenTextFile(settingPath, 2, true, -1);
    tso.WriteLine(key + "\t" + dic[key]);
    for(var key in dic){
      tso.WriteLine(key + "\t" + dic[key]);
    }
    tso.Close();
   }
   }
  tso.Close();
}
}


328行目: 577行目:
   if(settingPath == ""){
   if(settingPath == ""){
     window.Alert("Mery.ini ファイルが見つかりません");
     window.Alert("Mery.ini ファイルが見つかりません");
    window.Quit();
   }
   }
   return settingPath;
   return settingPath;
}
}
</source>
</source>

2020年3月15日 (日) 16:33時点における版

概要

Eclipse風なコメントアウト <=> コメントの除去を行います。

ksさんの作成された、Eclipse風コメントアウトは、私にとって欠かせないツールです。

便利に使わせていただく一方、細かい挙動が気になって変更したり、機能を追加しているうちに、すっかり別物になってしまいました。

オリジナルを作成されたksさんに感謝するとともに、せっかく作成したので改造版をここに公開します。


Shiftキーの状態を取得するために、GetKeyState.exe(キー状態取得実行ファイル)を使用しています。

本体マクロと併せて上記実行ファイルも必要になります。

zipファイルをダウンロードしたら、ファイルのプロパティ画面で「ブロックの解除」を行ってください。 (これをしないと実行時に警告が表示されることがあります)

その後、zipファイルを展開して、Macrosフォルダーに配置してください。

更新履歴

2019/3/4 新規作成

2019/4/12 window.Quit() メソッドの使用排除

2020/3/15 Mery 3.0.0以降対応版の追加(document.tagプロパティを使用)

コード

このスクリプトはMery Ver.3.0.0以降対応版です Mery 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;
}


以下は、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;
}
スポンサーリンク