コメントマーク付け外し

提供: MeryWiki
2020年6月28日 (日) 15:50時点におけるSukemaru (トーク | 投稿記録)による版 (sukemaru 版: マルチカーソル対応。ZIP 書庫を更新)
ナビゲーションに移動 検索に移動

手石 版 (2014/03)

コメントマークの付け外しをするマクロです。
js 以外の拡張子に対応させる時は、最後の関数に追加してください。

更新履歴

  • 2013/03/28
    • 無題のときに対応しました。
  • 2014/03/22
    • できるだけ短くしてみました。

ソースコード

// コメントマーク.js
// 行頭コメントマークを付けたり外したり。
// 空白文字の後ろにあっても外す。つけるときは行頭に。

var sel = Editor.ActiveDocument.Selection;
var ty = sel.GetTopPointY( mePosLogical );
var bx = sel.GetBottomPointX( mePosLogical );
var by = sel.GetBottomPointY( mePosLogical );
if ( bx == 1 && ty != by ){ by--; };
sel.SetActivePoint( mePosLogical, 1, ty, false );
sel.SetActivePoint( mePosLogical, 1, by+1, true );

var mark = commentMark();
var reg = new RegExp( "^([ \t]*" + mark + "\\s?)?(?=.)", "mg" );
mark += " ";

sel.Text = sel.Text.replace( reg, function( s0, s1 ){ return ( s1 == undefined )? mark : "" } );

function commentMark(){
	switch( Document.Mode.toLowerCase() ){
	case "text" : return "//";
	case "javascript" : return "//";
	case "tex" : return "%";
	case "ruby" : return "#";
	default : return Prompt( "コメントマーク?", "//");
	};
};

masme 版

マクロ「テキスト整形」の「行頭 // を挿入/削除」を独立・改造したものです。
論理行頭にコメント文字が有れば削除(アンコメント)し、無ければ挿入(コメントアウト)します。

  • 空白行(改行/半角空白/水平タブのみの行)はコメントアウトしないようにしました。
  • 初期設定では、インデントされたコメント文字には対応していません。
    「indent」変数を「false」から「true」に書き換えると、手石 版のように行頭空白後のコメント文字も削除するようになります。
    インデントへの対応は、手石 版と同様に削除限定です。挿入するときは論理行頭になります。
  • 編集モードによる定義切替は、マクロ「Eclipse風コメントアウト」を参考にしました。

更新履歴

2019/06/01
  • コメント文字を付け外しした次の行に変更行の印がつかないようにした。
    末尾の改行(次の行頭)を範囲に含めず書き換えるように変更。
2016/02/28
  • 編集モードによる定義切替が正常に機能していないミスを修正。
2015/02/14
  • 特殊文字があると誤動作する不具合を再修正。
2015/02/14
  • 「行コメント文字の定義」に正規表現の特殊文字があると誤動作する不具合を修正。
  • 矩形選択(始点or終点が左下かつ論理行頭)時、下端の行が範囲から漏れる不具合を修正。
  • テキストの処理方法を変更。
2014/02/22
  • 初版公開。

ソースコード

//■行コメントのアン・アウト
// 2014/02/11-2019/06/01
//・行頭にコメント文字が有れば削除し、無ければ挿入する。空白行には挿入しない。

//■行コメント文字の定義 ●初期値="//"
var comment = "//";
//■インデントされたコメント文字も削除(true:する/false:しない) ●初期値=false
var indent = false ? "[ \t]*" : "";

//▼編集モードによる定義切替
comment = (function(){
  switch (Document.Mode.toLowerCase()) {
  case "bat":
    return "::";
  case "c#":
  case "c++":
  case "javascript":
    return "//";
  case "ini":
  case "python":
  case "ruby":
    return "#";
  case "visualbasic":
  case "vbscript":
    return "'";
  default:
    return comment;
  }
}());

var Sel = Document.Selection;
var ty = Sel.GetTopPointY(mePosLogical);
var by = Sel.GetBottomPointY(mePosLogical);
var bx = Sel.GetBottomPointX(mePosLogical);
var nn =(Sel.Text.match(/\n/g)||[]).length;
if (bx===1 && nn<=by-ty && nn) by--; //末尾改行対策
Sel.SetActivePoint(mePosLogical, 1, by);
Sel.EndOfLine(false, mePosLogical);
Sel.SetAnchorPoint(mePosLogical, 1, ty);
Sel.Text = Sel.Text.replace(new RegExp(
  "^("+indent+")"+comment.replace(/[$()*+.?[\\\]^{|}]/g,"\\$&"); //コメント行
 +"|^(?![ \t]*$)" ,"gm") //空白行でない行頭
 ,function($0,$indent){return $0 ? $indent : comment}
);
Sel.SetActivePoint(mePosLogical,1,by+1);
Sel.SetAnchorPoint(mePosLogical,1,ty);

