「コメントマーク付け外し」の版間の差分

ナビゲーションに移動 検索に移動
(同じ利用者による、間の1版が非表示)
112行目: 112行目:
Sel.SetAnchorPoint(mePosLogical,1,ty);
Sel.SetAnchorPoint(mePosLogical,1,ty);
</source>
</source>


= sukemaru 版 =
= sukemaru 版 =
「行コメント」マクロ (コメントマーク付けはずし sukemaru版)
<br>
 
「行コメント」マクロ (コメントマーク付けはずし sukemaru版)<br>
'''ダウンロード:''' 「[[メディア:行コメント.zip|行コメント.zip]](アイコン入り)」(最終更新2019/04/07)
'''ダウンロード''' >> 「[[メディア:行コメント.zip|行コメント.zip]](アイコン入り)」(最終更新2019/11/10)
<br><br>
----
----


masme 版の設定用変数 indent = true の状態(インデントされたコメントマークを削除できる)を下地として、'''選択範囲内のもっとも字下げの少ない位置にあわせてコメントマークを付けられます。'''
masme 版の設定用変数 indent = true の状態(インデントされたコメントマークを削除できる)を下地として、'''インデントされた行の字下げ位置にあわせてコメントアウト''' できるようにしました。<br>
 
選択範囲内のもっとも字下げの少ない位置にあわせてコメントマークを付けられるので、コードブロックのコメントアウトのさいに各行の先頭位置が少しだけ分かりやすくなります。
:コードブロックのコメントアウトのさいに、各行の先頭位置が少しだけ分かりやすくなります。
:* 空白行(タブ文字/半角スペースのみの行と、完全な空行)は無視します。
:* 空白行(タブ文字/半角スペースのみの行と、完全な空行)は無視します。
:* 編集モードによる定義切替は、「コメントマーク付け外し」(masme版 2016/02/28)まま。
:* 編集モードによる定義切り替えは、「コメントマーク付け外し」(masme版 2016/02/28)のコードを翻案しています。
:* 設定変数 comment の定義に "'''><span style="color:#c0c0c0;">␣</span>'''" などの引用マークを指定すると、引用マークの付けはずしにも利用できます。
:* 設定変数 comment の定義に "'''><span style="color:#c0c0c0;">␣</span>'''" などの引用マークを指定すると、引用マークの付けはずしにも利用できます。




「コメントアウトするときは "'''//<span style="color:#c0c0c0;">␣</span>コメント'''" "'''><span style="color:#c0c0c0;">␣</span>コメント'''" のようにうしろに半角スペースを入れたいけれど、拾い物のコード内やコピペした文章内の半角スペースなしのコメント行 "'''//コメント'''" "'''>コメント'''" も手軽にアンコメントしたい」という使い方も想定しています。
「コメントアウトするときは '''//<span style="color:#c0c0c0;">␣</span>コメント''''''><span style="color:#c0c0c0;">␣</span>コメント'''のようにうしろに半角スペースを入れたいけれど、拾い物のコード内やコピペした文章内の半角スペースなしのコメント行 '''//コメント''''''>コメント'''も手軽にアンコメントしたい」という使い方も想定しています。
:* コメントマークの定義の末尾に「半角スペース×1」がついている状態をデフォルト状態にしてあります(初期値も編集モードごとの個別定義も)。
:* コメントマークの定義の末尾に「半角スペース×1」がついている状態をデフォルト状態にしてあります(初期値も編集モードごとの個別定義も)。




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




