SHARE
TWEET

Mery_練習で作ってみたが、うまくないマクロ

sukemaru Aug 13th, 2018 (edited) 138 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. 【練習で作ってみたが、うまくないマクロ】
  2. (最終更新:2018/12/02)
  3.  
  4. https://pastebin.com/70QW2YMq
  5. [RAW]   https://pastebin.com/raw/70QW2YMq
  6. ページのスクロールが重いばあいは RAW(平文)で閲覧、または RAW ページをテキストとして保存してください
  7.  
  8. ※勉強・練習用なので、各行ごとの冗長なコメントにはご勘弁願います
  9.   (タブ幅 = 半角8文字 で書いたので設定が違うと見づらいかも)
  10. ※マクロライブラリに転載していないもの、転載したものに変更を加えたものには不安要素が含まれています
  11.  
  12.  ・「引用符/コメントマークを追加...」
  13.     (Last modified: 2018/11/19, ※マクロライブラリの最終更新: 2018/10/28 - 2018/10/30
  14.  ・「行コメント (付けはずし)」 ◆ 人柱版 ◆
  15.     (Last modified: 2018/12/02, ※マクロライブラリの最終更新: 2018/11/19
  16.  ・「インデント」
  17.     (Added: 2018/11/15, ※マクロライブラリの最終更新: 2018/11/16
  18.  ・「逆インデント」
  19.     (Last modified: 2018/11/16, ※マクロライブラリの最終更新: 2018/11/16
  20.  ・「字下げ (スペース×2 追加)
  21.     (Added: 2018/11/04, ※マクロライブラリの最終更新: 2018/11/02)
  22.  ・「字上げ (スペース×2 削除)
  23.     (Last modified: 2018/11/19, ※マクロライブラリの最終更新: 2018/11/02)
  24.  ・「行を上に移動 (複数行可)(Last modified: 2018/10/21)
  25.  ・「行を下に移動 (複数行可)(Last modified: 2018/10/21)
  26.  ・「行を複製 (複数行可)
  27.     (Last modified: 2018/11/20, ※マクロライブラリの最終更新: 2018/08/24
  28.  ・「行の先頭に貼り付け (複数行可)」    (※マクロライブラリの最終更新: 2018/08/24
  29.  ・「カッコで囲う...」 ◆ 人柱版 ◆
  30.     (Last modified: 2018/11/19, ※マクロライブラリの最終更新: 2018/08/24 - 2018/10/29
  31.  ・「"引用符" で囲う (付けはずし)
  32.     (Last modified: 2018/11/14, ※マクロライブラリの最終更新: 2018/10/19 - 2018/10/26
  33.  ・「検索先にジャンプ...」 ◆ 人柱版 ◆
  34.     (Last modified: 2018/11/25, ※マクロライブラリの最終更新: 2018/11/12 - 2018/11/25
  35.  
  36.  
  37. // -----------------------------------------------------------------------------
  38.  
  39.  
  40. #title = "引用符..."
  41. #tooltip = "引用符を追加"
  42. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",96
  43. // 選択範囲の行頭に引用符/コメントマークを追加・削除する
  44. // 公式wikiのマクロライブラリより「引用の追加」を改造した
  45. // ※マクロライブラリに転載済み (2018/10/28 - 2018/10/30)
  46.  
  47. // (Last modified: 2018/11/19)  「JS コメントアウト2」の字下げ位置の検出方法を変更
  48.  
  49. /**
  50.  * -----------------------------------------------------------------------------
  51.  * 引用の追加      ( => 2018/10/14 公開停止)
  52.  * Orginal Copyright (c) Kuro. All Rights Reserved.
  53.  * www:    http://www.haijin-boys.com/
  54.  * -----------------------------------------------------------------------------
  55.  * Modified by sukemaru
  56.  * 「引用符を追加」または「引用符/コメント」
  57.  * -----------------------------------------------------------------------------
  58.  * Kuro 版からの変更点
  59.  *
  60.  * ・引用符の種類を増やした(※ 基本的に「メタ文字+半角スペース」)。
  61.  * ・「クリップボード」と「任意の文字列」を追加。
  62.  * ・配列に削除用の要素(半角スペースなしのメタ文字のみの差分)も余分に追加した。
  63.  *   ※「すべて削除」では、半角スペース、全角スペース、タブ文字での字下げをすべて削除する。
  64.  *   ※「クリップボード」、「任意の文字列」、「JS/XML コメントアウト」は、「1つ削除//すべて削除」では削除できない。
  65.  *
  66.  * ・連続で 実行/undo すると選択範囲が解除されるので、選択範囲があったときには行全体に拡張・復帰するコードにした。
  67.  * ・選択範囲なしの状態からカーソル行にたいして「追加/1つ削除/すべて削除」を実行したときは、
  68.  *   実行前の位置にカーソルを返せるようにした(undo すると行全体が選択範囲になってしまうのはマクロの仕様)。
  69.  * ・「1つ削除」の不具合箇所を修正した。
  70.  *
  71.  * ※ 「任意の文字列」について ※
  72.  * ・文字コードでの入力には非対応(入力されたままの文字列を返す)。
  73.  * ・改行コードとタブ文字は、それぞれ「\\\n」と「\\\t」で入力されたものを「\n」と「\t」に置換する。
  74.  *   パスの入力に配慮しただけの簡易的な置換処理なので、「\」を4つ以上かさねた場合を考慮していない。
  75.  *
  76.  * ※ 「JS コメントアウト」と「JS アンコメント」について ※
  77.  * ・「引用の追加」では選択範囲を拡張してコメントアウトするので、
  78.  *   行の中間部分だけをコメントアウトするなら「カッコで囲う」マクロが適する。
  79.  * ・JSアンコメントに副作用(コメント文の冒頭のアスタリスク「*」を消してしまう) があるので要注意。
  80.  *   基本的にこのマクロでつけられた、「中間行にアスタリスクを打った JS コメント」しか考慮していない。
  81.  * ・ほかにも注意事項があるので、該当コード部分の注意書きを参照のこと!
  82.  *
  83.  * ポップアップメニューの項目は、m.Add( … ); の不要な行をコメントアウトすれば隠すことができる。
  84.  *   ただし、メニューから隠しても、配列 q にある要素は「1つ削除/すべて削除」の対象になる。
  85.  * (配列から削除する場合は "" の中身だけを消すこと。
  86.  *   "" として空要素を残しておかないと、メニューや処理コードの ID と一致しなくなる)
  87.  */
  88.  
  89. // 引用符の種類
  90. var q = new Array( "" ,     // 以下 r = 1~10、11~20、21~30、31~ の ID 順
  91.   "> " ,  "・" ,  " * " ,  "- " ,  " " ,  " " ,  "\t" ,  "// " ,  "# " ,  "; " ,
  92.   "' " ,  "-- " ,  ": " ,  ":: " ,  "REM " ,  "※" ,  "" ,  "" ,  ">> " ,  ">>" ,
  93.   ">" ,  "・ " ,  "・" ,  "· " ,  "·" ,  "* " ,  "*" ,  "--" ,  "-" ,  "//" ,
  94.   "#" ,  ";" ,  "'" ,  "::" ,  ":" );
  95.  
  96.   // ※半角スペースの有無で「1つ削除/すべて削除」がマッチしなくなるので、
  97.   //   ">> " 以降に半角スペース あり/なし の差分要素を適当に追加してある。
  98.   // ※半角スペース差分(中黒=ビュレットは全角/半角差分も)の変更は、配列内の編集ではなく
  99.   //   ポップアップメニュー項目のID(番号)変更で対応しないと、「1つ削除/すべて削除」が効かなくなります
  100.   // (同一文字をふくむ要素は文字列の長いものが先に置かれていないとダメ)。
  101.   // 「・」は半角カナの中黒(U+FF65)、「·」は欧文用ユニコード文字のビュレット(U+00B7)
  102.  
  103.  
  104. // ポップアップメニューの項目とID
  105. var m = CreatePopupMenu();
  106.   // m.Add( "ラベル", r ); の各行は、任意に上下移動(並べ替え)してよいが、
  107.   // r の数値は上の配列 q の並び順やテキスト変換処理の case r: に対応しているので変更しないこと!
  108.  
  109. m.Add( "    任意の文字列 (&E)", 50 );
  110. m.Add( "    クリップボード (&C)", 40 );
  111.  
  112. m.Add( "", 0, meMenuSeparator );
  113. m.Add( ">   > メール引用符 (&>)", 1 );
  114. m.Add( ">>  >> BBS アンカー (&>)", 20 );
  115. m.Add( "・ ・ 箇条書き (&/)", 2 );
  116. m.Add( " *  * 箇条書き (&*)", 3 );
  117. m.Add( "-   - 箇条書き (&-)", 4 );
  118. m.Add( "※ ※注意書き (&K)", 16 );
  119.  
  120. m.Add( "", 0, meMenuSeparator );
  121. m.Add( "␣ 半角スペース (&1)", 5 );
  122. m.Add( "⃞ 全角スペース (&2)", 6 );
  123. m.Add( "› タブコード (&T)", 7 );
  124.  
  125. m.Add( "", 0, meMenuSeparator );    // ※ 選択範囲の論理行全体をコメントアウト
  126. m.Add( "\/\/    JS・C コメント (&J)", 8 );
  127. m.Add( "#     Perl コメント (&P)", 9 );
  128. m.Add( ";     INI コメント (&I)", 10 );
  129. m.Add( "’     VB コメント (&V)", 11 );
  130. m.Add( "--  SQL コメント (&S)", 12 );
  131. m.Add( ":     MS-DOS ラベル (&M)", 13 );
  132. m.Add( "::  BAT コメント (&B)", 14 );
  133. m.Add( "REM     BAT コメント (&R)", 15 );
  134.  
  135. m.Add( "", 0, meMenuSeparator );
  136. m.Add( "    1つ削除 (&D)", 17 );
  137. m.Add( "    すべて削除 (&A)", 18 );
  138. m.Add( "", 0, meMenuSeparator );
  139. m.Add( "    任意の文字列を削除 (&Q)", 51 );
  140.  
  141. m.Add( "", 0, meMenuSeparator );    // ※ 選択範囲の論理行全体をコメントアウト
  142. m.Add( "/*  *  */   JS コメントアウト 2 (&J)", 42 );
  143. m.Add( "/*  */  JS コメントアウト 1  (&J)", 41 );
  144. m.Add( "<!--  -->   XML コメントアウト (&X)", 44 );
  145. m.Add( "", 0, meMenuSeparator );
  146. m.Add( "    JS アンコメント (&U)", 43 );
  147. m.Add( "    XML アンコメント (&L)", 45 );
  148.  
  149. // m.Add( "", 0, meMenuSeparator );
  150. // m.Add( "キャンセル", 0 );       // Escキーでキャンセルできるのでアクセラレータなし
  151.  
  152.  
  153. // ポップアップメニューの表示
  154. // m.Track(0); ならキャレット位置、m.Track(1); ならカーソル位置にサブメニューがポップアップ
  155. var r = m.Track( mePosMouse = 1 );  // 選択されたメニュー項目のIDを r に格納する
  156.  
  157. if ( r > 0 ) {
  158.   Redraw = false;
  159.   var sx = ScrollX, sy = ScrollY;
  160.     // スクロール位置を保存
  161.   var s = document.selection;
  162.  
  163.   // 選択範囲がないときのカーソル位置を取得
  164.   if ( s.IsEmpty )
  165.     var pos = s.GetActivePos();     // pos は「マクロ実行前に選択範囲なし」フラグとしても使う
  166.  
  167.   // 選択範囲を取得する
  168.   var ax = s.GetTopPointX( mePosLogical );
  169.   var ay = s.GetTopPointY( mePosLogical );
  170.   var bx = s.GetBottomPointX( mePosLogical );
  171.   var by = s.GetBottomPointY( mePosLogical );
  172.  
  173.   // 選択範囲の末尾が行頭にあるときの調整
  174.   // bx = 1 で charAt(s.GetActivePos()) がないなら末尾空行 ^[EOF] とみなして、末尾調整から除外する
  175.   if ( ay != by && bx == 1 && document.Text.charAt( s.GetActivePos() ) )
  176.     by --;
  177.  
  178.   // 選択範囲を拡張して確定
  179.   s.SetActivePoint( mePosLogical, 1, by );
  180.   s.EndOfLine( false, mePosLogical );
  181.   s.SetAnchorPoint( mePosLogical, 1, ay );
  182.  
  183.   // 選択範囲の文字列を取得
  184.   var st = document.selection.Text;
  185.  
  186.   // IDごとのテキスト変換処理
  187.   switch ( r ) {
  188.  
  189.  
  190.     // 引用符を追加
  191.     case 1:  case 2:  case 3:  case 4:  case 5:  case 6:  case 7:  case 8:  case 9:  case 10:
  192.     case 11:  case 12:  case 13:  case 14:  case 15:  case 16:  case 20:
  193.  
  194.       s.Text = InsertQuote( st, q[r] );     // 各行の先頭に引用符/コメントマークを追加
  195.  
  196.       /* とりあえずコメントアウトしておく? */
  197. //       if ( pos ) {               // マクロ実行前に選択範囲がなかった場合は
  198. //         s.SetActivePos( pos + q[r].length ); // カーソルを元の位置に戻す
  199. //         Quit();
  200. //       }
  201.       break;
  202.  
  203.  
  204.     // 1つ削除
  205.     case 17:
  206.       // 各行ごとに、配列 q の並び順で最初にマッチした引用符/コメントマークを削除
  207.  
  208.       var dt = DeleteQuote( st );   // 各行の先頭の引用符/コメントマークを削除
  209.  
  210.       // 選択範囲に引用符/コメントマークがなかった場合 undo 履歴を残さない
  211.       if ( dt == st ) {     // deleteQuote() 処理の前後でテキストが一致したら
  212.         // マクロ実行前に選択範囲がなかった場合はカーソルを元の位置に戻す
  213.         if ( pos ) { s.SetActivePos( pos );  Quit(); }
  214.         break;      //   中止 (undo 履歴を残さない)
  215.       }
  216.  
  217.       s.Text = dt;  // 削除完了
  218.  
  219.       if ( pos && dt.length ) {         // マクロ実行前に選択範囲がなかった場合は
  220.         s.SetActivePos( pos - ( st.length - dt.length ) );  // カーソルを元の位置に戻す
  221.         Quit();
  222.       }
  223.       break;
  224.  
  225.  
  226.     // すべて削除
  227.     case 18:
  228.       // 各行ごとに、配列 q の並び順で最初にマッチした引用符を削除(最大 40回 まで削除を試行)
  229.  
  230.       var org = st;         // deleteQuote() のループ処理前のテキスト
  231.       for ( var i = 0; i < 40; i ++ ) { // st を最大40回 deleteQuote() でループ処理
  232.         var dt = DeleteQuote( st ); // 1サイクル ごとに、削除済みで返された全体を dt に取得
  233.         if ( dt == st )         // deleteQuote() 処理の前後でテキストが一致したら、
  234.           break;            //   ループを抜ける
  235.         else
  236.           st = dt;          // deleteQuote() 処理したテキスト dt を st に再代入
  237.       }
  238.  
  239.       // 選択範囲に引用符/コメントマークがなかった場合 undo 履歴を残さない
  240.       if ( dt == org ) {    // deleteQuote() ループ処理の前後でテキストが一致したら
  241.         // マクロ実行前に選択範囲がなかった場合はカーソルを元の位置に戻す
  242.         if ( pos ) { s.SetActivePos( pos );  Quit(); }
  243.         break;      //   中止
  244.       }
  245.  
  246.       s.Text = dt;  // 削除完了
  247.  
  248.       if ( pos && dt.length) {          // マクロ実行前に選択範囲がなかった場合は
  249.         s.SetActivePos( pos - ( org.length - dt.length ) ); // カーソルを元の位置に戻す
  250.         Quit();
  251.       }
  252.       break;
  253.  
  254.  
  255.     // クリップボード
  256.     case 40:
  257.       var cb = ClipboardData.GetData();     // クリップボードのテキストデータを取得
  258.       if ( cb )
  259.         s.Text = InsertQuote( st, cb );     // 各行の先頭に追加
  260.  
  261.        /* とりあえずコメントアウトしておく? */
  262. //       if ( pos ) {               // マクロ実行前に選択範囲がなかった場合は
  263. //         s.SetActivePos( pos + cb.length );   //   カーソルを元の位置に戻す
  264. //         Quit();
  265. //       }
  266.       break;
  267.  
  268.  
  269.     // 任意の文字列   ※テキストボックス
  270.     case 50:
  271.       // 文字コードには非対応(入力されたままの文字列を返す)
  272.       var p = Prompt(       // ダイアログのテキスト入力フィールドから文字列を取得
  273.         "前につける文字列:\t改行=\\\\\\n ; タブ=\\\\\\t  (注:¥記号3つ)", ""
  274.       ).replace( /\\\\\\n/g , "\n" ).replace( /\\\\\\t/g , "\t" );
  275.       if ( p )
  276.         s.Text = InsertQuote( st, p );      // 各行の先頭に追加
  277.  
  278.       /* とりあえずコメントアウトしておく? */
  279. //       if ( pos ) {               // マクロ実行前に選択範囲がなかった場合は
  280. //         s.SetActivePos( pos + p.length );    //   カーソルを元の位置に戻す
  281. //         Quit();
  282. //       }
  283.       break;
  284.  
  285.  
  286.     // 任意の文字列を削除
  287.     case 51:
  288.       var p = Prompt(       // ダイアログのテキスト入力フィールドから文字列を取得
  289.         "行頭から削除する文字列:\tタブ=\\\\\\t  (注:¥記号3つ)", ""
  290.       ).replace( /\\\\\\t/g , "\t" );
  291.       var reg = new RegExp( "^" + Quote( p ) , "gm" );
  292.       // Quote( p ) は p.replace( /\W/g, "\\$0" )
  293.       dt = st.replace( reg , "" );  // 各行の先頭の指定文字列を削除
  294.  
  295.       // 選択範囲に指定文字列がなかった場合 undo 履歴を残さない
  296.       if ( dt == st ) {     // replace() 処理の前後でテキストが一致したら
  297.         // マクロ実行前に選択範囲がなかった場合はカーソルを元の位置に戻す
  298.         if ( pos ) { s.SetActivePos( pos );  Quit(); }
  299.         break;          //   中止
  300.       }
  301.       else
  302.         s.Text = dt;        // 削除完了
  303.  
  304.       if ( pos && dt.length ) {         // マクロ実行前に選択範囲がなかった場合は
  305.         s.SetActivePos( pos - ( st.length - dt.length ) );  // カーソルを元の位置に戻す
  306.         Quit();
  307.       }
  308.       break;
  309.  
  310.  
  311.     /* JavaScript コメントアウト1 */
  312.     // <!-- XML コメントアウト -->  
  313.     case 41:  case 44:
  314.       // 「引用符/コメント」では行単位に拡張した選択範囲をまとめてコメントアウトするので、
  315.       // 行の中間部分だけをコメントアウトするなら「カッコで囲う」マクロを使うこと。
  316.  
  317.       var p1 = ( r == 41 ) ? "/* " :        // */
  318.               /* r == 42 */  "<!-- " ;
  319.       var p2 = ( r == 41 ) ? " */" :
  320.               /* r == 42 */  " -->";
  321.       s.Text = p1 + st + p2;            // 選択範囲 st をコメントアウト
  322.  
  323.       if ( ! st ) {             // マクロ実行前に空行だった場合は p1 & p2 だけ挿入
  324.         s.SetActivePos( pos + p1.length );  // カーソルをコメント枠のなかに移動
  325.         Quit();
  326.       }
  327.       break;
  328.  
  329.  
  330.     /* * JavaScript コメントアウト2 */
  331.     case 42:
  332.       /**
  333.        * ※ 行頭の字下げされた位置でコメントアウトする(コメントドキュメント向け)
  334.        * ・選択範囲内の最小の字下げ位置にあわせる。
  335.        * ・基本的に「JS アンコメント」してもレイアウトを保持できるが、
  336.        *   各行の字下げルールが同じである前提なので、半角スペースもタブコードも1文字として数える。
  337.        * ・空白文字だけの行は空行と見做し、行頭記号 " * " を付けた後ろに空白文字を残さない。
  338.        * ・「引用符/コメント」では行単位でコメントアウトするので、
  339.        *   行の中間部分だけをコメントアウトするなら「カッコで囲う」マクロを使うこと。
  340.        */
  341.  
  342.       var p1 = "/* ",  p2 = " */",  ast = " * ",  nl = "\n";    // 接頭辞 p1 は任意で "/** " に     */
  343.       s.Text = CommentOutJS( st, p1, p2, ast );     // 全体を /* *コメントアウト */
  344.  
  345.       if ( ! st ) {     // マクロ実行前に空行だった場合は /* \n & * & \n */ だけ挿入
  346.         s.SetActivePos( pos + ( p1 + nl + ast ).length  );  // カーソルをコメント枠のなかに移動
  347.         Quit();
  348.       }
  349.       break;
  350.  
  351.  
  352.     // JSアンコメント     ※選択範囲内の各行頭のコメントマークにのみマッチ
  353.     case 43:
  354.       // case 41 & 42 の JavaScript コメント をアンコメントする
  355.       /**
  356.        * ・この文章のようなインデントされたコメントブロックの字下げ位置を考慮するが、
  357.        *   先頭のコメントマーク "/*" のスラッシュの前の字下げ(空白部分)が基準となる。
  358.        *   cf.「カッコで囲う」マクロは字下げされた複数行のコメントをアンコメントできない。
  359.        *
  360.        * ・複数のコメントブロックが選択範囲内にある場合、最初のコメントブロックしかアンコメントしない。
  361.        *
  362.        * ・中間行の行頭記号はアスタリスク「*」と中黒「・」「・」を削除対象とする。
  363.        *   (行頭記号と前後の半角スペース各1を削除する)
  364.        * ・JSコメントでない箇条書き文で実行した場合も行頭記号を削除する。
  365.        *
  366.        * ▼ 注意事項 ▼
  367.        * ・選択範囲がJSコメントか箇条書き文であれば、選択範囲の先頭/末尾の余計な空白行も削除する。
  368.        *   中間行の末尾空白文字も削除し、空白行ならインデント部分も削除する。
  369.        *   c.f.「カッコで囲う」マクロのアンコメントでは余計なものを削除しない。
  370.        *       
  371.        * コメントマークは 配列 [ "接頭辞" , "接尾辞" , "中間行の行頭記号" ] で用意する。
  372.        *   ※ 検索・置換で * の数や 半角スペースの有無による差分を考慮する必要があるため、
  373.        *     各要素はあらかじめJSの正規表現で記述しておくこと。
  374.        */
  375.  
  376.       // コメントの"接頭辞"と"接尾辞"と"行頭記号"を正規表現で配列に格納
  377.       var p = new Array( "\\/\\*+ ?" , " ?\\*\\/" , " ?(\\*|[・・]) ?" );
  378.       // コメントアウトを解除
  379.       var dc = DeleteComment( st, p )
  380.  
  381.       // 選択範囲に /* JSコメント */ がなかった場合 undo 履歴を残さない
  382.       if ( dc == st ) {     // 処理の前後でテキストが一致したら
  383.         // マクロ実行前に選択範囲がなかった場合はカーソルを元の位置に戻す
  384.         if ( pos ) { s.SetActivePos( pos );  Quit(); }
  385.         break;          // 中止
  386.       }
  387.  
  388.       // 先頭と末尾の空行を削除してアンコメント完了
  389.       var blank = /[\t  ]*$/gm;   // 行末空白文字の正規表現(空白行をふくむ)
  390.       s.Text = dc.replace( blank , "" ).replace( /^[\s ]*\n|\n[\s ]*$/g , "" );
  391.       break;
  392.  
  393.  
  394.     // XML アンコメント
  395.     case 45:
  396.       // case 44 の <!--␣ XMLコメント ␣--> をアンコメントする
  397.  
  398.       // 選択範囲内のコメントマークをすべて削除
  399.       var dc = st.replace( / ?<!-- ?| ?-- *> ?/g , "" );
  400.  
  401.       // 選択範囲に <!-- XMLコメント --> がなかった場合 undo 履歴を残さない
  402.       if ( dc == st ) {     // replace() の前後でテキストが一致したら
  403.         // マクロ実行前に選択範囲がなかった場合はカーソルを元の位置に戻す
  404.         if ( pos ) { s.SetActivePos( pos );  Quit(); }
  405.         break;          // 中止
  406.       }
  407.       s.Text = dc       // アンコメント完了
  408.       break;
  409.  
  410.  
  411.     default:
  412.       break;
  413.   }
  414.  
  415.   // 選択範囲を復元(移動/コピー/切り取り しやすいように末尾改行まで含める)
  416.   s.SetActivePos( s.GetActivePos() + 1 );
  417.   s.SetAnchorPoint( mePosLogical, 1, ay );
  418.  
  419.   // 選択範囲の中身が ^\n のみなら選択解除
  420.   if ( s.Text.match( /^\n$/g ) )
  421.     s.SetActivePos( s.GetAnchorPos() );
  422.  
  423.   ScrollX = sx; ScrollY = sy;       // スクロール位置を復元
  424.   Redraw = true;
  425. }
  426.  
  427.  
  428. /* 関数 InsertQuote( arg1, arg2 ) */
  429.   // Kuro版まま
  430. function InsertQuote( arg1, arg2 ) {
  431.  
  432.   var a = arg1.split( "\n" );       // a は 選択範囲 st を \n で区切った配列
  433.   for ( var i = 0; i < a.length; i ++ ) // i は 行の配列 a の要素数(選択範囲の行数)
  434.     a[i] = arg2 + a[i];         // 各行の先頭に 引用符/クリップボードのデータ を加える
  435.  
  436.   return a.join( "\n" );        // 各行を "\n" で区切って連結しなおす
  437. }
  438.  
  439.  
  440. /* 関数 DeleteQuote( arg1 ) */
  441.   // Kuro版から
  442.   //   ①変数名を変更
  443.   //   ②最後の if 文の「break;」を補遺し、「1つ削除」の不具合を修正
  444. function DeleteQuote( arg1, arg2 ) {
  445.  
  446.   var a = arg1.split( "\n" );           // a は 選択範囲 st を \n で区切った配列
  447.   for ( var i = 0; i < a.length; i ++ ) {   // i は 行の配列 a の要素数(選択範囲の行数)
  448.  
  449.     for ( var j = 0; j < q.length; j ++ ) { // j は 引用符の配列 q の要素数
  450.       if ( q[j].length == 0 )           // 引用符の配列 q の空の要素 "" はスキップ
  451.         continue;
  452.  
  453.       var qt = q[j];                // 変数 qt に 引用符の各要素 q[j] を順繰りに代入
  454.       if ( a[i].substr( 0, qt.length ) == qt ) {    // 行 a[i] の先頭部分の文字列が引用符 q[j] にマッチしたら
  455.         a[i] = a[i].substr( qt.length );    // 引用符を削除 (引用符よりも後ろの文字列を返す)
  456.         break;  // マッチした引用符を除去したら、その行 a[i] はオシマイ(q[j] の次以降の要素を試行しない)
  457.       }
  458.     }
  459.   }
  460.   return a.join( "\n" );    // 各行を "\n" で区切って連結しなおす
  461. }
  462.  
  463.  
  464. /* 関数 CommentOutJS( arg0, arg1, arg2, arg3 ) */ // CommentOutJS( st, p1, p2, ast )
  465.   /**
  466.    * ※ 行頭のインデントを維持して字下げされた位置でコメントアウトするパターン(コメントドキュメント向け)
  467.    *   ・選択範囲内の最小の字下げ位置にあわせる。
  468.    *   ・基本的に「JS アンコメント」してもレイアウトを保持できるが、
  469.    *     各行の字下げルールが同じである前提なので、半角スペースもタブコードも1文字として数える。
  470.    *   ・空白文字だけの行は空行と見做し、行頭記号 " * " を付けた後ろに空白文字を残さない。
  471.    */
  472. function CommentOutJS( arg0, arg1, arg2, arg3 ) {
  473.  
  474.   var a = arg0.split( "\n" );   // 選択範囲 st を "\n" で区切って配列 a に
  475.   var b = [];           // 各行の字下げ数 id を取得する配列
  476.   // 各行の字下げ数からの最小値を取得
  477.   for ( var i = 0; i < a.length; i ++ ) {   // 「1行め」から繰りかえし処理
  478.     var id = a[i].search( /[^ \t]/ );       // 字下げの空白文字数を取得(空白行では -1)
  479.     b.push( ( id < 0 ) ? 100000 : id );     // ※ -1 は sort のジャマなのでデタラメな数値に置きかえる
  480.   }
  481.   b.sort( CompareForSort );     // 配列 b を昇順で並びかえ( => 最小値 b[0] だけ使う)
  482.   var blanc = a[0].slice( 0, b[0] );    // 先頭行から最小の字下げ部分の「空白文字 ␣␣ 」を取得
  483.  
  484.   // 字下げ位置に中間行の行頭記号 " * " を追加
  485.   for ( var i = 0; i < a.length; i ++ ) {   // 「1行め」から繰りかえし処理
  486.     if ( a[i].match( /^[ \t]*$/ ) )     // 空白行
  487.       a[i] = blanc + arg3;
  488.     else
  489.       a[i] = blanc + arg3 + a[i].slice( b[0] );
  490.   }
  491.   // 各行を "\n" で区切って連結し、接頭辞と接尾辞を付け足す
  492.   var prefix = blanc + arg1 + "\n"; // 接頭辞 "/*" の前に「字下げ ␣␣ 」、後ろに改行
  493.   var suffix = "\n" + blanc + arg2; // 接尾辞 " */" の前に改行と「字下げ ␣␣ 」
  494.   return prefix + a.join( "\n" ) + suffix;
  495. }
  496.  
  497.  
  498. /* *関数 DeleteComment( arg1, arg2 ) */
  499.   /*
  500.    * 複数のコメントブロックが選択範囲内にある場合、最初のコメントブロックしかアンコメントしない
  501.    * 引数 arg2 は 配列[ "接頭辞" , "接尾辞" , "中間行の接頭辞" ] で、
  502.    *   各要素はあらかじめJSの正規表現で記述されていないとダメ
  503.    */
  504. function DeleteComment( arg1, arg2 ) {
  505.  
  506.   // 選択範囲 st を "\n" で区切って配列 a に
  507.   var a = arg1.split( "\n" );      
  508.   var reg, re, id, a1, a2;
  509.   var hit = false, line0 = 0, line1 = a.length; // 初期化の必要な変数
  510.  
  511.   // コメントの接頭辞と接尾辞を検索・置換する
  512.   for ( var j = 0; j < 2; j ++ ) {
  513.     if ( arg2[j] == "" )        // 接頭辞 p[0], 接尾辞 p[1] が定義されていないならスルー
  514.       continue;
  515.     for ( var i = line0; i < a.length; i ++ ) { // 先頭行からループ処理
  516.       /* 検索フラグに "g" を付けないので、同じ行に同じコメントマークがあっても1つしか処理しない */
  517.       reg = RegExp( arg2[j] , "" );     // 接頭辞 p[0], 接尾辞 p[1] の検索用正規表現変数
  518.       if ( a[i].match( reg ) ) {        // ヒットしたら
  519.         a[i] = a[i].replace( reg , "" );    // 置換処理(削除)
  520.         if ( j == 0 ) {
  521.           line0 = i;                // 接頭辞がヒットした行
  522.           hit = true;               // ヒットフラグ = true
  523.           break;                // 接頭辞を処理したら接尾辞の処理へ
  524. /* i をインクリメントせず、j をインクリメントするので、以降の行 i++ で接頭辞 p[0] を検索・置換しない */
  525.         }
  526.         else {  // ( j == 1 )
  527.           line1 = i;                // 接尾辞がヒットした行
  528.           break;                // 接尾辞を処理したらループを抜ける
  529. /* i をインクリメントせず、j のループも終わるので、以降の行 i++ で接尾辞 p[1] を検索・置換しない */
  530.         }
  531.       }
  532.     }
  533.   }
  534.  
  535.   // 中間行の行頭記号 p[2] (アスタリスク、中黒)を検索・置換する
  536.   // 行頭空白文字の後ろの2文字までを置換対象にする    |^   a*bcdefg には誤爆しないはず
  537.   if ( arg2[2].length ) {
  538.     // 接頭辞(よりも前)の行と接尾辞(よりも後ろ)の行は、検索・置換の対象外にする
  539. //  for ( var i = ( hit ) ? line0 + 1 : 0; i < line1; i ++ ) {
  540.     /* 中間行の for 文は、以下の書き方のほうが読みやすいかも? */
  541.     for ( var i = 0; i < a.length; i ++ ) { // ※以下の条件付きでループの範囲を制限する }
  542.      if ( hit && i <= line0 )           // 接頭辞がヒットした行まではスキップする
  543.        continue;
  544.      if ( i == line1 )              // 接尾辞がヒットした行の手前まででループ終了
  545.        break;
  546.  
  547.       re = RegExp( "^[  \\t]*" + arg2[2] , "" );  // 行頭空白+行頭記号 検索用の正規表現変数
  548.       if ( a[i].match( re ) ) {             // 行頭記号がヒットしたら
  549.         id = a[i].indexOf( a[i].match( /[^  \t]/ ) ) + 2; // 置換範囲(空白文字数+2文字)
  550.         reg = RegExp( arg2[2] , "" );           // 行頭記号 置換用の正規表現変数
  551.         a1 = a[i].slice( 0, id ).replace( reg , "" );   // 空白文字の後ろの2文字までを置換
  552.         a2 = a[i].slice( id );      // 行頭記号よりも後ろの文字列は置換対象にしない
  553.         a[i] = a1 + a2;
  554.       }
  555.     }
  556.   }
  557.  
  558.   // 各行を "\n" で区切って連結しなおす
  559.   return a.join( "\n" );
  560. }
  561.  
  562.  
  563.  /* 以下の関数は『JavaScript/正規表現 - Wikibooks』より
  564.   https://ja.wikibooks.org/wiki/JavaScript/正規表現
  565.   https://ja.wikibooks.org/wiki/JavaScript/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE */
  566. // PerlのquotemetaやRubyのRegExp.quoteのように、()や[]など正規表現のメタ文字と解釈される可能性のある文字をエスケープして返す関数は、Stringオブジェクトのreplaceメソッドを使用して簡単に作成することができます。
  567. function Quote( str ) {
  568.     return str.replace( /\W/g, function( $0 ) {
  569.         return '\\' + $0;
  570.     } );
  571. };
  572.  
  573.  
  574.  /* 以下の関数は『sort メソッド (Array) (JavaScript) | MSDN』より
  575.   https://msdn.microsoft.com/ja-jp/library/4b4fbfhk%28v=vs.94%29.aspx */
  576. // Sorts array elements in ascending order numerically.
  577. // sort メソッドデフォルトの ascii 昇順 (1, 10, 2, 20) ではなく、数値の大きさ (1, 2, 10, 20) でソート
  578. function CompareForSort( first, second ) {
  579.   if ( first == second )
  580.     return 0;
  581.   if ( first < second )
  582.     return -1;
  583.   else  // ( first > second )
  584.     return 1;
  585. }
  586.  
  587.  
  588. // -----------------------------------------------------------------------------
  589.  
  590.  
  591. #title = "行コメント"
  592. #tooltip = "コメントマーク付けはずし"
  593. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",215
  594.  
  595. // 行コメント(sukemaru版)
  596. // 公式wikiの「コメントマーク付けはずし」マクロを改変
  597. // ref. 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
  598.  
  599. // マクロライブラリに転載済み (2018/10/28 + 2018/11/19)
  600. // (Last modified: 2018/12/02)  ◆ 人柱版 追加コード ◆       2018/11/14
  601. //              行の途中・右側のコメントに対応   2018/12/02
  602.  
  603. /**
  604.  * コメントマーク付けはずし
  605.  * ・手石/masme 版の「字下げされたコメントマークを削除できる」機能を下地として、
  606.  *   選択範囲のもっとも字下げの少ない位置にあわせてコメントマークを付けられます。
  607.  * ・空白行(タブ文字/半角スペースのみの行と、完全な空行)は無視します。
  608.  *
  609.  * ・範囲選択なしや複数行選択の状態なら、行頭でコメントアウト/アンコメントします。
  610.  *   1行内の選択範囲がある場合は、選択範囲の先頭位置でコメントアウト/アンコメントします。
  611.  *    ※ 選択範囲の先頭が空白文字なら字下げオプションに準じて処理します。
  612.  *
  613.  * ・編集モードによる定義切替は、masme 版まま。
  614.  *    "編集モードによる定義切替は、マクロ「Eclipse風コメントアウト」を参考にしました" とのこと。
  615.  * ・変数 comment の定義に "> " などの引用マークを指定すると、引用マークの付けはずしにも使用できます。
  616.  *
  617.  * ▼ 注意事項(仕様上の制限) ▼
  618.  * ※ 字下げルールが「半角スペースのみである または タブ文字のみである」か、
  619.  *   混在する場合には「半角スペースとタブ文字の出現順序が同じである」という前提になっています。
  620.  *   タブ文字ひとつを半角スペースひとつと同じように数え、表示上の幅で評価しません。
  621.  * ※ 行コメント文字の変数 comment = "" の先頭が空白文字だとアンコメントできません。
  622.  *
  623.  * ◆ 人柱版の追加オプション ◆
  624.  * ・comment 定義の末尾に空白×1 "//␣" があっても、"//こういうコメント行" をアンコメントできます。
  625.  * ※ 末尾空白2つ以上 "//␣␣" で定義して "//␣こういうコメント行" をアンコメントした場合
  626.  *   行頭に空白が1つ残ります。
  627.  *   → 字下げ対応で再度コメントアウトすると、1つ字下げした位置にコメントマークが付いてしまいます。
  628.  *
  629.  * ※ コメントマークの「付け/はずし」を各行に対してトグルするので、
  630.  *   以下のようなコードブロックをまとめて操作すると、1~3行目はアンコメントし、
  631.  *   4行目以降はコメントアウトします(indent > 0)。
  632.  
  633.     ※ コメントマークの定義 "//␣" (末尾に半角スペースつき)
  634.        → ◆ 人柱版 ◆ sEnable = true; ◆ なら "//コメント0" の行のアンインデント可
  635.  
  636. 例0-1. 字下げに非対応だと…  ※ indent = 0;  sEnable = false;  のばあい
  637. //コメント0           =>      |// //コメント0      =>        |//コメント0  
  638. // コメント1          =>      |コメント1           =>        |// コメント1  
  639.   // コメント2        =>      |//  // コメント2    =>        |  // コメント2
  640.  
  641. 例0-2. 字下げには非対応でも…   ※ indent = 0;  ◆sEnable = true;  (sukemaru版 独自拡張)
  642. //コメント0           =>      |コメント0           =>        |// コメント0  
  643. // コメント1          =>      |コメント1           =>        |// コメント1  
  644.   // コメント2        =>      |//  // コメント2    =>        |  // コメント2
  645.  
  646. 例1-1. 6行まとめて選択すると…    ※ indent = 1;  sEnable = false;  (従来版とおなじ動作)
  647. //コメント0           =>      |// //コメント0      =>        |//コメント0  
  648. // コメント1          =>      |コメント1           =>        |// コメント1  
  649.   // コメント2        =>      |  コメント2         =>        |//   コメント2
  650.   hoge                 =>      |//   hoge            =>        |  hoge        
  651.     fuga               =>      |//     fuga          =>        |    fuga      
  652.       piyo             =>      |//       piyo        =>        |      piyo    
  653.  
  654. 例1-2. 6行まとめて選択でも…       ※ ●indent = 1;  ◆sEnable = true;  (sukemaru版 独自拡張)
  655. //コメント0           =>      |コメント0           =>        |// コメント0  
  656. // コメント1          =>      |コメント1           =>        |// コメント1  
  657.   // コメント2        =>      |  コメント2         =>        |//   コメント2
  658.   hoge                 =>      |//   hoge            =>        |  hoge        
  659.     fuga               =>      |//     fuga          =>        |    fuga      
  660.       piyo             =>      |//       piyo        =>        |      piyo    
  661.                                    
  662. 例2-1. 下3行だけを選択すれば…    ※ ●indent = 2 or 3;  (sukemaru版 独自拡張)
  663. //コメント0           =>      |//コメント0         =>        |//コメント0  
  664. // コメント1          =>      |// コメント1        =>        |// コメント1  
  665.   // コメント2        =>      |  // コメント2      =>        |  // コメント2
  666.   hoge                 =>      |  // hoge            =>        |  hoge        
  667.     fuga               =>      |  //   fuga          =>        |    fuga      
  668.       piyo             =>      |  //     piyo        =>        |      piyo    
  669.  
  670. 例2-2. 下4行を選択だと… ※ ●indent = 2 or 3;  (sukemaru版 独自拡張)
  671. //コメント0           =>      |//コメント0         =>        |//コメント0  
  672. // コメント1          =>      |// コメント1        =>        |// コメント1  
  673.   // コメント2        =>      |  コメント2         =>        |  // コメント2
  674.   hoge                 =>      |  // hoge            =>        |  hoge        
  675.     fuga               =>      |  //   fuga          =>        |    fuga      
  676.       piyo             =>      |  //     piyo        =>        |      piyo    
  677.  
  678. 例3. 6行まとめて選択しても、コメントアウトとアンコメントで別々の先頭位置を使うこともできる
  679.     ※ ●indent = 3;  ◆sEnable = true;  (sukemaru版 独自拡張)
  680. //コメント0           =>      |コメント0           =>        |// コメント0  
  681. // コメント1          =>      |コメント1           =>        |// コメント1  
  682.   // コメント2        =>      |  コメント2         =>        |//   コメント2
  683.   hoge                 =>      |  // hoge            =>        |  hoge        
  684.     fuga               =>      |  //   fuga          =>        |    fuga      
  685.       piyo             =>      |  //     piyo        =>        |      piyo    
  686.  
  687. 例4. 一応、こういうこともできる
  688.     ※ ●indent = 4;  ◆sEnable = true;  (sukemaru版 独自拡張)
  689. //コメント0           =>      |コメント0           =>        |// コメント0  
  690. // コメント1          =>      |コメント1           =>        |// コメント1  
  691.   //コメント2         =>      |  コメント2         =>        |  // コメント2
  692.   hoge                 =>      |  // hoge            =>        |  hoge        
  693.     fuga               =>      |    // fuga          =>        |    fuga      
  694.       piyo             =>      |      // piyo        =>        |      piyo    
  695.  
  696. 例5. コードブロックをまとめてコメントアウトするなら「引用符/コメント」マクロが適している...
  697.     ※ 以下の用例は「引用符/コメント」マクロの 「// JS-C コメント」と「1つ削除」
  698.  
  699. //コメント0           =>      |// //コメント0      =>        |//コメント0  
  700. // コメント1          =>      |// // コメント1     =>        |// コメント1  
  701.   // コメント2        =>      |//   // コメント2   =>        |  // コメント2
  702.   hoge                 =>      |//   hoge            =>        |  hoge        
  703.    fuga                =>      |//     fuga          =>        |    fuga      
  704.      piyo              =>      |//       piyo        =>        |      piyo    
  705.  */
  706.  
  707. // ●字下げされたコメントマークも削除するか?
  708. var indent = 3;
  709.   // indent = 0; なら 追加/削除 する位置は「常に行頭」のみ(字下げされたコメントマークを削除しない)
  710.   //  ※ 1 ~ 4  なら字下げされたコメントマークも削除する。追加する位置は以下のとおり。
  711.   // indent = 1; なら「常に先頭」にコメントマークを追加する(例1.の使い方 ※従来版とおなじ挿入パターン)
  712.   //  ※ 2 ~ 4  なら追加する位置は字下げに対応可。
  713.   // indent = 2; なら追加と削除で同じ判定基準の先頭位置検出をする(例2.の使い方ができる)
  714.   // indent = 3; なら追加と削除で別々の判定基準の先頭位置検出をする(例3.の使い方)
  715.   // indent = 4; なら「常に各行の字下げ位置」にあわせてコメントマークを追加する(例4.の使い方)
  716.  
  717.  
  718. // ◆ 人柱版の追加オプション ◆  (※ 動作確認は不十分)
  719. // ◆コメントマーク末尾に空白つきで定義しているときに、末尾空白のないコメントマークも削除するか?
  720. var sEnable = true;
  721.   // (※ comment = "// "; のときに "//こういうコメント行" をアンコメントするか?)
  722.   // sEnable = true;  なら削除する
  723.   // sEnable = false; なら削除しない
  724.   // ※ 再度コメントアウトするさいは comment で定義したコメントマーク(末尾空白つき)になります。
  725.   //   コメントマークを comment 末尾に空白なしで定義した場合は無視されます。
  726.  
  727. // ◆ 人柱版 ◆ はコメントマークの定義に "末尾空白" ありがデフォルト
  728. /* ここから「コメントマーク付け外し」(masme版 2016/02/28)より流用 */
  729. // ■行コメント文字の定義  ●初期値="// "
  730. var comment = "// ";
  731.   // 「var comment = "> ";」にするか、下の定義切替ブロックに「case "text": return "> ";」
  732.   // を追加すると引用マークの付けはずしにもなります (sukemaru)
  733.  
  734. // ▼編集モードによる定義切替
  735. comment = ( function() {
  736.  
  737.   // ▼ファイル名/拡張子による定義切り替え
  738.   // 拡張子で切り替え
  739.   if ( document.Name.match( /\.def$|\.asm$|\.reg$|\.key$|\.inf$/i ) )
  740.     return "; ";
  741.   else if ( document.Name.match( /\.msy$|^hosts$/i ) )
  742.     return "# ";
  743.   // ファイル名で切り替え
  744.   // else if ( document.Name.toLowerCase() == "hoge.txt" )
  745.   //   return "※ ";
  746.   // フォルダ名で切り替え
  747.   // else if ( document.FullName.match( /\\mery\\(?!macros)/ ) )
  748.   //   return "> ";
  749.  
  750.   else
  751.     // ▼編集モードによる定義切り替え
  752.     switch ( document.Mode.toLowerCase() ) {
  753.       case "bat":
  754.         return ":: ";   // return "REM ";  ": " や "' " でも可
  755.  
  756.       case "c#":  case "c++":  case "javascript":
  757.       // case "delphi":  case "java":  case "jsp":
  758.       // case "windows script":  case "mery_macros_js":
  759.         return "// ";
  760.  
  761.       case "ini":  case "python":  case "ruby":
  762.       // case "perl":  case "perlscript":  case "php":  case "python":
  763.       // case "powershell":  case "ruby":  case "autohotkey":  case "mery msy":
  764.         return "# ";
  765.  
  766.       case "visualbasic":  case "vbscript":
  767.         return "' ";
  768.  
  769.       // case "hsp":
  770.       //   return "; ";
  771.       // case "sql":
  772.       //   return "-- ";
  773.       // case "tex":
  774.       //   return "% ";
  775.  
  776.       // case "text":
  777.       //   return "> ";
  778.  
  779.       default:
  780.         return comment;
  781.     }
  782. } )();
  783. /* ここまで「コメントマーク付け外し」(masme版 2016/02/28)より流用 */
  784.  
  785.  
  786. // ◆ コメントマークの末尾が空白文字の場合、末尾空白なしのパターンを定義 ◆ 人柱版 ◆
  787. if ( sEnable && comment.match( /\s+$/ ) )
  788.   var cStr = comment.replace( /\s+$/ , "" );
  789.  
  790. // 選択範囲
  791. var s = document.selection;
  792. var tx = s.GetTopPointX( mePosLogical );
  793. var ty = s.GetTopPointY( mePosLogical );
  794. var bx = s.GetBottomPointX( mePosLogical );
  795. var by = s.GetBottomPointY( mePosLogical );
  796. var anc = s.GetAnchorPos();     // 選択範囲の開始位置
  797. var act = s.GetActivePos();     // 選択範囲の終了位置
  798. var pos = ( s.IsEmpty ) ? true : false; // 範囲選択なしのフラグ
  799.  
  800. // 1行内で範囲選択しているとき(右側のコメントアウト)
  801. if ( ty == by && ! pos )
  802.   var part = true;          // 部分選択のフラグ
  803.  
  804. // 範囲選択なし または 複数行選択のとき(行全体のコメントアウト)
  805. else {
  806.   // 選択範囲の末尾が行頭にあるときの調整
  807.   if ( ty != by && bx == 1 )
  808.     by --;
  809.   // 選択範囲を拡張
  810.   s.SetActivePoint( mePosLogical, 1, by );
  811.   s.EndOfLine( false, mePosLogical );
  812.   s.SetAnchorPoint( mePosLogical, 1, ty );
  813. }
  814.  
  815. var st = s.Text;            // 元の文字列を取得
  816. var ad = AddDeleteComment( st );    // コメントアウト/アンコメント処理
  817.  
  818. if ( ad != st )     // (処理の前後で変化なしなら undo 履歴に残さない)
  819.   s.Text = ad;      // コメントマークの付けはずし完了
  820. var gap = st.length - ad.length;
  821.  
  822. // 選択範囲なしで実行したときは範囲選択を残さない
  823. if ( pos ) {
  824.     s.SetActivePoint( mePosLogical, ( gap < tx ) ? tx - gap : 1, ty );
  825. }
  826. // 選択範囲が1行だけのときは選択範囲を復旧する
  827. else if ( part ) {
  828.   s.SetActivePos( ( anc < act ) ? act - gap : act );
  829.   s.SetAnchorPos( ( anc < act ) ? anc : anc - gap );
  830. }
  831. // 複数行選択なら拡張した選択範囲を復旧する
  832. else {
  833.   s.SetActivePoint( mePosLogical, 1, by + 1 );
  834.   s.SetAnchorPoint( mePosLogical, 1, ty );
  835. }
  836.  
  837.  
  838. // ◆ 人柱版 ◆
  839.  /* 関数 AddDeleteComment() */
  840.   // 選択範囲の各行の字下げ量をチェックして、最小の字下げ位置にあわせてコメントアウトする
  841.   // コメントマークのチェックには正規表現を使っていないので、誤爆はないはず
  842.   // ※変数 comment の先頭が空白文字(半角スペース、タブコード \t)だとアンコメントできない
  843.  
  844. function AddDeleteComment( arg1 ) {
  845.  
  846.   // 選択範囲が1行内で、行の途中の空白文字の場合はコメントアウト
  847.   if ( part && tx != 1 && str.match( /^[ \t]*$/ ) )
  848.     return comment + str;
  849.  
  850.   else {
  851.     var a = arg1.split( "\n" ); // 選択範囲を行単位に分解して配列 a に
  852.     var b = [], c = [], d = []; // 空の配列(id, _id を格納する)
  853.     var id, _id;        // 字下げ量(空白以外の文字の最初の出現位置)
  854.  
  855.     // 選択範囲内の各行の字下げ量を取得 => 配列 b c d に
  856.     for ( var i = 0; i < a.length; i ++ ) {
  857.       id = a[i].indexOf( a[i].match( /[^ \t]/ ) );  // 空白行では -1
  858.  
  859.       // -1 は sort のジャマなのでデタラメな数値にしておく(配列内の最小値を 0 以上に)
  860.       if ( id < 0 )
  861.         id = 1000000;       // 空白行はコメントアウトしないから数値は大きく
  862.       b.push( id );     // id を配列 b c に格納
  863.       if ( indent == 2 )
  864.         c.push( id );
  865.       if ( indent == 3 ) {  // コメント行の数値もデタラメに
  866.         _id = ( a[i].substr( b[i], comment.length ) == comment ) ? 1000000 : id;
  867.         d.push( _id );      // _id を配列 d に格納
  868.       }
  869.     }   // end for
  870.  
  871.     // 配列 c d を昇順で並びかえ( => 最小値 c[0] d[0] だけ使う)
  872.     if ( indent == 2 )
  873.       c.sort( CompareForSort );
  874.     if ( indent == 3 )
  875.       d.sort( CompareForSort );
  876.  
  877.     // 各行をコメントアウト/アンコメント処理
  878.     for ( var i = 0; i < a.length; i ++ ) {
  879.       if ( b[i] == 1000000 )        // 空白行はスキップ
  880.         continue;
  881.  
  882.       // 行頭の空白 b[i] の直後がコメントマークかチェック
  883.       // "// コメント行" なら...
  884.       if ( a[i].substr( b[i], comment.length ) == comment ) {
  885.         a[i] =
  886.           ( indent != 0 || b[i] == 0 ) ? a[i].substr( 0, b[i] ) + a[i].substr( b[i] + comment.length ) :
  887.          /* indent == 0 && b[i] != 0 */  comment + a[i];
  888.       }
  889.  
  890.       // ◆ 人柱版 追加コード ◆
  891.       // 定義されたコメントマークの末尾が空白文字つき "// " なら...
  892.       // 各行が末尾空白なしの "//" でコメントアウトされているか再チェックして処理
  893.       else if ( sEnable && cStr && a[i].substr( b[i], cStr.length ) == cStr ) {
  894.         a[i] =
  895.           ( indent != 0 || b[i] == 0 ) ? a[i].substr( 0, b[i] ) + a[i].substr( b[i] + cStr.length ) :
  896.          /* indent == 0 && b[i] != 0 */  comment + a[i];
  897.       } // ◆ 人柱版 追加コード ◆ ここまで
  898.  
  899.       // 非コメント行なら... コメントマークを追加する
  900.       else {
  901.         a[i] = ( indent == 4 ) ? a[i].slice( 0, b[i] ) + comment + a[i].slice( b[i] ) :
  902.                ( indent == 3 ) ? a[i].slice( 0, d[0] ) + comment + a[i].slice( d[0] ) :
  903.                ( indent == 2 ) ? a[i].slice( 0, c[0] ) + comment + a[i].slice( c[0] ) :
  904.                /*   else    */   comment + a[i];
  905.       }
  906.  
  907.     }   // end  for
  908.     return a.join( "\n" );
  909.   } // end  else
  910. }   // end  function
  911.  
  912.  
  913.  /* 以下の関数は『sort メソッド (Array) (JavaScript) | MSDN』より
  914.   https://msdn.microsoft.com/ja-jp/library/4b4fbfhk%28v=vs.94%29.aspx */
  915. // Sorts array elements in ascending order numerically.
  916. // sort メソッドデフォルトの ascii 昇順 (1, 10, 2, 20) ではなく、数値の大きさ (1, 2, 10, 20) でソート
  917. function CompareForSort( first, second ) {
  918.   if ( first == second )
  919.     return 0;
  920.   else if ( first < second )
  921.     return -1;
  922.   else  // ( first > second )
  923.     return 1;
  924. }
  925.  
  926.  
  927. // -----------------------------------------------------------------------------
  928.  
  929.  
  930. #title = "インデント"
  931. #tooltip = "選択範囲がなくてもインデント"
  932. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",260
  933.  
  934. // ・選択範囲なしでも、論理行全体をタブインデント(行頭)して範囲選択する
  935. //   選択範囲が1行内ならもとの選択範囲を維持し、複数行なら対象の論理行全体を範囲選択する
  936. // ・またはカーソル位置にタブ文字を挿入する
  937. // ※機能は「字上げ(スペース×2 追加)」マクロとほぼ同じだが、こちらの場合は挿入する空白は「タブ文字」のみで、空白行にたいしてもインデントする
  938. // 【推奨設定】 Tab キーに割りあてるなら tabEnable = 2, ツールバーアイコンにするなら tabEnable = 0
  939.  
  940.  
  941. // ■選択範囲があるときに、選択範囲を「タブ文字」にするか? 行全体をタブインデントするか?
  942. var tabEnable = 0;
  943.  
  944.   // 0 にすると、選択範囲がなくてもつねに行全体をタブインデント(行頭)
  945.   // 1 にすると、選択範囲があれば行全体をタブインデント(※ツールバーアイコンの「インデント」に似た動作)
  946.   // 2 にすると、選択範囲が1行内のときだけ選択範囲を「タブ文字」にする (※Tab キーの通常動作にちかい)
  947.   // 3 にすると、つねに選択範囲を「タブ文字」にする(※インデントしない)
  948.  
  949.   // ※ 0 の場合、「タブ文字」を挿入することができないので、ツールバーアイコン向けの設定。
  950.   // ※ 1 の場合、選択範囲を「タブ文字」にすることができないので、Tab キーにマクロを割りあてると少し不便になるかも?
  951.   //   範囲選択 → 削除 (Delete / BackSpace) → 「インデント」マクロ (Tab)
  952.   // ※ 2 の場合に1行だけインデントさせるなら、行頭でクリックするか、行内でトリプルクリック
  953.   //   または行番号のクリックで行全体を選択範囲にして「インデント」マクロ (末尾改行まで含める必要あり)。
  954.   //   [EOF] マークのある(さいごに改行がない)文書末行だけの1行選択ではインデントできない。
  955.   //   ⇔ Tab キーの通常動作では末尾改行を含める必要はない
  956.   // ※ 3 は、わざわざマクロでやる意味もないかと。
  957.  
  958.  
  959. var sx = ScrollX,  sy = ScrollY;
  960. var s = document.selection;
  961.  
  962. // 選択範囲
  963. var act = s.GetActivePos();
  964. var anc = s.GetAnchorPos();
  965. var ty = s.GetTopPointY( mePosLogical );
  966. var bx = s.GetBottomPointX( mePosLogical );
  967. var by = y = s.GetBottomPointY( mePosLogical );
  968.  
  969. // カーソル位置にタブを挿入して終了するパターン
  970. if ( ( s.IsEmpty && tabEnable == 1 ) || ( tabEnable == 2 && ty == by ) || tabEnable == 3 ) {
  971.   s.Text = "\t";
  972.   Quit();
  973. }
  974.  
  975. // 選択範囲を拡張
  976. if ( ty != by && bx == 1 )
  977.   y --;     // 選択範囲の末尾が行頭 x = 1 にあるときの調整
  978. s.SetActivePoint( mePosLogical, 1, y );
  979. s.EndOfLine( false, mePosLogical );
  980. s.SetAnchorPoint( mePosLogical, 1, ty );
  981. var st = s.Text;
  982.  
  983. // インデント
  984. s.Text = st.replace( /^/gm , "\t" );
  985.  
  986. // 選択範囲を復元
  987. if ( ty == by ) {   // 1行なら、もとの選択範囲を復元
  988.   s.SetActivePos( act + 1 );
  989.   s.SetAnchorPos( anc + 1 );
  990. }
  991. else {          // 複数行なら、論理行を選択範囲に
  992.   s.SetActivePos( s.GetActivePos() + 1 );
  993.   s.SetAnchorPoint( mePosLogical, 1, ty );
  994. }
  995. ScrollX = sx;  ScrollY = sy;
  996.  
  997.  
  998. // -----------------------------------------------------------------------------
  999.  
  1000.  
  1001. #title = "逆インデント"
  1002. #tooltip = "選択範囲がなくてもアンインデント"
  1003. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",261
  1004.  
  1005. // 選択範囲なしでも、行頭またはカーソル付近の「タブ文字×1」か、行頭の「半角スペース×2」を削除する
  1006. // ・選択範囲なしならカーソル付近のタブを削除するか
  1007. //   またはカーソルのある1行をアンインデントして、カーソル位置を復帰する
  1008. // ・選択範囲ありなら論理行全体をアンインデントして範囲選択する
  1009. // ※機能は「字上げ(スペース×2 削除)」マクロとほぼ同じだが、削除できる「半角スペース×n」の最大数をかんたんに設定できるようにした ( "␣␣␣␣", "␣␣␣", "␣␣", "␣" なら 4 と指定するだけ)
  1010. // 設定用変数 deleteSpace = n で 3 以上の数値を指定するさいは、Mery のオプション設定の「タブの桁数」を目安にすること(大きな数字や非整数値を入れての動作検証はしていない)。
  1011.  
  1012.  
  1013. // ■選択範囲なしのときに、カーソル位置の前後にある「タブ文字」を優先的に削除するか?
  1014. // var nearestTab = false;
  1015. var nearestTab = true;
  1016.  
  1017.   // false にすると、つねに行頭の空白文字のみを削除
  1018.   // true にすると、カーソル付近の「タブ文字×1」を優先的に削除(タブ文字がなければ行頭の空白を削除)
  1019.  
  1020.  
  1021. // ■行頭の「半角スペース」や「「全角スペース」も削除するか?
  1022. var deleteSpace = 1;
  1023.  
  1024.   // ※ 正の整数値で指定してください
  1025.   // 0 にすると、「タブ文字×1」だけを削除
  1026.   // 1 にすると、行頭の「半角スペース×2」と「半角スペース×1」も削除
  1027.   // 2 にすると、行頭の「半角スペース×2」と「半角スペース×1」と「全角スペース×1」も削除
  1028.   // 3 以上にすると、1回の逆インデントで削除できる「半角スペース×n」の最大数が増加
  1029.   //   → 削除できる「全角スペース」の最大数は n / 2 (初期設定では小数点以下を切り捨て)
  1030.  
  1031.  
  1032. var sx = ScrollX,  sy = ScrollY;
  1033. var s = document.selection;
  1034.  
  1035. // "選択範囲なし" のフラグ
  1036. if ( s.IsEmpty )
  1037.   var pos = s.GetActivePos();
  1038.  
  1039. // カーソル付近の「タブ文字×1」を削除する場合(左側優先)
  1040. if ( pos && nearestTab ) {
  1041.   if ( document.Text.charAt( pos - 1 ) == "\t" ) {
  1042.     s.DeleteLeft();  Quit();
  1043.   }
  1044.   else if ( document.Text.charAt( pos ) == "\t" ) {
  1045.     s.Delete();  Quit();
  1046.   }
  1047. }
  1048.  
  1049. // 選択範囲
  1050. var act = s.GetActivePos();
  1051. var anc = s.GetAnchorPos();
  1052. // var tp = ( anc < act ) ? anc : act;  // 選択範囲の先頭位置
  1053. // var bp = ( anc < act ) ? act : anc;  // 選択範囲の末尾位置
  1054. // var tx = s.GetTopPointX( mePosLogical );
  1055. var ty = s.GetTopPointY( mePosLogical );
  1056. var bx = s.GetBottomPointX( mePosLogical );
  1057. var by = y = s.GetBottomPointY( mePosLogical );
  1058. // 選択範囲を拡張
  1059. if ( ty != by && bx == 1 )
  1060.   y --;     // 選択範囲の末尾が行頭 x = 1 にあるときの調整
  1061. s.SetActivePoint( mePosLogical, 1, y );
  1062. s.EndOfLine( false, mePosLogical );
  1063. s.SetAnchorPoint( mePosLogical, 1, ty );
  1064. var st = s.Text;
  1065.  
  1066. // 逆インデント
  1067. // ( deleteSpace >= 3 ) では、/^\t|^[ ]{1,n}|^[ ]{1,m}/gm  の n に deleteSpace の値、m に n/2 を代入 ※toString().replace() で小数点以下を切り捨て
  1068. // ■ m = n/2 の小数点以下を切り上げ(四捨五入)にするなら Math.round() 関数の行を使用する
  1069. // ※必ず ( deleteSpace >= 3 ) の行のひとつをコメントアウト状態にしておくこと
  1070. var indent = ( deleteSpace == 1 ) ? "^\\t|^[ ]{1,2}" :
  1071.              ( deleteSpace == 2 ) ? "^\\t|^[ ]{1,2}|^[ ]" :
  1072.              ( deleteSpace >= 3 ) ? "^\\t|^[ ]{1," + deleteSpace + "}|^[ ]{1," + ( deleteSpace / 2 ).toString().replace( /\.\d+$/ , "" ) + "}" :
  1073. //           ( deleteSpace >= 3 ) ? "^\\t|^[ ]{1," + deleteSpace + "}|^[ ]{1," + Math.round( deleteSpace / 2 ) + "}" :
  1074.              /*      else      */   "^\\t";
  1075. var u = st.replace( new RegExp( indent , "gm" ) , "" );
  1076. if ( u != s.Text )
  1077.   s.Text = u;
  1078.  
  1079. // カーソル位置または選択範囲を復元
  1080. if ( ty == by ) {   // 1行なら、もとの選択範囲を復元
  1081.   s.SetActivePos( act - ( st.length - u.length ) );
  1082.   s.SetAnchorPos( anc - ( st.length - u.length ) );
  1083.   if ( s.GetTopPointY( mePosLogical ) != ty )   // ダメなら行頭へ
  1084.     s.SetActivePoint( mePosLogical, 1, ty );
  1085. }
  1086. else {          // 複数行なら、論理行を選択範囲に
  1087.   s.SetActivePos( s.GetActivePos() + 1 );
  1088.   s.SetAnchorPoint( mePosLogical, 1, ty );
  1089. }
  1090. ScrollX = sx;  ScrollY = sy;
  1091.  
  1092.  
  1093. // -----------------------------------------------------------------------------
  1094.  
  1095.  
  1096. #title = "字下げ"
  1097. #tooltip = "スペース×2 追加"
  1098. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",247
  1099.  
  1100. // 選択範囲がなかった場合は「タブ文字」を追加/または「半角スペース×2」を行頭に追加する
  1101. // 選択範囲があった場合は、つねに「半角スペース×2」を行頭に追加する(空行は無視)
  1102. // ※「引用の追加」マクロから行頭に文字列を追加するコードを拝借した
  1103. // (※マクロライブラリに転載済み 2018/11/02)
  1104.  
  1105.  
  1106. // ■選択範囲なしのときには「タブ文字×1」を追加するか?
  1107. var tabEnable = 0;
  1108.   // 0 なら、「半角スペース×2」を行頭に追加する(空行は無視)
  1109.   // 1 なら、選択範囲なしのときは「タブ文字×1」を行頭に追加する
  1110.   // 2 なら、選択範囲なしのときは「タブ文字×1」をキャレット位置に追加する
  1111.  
  1112. // ■行頭に追加する空白文字の定義(初期値:「半角スペース×2」)
  1113. var blank = "  ";       // 半角スペース×2
  1114.  
  1115.  
  1116. var s = document.selection;
  1117.  
  1118. // "選択範囲なし" のフラグ
  1119. var pos = ( s.IsEmpty ) ? s.GetActivePos() : "";
  1120.  
  1121. // キャレット位置に「タブ文字×1」を挿入して終了するパターン
  1122. if ( pos && tabEnable > 1 ) {
  1123.   s.Text = "\t";
  1124.   Quit();
  1125. }
  1126.  
  1127. var sx = ScrollX,  sy = ScrollY;
  1128. // 選択範囲を取得
  1129. var ty = s.GetTopPointY( mePosLogical );
  1130. var bx = s.GetBottomPointX( mePosLogical );
  1131. var by = s.GetBottomPointY( mePosLogical );
  1132. // 選択範囲を拡張
  1133. if ( by != ty && bx == 1 )
  1134.   by -= 1;
  1135. s.SetActivePoint( mePosLogical, 1, by );
  1136. s.EndOfLine( false, mePosLogical );
  1137. s.SetAnchorPoint( mePosLogical, 1, ty );
  1138.  
  1139. // 選択範囲の文字列を取得
  1140. var st = s.Text;
  1141.  
  1142. // 最初に選択範囲がなかった場合は、行頭に「タブ文字×1」を追加
  1143. if ( pos && tabEnable == 1 ) {
  1144.   var tab = "\t";
  1145.   s.Text = InsertSpace( st, tab );
  1146.   s.SetActivePos( pos + tab.length );   // 範囲選択を残さない
  1147. }
  1148.  
  1149. // 選択範囲があった場合は、行頭に「半角スペース×2」を追加(空行は無視)
  1150. else {          // ( ! pos || tabEnable == 0 )
  1151.   var t = InsertSpace( st, blank );
  1152.   if ( t != st )
  1153.     s.Text = t;
  1154.  
  1155.   if ( pos )        // 範囲選択を残さない
  1156.     s.SetActivePos( pos + ( t.length - st.length ) );
  1157.   else {        // 範囲選択を残す(論理行を選択範囲に)
  1158.     s.SetActivePoint( mePosLogical, 1, by + 1 );
  1159.     s.SetAnchorPoint( mePosLogical, 1, ty );
  1160.   }
  1161. }
  1162.  
  1163. ScrollX = sx;  ScrollY = sy;
  1164.  
  1165.  
  1166. // 「引用の追加」マクロより拝借
  1167. function InsertSpace( arg1, arg2 ) {
  1168.   var a = arg1.split( "\n" );
  1169.   for ( var i = 0; i < a.length; i ++ )
  1170.     if ( a[i].length || arg2 == "\t" )
  1171.       a[i] = arg2 + a[i];
  1172.   return a.join( "\n" );
  1173. }
  1174.  
  1175.  
  1176. // -----------------------------------------------------------------------------
  1177.  
  1178.  
  1179. #title = "字上げ"
  1180. #tooltip = "スペース×2 削除"
  1181. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",249
  1182.  
  1183. // 行頭の「空白文字」を削除/またはキャレット位置の前後にある「タブ文字」を削除する
  1184. // 選択範囲があった場合は、つねに行頭の「空白文字」だけを削除する
  1185. // 削除対象の「空白文字」は、「半角スペース×2」以外の空白文字もふくめて配列 blank で定義する
  1186. // ※「引用の追加」マクロから行頭の文字列を削除するコードを拝借した
  1187. // (※マクロライブラリに転載済み 2018/11/02)
  1188.  
  1189. // (最終更新: 2018/11/19)
  1190.  
  1191.  
  1192. // ■選択範囲なしのときに、キャレット位置の前後にある「タブ文字」を優先的に削除するか?
  1193. var nearestTab = true;
  1194.  
  1195.   // false にすると、つねに行頭の空白文字のみを削除
  1196.   // true にすると、キャレット付近の「タブ文字×1」を優先的に削除(タブ文字がなければ行頭の空白を削除)
  1197.  
  1198. // ■削除対象(削除の単位)にする行頭の空白文字の定義
  1199. var blank = new Array( "  " , " " , " " , "\t" );
  1200.  
  1201.   // 初期値: new Array( "  " , " " , " " , "\t" )
  1202.   // i.e. 「半角スペース×2 "  "」「半角スペース×1 " "」「全角スペース×1 " " 」「タブ文字×1 "\t"」
  1203.   // ※ 前に置いたもののほうが優先順位が高くなるので、行頭に半角スペースが3つある行で連続で実行した場合、
  1204.   //   1回目では「半角スペース×2」を削除し、2回目で「半角スペース×1」を削除する
  1205.   // ※ 空白文字以外の "文字列" を Array() のなかに追加するのも可
  1206.  
  1207.  
  1208. var s = document.selection;
  1209.  
  1210. // "選択範囲なし" のフラグ
  1211. var pos = ( s.IsEmpty ) ? s.GetActivePos() : "";
  1212.  
  1213. // キャレット付近の「タブ文字×1」を優先的に削除するパターン
  1214. if ( pos && nearestTab ) {
  1215.   if ( document.Text.charAt( pos - 1 ) == "\t" ) {
  1216.     s.DeleteLeft();
  1217.     Quit();
  1218.   }
  1219.   else if ( document.Text.charAt( pos ) == "\t" ) {
  1220.     s.Delete();
  1221.     Quit();
  1222.   }
  1223. }
  1224.  
  1225. var sx = ScrollX,  sy = ScrollY;
  1226.  
  1227. // 選択範囲を取得
  1228. var ty = s.GetTopPointY( mePosLogical );
  1229. var by = s.GetBottomPointY( mePosLogical );
  1230. var bx = s.GetBottomPointX( mePosLogical );
  1231. // 選択範囲を拡張
  1232. if ( by != ty && bx == 1 )
  1233.   by -= 1;
  1234. s.SetActivePoint( mePosLogical, 1, by );
  1235. s.EndOfLine( false, mePosLogical );
  1236. s.SetAnchorPoint( mePosLogical, 1, ty );
  1237.  
  1238. // 選択範囲の文字列を取得
  1239. var st = s.Text;
  1240.  
  1241. // 行頭の空白文字を削除
  1242. var t = DeleteSpace( st, blank );
  1243. if ( t != st )
  1244.   s.Text = t;
  1245.  
  1246. if ( pos ) {    // 範囲選択を残さない
  1247.   if ( st.length - t.length >= tx )
  1248.     s.SetActivePoint( mePosLogical, 1, ty );
  1249.   else
  1250.     s.SetActivePos( pos - ( st.length - t.length ) );
  1251. }
  1252. else {      // 範囲選択を残す(論理行を選択範囲に)
  1253.   s.SetActivePoint( mePosLogical, 1, by + 1 );
  1254.   s.SetAnchorPoint( mePosLogical, 1, ty );
  1255. }
  1256.  
  1257. ScrollX = sx;  ScrollY = sy;
  1258.  
  1259.  
  1260. // 「引用の追加」マクロより拝借
  1261. function DeleteSpace( arg1, arg2 ) {
  1262.   var a = arg1.split( "\n" );
  1263.   for ( var i = 0; i < a.length; i ++ ) {
  1264.     for ( var j = 0; j < arg2.length; j ++ ) {
  1265.       if ( arg2[j].length == 0 )
  1266.         continue;
  1267.       if ( a[i].substr( 0, arg2[j].length ) == arg2[j] ) {
  1268.         a[i] = a[i].substr( arg2[j].length );
  1269.         break;
  1270.       }
  1271.     }
  1272.   }
  1273.   return a.join( "\n" );
  1274. }
  1275.  
  1276.  
  1277. // -----------------------------------------------------------------------------
  1278.  
  1279.  
  1280. #title = "行を上に移動 (複数行可)"
  1281. #tooltip = "選択範囲(複数行可)の論理行を上の行と入れ替える"
  1282. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",220
  1283.  
  1284. // 選択範囲を拡張してカーソル行(論理行)を上の行と入れ替える (複数行可)
  1285. // 文書末の空改行の空行 ( ^[EOF] ) を選択範囲にふくめて移動させると、末尾の空行 ^\n を置き忘れる…
  1286. // あらかじめ文書終端の空行に空白文字などを入れればぶら下げて移動できる
  1287. // (Last modified: 2018/10/21)
  1288.  
  1289. var s = document.selection;
  1290.  
  1291. // 移動元の選択範囲を拡張する
  1292. var ay = s.GetTopPointY( mePosLogical );    // 選択範囲の先頭行のYを取得
  1293. var by = s.GetBottomPointY( mePosLogical ); // 選択範囲の最終行のYを取得
  1294. var bx = s.GetBottomPointX( mePosLogical ); // 選択範囲の最終行のXを取得
  1295.  
  1296. // ※"行を上に移動"の中断処理※
  1297. if ( ay == 1 ) {                // 上にいけない
  1298.   Status = "ファイルの先頭です";
  1299.   Quit();
  1300. }
  1301.  
  1302. // 選択範囲の末尾が終端の空行 ( ^[EOF] ) にあるときの調整
  1303. var eof = ( bx == 1 && ! document.Text.charAt( s.GetActivePos() ) ) ? true : false;
  1304. // カーソル位置に文字がないばあいを [EOF] と判定する
  1305.  
  1306. // 選択範囲の末尾が行頭にあるときの調整
  1307. if ( ay != by && bx == 1 )
  1308.   by --;
  1309.  
  1310. // 選択範囲を拡張する
  1311. s.SetAnchorPoint( mePosLogical, 1, ay - 1 );
  1312. s.SetActivePoint( mePosLogical, 1, by, true );
  1313. s.EndOfLine( true, mePosLogical );
  1314. if ( eof )
  1315.   s.SetActivePos( s.GetActivePos() + 1, true );
  1316.  
  1317. // 選択行を上へ移動
  1318. var a = s.Text.split( "\n" );   // split([separator])   拡張した選択範囲のテキストを論理行ごとに区切って配列に
  1319. a.push( a.shift() );        // shift()      配列の先頭の要素を削除し、削除した要素を返す
  1320.                 // push()       配列の末尾に新しい要素を追加する
  1321. s.Text = a.join( "\n" );    // join([separator])    各要素を連結して1つの文字列として返す
  1322.  
  1323. // 移動元のテキストデータを範囲選択
  1324. s.StartOfLine( false, mePosLogical );           // カーソル位置は移動元の末尾(末尾改行 \n を含む)
  1325. s.SetAnchorPos( s.GetActivePos() );
  1326. s.SetActivePoint( mePosLogical, 1, ay - 1, true );  // 移動元のひとつ上の行の先頭まで範囲選択
  1327.                             // カーソルは移動後の先頭(末尾改行 \n を含む)
  1328.  
  1329.  
  1330. // -----------------------------------------------------------------------------
  1331.  
  1332.  
  1333. #title = "行を下に移動 (複数行可)"
  1334. #tooltip = "選択範囲(複数行可)の論理行を下の行と入れ替える"
  1335. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",229
  1336.  
  1337. // 選択範囲を拡張してカーソル行(論理行)を下の行と入れ替える (複数行可)
  1338. // 選択範囲の末尾に空改行の空行 ( ^\n ) をふくめて移動させるばあい、文書末尾の空改行の空行 ( ^[EOF] ) にむかって移動させると、選択範囲末尾の空改行の空行をつぶしてしまう…
  1339. // あらかじめ文書終端の空行に空白文字などを入れておけばつぶさない
  1340. // (Last modified: 2018/10/21)
  1341.  
  1342. var s = document.selection;
  1343.  
  1344. // 移動元の選択範囲を拡張する
  1345. var ay = s.GetTopPointY( mePosLogical );    // 選択範囲の先頭行のYを取得
  1346. var by = s.GetBottomPointY( mePosLogical ); // 選択範囲の最終行のYを取得
  1347. var bx = s.GetBottomPointX( mePosLogical ); // 選択範囲の最終行のXを取得
  1348.  
  1349. // 選択範囲の末尾が終端の空行 ( ^[EOF] ) にあるときの調整
  1350. var eof = ( bx == 1 && ! document.Text.charAt( s.GetActivePos() ) ) ? true : false;
  1351. // カーソル位置に文字がないばあいを [EOF] と判定する
  1352.  
  1353. // 選択範囲の末尾が行頭にあるときの調整
  1354. if ( ay != by && bx == 1 && eof == 0 )
  1355.   by --;
  1356.  
  1357. // ※"行を下に移動"の中断処理※
  1358. var ey = document.GetLines( 0 );    // 文書全体の最終行のYを取得
  1359. if ( by == ey || eof ) {
  1360.   Status = "ファイルの末尾です";   // 下にいけない;
  1361.   Quit();
  1362. }
  1363.  
  1364. // 選択範囲を拡張する
  1365. s.SetAnchorPoint( mePosLogical, 1, ay );
  1366. s.SetActivePoint( mePosLogical, 1, by + 1, true );
  1367. s.EndOfLine( true, mePosLogical );
  1368. if ( eof )
  1369.   s.SetActivePos( s.GetActivePos() + 1, true );
  1370.  
  1371. // 選択行を下へ移動
  1372. var a = s.Text.split( "\n" );   // split([separator])   拡張した選択範囲のテキストを論理行ごとに区切って配列に
  1373. a.unshift( a.pop() );       // pop()        配列の最後の要素を削除し、削除した要素を返す
  1374.                 // unshift()        配列の先頭に新しい要素を挿入する
  1375. s.Text = a.join( "\n" );    // join([separator])    各要素を連結して1つの文字列として返す
  1376.  
  1377. // 移動元のテキストデータを範囲選択
  1378. s.SetAnchorPos( s.GetActivePos() + 1 );         // 末尾のひとつ右にアンカー(次行の先頭 = 末尾改行 \n を含める)
  1379. s.SetActivePoint( mePosLogical, 1, ay + 1, true );  // 移動元のひとつ下の行の先頭まで範囲選択
  1380.                             // カーソルは移動後の先頭(末尾改行 \n を含む)
  1381.  
  1382.  
  1383. // -----------------------------------------------------------------------------
  1384.  
  1385.  
  1386. #title = "行を複製 (複数行可)"
  1387. #tooltip = "選択範囲(複数行可)の論理行を複製する"
  1388. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",222
  1389.  
  1390. // 選択範囲を拡張してカーソル行(論理行)を "複製" する (複数行可)
  1391. // マクロライブラリに転載済み (2018/08/24)
  1392. // Last modified (2018/11/20) 末尾空行のみで実行すると2行追加されててしまうのを修正
  1393. /**
  1394.  * 文書終端の空行 ( ^[EOF] ) を選択範囲の末尾にぶら下げての "複製" はできるが、可否について条件あり。
  1395.  *   選択範囲の確定時点でのキャレットの位置が "選択範囲の先頭にあるか" / "末尾 ( [EOF] マークの直前) にあるか" で判別する。
  1396.  *   文字列または行番号をドラッグ(または"クリック & Shift+クリック")して選択範囲を確定するさいに
  1397.  *   ・上(左)から下(右)にむけて選択範囲をつくった場合 → 終端の空行 ( ^[EOF] ) を含める
  1398.  *   ・下(右)から上(左)にむけて選択範囲をつくった場合 → 終端の空行 ( ^[EOF] ) を含めない
  1399.  *
  1400.  * 1行だけの複製なら
  1401.  * document.selection.DuplicateLine();
  1402.  */
  1403.  
  1404. var s = document.selection
  1405.  
  1406. // 選択範囲の各座標を取得
  1407. var ay = s.GetTopPointY( mePosLogical );    // 選択範囲の先頭行のYを取得
  1408. var by = s.GetBottomPointY( mePosLogical ); // 選択範囲の最終行のYを取得
  1409. var bx = s.GetBottomPointX( mePosLogical ); // 選択範囲の最終行のXを取得
  1410.  
  1411. // 選択範囲の末尾が終端の空行 ( ^[EOF] ) にあるときの調整
  1412. var eof = ( ty != by && bx == 1 && ! document.Text.charAt( s.GetActivePos() ) ) ? "\n" : "";
  1413. // カーソル位置に文字がないばあいを [EOF] と判定する
  1414.  
  1415. // 選択範囲の末尾が行頭にあるときの調整
  1416. if ( ay != by && bx == 1 ) 
  1417.   by --;
  1418.  
  1419. // 選択範囲の拡張
  1420. s.SetActivePoint( mePosLogical, 1, by );    // 選択範囲の最終行の行頭
  1421. s.EndOfLine( false, mePosLogical );     // 選択範囲の最終行の行末
  1422. s.SetAnchorPoint( mePosLogical, 1, ay );    // あらためて選択範囲の先頭行まで選択
  1423.  
  1424. // 選択範囲に改行を追加して複製
  1425. var st = s.Text;
  1426. s.Text = st + eof + "\n" + st;          // カーソル位置は複製した行の末尾
  1427.  
  1428. /* (下に)複製された行全体を範囲選択 */
  1429. if ( eof.length ) {                 // 終端の空行をふくめて複製したばあい
  1430.   s.SetActivePoint( mePosLogical, 1, by + 2 );      // 選択開始位置の調整
  1431.   s.EndOfDocument( true );              // カーソル位置は選択範囲の末尾
  1432. }
  1433. else {                          // 通常の行の複製のばあい
  1434.   s.SetAnchorPos( s.GetActivePos() + 1 );       // 末尾位置の調整(末尾改行 \n を含める)
  1435.   s.SetActivePoint( mePosLogical, 1, by + 1, true );    // カーソル位置は選択範囲の先頭
  1436. }
  1437.  
  1438. // /* (上の)複製元の行全体を範囲選択 */
  1439. // s.SetAnchorPoint( mePosLogical, 1, ty );
  1440. // s.SetActivePoint( mePosLogical, 1, by + 1, true );
  1441. // if ( e )
  1442. //   s.SetActivePos( s.GetActivePos() + 1, true );
  1443.  
  1444. /* 文書終端の空行を含めているかいないかで「行の複製」マクロ実行後のキャレットの位置をかえているのは、連続で「行の複製」を実行するさいに同じ範囲を選択状態にして複製させるための仕様 */
  1445.  
  1446.  
  1447. // -----------------------------------------------------------------------------
  1448.  
  1449.  
  1450. #title = "行の先頭に挿入 (複数行可)"
  1451. #tooltip = "各行の先頭に貼り付ける (挿入)"
  1452. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",251
  1453. // (または 250)
  1454. // マクロライブラリに転載済み (2018/08/24)
  1455.  
  1456. /**
  1457.  * 選択範囲をふくむ各行の先頭にクリップボードのデータを貼り付ける (挿入)
  1458.  * 複数行の選択範囲で末尾が改行 \n のとき、さいごの改行は除外する
  1459.  *
  1460.  * 文書終端の空行 ( ^[EOF] ) を選択範囲の末尾にぶら下げての "挿入" はできるが、可否について条件アリ
  1461.  *   選択範囲の確定時点でのキャレットの位置が "選択範囲の先頭にあるか" / "末尾 ( [EOF] マークの直前) にあるか" で判別する
  1462.  *   文字列または行番号をドラッグ(または"クリック & Shift+クリック")して選択範囲を確定するさいに
  1463.  *   ・上(左)から下(右)にむけて選択範囲をつくった場合 → 終端の空行 ( ^[EOF] ) を含める
  1464.  *   ・下(右)から上(左)にむけて選択範囲をつくった場合 → 終端の空行 ( ^[EOF] ) を含めない
  1465.  */
  1466.  
  1467. var sx = ScrollX, sy = ScrollY;         // スクロール位置を保存
  1468. var s = document.selection;
  1469.  
  1470. // 選択範囲の各座標を取得
  1471. var ay = s.GetTopPointY( mePosLogical );    // 選択範囲の先頭行のYを取得
  1472. var by = s.GetBottomPointY( mePosLogical ); // 選択範囲の最終行のYを取得
  1473. var bx = s.GetBottomPointX( mePosLogical ); // 選択範囲の最終行のXを取得
  1474.  
  1475. // 選択範囲の末尾が空の終端行 ( ^[EOF] ) にあるか判定
  1476. // カーソル位置に文字がないばあいを ^[EOF] と判定する
  1477. var eof = ( ! document.Text.charAt( s.GetActivePos() ) ) ? true : false;
  1478.  
  1479. // 選択範囲の末尾が行頭にあるときの調整
  1480. if ( ay != by && bx == 1 && ! eof )
  1481.   by --;
  1482.  
  1483. // 選択範囲を拡張する
  1484. s.SetActivePoint( mePosLogical, 1, by );    // 選択範囲の最終行の行頭
  1485. s.EndOfLine( false, mePosLogical );     // 選択範囲の最終行の行末(さいごの改行 \n を含まない)
  1486. s.SetAnchorPoint( mePosLogical, 1, ay );    // あらためて選択範囲の先頭行まで選択
  1487.  
  1488. var cb = ClipboardData.GetData();       // クリップボードのテキストデータを取得
  1489. s.Text = insertCb( s.Text, cb );        // "各行の先頭に貼り付け”
  1490.  
  1491. // 「引用の追加」マクロの関数を流用
  1492. function insertCb( arg1, arg2 ) {       // "各行の先頭に貼り付け”の実行コード
  1493.   var a = arg1.split( "\n" );           // 選択範囲のテキストを改行ごとに区切る
  1494.   for ( var i = 0; i < a.length; i++ )      // 行数の数だけ繰りかえし
  1495.     a[i] = arg2 + a[i];             // 各行の先頭にクリップボードのデータを挿入する
  1496.   return a.join( "\n" );            // 改行を復旧
  1497. }
  1498.  
  1499. s.SetAnchorPos( s.GetActivePos() + 1 );     // 選択範囲を復旧 (末尾改行 \n を含める)
  1500. s.SetActivePoint( mePosLogical, 1, ay, true );  // カーソルは選択範囲の先頭
  1501. ScrollX = sx; ScrollY = sy;         // スクロール位置を復元
  1502.  
  1503.  
  1504. // -----------------------------------------------------------------------------
  1505.  
  1506.  
  1507. #title = "カッコ..."
  1508. #tooltip = "カッコで囲う"
  1509. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",255
  1510.  
  1511. // ポップアップメニューからカッコの種類を選択して、選択範囲をカッコで囲う。
  1512. // 公式wikiのマクロライブラリより「引用の追加」と「括弧で挟む」のコードを参考にした
  1513. // マクロライブラリに転載済み (2018/08/24 - 2018/10/29)
  1514. // (Last modified: 2018/11/19)
  1515. // ◆ 人柱版 ◆    「任意の文字数/文字列を削除」を追加
  1516.  
  1517. /**
  1518.  * ・複数行の選択範囲で末尾が改行 \n のとき、さいごの改行は除外する。
  1519.  * ・非選択時には、それぞれことなる動作をする。
  1520.  *
  1521.  * ※ 「任意の文字列」について ※
  1522.  * ・「任意の文字列1」は選択範囲全体をひとくくりに、
  1523.  *   「任意の文字列2」は選択範囲内の各行ごとで個別に、指定した文字列で前後を囲う。
  1524.  * ・wiki 文字装飾タグ以外のカッコで各行ごとに囲いたい場合は、「任意の文字列2」を使用する。
  1525.  * ・文字コードでの入力には非対応(入力されたままの文字列を返す)。
  1526.  * ・改行コードとタブ文字は、それぞれ「\\\n」と「\\\t」で入力されたものを置換する。
  1527.  *   パスの入力に配慮しただけの簡易的な置換処理なので、「\」を4つ以上かさねた場合を考慮していない。
  1528.  *
  1529.  * ※ 「wiki 文字装飾タグ」について ※
  1530.  * ・選択範囲内の各行ごとで個別に、指定したタグで前後を囲う。
  1531.  *
  1532.  * ※ JS/XML コメントアウト と アンコメント について ※
  1533.  * ・「カッコで囲う」では行の中間部分だけをコメントアウトするので、
  1534.  *   行単位でコメントアウトするなら「引用符/コメント」マクロが適する。
  1535.  * ・「カッコで囲う」では行の先頭部分のコメントマークだけにしかマッチしないので、
  1536.  *   コメント部分がインデントされている場合も「引用符/コメント」マクロが適する。
  1537.  * ・ほかにも注意事項があるので、該当コード部分の注意書きを参照のこと。
  1538.  *
  1539.  * ※ ポップアップメニューの項目は、m.Add( … ); の不要な行を行をコメントアウトすれば隠せる。
  1540.  * (配列から削除する場合は中身だけ消して "" として空要素を残しておかないと、メニューや処理コードの ID と一致しなくなる)
  1541.  */
  1542.  
  1543. // ■「任意の文字列2」と、wiki 文字装飾タグで、複数行の選択範囲内の空白行をスキップするか?
  1544. var skip = true;
  1545.   // (skip = true; スキップする / skip = false; スキップしない)
  1546.  
  1547. // 開きカッコ p1 を配列で定義
  1548. var p1 = new Array( "" ,    // 以下 r = 1~10、11~20、21~ の ID 順
  1549.   "(" ,  "<" ,  "[" ,  "{" ,  "(" ,  "「" ,  "『" ,  "【" ,  " (" ,  " (" ,
  1550.   " \"" ,  " " ,  " - " ,  "――" ,  "~" ,  "'''" ,  "''" ,  "<u>" ,  "[[" , "<nowiki>" ,
  1551.   "" );
  1552. // 閉じカッコ p2 を配列で定義
  1553. var p2 = new Array( "" ,    // 以下 1~10、11~20、21~ の ID 順
  1554.   ")" ,  ">" ,  "]" ,  "}" ,  ")" ,  "」" ,  "』" ,  "】" ,  ") " ,  ") " ,
  1555.   "\" " ,  " " ,  " - " ,  "――" ,  "~" ,  "'''" ,  "''" ,  "</u>" ,  "]]" , "</nowiki>" ,
  1556.   "" );
  1557.  
  1558. // ポップアップメニュー項目の定義
  1559. var m = CreatePopupMenu();
  1560.   // m.Add( "ラベル", r ); の各行は、任意に上下移動(並べ替え)してよいが、
  1561.   // r の数値は上の配列の並び順やテキスト変換処理の case r: に対応しているので変更しないこと!
  1562. m.Add( "任意の文字列 (&E)", 50 ); // Enter the custom letter(s)   ダイアログのテキストボックス
  1563. m.Add( "任意の文字列 2 (&E)", 51 ); // 各行ごとに指定文字列で囲う(skip フラグを指定すること)
  1564. m.Add( "", 0, meMenuSeparator );
  1565.  
  1566. m.Add( " ( 半角 小カッコ )  (&P)", 1 );       // Parenthesis
  1567. m.Add( "< 半角 山カッコ > (&A)", 2 );     // Angle brackets   キーボードの [ね] / [る] キーの "<" / ">"
  1568. m.Add( " [ 半角 大カッコ ]  (&B)", 3 );       // square Brackets
  1569. m.Add( " { 半角 中カッコ }  (&C)", 4 );       // Curly brackets
  1570.  
  1571. m.Add( "", 0, meMenuSeparator );
  1572. m.Add( "( 全角 小カッコ ) (&R)", 5 );     // Round brackets
  1573.  
  1574. m.Add( "", 0, meMenuSeparator );
  1575. m.Add( "「 全角 かぎカッコ 」 (&K)", 6 );  // Kakko
  1576. m.Add( "『 全角 二重かぎカッコ 』 (&W)", 7 );    // White corner brackets
  1577. m.Add( "【 全角 スミ付きカッコ 】 (&L)", 8 );    // Lenticular brackets
  1578.  
  1579. m.Add( "", 0, meMenuSeparator );
  1580. m.Add( "␣( 全角 小カッコ )␣ (&Z)", 9 );   // Zenkaku (full-width)
  1581. m.Add( "␣ ( 半角 小カッコ ) ␣ (&H)", 10 );    // Hankaku (half-width)
  1582. m.Add( '␣ "  半角 引用符  " ␣ (&Q)', 11 ); // double Quotation mark    キーボードの [ふ] キーの "
  1583. m.Add( "␣ 半角 スペース ␣ (&S)", 12 );    // Space
  1584.  
  1585. m.Add( "", 0, meMenuSeparator );
  1586. m.Add( "  -  半角 ハイフン  -   (&-)", 13 );  // hyphen-minus     キーボードの [ほ] キーの "-"
  1587. m.Add( "―― 全角 ダッシュ ―― (&D)", 14 );  // Dash
  1588. m.Add( "~ 全角 チルダ ~ (&T)", 15 );       // Tilde        キーボードの [へ] キーの "~"
  1589.  
  1590. m.Add( "", 0, meMenuSeparator );
  1591. m.Add( "1文字ずつ前後を削除 (&1)", 31 );
  1592. m.Add( "2文字ずつ前後を削除 (&2)", 32 );
  1593. m.Add( "3文字ずつ前後を削除 (&3)", 33 );
  1594.  
  1595. /* 以下の2項目は動作検証不十分 ◆ 人柱版 ◆ */
  1596. m.Add( "", 0, meMenuSeparator );
  1597. m.Add( "行頭/行末から任意の 文字数 を削除 (&Y)", 52 );
  1598. m.Add( "行頭/行末から任意の 文字列 を削除 (&Z)", 53 );
  1599.  
  1600. m.Add( "", 0, meMenuSeparator );
  1601. m.Add( "/*  *  JS コメントアウト 2  */ (&J)", 34 );    // JavaScript comment out (multiple lines)
  1602. m.Add( "/*  JS コメントアウト 1  */ (&V)", 36 );   // jaVascript comment out
  1603. m.Add( "JS アンコメント (&U)", 35 );            // Uncomment
  1604. m.Add( "", 0, meMenuSeparator );
  1605. m.Add( "<!--  XML コメントアウト  --> (&X)", 38 );   // Xml comment out
  1606. m.Add( "XML アンコメント (&M)", 39 );         // xMl comment out
  1607.  
  1608. /* このブロックの項目は、複数行を選択しているとき「選択範囲の各行ごとに囲う」処理をおこなう
  1609.   (skip フラグを指定すること) */
  1610. //  /* とりあえずコメントアウトしておく */
  1611. // m.Add( "", 0, meMenuSeparator );
  1612. // m.Add( "'''  wiki 太字  ''' (&O)", 16 );       // bOld
  1613. // m.Add( "''   wiki 斜体   '' (&I)", 17 );       // Italic
  1614. // m.Add( "<u> wiki 下線 </u> (&_)", 18 );        // _ under line
  1615. // m.Add( "[[  wiki リンク  ]] (&@)", 19 );      // @ link
  1616. // m.Add( "<nowiki> </nowiki> (&N)", 20 );        // NoWiki
  1617.  
  1618. // m.Add( "", 0, meMenuSeparator );
  1619. // m.Add( "キャンセル", 0 );       // Escキーでキャンセルできるのでアクセラレータなし
  1620.  
  1621. // ポップアップメニューを表示
  1622. // m.Track(0); ならキャレット位置、Track(1); ならカーソル位置にサブメニューがポップアップ
  1623. var r = m.Track( mePosMouse = 1 );  // 選択されたメニュー項目のIDを r に格納する
  1624.  
  1625. if ( r > 0 ) {
  1626.   Redraw = false;
  1627.  
  1628.   // 選択範囲
  1629.   var s = document.selection
  1630.   var anc = s.GetAnchorPos();       // 選択範囲の開始位置 (キャレットのない側)
  1631.   var act = s.GetActivePos();       // 選択範囲の終了位置 (キャレットのある側)
  1632.   var tp = ( anc < act ) ? anc : act;   // 選択範囲の先頭位置  ( ax, ay )
  1633.   var bp = ( anc < act ) ? act : anc;   // 選択範囲の末尾位置
  1634.  
  1635.   if ( ! s.Text.length )        // 選択範囲がなければカーソル位置を取得
  1636.     var pos = s.GetActivePos();     // pos は「選択範囲なし」フラグとしても使う
  1637.  
  1638.   // 選択範囲の各座標を取得
  1639.   var ax = s.GetTopPointX( mePosLogical );
  1640.   var ay = s.GetTopPointY( mePosLogical );
  1641.   var bx = s.GetBottomPointX( mePosLogical );
  1642.   var by = s.GetBottomPointY( mePosLogical );
  1643.  
  1644.   // 選択範囲の末尾位置を調整(最後の \n を含めない)
  1645.   if ( ! s.IsEmpty && bx == 1 && r != 4 ) { // 選択範囲の末尾が行頭 x = 1 にあるばあい ~
  1646.                         // ※ { 中カッコ } のばあいは末尾の調整をしない
  1647.     s.SetActivePos( bp - 1 );           // 元の選択範囲の末尾より1行うえの末尾
  1648.     s.SetAnchorPos( tp );           // 元の選択範囲の先頭まで選択
  1649.   }
  1650.  
  1651.   // 選択範囲の文字列を取得
  1652.   var st = s.Text;
  1653.  
  1654.   // IDごとのテキスト変換処理
  1655.   switch ( r ) {
  1656.  
  1657.     // カッコ
  1658.     case 1:  case 2:  case 3:  case 4:  case 5:  case 6:
  1659.     case 7:  case 8:  case 9:  case 10:  case 11:  case 12:
  1660.       s.Text = p1[r] + st + p2[r];      // カッコ p1 & p2 で囲う
  1661.       if ( pos )                // 選択範囲がなければ
  1662.         s.SetActivePos( pos + p1[r].length );   // カーソルをカッコのなかに移動
  1663.       else                  // 選択範囲があれば
  1664.         s.SetAnchorPos( tp );           // 選択範囲を復元
  1665.       break;
  1666.  
  1667.  
  1668.     // ハイフン、ダッシュ、チルダ
  1669.     case 13:  case 14:  case 15:
  1670.       if ( pos )            // 選択範囲がなければ
  1671.         document.Write( p1[r] );    // 片側分 p1 だけ挿入
  1672.       else {                // 選択範囲があれば
  1673.         s.Text = p1[r] + st + p2[r];    // 選択範囲 st をダーシ p1 & p2 で囲う
  1674.         s.SetAnchorPos( tp );       // 選択範囲を復元
  1675.       }
  1676.       break;
  1677.  
  1678.  
  1679.     // n文字ずつ前後を削除
  1680.     case 31:  case 32:  case 33:
  1681.       if ( ! s.IsEmpty ) {      // 選択範囲があれば
  1682.         var n = ( r == 31 ) ? 1 :   // 1文字ずつ
  1683.                 ( r == 32 ) ? 2 :   // 2文字ずつ
  1684.                /* r == 33 */  3 ;   // 3文字ずつ
  1685.         s.Text = st.slice( n, st.length - n );  // 選択範囲の両端から n 文字ずつ消す
  1686.         s.SetAnchorPos( tp );           // 選択範囲を復元
  1687.       }
  1688.       break;
  1689.  
  1690.  
  1691.     // wiki 文字装飾タグ  ※ 太字/斜体/下線/<nowiki>
  1692.     case 16:  case 17:  case 18:  case 20:
  1693.       // 選択範囲内の「各行を囲う」処理をおこなう。
  1694.       // 複数行選択で空白行をスキップするかは冒頭の skip フラグで決定する。
  1695.       var ad = AddBrackets( st, p1[r], p2[r] ); // 選択範囲 st の各行を p1 & p2 で囲う
  1696.       if ( ad != st ) {
  1697.         s.Text = ad;
  1698.         if ( ! pos )            // 選択範囲があれば
  1699.           s.SetAnchorPos( tp );     // 選択範囲を復元
  1700.         else {                      // 選択範囲がなければ
  1701.           s.SetAnchorPos( pos + p1[r].length );     // カーソルをカッコのなかに移動
  1702.           s.SetActivePos( s.GetAnchorPos() + 1, true ); // 全角スペースを範囲選択する
  1703.         }
  1704.       }
  1705.       else {    // テキストに変更なし ( skip && st.match( /^\s*$/g ) )
  1706.         s.SetActivePos( act );  // 選択範囲を復元
  1707.         s.SetAnchorPos( anc );
  1708.       }
  1709.       break;
  1710.  
  1711.  
  1712.     // wiki 文字装飾        ※ 内部リンク用タグ    [[リンク|ラベル]]
  1713.     case 19:
  1714.       // 選択範囲内の「各行を囲う」処理をおこなう。
  1715.       // 複数行選択で空白行をスキップするかは冒頭の skip フラグで決定する。
  1716.       var ad = AddWikiLink( st, p1[r], p2[r] ); // 選択範囲 st の各行を [[str|str]] に置換
  1717.       if ( ad != st ) {
  1718.         s.Text = ad;
  1719.         if ( ! pos )                // 選択範囲があれば
  1720.           s.SetActivePos( tp + p1[r].length );  // p1 の後ろにカーソルを移動する
  1721.         else {                          // 選択範囲がなければ
  1722.           s.SetActivePos( pos + p1[r].length );         // カーソルをカッコの中に移動
  1723.           s.SetAnchorPos( s.GetActivePos() + " | ".length );    // カッコの中を範囲選択する
  1724.         }
  1725.       }
  1726.       else {    // テキストに変更なし ( skip && st.match( /^\s*$/g ) )
  1727.         s.SetActivePos( act );  // 選択範囲を復元
  1728.         s.SetAnchorPos( anc );
  1729.       }
  1730.       break;
  1731.  
  1732.  
  1733.     // /* * JavaScriptコメントアウト 2 */
  1734.     case 34:
  1735. /**
  1736.  *     基本的に1行めが行の先頭から始まることしか想定していないので、
  1737.  *       あらかじめコメントアウトする文字列は、行単位でまとまったブロックにしておくとよい。
  1738.  *     選択範囲の先頭/末尾が行の途中にある状態でコメントアウトする場合は、改行を追加する。
  1739.  */
  1740.       // 選択範囲の先頭座標が x = 1 でなければ改行させる
  1741.       var p1 = ( ax > 1 ) ? "\n/*\n" : "/*\n";      // /* */
  1742.       // 選択範囲末尾の後ろが改行 \n でなければ改行させる
  1743.       var p2 = ( document.Text.charAt( bp ) != "\n" ) ? "\n */\n" : "\n */";
  1744.       var ast = " * ";
  1745.       if ( ax > 1 ) // 先頭で改行させたときは、選択範囲の復元用の座標を調整
  1746.         tp ++;
  1747. //    s.Text = CommentOutJS( st, p1, p2, ast );     // コメントアウト(関数バージョン)
  1748.       /*  ※ JS コメントアウトの正規表現置換の確実性の検証は不十分 ※ */
  1749.       s.Text = p1                   // コメントアウト
  1750.              + st.replace( /^(.*)$/gm , ast + "$1" )
  1751.              + p2;
  1752.       if ( pos )                    // 選択範囲がなければ
  1753.         s.SetActivePos( s.GetActivePos() - p2.length ); // カーソルをコメント枠のなかに移動
  1754.       else                      // 選択範囲があれば
  1755.         s.SetAnchorPos( tp );               // 選択範囲を復元
  1756.       break;
  1757.  
  1758.  
  1759.     /* JavaScript コメントアウト 1 */
  1760.     // <!-- XML コメントアウト -->
  1761.     case 36:  case 38:
  1762.       var p1 = ( r == 36 ) ? " /* " : " <!-- ";     // /* */ <!-- -->
  1763.       var p2 = ( r == 36 ) ? " */ " : " --> ";
  1764.       s.Text = p1 + st + p2;            // p1, p2 でコメントアウト
  1765.       if ( pos )                // 選択範囲がなければ
  1766.         s.SetActivePos( pos + p1.length );  // カーソルをコメント枠のなかに移動
  1767.       else                  // 選択範囲があれば
  1768.         s.SetAnchorPos( tp );           // 選択範囲を復元
  1769.       break;
  1770.  
  1771.  
  1772. //  case 35:        ※ JS アンコメント
  1773.       // case 34 と case 36: の /* JavaScriptコメント */ をアンコメントする。
  1774.       // 選択範囲内の各行頭のコメントマーク "/* "  と " * " と " */" のみマッチ。
  1775.       // 「カッコで囲う」では行の先頭部分のコメントマークだけにしかマッチしないので、
  1776.       //   コメント部分がインデントされている場合は「引用符/コメント」マクロのJSアンコメントを使うこと。
  1777. /*
  1778.  * ・選択範囲に複数のコメントブロックがある場合を想定していない。
  1779.  * ・中間行の行頭記号はアスタリスク「 * 」、全角中黒「・」、半角中黒「・」を削除対象とする。
  1780.  *   (行頭記号と前後の半角スペース各1を削除する)
  1781.  * ・JSコメントでない箇条書き文で実行した場合も行頭のビュレット「* ・ ・」を削除する。
  1782.  */
  1783. /* このタイプのコメントにたいしてもアンコメント処理する。 */
  1784.  
  1785. //  case 39:        ※ XML アンコメント
  1786.       // case 38 の <!-- XMLコメント --> をアンコメントする。
  1787.       // 選択範囲の先頭の " <!-- " と 末尾の " --> " のみマッチ。
  1788.       // 選択範囲に複数のコメントがあると正常にアンコメントしない。
  1789.  
  1790.     case 35:  case 39:
  1791.       // 選択範囲の先頭と末尾のコメントマークを削除
  1792. //    var dc = ( r == 35 ) ? UnCommentJS( st ) :    // JS アンコメント(関数バージョン)
  1793.       /*  ※ JS アンコメントの正規表現置換の確実性の検証は不十分 ※ */
  1794.       var dc = ( r == 35 ) ? st.replace( /^ ?\/\*+ ?\n?|\n? ?\*+\/ ?$/gm , "" ) // JS アンコメント
  1795.                                .replace( /^ ?(\*+|[・・]) ?/gm , "" ) :
  1796.  
  1797.              /*( r == 36 )*/ st.replace( /^ ?<!-+ ?| ?-+ *>\ ?$/g , "" );   // XMLアンコメント
  1798.  
  1799.       // 選択範囲にコメントマークがなかった場合 undo 履歴を残さない
  1800.       if ( dc == st ) {     // アンコメント処理の前後でテキストが一致したら
  1801.         s.SetActivePos( act );  // 選択範囲を復元
  1802.         s.SetAnchorPos( anc );
  1803.       }
  1804.       else {
  1805.       s.Text = dc;      // アンコメント完了
  1806.       s.SetAnchorPos( tp ); // 選択範囲を復元
  1807.       }
  1808.       break;
  1809.  
  1810.  
  1811.     // 任意の文字列を追加  ※テキストボックス
  1812.     case 50:  case 51:
  1813.       // 文字コードには非対応
  1814.       // ダイアログのテキスト入力フィールドから文字列を取得
  1815.       var p1 = Prompt(
  1816.                  "前につける文字列:\t改行=\\\\\\n ; タブ=\\\\\\t  (注:¥記号3つ)", ""
  1817.                ).replace( /\\\\\\n/g , "\n" ).replace( /\\\\\\t/g , "\t" );
  1818.       var p2 = Prompt(
  1819.                  "後ろにつける文字列:\t改行=\\\\\\n ; タブ=\\\\\\t  (注:¥記号3つ)", ""
  1820.                ).replace( /\\\\\\n/g , "\n" ).replace( /\\\\\\t/g , "\t" );
  1821.  
  1822.       if ( p1 || p2 ) {
  1823.         if ( pos ) {                // 選択範囲がなければ
  1824.           document.Write( p1 + p2 );        //   p1 & p2 を挿入
  1825.           s.SetActivePos( pos + p1.length );    //   カーソルをカッコのなかに移動
  1826.         }
  1827.         else {                  // 選択範囲があれば
  1828.           if ( r == 50 )            //  「任意の文字列1」なら
  1829.             s.Text = p1 + st + p2;      //     選択範囲 st 全体を p1 & p2 で囲う
  1830.           else {    // ( r == 51 )      //  「任意の文字列2」なら
  1831.             var ab = AddBrackets( st, p1, p2 ); //     選択範囲 st の各行を p1 & p2 で囲う
  1832.             if ( ab != st )
  1833.               s.Text = ab;
  1834.             else        // テキストに変更なし ( skip && st.match( /^\s*$/g ) )
  1835.               s.SetActivePos( bp );
  1836.           }
  1837.           s.SetAnchorPos( tp );         // 選択範囲を復元
  1838.         }
  1839.       }
  1840.       break;
  1841.  
  1842.  
  1843.     // ◆ 人柱版 ◆
  1844.     // 各行の前後から任意の文字数/文字列を削除 ※テキストボックス
  1845.     case 52:  case 53:
  1846.       if ( ! pos ) {    // 選択範囲があれば
  1847.         // 「任意の文字数を削除」
  1848.         if ( r == 52 ) {
  1849.           // ダイアログのテキスト入力フィールドから文字列を取得
  1850.           // 半角に変換して数字以外の文字は削除
  1851.           var p1 = ToHalfWidth(
  1852.             Prompt( "行頭から削除する文字数 (数字のみ有効):", "" )
  1853.           ).replace( /[^0-9]/g , "" );
  1854.           var p2 = ToHalfWidth(
  1855.             Prompt( "行末から削除する文字数 (数字のみ有効):", "" )
  1856.           var dt = DeleteCharByNum( st, p1, p2 );   // 各行の先頭/末尾から指定文字数を削除
  1857.         }
  1858.         // 「任意の文字列を削除」
  1859.         else {  // ( r == 53 )
  1860.         // ダイアログのテキスト入力フィールドから文字列を取得
  1861.         var p1 = Prompt(
  1862.           "行頭から削除する文字列:\tタブ=\\\\\\t  (注:¥記号3つ)", ""
  1863.         ).replace( /\\\\\\t/g , "\t" );
  1864.         var p2 = Prompt(
  1865.           "行末から削除する文字列:\tタブ=\\\\\\t  (注:¥記号3つ)", ""
  1866.         ).replace( /\\\\\\t/g , "\t" );
  1867.         var reg1 = new RegExp( "^" + Quote( p1 ) , "gm" );
  1868.         var reg2 = new RegExp( Quote( p2 ) + "$" , "gm" );
  1869.         dt = st.replace( reg1 , "" ).replace( reg2 , "" );  // 各行の先頭/末尾の指定文字列を削除
  1870.         }
  1871.  
  1872.         // 選択範囲に指定文字列がなかった場合 undo 履歴を残さない
  1873.         if ( dt != st ) {
  1874.           s.Text = dt;          // 削除完了
  1875.           s.SetAnchorPos( tp );     // 選択範囲を復元
  1876.         }
  1877.       }
  1878.       break;
  1879.  
  1880.  
  1881.     default:
  1882.       break;
  1883.   }
  1884.  
  1885.   Redraw = true:
  1886. }
  1887.  
  1888.  
  1889. /* 関数 AddBrackets( st, p1, p2) */
  1890. function AddBrackets( arg0, arg1, arg2 ) {
  1891.   var a = arg0.split( "\n" );           // 選択範囲 st を "\n" で区切って配列 a に
  1892.   for ( var i = 0; i < a.length; i ++ ) {   // 「1行め」から繰りかえし処理
  1893.     if ( ! pos && skip && a[i].match( /^\s*$/g ) )  // skip = true のときは、空白行をスキップ
  1894.       continue;
  1895.     // 空行には全角スペースをはさむ
  1896.     var space = ( ( arg1.length && arg2.length ) && ( pos || ! a[i].length ) ) ? " " : "" ;
  1897.     a[i] = arg1 + space + a[i] + arg2;      // 各行をカッコ p1 & p2 で囲う
  1898.   }
  1899.   return a.join( "\n" );            // 各行を "\n" で区切って連結しなおす
  1900. }
  1901.  
  1902.  
  1903. /* 関数 AddWikiLink( st, p1, p2) */
  1904. function AddWikiLink( arg0, arg1, arg2 ) {
  1905.   var a = arg0.split( "\n" );           // 選択範囲 st を "\n" で区切って配列 a に
  1906.   for ( var i = 0; i < a.length; i ++ ) {   // 「1行め」から繰りかえし処理
  1907.     if ( ! pos && skip && a[i].match( /^\s*$/g ) )  // skip = true のときは、空白行をスキップ
  1908.       continue;
  1909.     var bar = ( pos || ! a[i].length ) ? " | " : "|" ;  // 空行には全角スペースつきではさむ
  1910.     a[i] =  arg1 + a[i] + bar + a[i] + arg2;    // 各行を [[str|str]] に置換
  1911.   }
  1912.   return a.join( "\n" );            // 各行を "\n" で区切って連結しなおす
  1913. }
  1914.  
  1915.  
  1916. /* 関数 DeleteCharByNum( st, p1, p2 ) */
  1917. function DeleteCharByNum( str, p1, p2 ) {
  1918.   var a = str.split( "\n" );
  1919.   for ( var i = 0; i < a.length; i ++ )
  1920.     a[i] = a[i].slice( p1, a[i].length - p2 );  // 各行の先頭/末尾からの指定文字数を削除
  1921.   return a.join( "\n" );
  1922. }
  1923.  
  1924.  
  1925. /* 関数 quote( str ) */
  1926. // 『JavaScript/正規表現 - Wikibooks』より
  1927. // https://ja.wikibooks.org/wiki/JavaScript/正規表現
  1928. // https://ja.wikibooks.org/wiki/JavaScript/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE
  1929. //
  1930. // PerlのquotemetaやRubyのRegExp.quoteのように、()や[]など正規表現のメタ文字と解釈される可能性のある文字をエスケープして返す関数は、Stringオブジェクトのreplaceメソッドを使用して簡単に作成することができます。
  1931. function Quote( str ) {
  1932.     return str.replace( /\W/g, function( $0 ) {
  1933.         return '\\' + $0;
  1934.     } );
  1935. }
  1936.  
  1937.  
  1938. /**
  1939.  * 全角から半角への変革関数 toHalfWidth( strVal )
  1940.  * 入力値の英数記号を半角変換して返却
  1941.  * [引数]   strVal: 入力値
  1942.  * [返却値] String(): 半角変換された文字列
  1943.  */
  1944. // https://webllica.com/add-comma-as-thousands-separator/ より
  1945. function ToHalfWidth( strVal ){
  1946.   // 半角変換
  1947.   var halfVal = strVal.replace( /[!-~]/g,
  1948.     function( tmpStr ) {
  1949.       // 文字コードをシフト
  1950.       return String.fromCharCode( tmpStr.charCodeAt(0) - 0xFEE0 );
  1951.     }
  1952.   );
  1953.   return halfVal;
  1954. }
  1955.  
  1956.  
  1957. /* -----------------------------------------------------------------------------
  1958.  * 以下の2つの関数は破棄してよいかも
  1959.  * (switch - case 文の中で replace メソッドでの置換処理に変更した)
  1960.  * ----------------------------------------------------------------------------- */
  1961.  
  1962. /*
  1963.  * 関数 CommentOutJS( st, pre, sur, ast )
  1964.  * このかたちにコメントアウトする
  1965.  */
  1966. function CommentOutJS( arg0, arg1, arg2, arg3 ) {
  1967.   var a = arg0.split( "\n" );           // 選択範囲 st を "\n" で区切って配列 a に
  1968.   for ( var i = 0; i < a.length; i ++ )     // 「1行め」から繰りかえし処理
  1969.     a[i] = arg3 + a[i];             // 各行の先頭に ast = " * " を追加する
  1970.   // 各行を "\n" で区切って連結し、先頭に p1 = "/*\n"、末尾に p2 = "\n */" を追加する
  1971.   return arg1 + a.join( "\n" ) + arg2;
  1972. }
  1973.  
  1974.  
  1975. /*
  1976.  * 関数 UnCommentJS( st )
  1977.  * 基本的にこのかたちのコメントブロックしか想定していない(インデントには非対応)。
  1978.  * また、複数のコメントブロックがある場合を想定していない。
  1979.  * 中間行の行頭記号はアスタリスク「*」と中黒「・」「・」を削除対象とする。
  1980.  */
  1981. function UnCommentJS( arg1 ) {          // UnCommentJS( st )
  1982.   var re1 = "^ ?\\/\\*+ ?\\n?";         // 先頭行のコメントマークの正規表現
  1983.   var re2 = "\\n? ?\\*+\\/ ?$";         // 末行のコメントマークの正規表現
  1984.   var reg = new RegExp( re1 + "|" + re2 , "g" );    // 正規表現 / … /g に変換
  1985.   var re3 = /^ ?(\*+|[・・]) ?/;          // 中間行の行頭記号の正規表現
  1986.   var a = arg1.split( "\n" );           // 選択範囲 st を "\n" で区切って配列 a に
  1987.  
  1988.   // 中間行の行頭記号を削除する
  1989.   for ( var i = 0; i < a.length; i ++ ) {   // 「1行め」から繰りかえし処理
  1990.     if ( a[i].match( reg ) )            // 先頭行と末行のコメントマークがある行はスキップ
  1991.       continue;
  1992.     a[i] = a[i].replace( re3 , "" );        // 中間行の行頭記号を削除
  1993.   }
  1994.   // 各行を "\n" で区切って連結し、先頭行と末行のコメントマークを削除
  1995.   return a.join( "\n" ).replace( reg , "" );
  1996. }
  1997.  
  1998.  
  1999. // -----------------------------------------------------------------------------
  2000.  
  2001.  
  2002. #title = "''引用符'' で囲う"
  2003. #tooltip = "ダブルクォーテーションで囲う"
  2004. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",100
  2005.  
  2006. // 選択範囲を指定の文字列("引用符")で囲う
  2007. // 選択範囲がすでに "引用符" で囲われていたら引用符ふたつ "" を削除する
  2008. // 複数行の選択範囲のとき、さいごの改行はふくめない
  2009. // マクロライブラリに転載済み (2018/10/19 - 2018/10/26)
  2010.  
  2011. // ( last modified: 2018/11/14 )
  2012.  
  2013. /* ■文字列を指定 */
  2014. var pre = '"';      // 前に付ける文字列
  2015. var sur = '"';      // 後に付ける文字列
  2016.  
  2017.   // ※ 文字列をダブルクォーテーション "" で囲うなら、中の「 " 」は要エスケープ 「'"'」=> 「"\""」
  2018.   // ※ 引用符以外の文字列を指定するなら 「'"'」=> 「"ほげ"」「"ふが"」
  2019.   // ※ 片側しか必要ないならいずれかを 「'"'」=> 「""」
  2020.  
  2021.  
  2022. /* ■複数行フラグ */
  2023. var multi = false;
  2024.  
  2025.   // ・multi = false; では、選択範囲「全体」の前後に文字列 pre / sur を追加
  2026.   // ・multi = true; では、選択範囲の「各行」ごとに文字列 pre / sur で囲う
  2027.  
  2028.  
  2029. /* ■挿入フラグ */
  2030. var ins = false;
  2031.  
  2032.   // ・ins = false; では、選択範囲がないときはマクロを中止する
  2033.   //   また、■複数行フラグが有効 ( multi = true ) のときに、空行には挿入しない
  2034.   //   選択範囲の末尾に空行があった場合、マクロ実行後のカーソルの復帰位置が■終了後フラグの説明どおりにならないことがある
  2035.   // ・ins = true; では、選択範囲がないときにはカーソル位置に pre / sur を挿入する
  2036.   //   また、■複数行フラグが有効 ( multi = true ) のときに、空行にも挿入する
  2037.   // ※■複数行フラグが有効 ( multi = true ) のときは、空白文字だけの行は空行と見做す
  2038.  
  2039.  
  2040. /* ■終了後フラグ */
  2041. var endPos = 5;     // 指定できる値は 0 ~ 5 ( 6 以上の値は 0 と同じ)
  2042.  
  2043.   // 0. カーソルは "引用符" の後ろへ  (※範囲選択なし)
  2044.   // 1. カーソルは最後の "引用符" の中へ移動する  (※範囲選択なし)
  2045.   // 2. マクロ実行前に範囲選択がなければカーソルは最後の "引用符" の中へ、
  2046.   //    あれば "引用符" の後ろへ移動する  (※範囲選択なし)
  2047.   // 3. マクロ実行前に範囲選択がなければカーソルは最後の "引用符" の中へ移動  (※範囲選択なし)、
  2048.   //    あれば "引用符" を含めた全体を選択範囲にする  (※カーソルは選択範囲の後ろへ)
  2049.   // 4. "引用符" を含めた全体を選択範囲にする  (※カーソルは選択範囲の後ろへ)
  2050.   // 5. "引用符" を含めた全体を選択範囲にする  (※カーソル位置はマクロ実行前の側(先頭 or 末尾)へ)
  2051.   //
  2052.   //   ※ "引用符" を含めた選択範囲を残すようにすると、連続実行で 追加 <=> 削除 のトグルができる。( 3 ~ 5 )
  2053.   //   ただし、後に付ける文字列の末尾が "\n" の場合、連続実行での 追加 <=> 削除 のトグルはできない。
  2054.   //   ※ 複数フラグが有効 ( multi = true ) のとき、"引用符" の中へ移動する「0 と 1」は適さないとおもわれる。
  2055.   //   ※ 「範囲選択なし」になる終了後フラグで "引用符" を削除したとき、カーソルの復帰位置は上の説明どおりにはならないことがある。
  2056.  
  2057.  
  2058. Redraw = false;
  2059.  
  2060. // 選択範囲
  2061. var s = document.selection;
  2062. var anc = s.GetAnchorPos();     // 選択範囲の開始位置 (キャレットのない側)
  2063. var act = s.GetActivePos();     // 選択範囲の終了位置 (キャレットのある側)
  2064. var tp = ( anc < act ) ? anc : act; // 選択範囲の先頭位置
  2065. var bp = ( anc < act ) ? act : anc; // 選択範囲の末尾位置
  2066.  
  2067. // 選択範囲の先頭&末尾の各座標
  2068. var bx = s.GetBottomPointX( mePosLogical );
  2069. var by = s.GetBottomPointY( mePosLogical );
  2070.  
  2071. // 選択範囲の末尾が行頭 x = 1 にあるときの調整(末尾の改行を含めない)
  2072. if ( tp < bp && bx == 1 ) {
  2073.   s.SetActivePos( tp );
  2074.   s.SetAnchorPos( bp - 1 );
  2075. }
  2076.  
  2077. // 選択範囲の文字列を取得
  2078. var st = s.Text;
  2079.  
  2080. // AddDelBrackets() で "引用符" を追加/削除
  2081. var t = AddDelBrackets( st, pre, sur );
  2082.  
  2083. // AddDelBrackets() 処理の前後で文字列に変化がないなら undo 履歴を残さない
  2084. if ( t == st ) {
  2085.   s.SetActivePos( act );
  2086.   s.SetAnchorPos( anc );
  2087.   Quit();
  2088. }
  2089.  
  2090. // "引用符" を追加/削除
  2091. s.Text = t;
  2092.  
  2093. // case 0. この時点でカーソルは "引用符" のうしろ ※範囲選択なし(末尾調整されたままの位置)
  2094. var dp = s.GetActivePos();
  2095.  
  2096.  
  2097. // ■終了後フラグの指定動作  ※カーソルを移動/選択範囲を復旧
  2098. switch ( endPos ) {
  2099.  
  2100.   case 1:   // カーソルは最後の "引用符" の中へ移動する  ※範囲選択なし
  2101.     SearchLastBracket();
  2102.     break;
  2103.  
  2104.   case 2:   // マクロ実行前に範囲選択がなければカーソルは最後の "引用符" の中へ
  2105.         // あれば選択範囲の後ろへ移動する  ※範囲選択なし
  2106.     if ( ! st )
  2107.       SearchLastBracket();
  2108.     else
  2109.       MoveToEndPos();
  2110.     break;
  2111.  
  2112.   case 3:   // マクロ実行前に範囲選択がなければカーソルは最後の "引用符" の中へ移動  ※範囲選択なし
  2113.         // あれば "引用符" を含めた全体を選択範囲にする  ※カーソルは選択範囲の後ろへ
  2114.     if ( ! st )
  2115.       SearchLastBracket();
  2116.     else {
  2117.       MoveToEndPos();
  2118.       s.SetAnchorPos( tp );
  2119.     }
  2120.     break;
  2121.  
  2122.   case 4:   // "引用符" を含めた全体を選択範囲にする  ※カーソルは選択範囲の後ろへ
  2123.     MoveToEndPos();
  2124.     s.SetAnchorPos( tp );
  2125.     break;
  2126.  
  2127.   case 5:   // "引用符" を含めた全体を選択範囲にする  ※カーソル位置はマクロ実行前の側(先頭 or 末尾)へ
  2128.     MoveToEndPos();
  2129.     if ( anc <= act )       // マクロ実行前のキャレットの位置が選択範囲の末尾だったとき
  2130.       s.SetAnchorPos( tp );
  2131.     else            // マクロ実行前のキャレットの位置が選択範囲の先頭だったとき
  2132.       s.SetActivePos( tp, true );
  2133.     break;
  2134.  
  2135.   default:
  2136.     break;
  2137. }
  2138.  
  2139.  
  2140. /* 関数 AddDelBrackets( st, pre, sur) */
  2141. function AddDelBrackets( arg1, arg2, arg3 ) {
  2142.   // カッコを 追加/削除
  2143.  
  2144.   // ■複数行フラグ ( multi ) 判定
  2145.   // 有効なら ( true ) 選択範囲 st を行で区切って配列 a に
  2146.   // 無効なら ( false )  選択範囲の文字列 st 全体をそのまま配列 a に格納する
  2147.   var a = ( multi ) ? arg1.split( "\n" )
  2148.                     : [ arg1 ];
  2149.   for ( var i = 0; i < a.length; i ++ ) {   // 「1行め」から繰りかえし処理
  2150.  
  2151.     // 選択範囲がカッコで囲われているとき
  2152.     // (先頭と末尾の文字列をカッコと比較して一致したとき)
  2153.     if ( a[i].substr( 0, arg2.length ) == arg2 &&
  2154.          a[i].substr( a[i].length - arg3.length, arg3.length ) == arg3
  2155.     )
  2156.       // 各行のカッコを削除
  2157.       a[i] = a[i].slice( arg2.length, a[i].length - arg3.length );
  2158.  
  2159.     // 選択範囲がカッコで囲われていないとき
  2160.     // ■挿入フラグが有効 ( ins = true ) なら、または a[i] が空白文字列でないなら
  2161.     else if ( ins || ! a[i].match( /^[\s ]*$/g ) )
  2162.       // 前後にカッコをつける
  2163.       a[i] = arg2 + a[i] + arg3;
  2164.  
  2165.     // ■挿入フラグが無効 ( ins = false ) のときの空白文字列は、スルー(空白のまま)
  2166.     else
  2167.       continue;
  2168.   }
  2169.   // 各行を "\n" で区切って連結しなおす
  2170.   return a.join( "\n" );
  2171. }
  2172.  
  2173.  
  2174. /* 関数 SearchLastBracket() */
  2175. function SearchLastBracket() {
  2176.   // カーソルを最後の閉じカッコの前へ移動  ※範囲選択なし
  2177.  
  2178.   if ( t.length < st.length )   // カッコを削除したときは。先頭へ
  2179.     s.SetActivePos( tp );
  2180.   else {            // カッコを追加したときは、選択範囲内の最後の閉じカッコの前へ
  2181.     if ( sur.length ) {
  2182.       s.SetAnchorPos( tp );
  2183.       s.SetActivePos( tp + s.Text.lastIndexOf( s.Text.match( Quote( sur ) ) ) );
  2184.     }
  2185.     else            // 閉じカッコ sur が未指定 "" の場合は、先頭へ
  2186.       s.SetActivePos( tp );
  2187.   }
  2188. }
  2189.  
  2190. /* 関数 MoveToEndPos() */
  2191. function MoveToEndPos() {
  2192.   // マクロ実行前に選択範囲があったとき、カーソルを元の選択範囲の末尾位置へ移動  ※範囲選択なし
  2193.  
  2194.   if ( tp < bp && bx == 1 )         // 選択範囲の末尾調整をしていたときは
  2195.     s.SetActivePoint( mePosLogical, 1, by );    // カーソルは元の末尾位置に復帰
  2196.   else                      // 末尾調整をしていなかったときは
  2197.     s.SetActivePos( dp );           // カーソル位置はそのまま
  2198. }
  2199.  
  2200.  
  2201.  /* 以下の関数は『JavaScript/正規表現 - Wikibooks』より
  2202.   https://ja.wikibooks.org/wiki/JavaScript/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE */
  2203. // PerlのquotemetaやRubyのRegExp.quoteのように、()や[]など正規表現のメタ文字と解釈される可能性のある文字をエスケープして返す関数は、Stringオブジェクトのreplaceメソッドを使用して簡単に作成することができます。
  2204. function Quote( str ) {
  2205.     return str.replace( /\W/g, function( $0 ) {
  2206.         return '\\' + $0;
  2207.     } );
  2208. };
  2209.  
  2210.  
  2211. // -----------------------------------------------------------------------------
  2212.  
  2213.  
  2214. #title = "ジャンプ..."
  2215. #tooltip = "ポップアップメニューで検索先にジャンプ"
  2216. #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",229
  2217. // むしろジャンプしないほうが便利な? 検索ポップアップメニュー
  2218. // マクロライブラリに転載済み (2018/11/12 - 2018/11/25)
  2219. // (最終更新: 2018/11/25) ◆ 人柱版 ◆
  2220.  
  2221. // ◆ 人柱版 ◆「空行+空白行」の検索に対応 ◆
  2222. //      「空行+空白行」の検索に対応
  2223. //      「ヒット件数(出現回数)」を表示
  2224. /**
  2225.  * ------------------------------------------------------------
  2226.  * "ポップアップメニューで検索先にジャンプ"
  2227.  * pooupJump.js
  2228.  * Original Copyright: 手石 (2014/04/04)
  2229.  * ------------------------------------------------------------
  2230.  * ● 手石版から引き継いだ機能 ●
  2231.  * ポップアップメニューで検索にヒットした箇所へジャンプできます。
  2232.  * ・選択した文字列(選択していないときはカーソルのある語)を検索します。
  2233.  * ・ヒットした行をポップアップメニューに表示し、選択するとその行へジャンプします。
  2234.  * ・同一行にヒットする箇所が複数あったときは最初のヒット箇所にジャンプします。
  2235.  * ・検索文字列の強調解除は、変更していなければ「Alt+F3」です。
  2236.  *
  2237.  * ------------------------------------------------------------
  2238.  * Modified by: sukemaru (2018/11/12 - 2018/11/25)
  2239.  * ------------------------------------------------------------
  2240.  * ■ 手石版からの変更点 ■
  2241.  * ・エディタ設定の「行の表示方法」にあわせられるように
  2242.  *   ポップアップメニューに表示する行番号は表示行/論理行を選択できます(■変数で設定)。
  2243.  * ・検索文字列がほかの行でヒットしなかった場合や
  2244.  *   ポップアップメニューからジャンプしなかった(キャンセル)場合には
  2245.  *   検索履歴に残らないようにしてあります。
  2246.  *   そのさい、マクロの実行前に選択範囲なしだったときは単語選択もキャンセルします。
  2247.  * ・ジャンプした後の「文字列の強調表示」を解除できます(■変数で設定)。
  2248.  *   ただし、検索をキャンセルした場合は、設定の有効/無効によらず強調表示しません。
  2249.  * ・ヒットした行数や文書全体の行数をステータスバーに表示します。
  2250.  * ・論理行全体を範囲選択しているときは末尾改行を無視して検索するので
  2251.  *   重複行の有無をチェックできます。
  2252.  * ・ポップアップメニューをキャンセルすればムダな検索履歴が残らないので
  2253.  *   検索文字列のダメ文字条件をなくしました。
  2254.  *
  2255.  * ※「行の表示方法」が表示座標(表示行)で
  2256.  *   折り返しにより検索文字列が途切れている場合はヒットしません
  2257.  *   (Mery 標準の検索ダイアログなら検出できるのですが…)。
  2258.  * ※ポップアップメニューは ESC キーでキャンセルできます。
  2259.  *
  2260.  * ------------------------------------------------------------
  2261.  * ◆ 人柱版の追加機能 ◆
  2262.  * ・検索のさいに「大文字/小文字を区別」するかしないかを選択できます(◆変数で設定)。
  2263.  * ・空行にキャレットがある状態か、"末尾改行をふくめて" 空白行を範囲選択している状態から
  2264.  *   「すべての空行+空白行」を検索できるオプションを追加しました(◆変数で設定)。
  2265.  * ・検索対象が「空行+空白行」でないときは、ヒットした行数とは別に
  2266.  *   ヒットした件数をステータスバーに表示できます(◆変数で設定)。
  2267.  *    ・「ヒット件数」の判定は、大文字/小文字オプションの設定に依拠します。
  2268.  * ・検索対象が「空行+空白行」でないとき、ポップアップメニューの右隅に以下のマーキングを表示できます
  2269.  *   (「ヒット件数」オプションが有効の場合のみ)。
  2270.  *    ・検索文字列が行全体のとき、アクティブ行に「 ⏎ 」マーク
  2271.  *    ・アクティブ行と完全に一致する重複行に「 ** 」マーク  (※行検索でないときにも表示)
  2272.  *    ・検索文字列と完全に一致する行に「 * 」マーク
  2273.  *    ・検索文字列が複数回ヒットした行に「 x2 」マーク
  2274.  *   「一致」の判定では、つねに大文字/小文字を区別します。
  2275.  * ・ポップアップメニューを Space キーでもキャンセルできるようにしました。
  2276.  *   ただし、メニューに表示されるヒットした行の文字列に
  2277.  *   「アンパサンドと半角スペース "&␣"」があるときは Esc キーのみ( "&&␣" なら可)。
  2278.  *
  2279.  * ※「空行/空白行」オプションが有効 ( true ) の場合は
  2280.  *   末尾改行 "\n" をふくめて「空白文字のみの行」を範囲選択しているときに
  2281.  *   すべての「空行+空白行」を検索対象にします。
  2282.  *   末尾改行をふくめずに「空白文字のみの行」を範囲選択しているときは
  2283.  *   通常の検索メソッドで「一致する空白文字列」を検索対象にします。
  2284.  * ※「空行/空白行」オプションが無効 ( false ) の場合
  2285.  *   「空白文字のみの行」を範囲選択しているときには「一致する空白文字列」を検索対象にします。
  2286.  *   空行で実行した場合にはポップアップメニューは表示されません。
  2287.  * ※「空行+空白行」が対象のとき以外は正規表現を使わずに行単位で検索するので
  2288.  *   選択範囲が複数行(末尾以外に改行 "\n" がある)の場合や
  2289.  *   空白行オプションが無効で選択範囲が空行 "^\n" の場合は検索できません。
  2290.  * ※大きな文書の場合、「空行/空白行/空白文字列」や
  2291.  *   「頻出する文字/単語」の検索では処理に時間がかかります。
  2292.  * 「人柱版 設定項目」の変数の値をすべて無効 false にすれば通常版とおなじ動作になります。
  2293.  *
  2294.  */
  2295.  
  2296. // ---------- ▼ 通常版 設定項目 ▼ ----------
  2297.  
  2298. // ■行の表示方法 (true; 論理座標 /false; 表示座標)
  2299. var logical = true;     // ■初期値 = true;  (論理座標)
  2300.  
  2301. // ■検索文字列の強調表示を残すか? (true; 残す /false; 残さない)
  2302. var highlightEnable = false;    // ■初期値 = true; (残す)
  2303.  
  2304. // ■選択範囲なしの状態から実行したときに自動マーカーを表示するか? (true; 表示する / false; 表示しない)
  2305. // ※ [表示]メニュー >> [マーカー] >> [自動マーカー] が OFF なら効果なし。
  2306. var markerEnable = true;    // ■初期値 = true; (表示する)
  2307.  
  2308. // ---------- ▼ 人柱版 設定項目 ▼ ----------
  2309.  
  2310. // ◆検索文字列の大文字/小文字を区別するか? (true; 区別する / false; 区別しない)
  2311. var caseEnable = false;     // ◆初期値 = false; (区別しない)
  2312.  
  2313. // ◆空行/空白行を検索対象にするか? (true; する /false; しない)
  2314. var blankEnable = true;     // ◆初期値 = true; (する)
  2315.  
  2316. // ◆ヒット件数(出現回数)を表示するか? (true; する /false; しない)
  2317. var countEnable = true;     // ◆初期値 = true; (する)
  2318.  
  2319. // ---------- ▼ 手石版 設定項目 ▼ ----------
  2320.  
  2321. // ●ポップアップメニューに表示する文字数
  2322. var menuWidth = 66;
  2323.  
  2324. // ---------- ▲ 設定項目 ここまで ▲ ----------
  2325.  
  2326. Redraw = markerEnable;
  2327. var sx = ScrollX,  sy = ScrollY;
  2328. var d = document;
  2329. var s = document.selection;
  2330.  
  2331. /* 検索文字列の準備 */
  2332. var blank = new RegExp( "^[\t  ]*$" , "" );   // 空白行の正規表現
  2333. // 選択範囲なしならキャレット位置の単語を選択する
  2334. if ( s.IsEmpty ) {
  2335.   var p = s.GetActivePos(); // "選択範囲なし" のフラグ
  2336.   s.SelectWord();
  2337. }
  2338. var st = s.Text;        // 検索文字列
  2339. // 選択範囲の末尾が改行 "\n" なら検索文字列から除外する
  2340. if ( ! st || st.charAt( st.length - 1 ) == "\n" ) {
  2341.   st = st.replace( /\n$/g , "" );
  2342.   // 自動マーカーを効かせるために選択範囲も調整する
  2343.   var anc = s.GetAnchorPos();
  2344.   var act = s.GetActivePos();   // "末尾調整" フラグ
  2345.   if ( anc < act && ! ( blankEnable && st.match( blank ) ) )
  2346.     s.SetActivePos( act - 1, true );
  2347.   if ( act < anc && ! ( blankEnable && st.match( blank ) ) ) {
  2348.     s.SetAnchorPos( anc - 1 );
  2349.     s.SetActivePos( act, true );
  2350.   }
  2351.   if ( blankEnable && st.match( blank ) )
  2352.     var re = true;  // "空白行の正規表現検索" フラグ
  2353. }
  2354. // 選択範囲の先頭位置と、文書全体の行数(論理行/表示行)
  2355. var ty = s.GetTopPointY( logical ? mePosLogical : mePosView );
  2356. var lines = d.GetLines( logical ? 0 : meGetLineView );
  2357. var cancel = 5;     // "キャンセル" フラグ
  2358.  
  2359. // 検索文字列がないとき(空行)
  2360. if ( ! blankEnable && ! st )
  2361.   cancel = 1;
  2362. // 検索条件エラー(選択範囲に改行あり)
  2363. else if ( st.match( /\n/g ) )
  2364.   cancel = 2;
  2365.  
  2366. // ポップアップメニューでジャンプ先リスト
  2367. else {
  2368.   /* 文書全体を行単位で分割し、配列に */
  2369.   if ( logical )    // 論理行
  2370.     var a = d.Text.split( "\n" );
  2371.   else          // 表示行
  2372.     for( var i = 1, a = []; i <= lines ; i ++ )
  2373.       a.push( d.GetLine( i, meGetLineView ) );
  2374.   a.unshift( "" );  // i = 論理行番号 になるよう a[0] に空要素を追加
  2375.  
  2376.   /* ポップアップメニューの最上部に表示するアイテム */
  2377.   var m = CreatePopupMenu();
  2378.   // 文字列の検索では先頭に「キャンセル」のアイテムを表示
  2379.   if ( ! re ) {
  2380.     m.Add( "         キャンセル    & ", 0 );   // Space キーか Esc キーでキャンセル可
  2381.     m.Add( "", 0, meMenuSeparator );
  2382.     var gt = 0 , h = 0;
  2383.     // アクティブ行(検索開始行)全体の文字列を取得
  2384.     if ( countEnable )
  2385.       var activeLine = d.GetLine( ty, logical ? 0 : meGetLineView );
  2386.   }
  2387.   // 「空行+空白行」の検索では配列を使用する
  2388.   else {
  2389.     var mArray = [],  sm1Array = [],  sm2Array = [];
  2390.     var h = 0,  b = 0,  n = 0,  w = 0;
  2391.   }
  2392.  
  2393.   /* 検索文字列がヒットした行をポップアップメニューのアイテムとして取得する */
  2394.   for( var i = 1; i < a.length; i ++ ) {    // a[0] = 空要素、i = 行番号 => y
  2395.     // 空行からの検索なら「空行+空白行」以外はスキップ
  2396.     if ( re && ! a[i].match( blank ) )
  2397.       continue;
  2398.     // 「大文字/小文字を区別」する/しない
  2399.     var findCaseTF =
  2400.       caseEnable ? a[i].indexOf( st ) :
  2401.       /* else */   a[i].toLowerCase().indexOf( st.toLowerCase() );
  2402.     // 検索文字列がヒットしたら
  2403.     if ( ( ! re && findCaseTF >= 0 ) || ( re && a[i].match( blank ) ) ) {
  2404.       // 行内でのヒット回数
  2405.       if ( ! re && countEnable ) {  // if ( ! st.match( blank ) )
  2406.         var t = a[i].match(
  2407.           RegExp( st.replace( /\W/g , "\\$&" ) , caseEnable ? "g" : "gi" )
  2408.         );
  2409.         gt += t.length;     // 総ヒット回数(大文字/小文字を区別できる)
  2410.       }
  2411.       // 右側につけるマーキング
  2412.       var check = ( ! re && countEnable ) ? Marking() : "";
  2413.       // アクティブ行は左に ✓ チェックマーク付き
  2414.       var flags = ( i == ty ) ? meMenuChecked : 0;  // + meMenuGrayed
  2415.  
  2416.       /* ポップアップメニューにアイテム(行)を追加する */
  2417.       if ( ! re ) {
  2418.         // 行頭空白は除去、空白文字は半角スペースに置換、文字数を圧縮して取得
  2419.         m.Add( Labeling( a[i], i ) + check, i, flags );     // ヒットした行
  2420.         h ++;       // ヒットした行数
  2421.       }
  2422.       // 「空行+空白行」の検索ではサブメニュー用の配列に分別
  2423.       else {    // if ( re )
  2424.         b ++;       // 空行+空白行数
  2425.         if ( a[i] == st ) {
  2426.           mArray.push( [ Labeling( a[i], i ) + check, i, flags ] ); // 一致した行
  2427.           h ++;     // 一致した行数
  2428.         }
  2429.         if ( st && a[i] == "" ) {
  2430.           sm1Array.push( [ Labeling( a[i], i ) + check, i, flags ] );   // 空行
  2431.           n ++;     // 空行数
  2432.         }
  2433.         else if ( a[i].length ) {
  2434.           sm2Array.push( [ Labeling( a[i], i ) + check, i, flags ] );   // 空白行
  2435.           w ++;     // 空白行数
  2436.         }
  2437.       }
  2438.     }   // end if{ 検索文字列がヒットしたら }
  2439.   } // end for( ヒットした行を取得する )
  2440.  
  2441.   // 配列から「空行+空白行」をポップアップメニューに追加する
  2442.   if ( re ) {
  2443.     if ( b != h ) {
  2444.       m.Add( " すべての空行+空白行: " + SeparateNum( b ) + " 行", 0 );    // , meMenuGrayed
  2445.       m.Add( "", 0, meMenuSeparator );
  2446.     }
  2447.     if ( n && st ) {            // n == sm1Array.length
  2448.       var sm1 = CreatePopupMenu();
  2449.       m.AddPopup( " すべての空行: " + SeparateNum( n ) + " 行 (&N)", sm1 );
  2450.       for ( var i = 0; i < n; i ++ )
  2451.         sm1.Add( sm1Array[i][0], sm1Array[i][1], sm1Array[i][2] );
  2452.     }
  2453.     if ( w && ( n + h != b ) ) {    // w == sm2Array.length
  2454.       var sm2 = CreatePopupMenu();
  2455.       m.AddPopup( " すべての空白行: " + SeparateNum( w ) + " 行 (&W)", sm2 );
  2456.       for ( var i = 0; i < w; i ++ )
  2457.         sm2.Add( sm2Array[i][0], sm2Array[i][1], sm2Array[i][2] );
  2458.     }
  2459.     if ( n && st || w && ( n + h != b ) )
  2460.       m.Add( "", 0, meMenuSeparator );
  2461.     // キャンセルを兼ねる(Space キーでキャンセル可) , meMenuGrayed
  2462.     m.Add( " ▼    一致した行: " + SeparateNum( h ) + " 行   ▼\t& ", 0 );
  2463.     for ( var i = 0; i < h; i ++ )  // h == mArray.length
  2464.       m.Add( mArray[i][0], mArray[i][1], mArray[i][2] );
  2465.   }
  2466.  
  2467.   // ポップアップメニューを表示するのは、検索ヒット行が複数のとき
  2468.   if ( h > 1 || b > 1) {
  2469.     // ポップアップメニューを出すまえにステータスバー表示させること
  2470.     Status =
  2471.       ( re ? " 一致した行数: " + SeparateNum( h ) + " 行"
  2472.                + " / すべての空(白)行数: " + SeparateNum( b ) + " 行" :
  2473.    /* ! re */  ( gt ? ( " ヒット数: " + SeparateNum( gt ) + " 件 /" ) : "" )
  2474.                + " ヒットした行数: " + SeparateNum( h ) + " 行"
  2475.       )
  2476.       + " / 全体の行数: " + SeparateNum( lines )
  2477.       + ( logical ? " 行 (論理行)" : " 行 (表示行)" );
  2478.  
  2479.     /* カーソル位置にポップアップメニューを表示 */
  2480.     var y = m.Track( mePosMouse );  // Track( 0 ) ならキャレット位置
  2481.  
  2482.     /* 選択した行番号(行頭)にジャンプして検索文字列を選択 */
  2483.     if ( y > 0 ) {
  2484.       s.SetActivePoint( logical ? mePosLogical : mePosView, 1, y );
  2485.       // 空白行でジャンプしたときは検索履歴に残さない
  2486.       if ( re && d.GetLine( y ) )       // 行(空白文字列)全体を範囲選択
  2487.         s.SetAnchorPoint( logical ? mePosLogical : mePosView, 1, y + 1 );
  2488.       // 文字列でジャンプしたときは検索履歴に残す
  2489.       else if ( ! re )
  2490.         s.Find( st, meFindNext );       // Mery の検索機能で文字列を範囲選択
  2491.       d.HighlightFind = highlightEnable;    // 「検索文字列の強調表示」を解除する/しない
  2492.       cancel = 0;               // cancel フラグを解除
  2493.     }
  2494.  
  2495. /* キャンセル */
  2496.     // ポップアップメニューをキャンセルした場合 ( y == 0 )
  2497.     else  cancel = 3;
  2498.   } // end if{ ポップアップメニューを表示 }
  2499.   // ほかの行でヒットしなかったとき ( h == 0 )
  2500.   else  cancel = 4;
  2501. }   // end else{ ポップアップメニューでジャンプ先リスト }
  2502. /* ジャンプしなかったときは、キャレット位置/選択範囲を復帰 */
  2503. if ( cancel ) {
  2504.   if ( p )
  2505.     s.SetActivePos( p );
  2506.   else if ( anc < act )
  2507.     s.SetActivePos( act, true );
  2508.   else if ( act < anc ) {
  2509.     s.SetAnchorPos( anc );
  2510.     s.SetActivePos( act, true );
  2511.   }
  2512.   // ステータスバーにメッセージを表示
  2513.   Status =
  2514.     ( ( cancel == 1 ) ? " 検索文字列がありません(空行)。" :
  2515.       ( cancel == 2 ) ? " 検索文字列に【 改行 】を含めることはできません。" :
  2516.       ( cancel == 3 ) ? " キャンセルしました。 ヒット: "
  2517.                         + ( gt ? ( SeparateNum( gt ) + " 件 ・ " ) : "" )
  2518.                         + SeparateNum( h ) + " 行" :
  2519.       ( cancel == 4 ) ? " ほかの行には見つかりませんでした。" :
  2520.        /*  else  */     " 無効な検索文字列(ダメ文字)。"
  2521.     )
  2522.     + " / 全体の行数: " + SeparateNum( lines )
  2523.     + ( logical ? " 行 (論理行)" : " 行 (表示行)" );
  2524.   ScrollX = sx;  ScrollY = sy;
  2525. }
  2526. Redraw = true;
  2527.  
  2528. /* 関数 Marking() */
  2529. // ポップアップメニューの右側に表示するマーキング
  2530. function Marking() {
  2531.   var _check = (
  2532.     ( i != ty && a[i] == activeLine ) ? "\t **" :   // ①アクティブ行と完全一致する行(重複行)
  2533.     ( t && t.length > 1 )     ? "\t x" + t.length : // ②検索文字列が複数ヒットした行
  2534.     ( i == ty && a[i] == st ) ? "\t ⏎" :      // ③アクティブ行(行検索のとき)✓↵
  2535.     ( i != ty && a[i] == st ) ? "\t *" :        // ④検索文字列と完全一致する行
  2536.                                 ""          // ⑤検索文字列を含む行
  2537.   );
  2538.   return _check;
  2539. }
  2540.  
  2541. /* 関数 Labeling( str, num ) */
  2542. // ポップアップメニューに表示する文字列の整形
  2543. function Labeling( line, i ) {      // ※ line = a[i] ヒットした行全体
  2544.   // 行頭空白を除去、空白文字は半角スペースに置換、文字数を圧縮して取得
  2545.   var label = line.replace( /^[\t  ]+/ , "" )
  2546.                   .replace( /(\t|[ ]{2,}|[ ])+/g , "   " );
  2547.   label = (
  2548.     ( ! line.length )  ? "( 空行 )" :
  2549.     ( ! label.length ) ?
  2550.     ( line == st )     ? "( 空白行 " + line.length + " 文字 * )" :
  2551.                          "( 空白行 " + line.length + " 文字 )" :
  2552.     ( label.length > menuWidth + 1 ) ? label.slice( 0, menuWidth ) + "..." :
  2553.      /* else */                        label
  2554.    );
  2555.   return "" + ( "    " + i ).slice( -4 ) + " : " + label;
  2556. }
  2557.  
  2558. /* 関数 SeparateNum( num ) */
  2559. // 数値を3ケタ区切りに
  2560. function SeparateNum( num ) {
  2561.   return num.toString().replace( /(\d)(?=(?:\d{3})+$)/g , "$1," );
  2562. }
  2563.  
  2564.  
  2565. // -----------------------------------------------------------------------------
  2566.  
  2567. /*
  2568.         ▼タブインデントされた行へのJSコメントアウト2の比較
  2569.                 abcdefg
  2570.  */
  2571.  
  2572.         /*
  2573.          * ■「引用符/コメント」マクロの JSコメントアウト2
  2574.          *      abcdefg
  2575.          */
  2576.  
  2577. /*
  2578.  *      ■「カッコで囲う」マクロの JSコメントアウト2
  2579.  *              abcdefg
  2580.  */
  2581.  
  2582.  
  2583. // (「引用符/コメント」「カッコで囲う」マクロにはアスタリスク+半角スペース×2「␣*␣」の箇条書き行頭記号の追加/削除ができるようにしてあります)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top