sukemaru 版

「行コメント」マクロ (コメントマーク付けはずし sukemaru版)

ダウンロード >> 「行コメント.zip」(アイコン入り) 最終更新 2020/06/28

マルチカーソル/複数選択範囲に対応




masme 版の設定用変数 indent = true の状態(インデントされたコメントマークを削除できる)を下地として、インデントされた行の字下げ位置にあわせてコメントアウト できるようにしました。
選択範囲内のもっとも字下げの少ない位置にあわせてコメントマークを付けられるので、コードブロックのコメントアウトのさいに各行の先頭位置が少しだけ分かりやすくなります。

  • 空白行(タブ文字/半角スペースのみの行と、完全な空行)は無視します。
  • 編集モードによるコメントマーク定義の切り替えは、masme版 (2016/02/28) のコードを翻案しています。
  • 設定変数 comment の定義に ">" などの引用マークを指定すると、引用マークの付けはずしにも利用できます。


「コメントアウトするときは // コメント  や > コメント のように コメントマークのうしろに半角スペース を入れたいけれど、拾い物のコード内やコピペした文章内の 半角スペースなしのコメント行 //コメント や >コメント も手軽にアンコメントしたい」という使い方も想定しています。

  • コメントマークの定義の末尾に「半角スペース×1」がついている状態をデフォルト状態にしてあります(初期値も編集モードごとの個別定義も)。


選択範囲が1行内の場合は、選択範囲の先頭位置で コメントアウト/アンコメント できますので、行の途中からのインラインコメントアウトができます(設定項目 var inLineEnable = true; の場合。※ 初期値 true)。

  • 選択範囲の先頭が空白文字なら字下げオプションに準じて処理します。
  • 行の途中から1行内の // インラインコメント部分 を範囲選択している状態で Ctrl キーを押しながらマクロを実行した場合は、選択範囲の先頭のコメントマークを削除します(アンコメント)。


このマクロは、pizz 氏作成の「GetKeyState.exe(キー状態取得実行ファイル)」で機能を拡張できます。
マクロライブラリから ZIP ファイルをダウンロードして Mery\Macros フォルダに実行ファイル GetKeyState.exe を配置してください。

Ctrl キー を押しながら実行したときは、コメントアウト状態の反転ではなく、選択範囲をふくむ行全体を 強制的にコメントアウト します。

  • // コメント行 を含むコードブロックをまとめてコメントアウトするさいに、既存の // コメント行 を // // 二重にコメントアウト できます。
  • 強制コメントアウトでコメントマークを挿入する位置は、基本的に 行頭 に限定されます(字下げ位置を考慮しない)。
※ 設定項目 var inLineEnable = true; の場合は、選択範囲が1行内のときに選択範囲の先頭位置で強制コメントアウト(インライン)します。
  • 空行にもコメントマークを挿入できます。
  • 「GetKeyState.exe」を導入している場合、Ctrl キーの押し下げ状態でマクロの機能を切り替えるので、このマクロに ショートカットキー を割り当てる場合は、「Ctrl キーをふくむキーパターン」と「Ctrl キーをふくまないキーパターン」の2つを登録する必要があります。
e.g.1 「Ctrl + /」キー と 「Alt + /」キー
e.g.2 「Ctrl + Alt + /」キー と 「Alt + /」キー
※ ツールバーアイコンやメニューから実行するときも、Ctrl キーを押し下げながらのクリックにより "強制コメントアウトモード" になります。
  • 「GetKeyState.exe」を導入してない場合でも、"強制コメントアウト" 以外の機能はそのまま使用できます。


ブックマーク行のある文書/選択範囲でこのマクロを実行しても ブックマークを保持 します(2019/11/10)。

  • Mery ver 2.8.6 以降でブックマークを正常に保持できることを確認してあります。
それ以前のバージョンでは、Mery 本体側のブックマーク機能の仕様が安定していないので、ブックマークを正しく復元できないことがあります。


マルチカーソル/複数選択範囲」に対応(2020/06/28)。

  • Mery ver 3.0.1 以降で「マルチカーソル/複数選択範囲」での動作確認をしてあります。
※ それぞれの選択範囲ごとに、それぞれの選択範囲の行数に応じて、「インラインコメントアウト/アンコメント」と「字下げオプションに応じた行頭コメントアウト/アンコメント」の動作をします。