<div class="warningbox">
<div class="warningbox">
このマクロは、以下の外部実行ファイルで機能を拡張できます。<br> マクロライブラリから ZIP ファイルをダウンロードして Mery\Macros フォルダに解凍してください。
このマクロは、以下の外部実行ファイルで機能を拡張できます。<br> マクロライブラリから ZIP ファイルをダウンロードして '''Mery\Macros''' フォルダに解凍してください。
* '''pizz 氏作成の "[[GetKeyState.exe(キー状態取得実行ファイル)]]" を Macros フォルダに配置してください。'''
* '''pizz 氏作成の "[[GetKeyState.exe(キー状態取得実行ファイル)]]" を Macros フォルダに配置してください。'''
ソースコードは "GetKeyState" を導入している前提で書いています。<br><u> "GetKeyState" を導入しない場合は、ソースコード冒頭部分の指定された2行をコメントアウトしてください。</u>
</div>
</div>
'''Ctrl キー'''を押しながら実行したときは、コメントアウト状態の反転ではなく、選択範囲をふくむ行全体を'''強制的にコメントアウト'''します。
'''Ctrl キー'''を押しながら実行したときは、コメントアウト状態の反転ではなく、選択範囲をふくむ行全体を'''強制的にコメントアウト'''します。
:* "'''// コメント行'''" を含むコードブロックをまとめてコメントアウトするさいに、既存の "'''// コメント行'''" を "'''// // 二重にコメントアウト'''" できます。
:* "'''// コメント行'''" を含むコードブロックをまとめてコメントアウトするさいに、既存の "'''// コメント行'''" を "'''// // 二重にコメントアウト'''" できます。
:* 強制コメントアウトでコメントマークを挿入する位置は、行頭に限定されます。
:* <span style="color:#c00;">強制コメントアウトでコメントマークを挿入する位置は、行頭に限定されます。</span>
:* Ctrl キーの押し下げ状態でマクロの機能を切り替えるので、このマクロに'''ショートカットキー'''を割り当てる場合は、「Ctrl キーをふくむキーパターン」と「Ctrl キーをふくまないキーパターン」の2つを登録する必要があります。
:* Ctrl キーの押し下げ状態でマクロの機能を切り替えるので、このマクロに'''ショートカットキー'''を割り当てる場合は、「Ctrl キーをふくむキーパターン」と「Ctrl キーをふくまないキーパターン」の2つを登録する必要があります。
:: e.g.1 「Ctrl + /」キー  と  「Alt + /」キー
:: e.g.1 「Ctrl + /」キー  と  「Alt + /」キー
150行目: 150行目:




; 2019/11/10:
ブックマーク行のあるドキュメント/選択範囲でこのマクロを実行しても、ブックマーク状態を保持できるようにしました。
:* <span style="color:#c00;">※ ブックマークを正常に保持できるのは '''Mery ver 2.8.6''' 以上の場合だけです。</span>
:: それ以前のバージョンでは、Mery 本体側のブックマーク機能の仕様が安定していないので、ブックマークを正しく復元できません。
<br>
----
<br>
▼ '''注意事項''' (仕様上の制限) ▼
▼ '''注意事項''' (仕様上の制限) ▼


162行目: 169行目:
* "GetKeyState" を導入しない場合は、コメントアウトの状態を'''反転'''させるだけのマクロとなり、"// コメントアウトされている行" を二重にコメントアウトすることはできなくなります。
* "GetKeyState" を導入しない場合は、コメントアウトの状態を'''反転'''させるだけのマクロとなり、"// コメントアウトされている行" を二重にコメントアウトすることはできなくなります。
: 字下げオプションの設定値が 0 でも、行頭1文字目にコメントマークがある行は、かならずアンコメントされます。
: 字下げオプションの設定値が 0 でも、行頭1文字目にコメントマークがある行は、かならずアンコメントされます。
* コメントマークの定義が "'''>'''" または "'''>'''<span style="color:#c0c0c0;">␣</span>" のときに、行頭が 「>><span style="color:#c0c0c0;">␣</span>」 の行で実行すると、以下のように作用します。
::* 1回目: さいしょの "'''>'''" を削除 (アンコメント)
::* 2回目: つぎの "'''>'''" または "'''>'''<span style="color:#c0c0c0;">␣</span>" を削除 (アンコメント)
::* 3回目: 先頭に "'''>'''" または "'''>'''<span style="color:#c0c0c0;">␣</span>" を追加 (コメントアウト)
:: <span style="color:#c00;">この場合、連続で実行しても アンコメント/コメントアウト トグルによる元の状態への復元はできません。</span>


* コメントマーク末尾の半角空白 あり/なし の差分について。
* コメントマーク末尾の半角空白 あり/なし の差分について。
170行目: 183行目:
* <span style="color:#c00;"> コメント定義の先頭には空白文字をつけないでください。</span>
* <span style="color:#c00;"> コメント定義の先頭には空白文字をつけないでください。</span>
: 行コメント文字の変数 comment = "hoge"; の先頭が空白文字だとアンコメントできなくなるので、先頭の空白文字は無視します。
: 行コメント文字の変数 comment = "hoge"; の先頭が空白文字だとアンコメントできなくなるので、先頭の空白文字は無視します。
 
<br>
 
----
<br>
▼ '''使用例''' ▼
▼ '''使用例''' ▼


271行目: 285行目:


== ソースコード ==
== ソースコード ==
<br>
(最終更新2019/11/10) <br>
'''ダウンロード:''' 「[[ファイル:行コメント.zip|行コメント.zip]](アイコン入り)」(最終更新2019/04/07)
'''ダウンロードページ''' >> 「[[ファイル:行コメント.zip|行コメント.zip]](アイコン入り)」
: ※以前の '''人柱版''' の追加コードを統合してあります。
: ※ 以前の '''人柱版''' の追加コードを統合してあります。
: ※ Mery 本体が ver 2.8.5 以前であれば、2019/04/07 版を。


<source lang="javascript" style="height:80em; overflow:auto;">
<source lang="javascript" style="height:80em; overflow:auto;">
#title = "行コメント"
#title = "行コメント"
#tooltip = "コメントマーク付けはずし"
#tooltip = "コメントマーク付けはずし"
#icon = "double-slash[1].ico"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",215
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",215


var $ctrl = 0; // この行をコメントアウトしないこと
/**
* --------------------------------------------------------------
* 「行コメント」マクロ (コメントマーク付け外し sukemaru版)
*  Orginal created by 手石 & masme, 2013/03/28 - 2016/02/28
*  Modified by        sukemaru,    2018/10/28 - 2019/11/10
* --------------------------------------------------------------
*/


// Ctrl キーの状態を取得(GetKeyState をインストールしていないなら以下の2行は無効化すること)
var start = new Date(); // 所要時間計測(開始)
var getKeyState = '"' + editor.FullName.replace( /mery\.exe$/i , "Macros\\" ) + 'GetKeyState.exe" control';
var d = editor.ActiveDocument;
$ctrl = new ActiveXObject( "WScript.Shell" ).Run( getKeyState, 0, true );
var $ctrl = 0;
var gks = editor.FullName.replace( /[^\\]+\.exe$/i , "" )
        + "Macros\\GetKeyState.exe";
if ( new ActiveXObject( "Scripting.FileSystemObject" ).FileExists( gks ) ) {
  var WshShell = new ActiveXObject( "WScript.Shell" );
  // Ctrl キーの状態を取得
  $ctrl = WshShell.Run( '"' + gks + '" ctrl', 0, true );
}




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


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


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


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


// ●字下げされたコメントマークも削除するか?
var indentMode = 3;


  // indentMode = 0; なら 追加/削除 する位置は「常に行頭」のみ(字下げされたコメントマークは削除しない)
// ■ 行コメント文字の定義  (※初期値  "// " )
  // ※ 1 ~ 4  なら字下げされたコメントマークも削除する。追加する位置は以下のとおり。
var comment = "// ";
  // indentMode = 1; なら「常に先頭」にコメントマークを追加する(例1.の使い方 ※従来版とおなじ挿入パターン)
   /**
   /2 ~ 4  なら追加する位置は字下げに対応可。
  * ver 2018/11/14 以降はコメントマークの定義に "末尾空白" ありがデフォルト
  // indentMode = 2; なら追加と削除で同じ判定基準の先頭位置検出をする(例2.の使い方ができる)
  * 「var comment = "> ";」にするか、下の定義切替ブロックに
  // indentMode = 3; なら追加と削除で別々の判定基準の先頭位置検出をする(例3.の使い方)
  * 「case "text":  return "> ";」を追加すると、引用マークの付けはずしにもなる
  // indentMode = 4; なら「常に各行の字下げ位置」にあわせてコメントマークを追加する(例4.の使い方)
  */