注意事項 (仕様上の制限) ▼

  • 動作モードの優先順位
1. Ctrl キーを押しながらの強制コメントアウト(行の先頭で強制コメントアウト)
2. インラインコメントアウト/アンコメント(1行内で行の途中からのコメントアウト)
3. 字下げオプションに応じたコメントアウト/アンコメントのトグル(反転)
  • 字下げルールが「半角スペースのみ または タブ文字のみである」か、混在する場合には「半角スペースとタブ文字の出現順序が同じである」という前提になっています。タブ文字ひとつを半角スペースひとつと同じように数え、表示上の幅で評価しません。
半角スペースとタブ文字が不規則に混在しているなら、字下げオプションの変数を indentMode = 0 または indentMode = 1 にして使ってください。手石・masme版と同様に行の先頭でコメントアウトします。
  • "GetKeyState" を導入しない場合は、コメントアウトの状態を反転させるだけのマクロとなり、// コメントアウトされている行 を二重にコメントアウトすることはできません。
字下げオプションの設定値が 0 でも、行頭1文字目にコメントマークがある行は、かならずアンコメントされます。
cf. 「Eclipse風コメントアウト」「Eclipse風コメントアウト(改)」マクロ
  • コメントマークの定義が ">" または ">" のときに、行頭が 「>>」 の行で連続実行すると、以下のように作用します。
  • 1回目: さいしょの ">" を削除 (アンコメント)
  • 2回目: つぎの ">" または ">" を削除 (アンコメント)
  • 3回目: 先頭に ">" または ">" を追加 (コメントアウト)
この場合、連続で実行しても アンコメント/コメントアウト トグルによる元の状態への復元はできません。
  • コメントマーク定義の末尾につける空白は半角スペース1文字しか想定していません。
  • コメント定義の先頭には空白文字をつけないでください。
行コメント文字の変数 var comment = "hoge"; の先頭が空白文字だとアンコメントできなくなるので、先頭の空白文字は無視します。


使用例

※コメントマークの定義文字列: "//"

例0-1. 字下げに非対応だと…

※ indentMode = 0; varEnable = false; のばあい
//comment 0     =>  |// //comment 0     =>  |//comment 0   
// comment 1    =>  |comment 1          =>  |// comment 1  
  // comment 2  =>  |//  // comment 2   =>  |  // comment 2

例0-2. 字下げには非対応でも…

※ indentMode = 0; varEnable = true; (sukemaru版 独自拡張)
//comment 0     =>  |comment 0          =>  |// comment 0  
// comment 1    =>  |comment 1          =>  |// comment 1  
  // comment 2  =>  |//  // comment 2   =>  |  // comment 2

例1-1. 6行まとめて選択すると…

※ indentMode = 1; varEnable = false; (従来版とおなじ動作)
//comment 0     =>  |// //comment 0     =>  |//comment 0   
// comment 1    =>  |comment 1          =>  |// comment 1  
  // comment 2  =>  |  comment 2        =>  |//   comment 2
  hoge          =>  |//   hoge          =>  |  hoge        
    fuga        =>  |//     fuga        =>  |    fuga      
      piyo      =>  |//       piyo      =>  |      piyo

例1-2. 6行まとめて選択でも…

※ indentMode = 1; varEnable = true; (sukemaru版 独自拡張)
//comment 0     =>  |comment 0          =>  |// comment 0  
// comment 1    =>  |comment 1          =>  |// comment 1  
  // comment 2  =>  |  comment 2        =>  |//   comment 2
  hoge          =>  |//   hoge          =>  |  hoge        
    fuga        =>  |//     fuga        =>  |    fuga      
      piyo      =>  |//       piyo      =>  |      piyo

例2-1. 下3行だけを選択すれば…

※ indentMode = 2 or 3; (sukemaru版 独自拡張)
//comment 0     =>  |//comment 0        =>  |//comment 0   
// comment 1    =>  |// comment 1       =>  |// comment 1  
  // comment 2  =>  |  // comment 2     =>  |  // comment 2
  hoge          =>  |  // hoge          =>  |  hoge        
    fuga        =>  |  //   fuga        =>  |    fuga      
      piyo      =>  |  //     piyo      =>  |      piyo

例2-2. 下4行を選択だと…

※ indentMode = 2 or 3; (sukemaru版 独自拡張)
//comment 0     =>  |//comment 0        =>  |//comment 0   
// comment 1    =>  |// comment 1       =>  |// comment 1  
  // comment 2  =>  |  comment 2        =>  |  // comment 2
  hoge          =>  |  // hoge          =>  |  hoge        
    fuga        =>  |  //   fuga        =>  |    fuga      
      piyo      =>  |  //     piyo      =>  |      piyo