// ■コメントマーク末尾に空白つきで定義しているときに、末尾空白のないコメントマークも削除するか?
// ▼ コメントマークの定義切替
// (※ comment = "// "; のときに "//こういうコメント行" もアンコメントするか?)
var varEnable = true;
 
  // varEnable = true; なら削除する
  // varEnable = false; なら削除しない
  // ※ 再度コメントアウトするさいは comment で定義したコメントマーク(末尾空白つき)になります。
  //  コメントマークを comment 末尾に空白なしで定義した場合は無視されます。
 
 
/* ここから「コメントマーク付け外し」(masme版 2016/02/28)より改変 */
// ◆行コメント文字の定義  ●初期値="// "
var comment = "// ";
 
// ▼コメントマークの定義切替
comment = ( function() {
comment = ( function() {


   // ▼拡張子による定義切り替え
   // ▼ 拡張子による定義切り替え ▼
   if ( document.Name.match( /\.def$|\.asm$|\.reg$|\.key$|\.inf$/i ) ) {
   if ( d.Name.match( /\.def$|\.asm$|\.reg$|\.key$|\.inf$/i ) ) {
     return "; ";
     return "; ";
   }
   }
   // ▼ファイル名による定義切り替え
 
   else if ( document.Name.match( /^hosts$/i ) ) {
   // ▼ ファイル名による定義切り替え ▼
   else if ( d.Name.match( /^hosts$/i ) ) {
     return "# ";
     return "# ";
   }
   }
   // else if ( document.Name.toLowerCase() == "hoge.txt" ) {
 
   //  return "> ";
  // // ▼ ファイル名による定義切り替え ▼
   // else if ( d.Name.toLowerCase() == "hoge.txt" ) {
   //  return ">> ";
   // }
   // }
   // // ▼フォルダ名による定義切り替え(正規表現)
 
   // else if ( document.FullName.match( /\\mery\\(?!macros\\)/ ) ) {
   // // ▼ フォルダ名による定義切り替え(正規表現) ▼
   //  return "> ";
   // else if ( d.FullName.match( /\\fuga\\(?!piyo\\)/i ) ) {
   //  return ">> ";
   // }
   // }


  // ▼ 編集モードによる定義切り替え ▼
   else {
   else {
    // ▼編集モードによる定義切り替え
     switch ( document.Mode.toLowerCase() ) {
     switch ( document.Mode.toLowerCase() ) {
      case "text":
        return "> ";
       case "bat":
       case "bat":
         return ":: "; // return "REM "; ": " や "' " でも可
         return ":: "; // return "REM "; // ": " や "' " でも可
       case "c#":  case "c++":  case "javascript":
       case "c#":  case "c++":  case "delphi": case "java":
      case "delphi": case "java":  case "jsp":  case "windows script":
      case "javascript":  case "jsp":  case "windows script":  
       case "mery_macro_js":  case "mery_macros_js":
       case "mery_macro_js":  case "mery_macros_js":  
      case "mery macro js":  case "mery macros js": 
       case "janestyle (正規表現用)":
       case "janestyle (正規表現用)":
         return "// ";
         return "// ";
       case "ini":  case "python": case "ruby": // ini は "; " のグループでも可
       case "ini":  case "mery msy":
       case "perl":  case "perlscript":  case "php":  case "python":
        return "# ";
      case "powershell": case "ruby":
       case "perl":  case "perlscript":  case "php":   
       case "mery msy":  case "autohotkey":
      case "python": case "ruby":   case "powershell":
       case: "ini":  case "mery msy": // ini は "; " でも可
         return "# ";
         return "# ";
       case "visualbasic":  case "vbscript":
       case "visualbasic":  case "vbscript":
         return "' ";
         return "' ";
       case "hsp":  // case: "ini": // ini はデフォルトで "# " のグループ
       case "hsp":  case "autohotkey":
         return "; ";
         return "; ";
       case "sql":
       case "sql":
365行目: 409行目:
       case "tex":
       case "tex":
         return "% ";
         return "% ";
      case "text":
        return "> ";
       default:
       default:
         return comment;
         return comment;
     }
     }
   }
   }
} )();
} )();
/* ここまで「コメントマーク付け外し」(masme版 2016/02/28)より改変 */


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