例3. 6行まとめて選択しても、コメントアウトとアンコメントで別々の先頭位置を使うこともできる

※ indentMode = 3; varEnable = true; (sukemaru版 独自拡張)
//comment 0     =>  |comment 0          =>  |// comment 0  
// comment 1    =>  |comment 1          =>  |// comment 1  
  // comment 2  =>  |  comment 2        =>  |//   comment 2
  hoge          =>  |  // hoge          =>  |  hoge        
    fuga        =>  |  //   fuga        =>  |    fuga      
      piyo      =>  |  //     piyo      =>  |      piyo

例4. 一応、こういうこともできる

※ indentMode = 4; varEnable = true; (sukemaru版 独自拡張)
//comment 0     =>  |comment 0          =>  |// comment 0  
// comment 1    =>  |comment 1          =>  |// comment 1  
  // comment 2  =>  |  comment 2        =>  |  // comment 2
  hoge          =>  |  // hoge          =>  |  hoge        
    fuga        =>  |    // fuga        =>  |    fuga      
      piyo      =>  |      // piyo      =>  |      piyo

例5. コードブロックをまとめて強制的にコメントアウトするなら

Ctrl キーを押しながらマクロを実行 (sukemaru版 独自拡張)
//comment 0     =>  |// //comment 0     =>  |//comment 0   
// comment 1    =>  |// // comment 1    =>  |// comment 1  
  // comment 2  =>  |//   // comment 2  =>  |  // comment 2
  hoge          =>  |//   hoge          =>  |  hoge        
   fuga         =>  |//     fuga        =>  |    fuga      
     piyo       =>  |//       piyo      =>  |      piyo


ソースコード

ダウンロードページ >> 「ファイル:行コメント.zip」(アイコン入り)
(最終更新 2020/06/28)

#title = "行コメント"
#tooltip = "コメントマーク付けはずし"
#icon = "double-slash[2].ico"
// #tooltip = "Ctrl: 強制コメントアウト"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",215

var d = editor.ActiveDocument;
var $ctrl = 0;

// Ctrl キーの状態を取得
var gks = editor.FullName.replace( /[^\\]+$/, "" )
        + "Macros\\GetKeyState.exe";
if ( new ActiveXObject( "Scripting.FileSystemObject" ).FileExists( gks ) ) {
  $ctrl = new ActiveXObject( "WScript.Shell" ).Run( '"' + gks + '" ctrl', 0, true );
}

var start = new Date();	// 所要時間計測(開始)

/**
 * --------------------------------------------------------------
 * 「コメントマーク付け外し」マクロ 
 *   Orginal created by 手石 & masme, 2013/03/28 - 2019/06/01 
 * 「行コメント」マクロ (sukemaru版)
 *   Modified by sukemaru, 2018/10/28 - 2020/06/28
 * --------------------------------------------------------------
 * https://www.haijin-boys.com/wiki/コメントマーク付け外し
 * https://www.haijin-boys.com/wiki/%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E3%83%9E%E3%83%BC%E3%82%AF%E4%BB%98%E3%81%91%E5%A4%96%E3%81%97
 * --------------------------------------------------------------
 * ※ このマクロは、以下の外部実行ファイルで機能拡張できます
 * ・pizz 氏作成の "GetKeyState.exe(キー状態取得実行ファイル)" を
 *   マクロライブラリからダウンロードして "Mery\Macros" フォルダに をZIP 解凍
 *  https://www.haijin-boys.com/wiki/GetKeyState.exe(キー状態取得実行ファイル)
 *  https://www.haijin-boys.com/wiki/GetKeyState.exe%28%E3%82%AD%E3%83%BC%E7%8A%B6%E6%85%8B%E5%8F%96%E5%BE%97%E5%AE%9F%E8%A1%8C%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%29
 * --------------------------------------------------------------
 * 2020/06/28: マルチカーソル/複数選択範囲に対応
 */

// ---------- ▼ 設定項目 ▼ ---------- //

// ● 行の途中にある選択範囲をコメントアウトするか?
var inLineEnable = true;	// (※初期値 true )
  /**
   * true  ならインラインコメントアウトする
   *   (選択範囲が1行内のとき、選択範囲の先頭位置でコメントアウト/アンコメント)
   * false ならインラインコメントアウトしない
   *   (各行の先頭位置でコメントアウト/アンコメント)
   */

// ● 字下げされたコメントマークも削除するか?
var mode = 3;	// (※初期値 3 )
  /**
   * mode = 0; なら 追加/削除 する位置は「常に行頭」のみ
   *               (字下げされたコメントマークは削除しない)
   * ※ 1 ~ 4  なら字下げされたコメントマークも削除する。
   *                追加する位置は以下のとおり。
   * mode = 1; なら「常に先頭」にコメントマークを追加する
   *               (例1.の使い方 ※従来版の挿入パターン)
   * ※ 2 ~ 4  なら追加する位置は字下げに対応可。
   * mode = 2; なら追加と削除で同じ判定基準の先頭位置検出をする
   *               (例2.の使い方ができる)
   * mode = 3; なら追加と削除で別々の判定基準の先頭位置検出をする(例3.の使い方)
   * mode = 4; なら「常に各行の字下げ位置」にあわせてコメントマークを追加する
   *               (例4.の使い方)
   */


// ■ 行コメント文字の定義  (※初期値  "// " )
var comment = "// ";
  /**
   * ※ コメントマークの定義に "末尾空白" ありがデフォルト
   * 「var comment = "> ";」にするか、下の定義切替ブロックに
   * 「case "text":  return "> ";」を追加すると、引用マークの付けはずしにもなる
   */

// ◆ コメントマーク末尾に空白つきで定義しているときに、末尾空白のないコメントマークも削除するか?
var varEnable = true;	// (※初期値 true )
  /**
   * ※ comment = "// ";  のときに  "//こういうコメント行"  もアンコメントするか?
   * varEnable = true  なら削除する
   * varEnable = false なら削除しない
   * ※ 再度コメントアウトするさいは comment で定義したコメントマーク(末尾空白つき)になる。
   *   コメントマーク comment を末尾に空白なしで定義した場合は無視する。
   */


// ▼ コメントマークの定義切替  ▼
comment = ( function( comment, d ) {

  // ▼ 拡張子による定義切り替え ▼
  if ( /\.def$|\.asm$|\.reg$|\.key$|\.inf$/i.test( d.Name ) ) {
    return "; ";
  }

  // ▼ ファイル名による定義切り替え ▼
  else if ( /^hosts$/i.test( d.Name ) ) {
    return "# ";
  }

  // // ▼ ファイル名による定義切り替え ▼
  // else if ( d.Name.toLowerCase() == "hoge.txt" ) {
  //   return "> ";
  // }

  // // ▼ フォルダ名による定義切り替え(正規表現) ▼
  // else if ( /\\mery\\(?!macros\\)/i.test( d.FullName ) ) {
  //   return "> ";
  // }

  // ▼ 編集モードによる定義切り替え ▼
  else {
    switch ( d.Mode.toLowerCase() ) {
      case "text":
        return "> ";
      case "bat":
        return ":: ";	// return "REM ";	// ": " や "' " でも可
      case "c#":  case "c++":  case "delphi":  case "java":
      case "javascript":  case "jsp":  case "windows script": 
      case "mery_macro_js":  case "mery_macros_js": 
      case "mery macro js":  case "mery macros js":  
      case "janestyle (正規表現用)":
        return "// ";
      case "ini":  case "mery msy":
        return "# ";
      case "perl":  case "perlscript":  case "php":  
      case "python":  case "ruby":   case "powershell":
      case "ini":  case "mery msy":		// ini は "; " でも可
        return "# ";
      case "visualbasic":  case "vbscript":
        return "' ";
      case "hsp":  case "autohotkey":
        return "; ";
      case "sql":
        return "-- ";
      case "tex":
        return "% ";
      default:
        return comment;
    }
  }

} )( comment, d ) || "// ";

// ---------- ▲ 設定項目 ▲ ---------- //


// ドキュメントが書き換え禁止なら終了
if ( d.ReadOnly ) {
  Status = " ドキュメントは書き換え禁止です。";
}
// コメントマークが空白文字だけなら終了
else if ( /^\s*$/.test( comment ) ) {
  Status = " コメントマークの定義が無効です。";
}

else {
  var cmStr = "";

  // コメントマークの先頭の空白文字を除去
  comment = comment.replace( /^\s+/, "" );
  // コメントマークの末尾が空白文字の場合、末尾空白なしのコメントマークを定義
  if ( varEnable && /\s+$/.test( comment ) ) {
    cmStr = comment.replace( /\s+$/, "" );
  }

  var s = d.selection;
  var sx = ScrollX,  sy = ScrollY;

  // マルチカーソル/複数選択に対応
  // 引数 ※ グローバルスコープ上の変数なので省略可能だけど、一応…
  var arg = [ inLineEnable, mode, varEnable, comment, cmStr, $ctrl, start ];
  // 選択範囲が1つで矩形選択ではないとき
  if ( ! s.Mode || s.Mode === meModeStream ) {
    CommentMacro_Main( arg );
  }
  // 複数行または複数選択のとき
  else {
    BeginUndoGroup();
    AddUndo();
    MultiFunction( CommentMacro_Main, arg );
    EndUndoGroup();
  }

  ScrollX = sx;  ScrollY = sy;
}