if ( document.ReadOnly ) {
// ドキュメントが書き換え禁止ならマクロを閉じる
if ( editor.ActiveDocument.ReadOnly ) {
   Status = " ドキュメントは書き換え禁止です。";
   Status = " ドキュメントは書き換え禁止です。";
}
}
// コメントマークが空白文字だけならマクロを閉じる
// コメントマークが空白文字だけならマクロを閉じる
else if ( comment.match( /^[ \t\n]*$/ ) ) {
else if ( /^\s*$/.test( comment ) ) {
   Status = " コメントマークの定義が無効です。";
   Status = " コメントマークの定義が無効です。";
}
}


else {
else {
   // コメントマークの先頭の空白文字は除去する
  var len = 0,  cmStr = "";
  Redraw = false;
 
   // コメントマークの先頭の空白文字を除去
   // ※comment の先頭に空白文字(半角空白、タブ文字、改行)があるとアンコメントできない
   // ※comment の先頭に空白文字(半角空白、タブ文字、改行)があるとアンコメントできない
   if ( comment.match( /^[ \t\n]*/ ) ) {
   comment = comment.replace( /^\s+/ , "" );
    comment = comment.replace( /^[ \t\n]*/ , "" );
  }
   // コメントマークの末尾が空白文字の場合、末尾空白なしのコメントマークを定義
   // コメントマークの末尾が空白文字の場合、末尾空白なしのコメントマークを定義
   if ( varEnable && comment.match( /\s+$/ ) ) {
   if ( varEnable && /\s+$/.test( comment ) ) {
     var comStr = comment.replace( /\s+$/ , "" );
     comStr = comment.replace( /\s+$/ , "" );
   }
   }


   // 選択範囲
   // 選択範囲
   var s = document.selection;
   var s = editor.ActiveDocument.selection;
   var tx = s.GetTopPointX( mePosLogical );
   var tx = s.GetTopPointX( mePosLogical );
   var ty = s.GetTopPointY( mePosLogical );
   var ty = s.GetTopPointY( mePosLogical );
   var bx = s.GetBottomPointX( mePosLogical );
   var bx = s.GetBottomPointX( mePosLogical );
   var by = s.GetBottomPointY( mePosLogical );
   var by = s.GetBottomPointY( mePosLogical );
   var anc = s.GetAnchorPos(); // 選択範囲の開始位置
   var anc = s.GetAnchorPos();
   var act = s.GetActivePos(); // 選択範囲の終了位置
   var act = s.GetActivePos();
   var pos = s.IsEmpty ? true : false; // 範囲選択なしのフラグ
   var pos = s.IsEmpty; // 範囲選択なしのフラグ
  var sx = ScrollX,  sy = ScrollY;


   // 1行内で範囲選択しているとき(右側のコメントアウト)
   // 1行内で範囲選択しているとき(インラインモード) ※選択範囲を拡張しない
  // ※選択範囲を拡張しない
   var inLine = ( ! pos && inLineEnable && ty == by );
   if ( inLineEnable && ty == by && ! pos ) {
    var inLine = true; // 部分選択のフラグ
  }


   // 範囲選択なし または 複数行選択のとき(行全体のコメントアウト)
   // 範囲選択なし または 複数行選択のとき(行全体のコメントアウト)
   else {
   if ( ! inLine ) {
 
     // 選択範囲の末尾が行頭にあるときの調整
     // 選択範囲の末尾が行頭にあるときの調整
     if ( ty != by && bx == 1 ) {
     if ( ty < by && bx == 1 ) {
       by --;
       by --;
     }
     }
     // 選択範囲を拡張
     // 選択範囲を拡張
     s.SetActivePoint( mePosLogical, 1, by ); // 選択範囲の最終行の行頭
     s.SetActivePoint( mePosLogical, 1, by );
     s.EndOfLine( false, mePosLogical ); // 選択範囲の最終行の行末
     s.EndOfLine( false, mePosLogical );
     s.SetAnchorPoint( mePosLogical, 1, ty ); // あらためて選択範囲の先頭行まで選択
     s.SetAnchorPoint( mePosLogical, 1, ty );
 
    // ブックマーク行を収集(選択範囲の先頭行は確認しない)
    if ( ty < by ) {
      var tp = s.GetAnchorPos(),  bp = s.GetActivePos();
      var bmArray = [];
      s.SetActivePos( tp );
      while ( s.NextBookmark() && s.GetActivePointY( mePosLogical ) <= by ) {
        bmArray.push( s.GetActivePointY( mePosLogical ) );
      }
      len = bmArray.length;
      s.SetAnchorPos( tp );  s.SetActivePos( bp, true );
      ScrollX = sx;  ScrollY = sy;
    }
   }
   }


   var st = s.Text; // 選択範囲の文字列を取得
  // コメントアウト/アンコメント
   var ad = AddDeleteComment( st ); // コメントアウト/アンコメント処理した文字列
   var st = s.Text; // 選択範囲の文字列
   var ad = AddDeleteComment( st, mode, comment, comStr, $ctrl );
  if ( ad != st ) { // 変更なしなら undo 履歴に残さない
    s.Text = ad;
  }


   if ( ad != st ) { // (処理の前後で変化なしなら undo 履歴に残さない)
  // ブックマークを復元
     s.Text = ad; // コメントマークの付けはずし完了
   if ( len ) {
    var ep = s.GetActivePos();
    for ( var i = 0, len = bmArray.length; i < len; i ++ ) {
      s.SetActivePoint( mePosLogical, 1, bmArray[i], false );
      s.SetBookmark();
    }
     s.SetActivePos( ep );
   }
   }
  var gap = st.length - ad.length;


   // 選択範囲なしで実行したときは範囲選択を残さない
  var gap = ad.length - st.length;
 
   // 選択範囲なしで実行したときは選択範囲を残さない
   if ( pos ) {
   if ( pos ) {
      s.SetActivePoint( mePosLogical, ( gap < tx ) ? tx - gap : 1, ty );
    var id = 1 + d.GetLine( ty, 0 ).search( /[^\s]/ );
    var x = ( gap > 0 && tx >= id ) ? tx + gap // コメントアウト
          : ( gap < tx && tx > id ) ? tx + gap // アンコメント
          : /*      else        */  tx; // 空振り(空白行)
    s.SetActivePoint( mePosLogical, x, ty );
   }
   }
   // 選択範囲が1行だけのときは選択範囲を復旧する
   // 選択範囲が1行だけのときは選択範囲を復旧する
   else if ( inLine ) {
   else if ( inLine ) {
     s.SetActivePos( ( anc < act ) ? act - gap : act );
     s.SetActivePos( ( anc < act ) ? act + gap : act );
     s.SetAnchorPos( ( anc < act ) ? anc : anc - gap );
     s.SetAnchorPos( ( anc < act ) ? anc : anc + gap );
   }
   }
   // 複数行選択なら拡張した選択範囲を復旧する
   // 複数行選択なら拡張した選択範囲を復旧する
446行目: 517行目:
     s.SetAnchorPoint( mePosLogical, 1, ty );
     s.SetAnchorPoint( mePosLogical, 1, ty );
   }
   }
  ScrollX = sx;  ScrollY = sy;
  Redraw = true;
  var elapsedSec = ( ( new Date() - start ) / 1000 ).toFixed( 3 );
  Status = " 「行コメント」マクロ  [ "
        + elapsedSec.replace( /\./, ". " )
        + " 秒 ]";
}
}


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