/**
 * 関数 CommentMacro_Main( [ inLineEnable, mode, varEnable, comment, cmStr, $ctrl, start ] )
 * 「行コメント」マクロ (sukemaru版)
 */
function CommentMacro_Main( arg ) {
  var inLineEnable = arg[0];
  var mode         = arg[1];
  var varEnable    = arg[2];
  var comment      = arg[3];
  var cmStr        = arg[4];
  var $ctrl        = arg[5];
  var start        = arg[6];

  // 選択範囲
  var d   = editor.ActiveDocument;
  var s   = editor.ActiveDocument.selection;
  var tx  = s.GetTopPointX( mePosLogical );
  var ty  = s.GetTopPointY( mePosLogical );
  var bx  = s.GetBottomPointX( mePosLogical );
  var by  = s.GetBottomPointY( mePosLogical );
  var anc = s.GetAnchorPos();
  var act = s.GetActivePos();
  var isEmpty = s.IsEmpty;

  // 1行内で範囲選択しているとき(インラインモード) ※選択範囲を拡張しない
  var inLine = ( ! isEmpty && inLineEnable && ty === by );

  // 範囲選択なし または 複数行選択のとき(行全体のコメントアウト)
  if ( ! inLine ) {
    // 選択範囲を拡張と末尾改行の調整
    if ( ty < by && bx === 1 ) { by --; }
    s.SetActivePoint( mePosLogical, d.GetLine( by, 0 ).length + 1, by );
    s.SetAnchorPoint( mePosLogical, 1, ty );
  }

  // コメントアウト/アンコメント
  var st = s.Text;
  var tmp = AddDeleteComment( st, mode, comment, cmStr, $ctrl );
  if ( tmp !== st ) {
    // ブックマークを保存
    var bmArray = GetBookmark( ty, by );

    s.Text = tmp;	// コメントアウト/アンコメント完了

    // ブックマークを復元
    RestoreBookmark( ty, by, bmArray );
  }

  var gap = tmp.length - st.length;

  // 選択範囲なしで実行したときは選択範囲を残さない
  if ( isEmpty ) {
    var id = d.GetLine( ty, 0 ).search( /[^\s]/ ) + 1;
    var x = ( gap > 0 && tx >= id ) ? tx + gap	// コメントアウト
          : ( gap < tx && tx > id ) ? tx + gap	// アンコメント
          : /*       else        */   tx;
    s.SetActivePoint( mePosLogical, x, ty );
  }
  // インラインモードのときは選択範囲を復旧する
  else if ( inLine ) {
    s.SetActivePos( ( anc < act ) ? act + gap : act );
    s.SetAnchorPos( ( anc < act ) ? anc : anc + gap );
  }
  // 拡張した選択範囲を復旧する
  else {
    s.SetActivePoint( mePosLogical, 1, by + 1 );
    s.SetAnchorPoint( mePosLogical, 1, ty );
  }

  var elapsedSec = ( ( new Date() - start ) / 1000 ).toFixed( 3 );
  Status = " 「行コメント」マクロ  [ "
         + elapsedSec.replace( /\./, ". " )
         + " 秒 ]";
}


// ---------- ▼ 関数 ▼ ---------- //

/**
 * 関数 AddDeleteComment()
 * 選択範囲の各行の字下げ量をチェックして、字下げ位置にあわせてコメントアウトする
 * ※ Ctrl キーで強制コメントアウト
 */ 
function AddDeleteComment( str, mode, comment, cmStr, $ctrl ) {
  // Ctrl キー押し下げで強制コメントアウト(※行頭にコメントマーク追加)
  if ( $ctrl === 1 ) {
    return str.replace( /^/gm, comment );
  }

  var a = str.split( "\n" );	// 選択範囲を行単位に分解
  var b = [];
  var len = a.length;
  var cmLength = comment.length;
  var cmStrLength = cmStr.length;
  var id,  c0,  d0;		// 字下げ量
  c0 = Infinity,  d0 = Infinity;

  // 各行の字下げ量(空白以外の文字の最初の出現位置)を取得
  for ( var i = 0; i < len; i ++ ) {
    // 各行ごとの字下げ量 (空白行では -1 )
    id = a[i].search( /[^ \t]/ );
    b.push( id );

    if ( mode === 3 && d0 && id > -1 && id < d0
    && a[i].substr( id, cmLength ) !== comment ) {
      d0 = id;	// 非コメント行の字下げ量
    }
    else if ( mode === 2 && c0 && id > -1 && id < c0 ) {
      c0 = id;	// 最小の字下げ量
    }
  }

  // 各行をコメントアウト/アンコメント処理
  for ( var i = 0, ai, bi; i < len; i ++ ) {
    if ( b[i] === -1 ) { continue; }	// 空白行はスキップ
    ai = a[i],  bi = b[i];

    // 行頭の空白 b[i] の直後がコメントマークかチェック
    // "// コメント行" なら...
    if ( ai.substr( bi, cmLength ) === comment ) {
      // アンコメント または コメントアウト
      a[i] = ( mode || bi === 0 )
           ? ai.substr( 0, bi ) + ai.substr( bi + cmLength )
           : comment + ai;
    }

    // コメントマーク定義の末尾が空白文字つき "// " ならば "//" で再チェック
    else if ( cmStr && ai.substr( bi, cmStrLength ) === cmStr ) {
      // アンコメント または コメントアウト
      a[i] = ( mode || bi === 0 )
           ? ai.substr( 0, bi ) + ai.substr( bi + cmStrLength )
           : comment + ai;
    }

    // 非コメント行なら字下げ位置にあわせてコメントマークを追加する
    else {
      a[i] = ( mode === 4 ) ? ai.slice( 0, bi ) + comment + ai.slice( bi )
           : ( mode === 3 ) ? ai.slice( 0, d0 ) + comment + ai.slice( d0 )
           : ( mode === 2 ) ? ai.slice( 0, c0 ) + comment + ai.slice( c0 )
           : /*  else  */    comment + ai;
    }

  }
  return a.join( "\n" );
}

/**
 * 関数 GetBookmark( ty, by )
 * 指定された範囲のブックマークを収集
 */
function GetBookmark( ty, by ) {
  var bmArray = [],  bmY;
  var s = editor.ActiveDocument.selection;
  if ( ty < by ) {
    var anc = s.GetAnchorPos(),  act = s.GetActivePos();

    if ( ty === 1 ) {
      s.SetActivePoint( mePosLogical, 1, 2 );
      if ( s.PreviousBookmark() ) {
        bmY = s.GetActivePointY( mePosLogical );
        if ( bmY >= ty && bmY <= by ) {
          bmArray.push( bmY );
        }
      }
      s.SetActivePos( 0 );
    }
    else { s.SetActivePoint( mePosLogical, 1, ty - 1 ); }

    while ( s.NextBookmark() ) {
      bmY = s.GetActivePointY( mePosLogical );
      if ( bmY >= ty && bmY <= by ) {
        bmArray.push( bmY );
      }
      else if ( bmY > by ) { break; }
    }
    s.SetActivePos( act );  s.SetAnchorPos( anc );
  }
  return bmArray;
}

/**
 * 関数 RestoreBookmark( ty, by, bmArray )
 * 指定された範囲のブックマークを復元
 */
function RestoreBookmark( ty, by, bmArray, sel ) {
  var bmCount = bmArray.length;
  if ( bmCount ) {
    var s = editor.ActiveDocument.selection;
    var anc = s.GetAnchorPos(),  act = s.GetActivePos();
    s.SetActivePoint( mePosLogical, 1, ty );
    s.ClearBookmark();
    for ( var i = 0; i < bmCount && bmArray[i] <= by; i ++ ) {
      if ( bmArray[i] < ty ) { continue; }
      s.SetActivePoint( mePosLogical, 1, bmArray[i], false );
      s.SetBookmark();
    }
    if ( sel ) {
      s.SetActivePos( act );  s.SetAnchorPos( anc );
    }
  }
}

/**
 * 関数 MultiFunction( Fn, arg )
 * マルチカーソル(複数選択範囲)に対応させる
 * 第1引数: Function; 選択範囲ごとに適用する処理の関数
 * 第2引数: Function に渡す引数をまとめた配列
 */