/**
/**
  * 関数 AddDeleteComment( str )
  * 関数 AddDeleteComment( str )
  * 選択範囲の各行の字下げ量をチェックして、字下げ位置にあわせてコメントアウトする
  * 選択範囲の各行の字下げ量をチェックして、字下げ位置にあわせてコメントアウトする
  * コメントマークのチェックには正規表現を使っていないので、誤爆はほぼないはず
  * ※ 変数 comment の先頭が空白文字(半角スペースやタブ、改行コード)だとアンコメントできない
  * ※変数 comment の先頭が空白文字(半角スペース、タブコード \t)だとアンコメントできない
  *   → メインスコープに comment 先頭の空白除去の処理を追加
  */  
  */  
function AddDeleteComment( str ) {
function AddDeleteComment( str, mode, comment, comStr, $ctrl ) {
 
   // Ctrl キー押し下げで強制コメントアウト(※行頭にコメントマーク追加)
   // Ctrl キー押し下げで強制コメントアウト(※行頭にコメントマーク追加)
   if ( $ctrl == 1 ) {
   if ( $ctrl == 1 ) {
     return str.replace( /^/gm , comment );
     return str.replace( /^/gm , comment );
   }
   }
   
  else {
    var id, _id, c0, d0; // 字下げ量(空白以外の文字の最初の出現位置)
    var a = str.split( "\n" ); // 選択範囲を行単位に分解して配列 a に
    var b = []; // 各行の字下げ量 id を格納する → 削除の基準 b[i]
    var c = []; // id をソートして最小の字下げ量を調べる → 追加の基準 c[0]
    var d = []; // 非コメント行の字下げ量 _id を格納する → 追加の基準 d[0]


    // 選択範囲内の各行の字下げ量を取得 → 配列 b, c, d に
  var id, c0, d0; // 字下げ量(空白以外の文字の最初の出現位置)
    for ( var i = 0, len = a.length; i < len; i ++ ) {
  var a = str.split( "\n" ); // 選択範囲を行単位に分解して配列 a に
      // 各行ごとの字下げ量
  var b = []; // 各行の字下げ量 id を格納する → 削除の基準 b[i]
      id = a[i].indexOf( a[i].match( /[^ \t]/ ) ); // a[i].search( /[^ \t]/ ) とおなじ
  var c = []; // id をソートして最小の字下げ量を調べる → 追加の基準 c[0]
  var d = []; // 非コメント行の字下げ量 _id を格納する → 追加の基準 d[0]
  var len = a.length;
  var comLength = comment.length;
  var comStrLength = comStr.length;


      // 空白行では -1 (sort のジャマ)が返されるはずなので
  // 選択範囲内の各行の字下げ量を取得 → 配列 b, c, d に
      // デタラメな数値(最小値を 0 以上に)にして id を配列 b, c に格納する
  for ( var i = 0; i < len; i ++ ) {
      id = ( id < 0 ) ? 1000000 : id; // 空白行はコメントアウトしないから数値は大きく
    // 各行ごとの字下げ量
      b.push( id );
    id = a[i].indexOf( a[i].match( /[^ \t]/ ) );
      if ( indentMode == 2 ) {
        c.push( id );
      }
      // コメント行の数値もデタラメな数値にして _id を配列 d に格納
      else if ( indentMode == 3 ) {
        _id = ( a[i].substr( b[i], comment.length ) == comment ) ? 1000000 : id;
        d.push( _id );
      }
    } // end for


     // 配列 c, d を昇順で並びかえ( → 最小値 c[0] d[0] だけ使う)
     // 空白行では -1 が返されるので、id をデタラメな値(∞)にして配列 b, c に格納する
     if ( indentMode == 2 ) {
    // (-1 は sort のジャマ、JScript では substr の第1引数に使用できない)
       c0 = c.sort( CompareForSort )[0];
    id = ( id < 0 ) ? Infinity : id; // 空白行はコメントアウトしないから数値は大きく
    b.push( id );
     if ( mode == 2 ) {
       c.push( id );
     }
     }
     else if ( indentMode == 3 ) {
    // コメント行の数値もデタラメな値(∞)にして _id を配列 d に格納
       d0 = d.sort( CompareForSort )[0];
     else if ( mode == 3 ) {
       id = ( a[i].substr( b[i], comLength ) == comment ) ? Infinity : id;
      d.push( id );
     }
     }
  }


    // 各行をコメントアウト/アンコメント処理
  // 配列 c, d を昇順で並びかえ( → 最小値 c[0] d[0] だけ使う)
     for ( var i = 0; i < a.length; i ++ ) {
  var CompareForSort = function( first, second ) {
      // 空白行(id にデタラメな数値を入れた行)はスキップ
     return  ( first == second ) ?  0
      if ( b[i] == 1000000 ) {
          : ( first < second ) ? -1
        continue;
          :/* first > second */   1;
      }
  }
      // 行頭の空白 b[i] の直後がコメントマークかチェック
  if ( mode == 2 ) {
      // "// コメント行" なら...
    c0 = c.sort( CompareForSort )[0];
      if ( a[i].substr( b[i], comment.length ) == comment ) {
  }
        // アンコメント または コメントアウト
  else if ( mode == 3 ) {
        a[i] = ( indentMode != 0 || b[i] == 0 )
    d0 = d.sort( CompareForSort )[0];
                  ? a[i].substr( 0, b[i] ) + a[i].substr( b[i] + comment.length )
  }
                  : comment + a[i]; // ← ( indentMode == 0 && b[i] != 0 )
 
      }
  // 各行をコメントアウト/アンコメント処理
  for ( var i = 0, ai, bi; i < len; i ++ ) {
    ai = a[i],  bi = b[i];
    if ( bi == Infinity ) { continue; } // 空白行はスキップ


      // 定義されたコメントマークの末尾が空白文字つき "// " ならば
    // 行頭の空白 b[i] の直後がコメントマークかチェック
      // 各行が末尾空白なしの "//" でコメントアウトされているか再チェック
    // "// コメント行" なら...
      else if ( varEnable && comStr
    if ( ai.substr( bi, comLength ) == comment ) {
            && a[i].substr( b[i], comStr.length ) == comStr ) {
      // ( mode > 0 ) または コメントマークが行頭 ならアンコメント
        // アンコメント または コメントアウト
      // ( mode = 0 ) で コメントマークが行頭以外 ならコメントアウト
        a[i] = ( indentMode != 0 || b[i] == 0 )
      a[i] = ( mode != 0 || bi == 0 )
                  ? a[i].substr( 0, b[i] ) + a[i].substr( b[i] + comStr.length )
          ? ai.substr( 0, bi ) + ai.substr( bi + comLength )
                  : comment + a[i]; // ← ( indentMode == 0 && b[i] != 0 )
          : comment + ai;
      }
    }


      // 非コメント行なら字下げ位置にあわせてコメントアウトする
    // 定義されたコメントマークの末尾が空白文字つき "// " ならば
      else {
    // 各行が末尾空白なしの "//" でコメントアウトされているか再チェック
        a[i] = ( indentMode == 4 ) ? a[i].slice( 0, b[i] ) + comment + a[i].slice( b[i] )
    else if ( comStr && ai.substr( bi, comStrLength ) == comStr ) {
            : ( indentMode == 3 ) ? a[i].slice( 0, d0 ) + comment + a[i].slice( d0 )
      // アンコメント または コメントアウト
            : ( indentMode == 2 ) ? a[i].slice( 0, c0 ) + comment + a[i].slice( c0 )
      a[i] = ( mode != 0 || bi == 0 )
            : /*    else      */  comment + a[i];
          ? ai.substr( 0, bi ) + ai.substr( bi + comStrLength )
      }
          : comment + ai;
    } // end for
     }
     return a.join( "\n" );
  } // end else
} // end function


    // 非コメント行なら字下げ位置にあわせてコメントマークを追加する
    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;
    }


/**
   }
* 以下の関数は『sort メソッド (Array) (JavaScript) | MSDN』より
   return a.join( "\n" );
* https://msdn.microsoft.com/ja-jp/library/4b4fbfhk%28v=vs.94%29.aspx
* Sorts array elements in ascending order numerically.
* sort メソッドデフォルトの ascii 昇順 (1, 10, 2, 20) ではなく、
* 数値の大きさ (1, 2, 10, 20) でソート
*/
function CompareForSort( first, second ) {
   if ( first == second )
    return 0;
   else if ( first < second )
    return -1;
  else // ( first > second )
    return 1;  
}
}
</source>
</source>
<br>
== 更新履歴 ==
<br>
* 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() メソッドを削除(※ '''第4版''')
* 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: ブックマークの保守方法を変更(undo しても選択範囲の復帰可)
              Mery 本体バージョンの自動チェックを削除(※ '''第5版''')


== おまけ ==
== おまけ ==
1,199

回編集

スポンサーリンク

案内メニュー

スポンサーリンク
スポンサーリンク
スポンサーリンク