function MultiFunction( Fn, arg ) {
  var d = editor.ActiveDocument;
  var s = d.selection;

  // 矩形選択範囲は行に分ける
  s.Mode = meModeMulti;

  // 選択範囲の座標を取得
  var sCount = s.Count;
  var Sel = [];
  for ( var i = 0; i < sCount; i ++ ) {
    Sel[i] = {
      act: s.GetActivePos( i ),
      anc: s.GetAnchorPos( i )
    };
  }

  // 各選択範囲を処理;
  for ( var i = 0, diff = 0, dl; i < sCount; i ++ ) {
    dl = d.TextLength;
    s.SetActivePos( Sel[i].act + diff );
    s.SetAnchorPos( Sel[i].anc + diff );

    Fn( arg );	// CommentMacro_Main()

    // Fn() の残した選択範囲(またはキャレット位置)を回収
    Sel[i].act = s.GetActivePos();
    Sel[i].anc = s.GetAnchorPos();
    diff += d.TextLength - dl;	// 文字数の増減量(累積)
  }

  // マルチカーソル(複数選択範囲)を復帰
  for ( var i = 0; i < sCount; i ++ ) {
    s.AddPos( Sel[i].anc, Sel[i].act );
  }
}


更新履歴(sukemaru 版)

* 2018/08/08: 自家用として改造に着手
* 2018/10/28: マクロライブラリに投稿(※初版)
* 2018/11/02: 字下げ対応の設定項目を indent 変数に一本化(※第2版)
* 2018/11/14: 人柱版コード(コメントマーク末尾の半角空白あり/なしの差分に対応)を追加
* 2018/12/02: インラインモード(行の途中から右側のコメントに対応)を追加
* 2019/03/19: 人柱版コードを統合
*             Ctrl キーで強制コメントアウト可(GetKeyState.exe が必要)
* 2019/03/25: マクロライブラリに投稿(※第3版)
* 2019/04/07: Quit() メソッドを削除(※第3版 ➁)
* 2019/04/11: ブックマーク対応コードを追加(Mery 2.7.0 以上 が必要)
* 2019/04/12: ブックマーク対応を設定変数で切り替え
* 2019/04/15: ブックマーク対応を Shift キーで切り替え(GetKeyState.exe)
              GetKeyState.exe の有無や Mery 本体バージョンの自動チェックを追加
* 2019/04/18: 本体バージョンの自動チェックを関数化
* 2019/10/15: 関数コード内の a[i], b[i] を変数に格納してみた
* 2019/11/10: ブックマークの保守方法を変更し、動作速度を改善(※第4版)
              undo しても選択範囲の復帰可
              Mery 本体バージョンの自動チェックを削除
* 2019/11/10: コードのミスを修正(※第4版 ➁)
              ブックマークの復元がバージョン依存なしになるように変更
* 2019/12/01: 関数コード内の配列 c, d を排除し、動作速度を改善(※第5版)
              複数行選択のときのみブックマークの保存/復元するように変更
* 2020/06/28: マルチカーソル/複数選択範囲に対応(※第6版)
*             ブックマークの収集/復元コードを関数化して、動作速度を改善
*             (ブックマークの収集範囲を選択範囲に限定し、
*              変換することが確定したときのみブックマークを保存、
*              ブックマーク行で実行したときのみブックマークの復元をするように変更)
*             


おまけ


ブロックコメント

/* と */ と * で複数行のコメントブロックをつくるなら、
カッコで囲う(ポップアップメニューあり)」マクロか「引用符/コメント」マクロで。

例: 字下げされている hoge, fuga, piyo の3行をコメントアウトする
      hoge
        fuga
          piyo
/*
 *       hoge
 *         fuga
 *           piyo
 */
  • 引用符/コメント」マクロの「JS コメントアウト2」
    字下げされたブロックの先頭位置へコメントマークを挿入します。
      /* 
       * hoge
       *   fuga
       *     piyo
       */

※どちらのマクロもアンコメント機能がありますが、「カッコで囲う」マクロは、「引用符/コメント」マクロによって字下げ位置に挿入されたコメントマークを正しく削除できません。


インラインコメントアウト

※どちらのマクロも /* と */ だけでコメントアウト(インライン)することもできます。

また、<!-- と --> でのコメントアウトとアンコメントもできます。


  • カッコで囲う」マクロは選択範囲内を、「引用符/コメント」マクロは選択範囲のある行全体をコメントアウトします。
例:
 「hijklmn」 を範囲選択して /* コメントアウト */ する
abcdefghijklmnopqrstuvwxyz

「カッコで囲う」マクロ
abcdefg /* hijklmn */ opqrstuvwxyz
abcdefg <!-- hijklmn --> opqrstuvwxyz

「引用符/コメント」マクロ
/* abcdefghijklmnopqrstuvwxyz */
<!-- abcdefghijklmnopqrstuvwxyz -->
スポンサーリンク