「カッコで囲う」の版間の差分

提供:MeryWiki
ナビゲーションに移動 検索に移動
(2018/10/29 (sukemaru))
(人柱版追加コード「行頭/行末から任意の 文字数 を削除」「行頭/行末から任意の 文字列 を削除」を追加)
715行目: 715行目:
   // 各行を "\n" で区切って連結し、先頭行と末行のコメントマークを削除
   // 各行を "\n" で区切って連結し、先頭行と末行のコメントマークを削除
   return a.join( "\n" ).replace( reg , "" );
   return a.join( "\n" ).replace( reg , "" );
}
</source>
= 人柱用 追加コード =
「カッコで囲う (ポップアップメニューあり)」のポップアップメニューの項目に
* 「行頭/行末から任意の '''文字数''' を削除」
* 「行頭/行末から任意の '''文字列''' を削除」
のふたつを追加します。 <br>
*「任意の文字列2」や「wiki 用文字修飾タグ」と同様に、選択範囲内の論理行の各行頭と行末にたいして作用します(選択範囲を論理行単位で拡張しないので、先頭行と末行においては行頭/行末ではなく「選択範囲の先頭/末尾」にたいして作用します)。
*「任意の文字数を削除」ではアラビア数字以外で入力された文字列をすべて排除します。例えば「'''1a2あ'''」と入力された場合は、「'''12'''」として扱います。
*「任意の文字列を削除」は簡易的な処理コードなので、正規表現を使用できません。<br> また、タブ文字の扱いは「任意の文字列2(追加)」の場合とおなじく「'''\\\t'''」で入力されたもの (注:¥記号3つ) をタブ文字('''\t''')として処理します。
<br><br>
作ってみたものの使う機会にとぼしく、動作検証が不十分なままなので<b style="color:#c00;">人柱版</b>としてコードだけ置いておきます。
== 任意の文字数/文字列を削除 ==
▼'''m.Add( ... );''' のグループ内に追加(位置は任意)▼
<source lang="javascript">
/* 以下の2項目は動作検証不十分 */
// m.Add( "", 0, meMenuSeparator );
m.Add( "行頭/行末から任意の 文字数 を削除 (&Y)", 52 );
m.Add( "行頭/行末から任意の 文字列 を削除 (&Z)", 53 );
</source>
▼␣␣␣␣'''default:''' ␣␣␣␣␣␣'''break;''' の上に追加▼
<source lang="javascript">
    // 各行の前後から任意の文字数/文字列を削除 ※テキストボックス
    case 52:  case 53:
      if ( ! pos ) { // 選択範囲があれば
        // 「任意の文字数を削除」
        if ( r == 52 ) {
          // ダイアログのテキスト入力フィールドから文字列を取得
          // 半角に変換して数字以外の文字は削除
          var p1 = ToHalfWidth(
            Prompt( "行頭から削除する文字数 (数字のみ有効):", "" )
          ).replace( /[^0-9]/g , "" );
          var p2 = ToHalfWidth(
            Prompt( "行末から削除する文字数 (数字のみ有効):", "" )
          ).replace( /[^0-9]/g , "" );
          // 各行の先頭/末尾から指定文字数を削除
          var dt = DeleteCharByNum( st, p1, p2 );
        }
        // 「任意の文字列を削除」
        else { // ( r == 53 )
        // ダイアログのテキスト入力フィールドから文字列を取得
        var p1 = Prompt(
          "行頭から削除する文字列:\tタブ=\\\\\\t  (注:¥記号3つ)", ""
        ).replace( /\\\\\\t/g , "\t" );
        var p2 = Prompt(
          "行末から削除する文字列:\tタブ=\\\\\\t  (注:¥記号3つ)", ""
        ).replace( /\\\\\\t/g , "\t" );
        var reg1 = new RegExp( "^" + Quote( p1 ) , "gm" );
        var reg2 = new RegExp( Quote( p2 ) + "$" , "gm" );
        // 各行の先頭/末尾の指定文字列を削除
        dt = st.replace( reg1 , "" ).replace( reg2 , "" );
        }
        // 選択範囲に指定文字列がなかった場合 undo 履歴を残さない
        if ( dt != st ) {
          s.Text = dt; // 削除完了
          s.SetAnchorPos( tp ); // 選択範囲を復元
        }
      }
      break;
</source>
▼ソースコード末尾(末行のした)に追加▼
<source lang="javascript">
/* 関数 DeleteCharByNum( st, p1, p2 ) */
  // 各行の先頭/末尾からの指定文字数を削除
function DeleteCharByNum( str, p1, p2 ) {
  var a = str.split( "\n" );
  for ( var i = 0; i < a.length; i ++ )
    a[i] = a[i].slice( p1, a[i].length - p2 );
  return a.join( "\n" );
}
/* 関数 quote( str ) */
// 『JavaScript/正規表現 - Wikibooks』より
// ref. https://ja.wikibooks.org/wiki/JavaScript/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE
// PerlのquotemetaやRubyのRegExp.quoteのように、()や[]など正規表現のメタ文字と解釈される可能性のある文字をエスケープして返す関数は、Stringオブジェクトのreplaceメソッドを使用して簡単に作成することができます。
function Quote( str ) {
    return str.replace( /\W/g, function( $0 ) {
        return '\\' + $0;
    } );
}
/**
* 全角から半角への変革関数 toHalfWidth( strVal )
* 入力値の英数記号を半角変換して返却
* [引数]  strVal: 入力値
* [返却値] String(): 半角変換された文字列
*/
// ref. https://webllica.com/add-comma-as-thousands-separator/ より
function ToHalfWidth( strVal ){
  // 半角変換
  var halfVal = strVal.replace( /[!-~]/g,
    function( tmpStr ) {
      // 文字コードをシフト
      return String.fromCharCode( tmpStr.charCodeAt(0) - 0xFEE0 );
    }
  );
  return halfVal;
}
}
</source>
</source>
746行目: 859行目:
:・「カッコで囲う.zip」を差し替え
:・「カッコで囲う.zip」を差し替え
* 2018/10/29 (sukemaru)
* 2018/10/29 (sukemaru)
:・「カッコで囲う (ポップアップメニューあり)」の節を更新
:・「カッコで囲う (ポップアップメニューあり)」の節を更新(本体のソースコードに追加コードを包摂)
:・「カッコで囲う (ポップアップメニューあり)」のメニュー項目に「任意の文字列2」を追加
:・「カッコで囲う (ポップアップメニューあり)」のメニュー項目に「任意の文字列2」を追加
:・「カッコで囲う (ポップアップメニューあり)」のソースコードをまとめてページ下部に移動
:・「カッコで囲う (ポップアップメニューあり)」のソースコードをまとめてページ下部に移動
:・「カッコで囲う.zip」を差し替え
:・「カッコで囲う.zip」を差し替え
* 2018/11/19 (sukemaru)
:・「カッコで囲う (ポップアップメニューあり)」用の人柱版追加コード「行頭/行末から任意の 文字数 を削除」「行頭/行末から任意の 文字列 を削除」を追加

2018年11月19日 (月) 22:43時点における版

カッコで囲う ポップアップメニュー.png

全部入りのソースをダウンロード → 「カッコで囲う.zip(アイコン入り)」 (最終更新 2018/10/29)

ZIP 書庫には以下のマクロの .JS ファイルと、 "マテリアルデザインっぽい" それぞれの専用アイコンがふくまれています。
  • カッコで囲う(ポップアップメニューあり)
  • カッコで囲う(ポップアップメニューなし)
  • 引用符を追加/削除


カッコで囲う(ポップアップメニューあり)

ポップアップメニューから任意の カッコダッシュ などの種類を選択して、選択範囲をカッコやいろいろな記号、文字列で囲います。
選択範囲がないばあい、基本的にはカーソル位置に ( ), < >, [ ], { }, 「 」, … などを挿入します。

行番号のドラッグでの複数行選択やトリプルクリックでの行選択などで末尾改行が含まれているばあい、さいごの改行を無視します。

  • 既存のポップアップメニュー項目を減らしたいばあいは、ソースコード内の "m.Add( … );" の行を // でコメントアウトするとその項目をメニューから隠せます。
  • メニュー項目を増やしたいばあいは、
  1. ソースコード冒頭の配列 p1, p2 の21番目~30番目に "記号" を追加する
  2. 対応する番号をつけて "m.Add( … );" の行を追加する
  3. 対応する番号をつけて "case XX:" を適当なグループに追加する
  • 作成にあたり、「引用の追加」マクロとキーアサイン集の「括弧で挟む」マクロのコードを参考にしました(※「引用の追加」マクロは 2018/10/14 付けで公開停止になりました)。





メニューの項目

任意の文字列

文字入力用のダイアログで「前につける文字列」と「後ろにつける文字列」を指定します。

  • 任意の文字列1
選択範囲全体を一組の指定文字列で前後を囲います。
  • 任意の文字列2
選択範囲内の各行ごとに指定文字列で前後を囲います。
ソースコード冒頭の skip フラグで、複数行選択のさいに空白行をスキップするか指定してください。
「wiki 文字装飾タグ」以外のカッコ/記号で各行ごとに囲いたい場合は、「任意の文字列2」を使用してください。

改行コードとタブ文字は、それぞれ「\\\n」と「\\\t」で入力されたもの (注:¥記号3つ) を改行コードとタブ文字に置換するようにしてあります。

※「\n」、「\t」と入力するとそのままの文字列「\n」、「\t」を返します。

文字コードでの入力には非対応です(入力されたままの文字列を返します)。


カッコ/記号 で囲う

選択範囲を指定したカッコ/記号で囲います。
選択範囲なしで実行した場合は、カーソル位置にカッコ一組を挿入します。

  • (半角丸カッコ) 、 <半角山カッコ> 、 [半角角カッコ] 、 {半角波カッコ}、
    (全角丸カッコ) 、 「全角かぎカッコ」 、 『二重かぎカッコ』 、 【スミ付きカッコ】
選択範囲をカッコで囲います。
  • ␣(半角丸カッコ)␣ 、 ␣"半角二重引用符"␣
選択範囲をカッコで囲い、さらに半角スペースで囲います。
  • ␣半角スペース␣
選択範囲を半角スペースで囲います。
  • - 半角ハイフン - 、 ――ダッシュ×2―― 、 ~チルダ~
「半角ハイフン」は、半角ハイフン=マイナス記号の両側に各1つずつ半角スペースがつきます(片側で半角3文字分)。
※この3種については、選択範囲なしで実行したときに片側分だけを挿入します。


n文字ずつ前後を削除

  • 1文字ずつ前後を削除 / 2文字ずつ前後を削除 / 3文字ずつ前後を削除
選択範囲内の先頭/末尾から指定の文字数ずつ削除します。


挿入型コメントアウト

3種類の 挿入型コメントアウト のメタ記号で選択範囲の文字列をコメントアウトできます。また、アンコメント用のコマンドでコメントアウト状態を解除できます。

  • /* JavaScript 挿入型コメントアウト1 */
選択範囲の両端を /* */ で囲います。
  • /* *JavaScript コメントアウト2(複数行) */
/*
​ * 選択範囲の両端を "/* \n" と "\n */" で囲い、
​ * 範囲内の各行の行頭に " * " を付けます。
​ */
  • <!-- XML 挿入型コメントアウト -->
選択範囲の両端を <!-- --> で囲います。


※ "JS アンコメント" と "XML アンコメント" では、先頭と末尾のコメントマークは選択範囲の両端でなければ削除されません(選択範囲の先頭/末尾に半角スペース×1が付いていても、コメントマークといっしょに削除できます)。
また、選択範囲内に2組以上のコメントがあると、正常にアンコメントできません。

※ "JS アンコメント" は中間行の行頭記号(アスタリスクと全角/半角中黒)とその前後の半角スペースを削除します。これらの行頭記号を使用した箇条書きを範囲選択して実行すると、同様に行頭記号を削除します。


wiki用 文字列装飾

5種類の wiki用 文字列装飾タグ(テキスト整形マークアップ)を挿入できます。

選択範囲内の各行ごとに指定のタグで前後を囲います。
ソースコード冒頭の skip フラグで、複数行選択のさいに空白行をスキップするか指定してください。

  • 太字
選択範囲の両端を '''(シングルクオート×3) で囲います。
  • 斜体(Italic)
選択範囲の両端を ''(シングルクオート×2) で囲います。
  • 下線
選択範囲の両端を <u></u> で囲います。
  • [[内部リンク]]
選択範囲の両端を [[]] で囲い、[[リンク|ラベル]] 型の 内部リンク にします。
  • <​nowiki>マークアップ回避<​/nowiki>
選択範囲の両端を <​nowiki><​/nowiki> で囲います。


※ wiki用 文字列装飾タグのままでは使いみちがないとおもいますので、HTML タグ <a> </a> などに書き換えてしまうか、ポップアップメニュー項目をコメントアウトしてしまうとよいでしょう(ZIP のソースでは初期状態でコメントアウトしてあります)。


カッコで囲う (ポップアップメニューなし)

簡易版です。

c.f. 追加と削除ができる機能強化版 → 「引用符を追加/削除

特定の種類のカッコを一発で追加する小マクロはキーアサイン集にもありますが、コードを改変して前後に付ける "カッコ" のかわりに "任意の文字列" を指定するばあいに「折り返し」表示と相性のよくない部分があります。

また、マクロ実行後のカーソル位置を選択範囲なしのときとありのときとで変えたいばあいも、こちらのコードがよいでしょう。

#title = "( カッコ )"
#tooltip = "( カッコ ) で囲う"
// MeryWiki の マクロライブラリ >> キーアサイン集 の「括弧で挟む」を改変
// 選択範囲の前後にカッコ以外にも任意の文字列を追加するマクロとしても流用できます

var s = document.selection;

// 選択範囲の各座標を取得
var ax = s.GetTopPointX( mePosLogical );
var ay = s.GetTopPointY( mePosLogical );

// 選択範囲のテキストを取得し、カッコを追加
var st = s.Text;
var pre = "(";	// 前に付ける文字列
var sur = ")";	// 後ろに付ける文字列
s.Text = pre + st + sur;

// カーソルを移動、または範囲選択
if ( ! st )	// 選択範囲なしだったばあい
  s.SetActivePos( s.GetActivePos() - sur.length );	// 後ろに付けた文字列 sur の前にカーソルを移動
else	// 選択範囲があったばあい
  s.SetAnchorPoint( mePosLogical, ax, ay );	// カッコを含めて範囲選択


引用符を追加/削除

カッコで囲う (ポップアップメニューなし)」の強化版です。

”引用符” を一発で追加する小マクロは 「マテリアルデザインっぽいアイコンと『小マクロ集』」 の 「”引用符”を追加」 にもありますが、こちらのマクロでは 「引用符(または指定した文字列)で囲う」操作と「囲っている引用符を削除する」操作をトグルできます。
※ 後ろにつける文字列の末尾が "\n" の場合はトグル不可。

  • 文字列指定は ”引用符” 以外の カッコHTML タグ などに変更できます。
  • 選択範囲が複数行(論理行)にまたがっている場合に、選択範囲「全体」を一組の ”引用符” で囲うか、選択範囲内の「各行ごと」に ”引用符” で囲うかを選択することもできます。
  • マクロ実行後のカーソル位置を選択範囲なしのときとありのときとで変えたい場合には、数種類のパターンから選択できるようになっています。
#title = "''引用符'' で囲う"
#tooltip = "ダブルクォーテーションで囲う"
// -------------------------------------------------------------------
// 選択範囲を指定の文字列("引用符")で囲う
// 選択範囲がすでに "引用符" で囲われていたら引用符ふたつ "" を削除する
// 複数行の選択範囲のとき、さいごの改行はふくめない
// -------------------------------------------------------------------

/* ■文字列を指定 */
var pre = '"';		// 前に付ける文字列
var sur = '"';		// 後に付ける文字列
  // ※ 文字列をダブルクォーテーション "" で囲うなら、中の「 " 」は要エスケープ 「'"'」=> 「"\""」
  // ※ 引用符以外の文字列を指定するなら 「'"'」=> 「"ほげ"」「"ふが"」
  // ※ 片側しか必要ないならいずれかを 「'"'」=> 「""」


/* ■複数行フラグ */
var multi = true;
  // ・multi = false; では、選択範囲「全体」の前後に文字列 pre / sur を追加
  // ・multi = true; では、選択範囲の「各行」ごとに文字列 pre / sur で囲う


/* ■挿入フラグ */
var ins = false;
  // ・ins = false; では、選択範囲がないときはマクロを中止する
  //   また、■複数行フラグが有効 ( multi = true ) のときに、空行には挿入しない
  //   選択範囲の末尾に空行があった場合、マクロ実行後のカーソルの復帰位置が■終了後フラグの説明どおりにならないことがある
  // ・ins = true; では、選択範囲がないときにはカーソル位置に pre / sur を挿入する
  //   また、■複数行フラグが有効 ( multi = true ) のときに、空行にも挿入する
  // ※■複数行フラグが有効 ( multi = true ) のときは、空白文字だけの行は空行と見做す

/* ■終了後フラグ */
var endPos = 5;		// 指定できる値は 0 ~ 5 ( 6 以上の値は 0 と同じ)
  // 0. カーソルは "引用符" の後ろへ  (※範囲選択なし)
  // 1. カーソルは最後の "引用符" の中へ移動する  (※範囲選択なし)
  // 2. マクロ実行前に範囲選択がなければカーソルは最後の "引用符" の中へ、
  //    あれば "引用符" の後ろへ移動する  (※範囲選択なし)
  // 3. マクロ実行前に範囲選択がなければカーソルは最後の "引用符" の中へ移動  (※範囲選択なし)、
  //    あれば "引用符" を含めた全体を選択範囲にする  (※カーソルは選択範囲の後ろへ) 
  // 4. "引用符" を含めた全体を選択範囲にする  (※カーソルは選択範囲の後ろへ) 
  // 5. "引用符" を含めた全体を選択範囲にする  (※カーソル位置はマクロ実行前の側(先頭 or 末尾)へ)
  // 
  //   ※ "引用符" を含めた選択範囲を残すようにすると、連続実行で 追加 <=> 削除 のトグルができる( 3 ~ 5 )
  //   ※ 複数フラグが有効 ( multi = true ) のとき、"引用符" の中へ移動する「0 と 1」は適さないとおもわれる
  //   ※ 「範囲選択なし」になる終了後フラグで "引用符" を削除したとき、カーソルの復帰位置は上の説明どおりにはならないことがある

// -------------------------------------------------------------------

Redraw = false;

// 選択範囲
var s = document.selection;
var anc = s.GetAnchorPos();		// 選択範囲の開始位置 (キャレットのない側)
var act = s.GetActivePos();		// 選択範囲の終了位置 (キャレットのある側)
var tp = ( anc < act ) ? anc : act;	// 選択範囲の先頭位置
var bp = ( anc < act ) ? act : anc;	// 選択範囲の末尾位置

// 選択範囲の先頭&末尾の各座標
var ty = s.GetTopPointY( mePosLogical );
var bx = s.GetBottomPointX( mePosLogical );
var by = s.GetBottomPointY( mePosLogical );

// 選択範囲の末尾が行頭 x = 1 にあるときの調整(末尾の改行を含めない)
if ( ty < by && bx == 1 ) {
  s.SetActivePos( tp );
  s.SetAnchorPos( bp - 1 );
}

// 選択範囲の文字列を取得
var st = s.Text;

// AddDelBrackets() で "引用符" を追加/削除
var t = AddDelBrackets( st, pre, sur );

// AddDelBrackets() 処理の前後で文字列に変化がないなら undo 履歴を残さない
if ( t == st ) {
  s.SetActivePos( act );
  s.SetAnchorPos( anc );
  Quit();
}

// "引用符" を追加/削除
s.Text = t;

// case 0. この時点でカーソルは "引用符" のうしろ ※範囲選択なし(末尾調整されたままの位置)
var dp = s.GetActivePos();


// ■終了後フラグの指定動作  ※カーソルを移動/選択範囲を復旧
switch ( endPos ) {

  case 1:	// カーソルは最後の "引用符" の中へ移動する  ※範囲選択なし
    SearchLastBracket();
    break;

  case 2:	// マクロ実行前に範囲選択がなければカーソルは最後の "引用符" の中へ
		// あれば選択範囲の後ろへ移動する  ※範囲選択なし
    if ( ! st )			// マクロ実行前に選択範囲がなかったとき
      SearchLastBracket();
    else			// マクロ実行前に選択範囲があったときは選択範囲の後ろへ
      MoveToEndPos();
    break;

  case 3:	// マクロ実行前に範囲選択がなければカーソルは最後の "引用符" の中へ移動  ※範囲選択なし
		// あれば "引用符" を含めた全体を選択範囲にする  ※カーソルは選択範囲の後ろへ
    if ( ! st )			// マクロ実行前に選択範囲がなかったとき
      SearchLastBracket();
    else {			// マクロ実行前に選択範囲があったとき
      MoveToEndPos();
      s.SetAnchorPos( tp );	// 先頭まで範囲選択
    }
    break;

  case 4:	// "引用符" を含めた全体を選択範囲にする  ※カーソルは選択範囲の後ろへ
    MoveToEndPos();
    s.SetAnchorPos( tp );
    break;

  case 5:	// "引用符" を含めた全体を選択範囲にする  ※カーソル位置はマクロ実行前の側(先頭 or 末尾)へ
    if ( anc <= act ) {		// マクロ実行前のキャレットの位置が選択範囲の末尾だったとき
      MoveToEndPos();
      s.SetAnchorPos( tp );
    }
    else {			// マクロ実行前のキャレットの位置が選択範囲の先頭だったとき
      MoveToEndPos();
      s.SetActivePos( tp, true );
    }
    break;

  default:
    break;
}

// -------------------------------------------------------------------

// 関数 AddDelBrackets()		カッコを 追加/削除
function AddDelBrackets( arg1, arg2, arg3 ) {	// ← AddDelBrackets( t, pre, sur )

  // ■複数行フラグ ( multi ) 判定
  // 有効なら ( true ) 選択範囲 st を行で区切って配列 a に格納する
  var a = ( multi ) ? arg1.split( "\n" ) : [];
  // 無効なら ( false )  選択範囲の文字列全体 st をそのまま配列 a に格納する
  if ( ! multi )
    a.push( arg1 );

  for ( var i = 0; i < a.length; i ++ ) {	// 「1行め」から繰りかえし処理

    // 選択範囲がカッコで囲われているとき (先頭と末尾の文字列をカッコと比較して一致したとき)
    if ( a[i].substr( 0, arg2.length ) == arg2 && a[i].substr( a[i].length - arg3.length, arg3.length ) == arg3 )
      // 各行のカッコを削除
      a[i] = a[i].slice( arg2.length, a[i].length - arg3.length );

    // 選択範囲がカッコで囲われていないとき
    // ■挿入フラグが有効 ( ins = true ) なら、または a[i] が空白文字列でないなら、前後にカッコをつける
    else if ( ins || ! a[i].match( /^[\s ]*$/g ) )
      a[i] = arg2 + a[i] + arg3;
    else
      // ■挿入フラグが無効 ( ins = false ) のときの空白文字列は、スルー(空白のまま)
      continue;
  }
  // 各行を "\n" で区切って連結しなおす
  return a.join( "\n" );
}


// 関数 SearchLastBracket()	カーソルを最後の閉じカッコの前へ移動  ※範囲選択なし
function SearchLastBracket() {
  if ( t.length < st.length )	// カッコを削除したときは。先頭へ
    s.SetActivePos( tp );
  else {			// カッコを追加したときは、選択範囲内の最後の閉じカッコの前へ
    if ( sur.length ) {	
      s.SetAnchorPos( tp );
      s.SetActivePos( tp + s.Text.lastIndexOf( s.Text.match( sur.replace( /[$()*+.?\[\\\]^{|}]/g , "\\$&" ) ) ) );
    }
    else			// 閉じカッコ sur が未指定 "")の場合は、先頭へ
      s.SetActivePos( tp );
  }
}

// 関数 MoveToEndPos()		マクロ実行前に選択範囲があったとき、カーソルを元の選択範囲の末尾位置へ移動  ※範囲選択なし
function MoveToEndPos() {
  if ( ty < by && bx == 1 )			// 選択範囲の末尾調整をしていたときは
    s.SetActivePoint( mePosLogical, bx, by );	// カーソルは元の末尾位置に復帰
  else						// 末尾調整をしていなかったときは
    s.SetActivePos( dp );			// カーソル位置はそのまま
}


カッコで囲う(ポップアップメニューあり)のソースコード

組み込み用コードをすべて追加済みの状態にしました。

#title = "カッコ..."
#tooltip = "カッコで囲う"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",255

// ポップアップメニューからカッコの種類を選択して、選択範囲をカッコで囲う。
// 公式wikiのマクロライブラリより「引用の追加」と「括弧で挟む」のコードを参考にした
// (2018/08/24 - 2018/10/29)

/*
 * ・複数行の選択範囲で末尾が改行 \n のとき、さいごの改行は除外する。
 * ・非選択時には、それぞれことなる動作をする。
 * 
 * ※ ポップアップメニューの項目は、m.Add( … ); の不要な行を行をコメントアウトすれば隠せる。
 * (配列から削除する場合は中身だけ消して "" として空要素を残しておかないと、メニューや処理コードの ID と一致しなくなる)
 */

// ■「任意の文字列2」と、wiki 文字装飾タグで、複数行の選択範囲内の空白行をスキップするか?
var skip = true;
  // (skip = true; スキップする / skip = false; スキップしない)

// 開きカッコ p1 を配列で定義
var p1 = new Array( "" ,	// 以下 r = 1~10、11~20、21~ の ID 順
  "(" ,  "<" ,  "[" ,  "{" ,  "(" ,  "「" ,  "『" ,  "【" ,  " (" ,  " (" ,
  " \"" ,  " " ,  " - " ,  "――" ,  "~" ,  "'''" ,  "''" ,  "<u>" ,  "[[" , "<nowiki>" ,
  "" );
// 閉じカッコ p2 を配列で定義
var p2 = new Array( "" ,	// 以下 1~10、11~20、21~ の ID 順
  ")" ,  ">" ,  "]" ,  "}" ,  ")" ,  "」" ,  "』" ,  "】" ,  ") " ,  ") " ,
  "\" " ,  " " ,  " - " ,  "――" ,  "~" ,  "'''" ,  "''" ,  "</u>" ,  "]]" , "</nowiki>" ,
  "" );

// ポップアップメニュー項目の定義
var m = CreatePopupMenu();
  // m.Add( "ラベル", r ); の各行は、任意に上下移動(並べ替え)してよいが、
  // r の数値は上の配列の並び順やテキスト変換処理の case r: に対応しているので変更しないこと!

m.Add( "任意の文字列 (&E)", 50 );	// ダイアログのテキストボックス
m.Add( "任意の文字列 2 (&E)", 51 );	// 各行ごとに指定文字列で囲う(skip フラグを指定すること)

m.Add( "", 0, meMenuSeparator );
m.Add( " ( 半角 小カッコ )  (&P)", 1 );
m.Add( "< 半角 山カッコ > (&A)", 2 );
m.Add( " [ 半角 大カッコ ]  (&B)", 3 );
m.Add( " { 半角 中カッコ }  (&C)", 4 );
m.Add( "", 0, meMenuSeparator );
m.Add( "( 全角 小カッコ ) (&R)", 5 );
m.Add( "", 0, meMenuSeparator );
m.Add( "「 全角 かぎカッコ 」 (&K)", 6 );
m.Add( "『 全角 二重かぎカッコ 』 (&W)", 7 );
m.Add( "【 全角 スミ付きカッコ 】 (&L)", 8 );
m.Add( "", 0, meMenuSeparator );
m.Add( "␣( 全角 小カッコ )␣ (&Z)", 9 );
m.Add( "␣ ( 半角 小カッコ ) ␣ (&H)", 10 );
m.Add( '␣ "  半角 引用符  " ␣ (&Q)', 11 );
m.Add( "␣ 半角 スペース ␣ (&S)", 12 );

m.Add( "", 0, meMenuSeparator );
m.Add( "  -  半角 ハイフン  -   (&-)", 13 );
m.Add( "―― 全角 ダッシュ ―― (&D)", 14 );
m.Add( "~ 全角 チルダ ~ (&T)", 15 );

m.Add( "", 0, meMenuSeparator );
m.Add( "1文字ずつ前後を削除 (&1)", 31 );
m.Add( "2文字ずつ前後を削除 (&2)", 32 );
m.Add( "3文字ずつ前後を削除 (&3)", 33 );

m.Add( "", 0, meMenuSeparator );
m.Add( "/*  *  JS コメントアウト 2  */ (&J)", 34 );
m.Add( "/*  JS コメントアウト 1  */ (&V)", 36 );
m.Add( "JS アンコメント (&U)", 35 );
m.Add( "", 0, meMenuSeparator );
m.Add( "<!--  XML コメントアウト  --> (&X)", 38 );
m.Add( "XML アンコメント (&M)", 39 );

/* このブロックの項目は、複数行を選択しているとき「選択範囲の各行ごとに囲う」処理をおこなう
  (skip フラグを指定すること) */ 
/* とりあえずコメントアウトしておく */ 
// m.Add( "", 0, meMenuSeparator );
// m.Add( "'''  wiki 太字  ''' (&O)", 16 );
// m.Add( "''   wiki 斜体   '' (&I)", 17 );
// m.Add( "<u> wiki 下線 </u> (&\\)", 18 );
// m.Add( "[[  wiki リンク  ]] (&@)", 19 );
// m.Add( "<nowiki> </nowiki> (&N)", 20 );

// m.Add( "", 0, meMenuSeparator );
// m.Add( "キャンセル", 0 );	// Escキーでキャンセルできるのでアクセラレータなし

// ポップアップメニューを表示
  var r = m.Track( mePosMouse = 1 );	// 選択されたメニュー項目のIDを r に
  // m.Track(0); ならキャレット位置、Track(1); ならカーソル位置にサブメニューがポップアップ

if ( r > 0 ) {
  Redraw = false;
  var s = document.selection

  // マクロ実行前の選択範囲の各座標を取得
  var ax = s.GetTopPointX( mePosLogical );
  var ay = s.GetTopPointY( mePosLogical );
  var bx = s.GetBottomPointX( mePosLogical );
  var by = s.GetBottomPointY( mePosLogical );
  var anc = s.GetAnchorPos();	// 選択範囲の開始位置 (キャレットのない側)
  var act = s.GetActivePos();	// 選択範囲の終了位置 (キャレットのある側)
  var tp = ( anc < act ) ? anc : act;	// 選択範囲の先頭位置  ( ax, ay )
  var bp = ( anc < act ) ? act : anc;	// 選択範囲の末尾位置

  if ( !s.Text.length )		// 選択範囲がなければ
    var pos = s.GetActivePos();		// カーソル位置を取得

  // 選択範囲の末尾位置を調整(最後の \n を含めない)
  if ( ! s.IsEmpty && bx == 1 && r != 4 ) {	//※ { 中カッコ } のばあいは末尾の調整をしない
    s.SetActivePos( bp - 1 );
    s.EndOfLine( false, mePosLogical );	
    s.SetAnchorPos( tp );
  }

  // 選択範囲の文字列を取得
  var st = s.Text;

  // IDごとのテキスト変換処理
  switch (r) {

    // カッコ
    case 1:  case 2:  case 3:  case 4:  case 5:  case 6:
    case 7:  case 8:  case 9:  case 10:  case 11:  case 12:
      if ( pos ) {
        document.Write( p1[r] + p2[r] );
        s.SetActivePos( pos + p1[r].length );
      }
      else {
        s.Text = p1[r] + st + p2[r];
        s.SetAnchorPos( tp );
      }
      break;


    // ハイフン、ダッシュ、チルダ
    case 13:  case 14:  case 15:
      if ( pos ) {
        document.Write( p1[r] );
      }
      else {
        s.Text = p1[r] + st + p2[r];
        s.SetAnchorPos( tp );
      }
      break;


    // n文字ずつ前後を削除
    case 31:  case 32:  case 33:
      if ( ! s.IsEmpty ) {
        var n;
        if ( r == 31 )  n = 1;
        else if ( r == 32 )  n = 2;
        else n = 3;	// ( r == 33 )
        s.Text = st.slice( n, st.length - n );
        s.SetAnchorPos( tp );
      }
      break;


    // wiki 文字装飾タグ	※ 太字/斜体/下線/<nowiki>
    case 16:  case 17:  case 18:  case 20:
      // 選択範囲内の「各行を囲う」処理をおこなう。
      // 選択範囲なしで実行するとタグの間がわかりづらくなるので全角スペースを挿入する。
      if ( pos ) {
        document.Write( p1[r] + " " + p2[r] );
        s.SetAnchorPos( pos + p1[r].length );
        s.SetActivePos( s.GetAnchorPos() + 1, true );
      }
      else {
        var ad = AddBrackets( st, p1[r], p2[r] );
        if ( ad != st ) {
          s.Text = ad;
          s.SetAnchorPos( tp );
        }
        else {
          s.SetActivePos( act );
          s.SetAnchorPos( anc );
        }
      }
      break;


    // wiki 文字装飾	※ 内部リンク用タグ	[[リンク|ラベル]]
    case 19:
      // 選択範囲内の「各行を囲う」処理をおこなう。
      if ( pos ) {
        document.Write( p1[r] + " | " + p2[r] );
        s.SetActivePos( pos + p1[r].length );
        s.SetAnchorPos( s.GetActivePos() + " | ".length );
      }
      else {
        var ad = AddWikiLink( st, p1[r], p2[r] );
        if ( ad != st ) {
          s.Text = ad;
          s.SetActivePos( tp + p1[r].length );
        }
        else {
          s.SetActivePos( act );
          s.SetAnchorPos( anc );
        }
      }
      break;


    // /* * JavaScriptコメントアウト 2 */
    case 34:
      // 選択範囲の先頭/末尾が行の途中にある状態でコメントアウトする場合は、改行を追加する。
      var p1 = ( ax > 1 ) ? "\n/*\n" : "/*\n";		// */
      var p2 = ( document.Text.charAt( bp ) != "\n" ) ? "\n */\n" : "\n */";
      var ast = " * ";
      if ( ax > 1 )	// 選択範囲の先頭座標が x = 1 でなければ改行させるので
        tp ++;		// 選択範囲の復元用座標を調整
      if ( pos ){
        document.Write( p1 + ast + p2 );
        s.SetActivePos( s.GetActivePos() - p2.length );
      }
      else {
        s.Text = CommentOutJS( st, p1, p2, ast );
        s.SetAnchorPos( tp );
      }
      break;


    /* JavaScript コメントアウト 1 */
    // <!-- XML コメントアウト --> 
    case 36:  case 38:
      var p1, p2;
      if ( r == 36 ) {		// /* JavaScript コメントアウト 1 */
        p1 = " /* "; p2 = " */ ";
      }
      else {	// ( r == 38 )	// <!-- XML コメントアウト --> 
        p1 = " <!-- "; p2 = " --> ";
      }
      if ( pos ){
        document.Write( p1 + p2 );
        s.SetActivePos( pos + p1.length );
      }
      else {
        s.Text = p1 + st + p2;
        s.SetAnchorPos( tp );
      }
      break;


//  case 35:		※ JS アンコメント
      // case 34 と case 36: の /* JavaScriptコメント */ をアンコメントする。

//  case 39:		※ XMLアンコメント
      // case 38 の <!-- XMLコメント --> をアンコメントする。

    case 35:  case 39:
      // 選択範囲の先頭と末尾のコメントマークを削除
      var dc
      if ( r == 35 )		// JS アンコメント
        dc = UnCommentJS( st );
      else	// ( r == 39 )	// XMLアンコメント
        dc = st.replace( /^ ?<!-- ?| ?-- *>\ ?$/g , "" );
      // 選択範囲にコメントマークがなかった場合 undo 履歴を残さない
      if ( dc == st ) {	
        s.SetActivePos( act );
        s.SetAnchorPos( anc );
        break;
      }
      s.Text = dc;
      s.SetAnchorPos( tp );
      break;


    // 任意の文字列を追加	※テキストボックス
    case 50:  case 51:
      // 文字コードには非対応
      // ダイアログのテキスト入力フィールドから文字列を取得
      var p1 = Prompt(
        "前につける文字列:\t改行=\\\\\\n ; タブ=\\\\\\t  (注:¥記号3つ)", ""
      ).replace( /\\\\\\n/g , "\n" ).replace( /\\\\\\t/g , "\t" );
      var p2 = Prompt(
        "後ろにつける文字列:\t改行=\\\\\\n ; タブ=\\\\\\t  (注:¥記号3つ)", ""
      ).replace( /\\\\\\n/g , "\n" ).replace( /\\\\\\t/g , "\t" );
      if ( p1 || p2 ) {
        if ( pos ) {
          document.Write( p1 + p2 );
          s.SetActivePos( pos + p1.length );
        }
        else {
          if ( r == 50 )	//  「任意の文字列1」なら
            s.Text = p1 + st + p2;
          else {	// ( r == 51 )	//  「任意の文字列2」なら
            var ab = AddBrackets( st, p1, p2 );
            if ( ab != st )
              s.Text = ab;
            else
              s.SetActivePos( bp );
          }
          s.SetAnchorPos( tp );
        }
      }
      break;

    default:
      break;
  }
}
Redraw = true;


// -------------------------------------------------------------------

/* 関数 AddBrackets() */
function AddBrackets( arg1, arg2, arg3 ) {
  var a = arg1.split( "\n" );
  for ( var i = 0; i < a.length; i ++ ) {
    if ( skip && a[i].match( /^\s*$/g ) )	// skip = true のときは空白行をスキップ
      continue;
    a[i] = arg2 + a[i] + arg3;	// 各行をカッコ p1 & p2 で囲う
  }
  return a.join( "\n" );
}

/* 関数 AddWikiLink() */
function AddWikiLink( arg1, arg2, arg3 ) {
  var a = arg1.split( "\n" );
  for ( var i = 0; i < a.length; i ++ ) {
    if ( skip && a[i].match( /^\s*$/g ) )	// skip = true のときは空白行をスキップ
      continue;
    a[i] =  arg2 + a[i] + "|" + a[i] + arg3;	// 各行を [[str|str]] に変換
  }
  return a.join( "\n" );


/* 
 * 関数 CommentOutJS()
 * このかたちにコメントアウトする
 */
function CommentOutJS( arg1, arg2, arg3, arg4 ) {
  var a = arg1.split( "\n" );
  for ( var i = 0; i < a.length; i ++ )	
    a[i] = arg4 + a[i];		// 各行の先頭に " * " を追加
  // 各行を "\n" で区切って連結し、先頭に "/*\n"、末尾に "\n */" を追加
  return arg2 + a.join( "\n" ) + arg3;
}

/* 
 * 関数 UnCommentJS() 
 * 基本的にこのかたちのコメントブロックしか想定していない。
 * また、複数のコメントブロックがある場合を想定していない。
 * 中間行の行頭記号はアスタリスク「*」と中黒「・」「・」を削除対象とする。
 */ 
function UnCommentJS( arg1 ) {
  var re1 = "^ ?\\/\\*+ ?\\n?";	// 先頭行のコメントマークの正規表現
  var re2 = "\\n? ?\\*+\\/ ?$";	// 末行のコメントマークの正規表現
  var reg = new RegExp( re1 + "|" + re2 , "g" );	// 正規表現 / … /g に変換
  var re3 = /^ ?(\*+|[・・]) ?/;		// 中間行の行頭記号の正規表現
  var a = arg1.split( "\n" );	// 選択範囲 st を "\n" で区切って配列 a に
  // 中間行の行頭記号を削除する
  for ( var i = 0; i < a.length; i ++ ) {
    if ( a[i].match( reg ) )	// 先頭行と末行のコメントマークがある行はスキップ
      continue;
    a[i] = a[i].replace( re3 , "" );	// 中間行の行頭記号を削除
  }
  // 各行を "\n" で区切って連結し、先頭行と末行のコメントマークを削除
  return a.join( "\n" ).replace( reg , "" );
}


人柱用 追加コード

「カッコで囲う (ポップアップメニューあり)」のポップアップメニューの項目に

  • 「行頭/行末から任意の 文字数 を削除」
  • 「行頭/行末から任意の 文字列 を削除」

のふたつを追加します。

  • 「任意の文字列2」や「wiki 用文字修飾タグ」と同様に、選択範囲内の論理行の各行頭と行末にたいして作用します(選択範囲を論理行単位で拡張しないので、先頭行と末行においては行頭/行末ではなく「選択範囲の先頭/末尾」にたいして作用します)。
  • 「任意の文字数を削除」ではアラビア数字以外で入力された文字列をすべて排除します。例えば「1a2あ」と入力された場合は、「12」として扱います。
  • 「任意の文字列を削除」は簡易的な処理コードなので、正規表現を使用できません。
    また、タブ文字の扱いは「任意の文字列2(追加)」の場合とおなじく「\\\t」で入力されたもの (注:¥記号3つ) をタブ文字(\t)として処理します。



作ってみたものの使う機会にとぼしく、動作検証が不十分なままなので人柱版としてコードだけ置いておきます。


任意の文字数/文字列を削除

m.Add( ... ); のグループ内に追加(位置は任意)▼

/* 以下の2項目は動作検証不十分 */ 
// m.Add( "", 0, meMenuSeparator );
m.Add( "行頭/行末から任意の 文字数 を削除 (&Y)", 52 );
m.Add( "行頭/行末から任意の 文字列 を削除 (&Z)", 53 );


▼␣␣␣␣default: ␣␣␣␣␣␣break; の上に追加▼

    // 各行の前後から任意の文字数/文字列を削除	※テキストボックス
    case 52:  case 53:
      if ( ! pos ) {	// 選択範囲があれば

        // 「任意の文字数を削除」
        if ( r == 52 ) {
          // ダイアログのテキスト入力フィールドから文字列を取得
          // 半角に変換して数字以外の文字は削除
          var p1 = ToHalfWidth(
            Prompt( "行頭から削除する文字数 (数字のみ有効):", "" )
          ).replace( /[^0-9]/g , "" );
          var p2 = ToHalfWidth(
            Prompt( "行末から削除する文字数 (数字のみ有効):", "" )
          ).replace( /[^0-9]/g , "" );
          // 各行の先頭/末尾から指定文字数を削除
          var dt = DeleteCharByNum( st, p1, p2 );
        }

        // 「任意の文字列を削除」
        else {	// ( r == 53 )
        // ダイアログのテキスト入力フィールドから文字列を取得
        var p1 = Prompt(
          "行頭から削除する文字列:\tタブ=\\\\\\t  (注:¥記号3つ)", ""
        ).replace( /\\\\\\t/g , "\t" );
        var p2 = Prompt(
          "行末から削除する文字列:\tタブ=\\\\\\t  (注:¥記号3つ)", ""
        ).replace( /\\\\\\t/g , "\t" );
        var reg1 = new RegExp( "^" + Quote( p1 ) , "gm" );
        var reg2 = new RegExp( Quote( p2 ) + "$" , "gm" );
        // 各行の先頭/末尾の指定文字列を削除
        dt = st.replace( reg1 , "" ).replace( reg2 , "" );
        }

        // 選択範囲に指定文字列がなかった場合 undo 履歴を残さない
        if ( dt != st ) {
          s.Text = dt;			// 削除完了
          s.SetAnchorPos( tp );	// 選択範囲を復元
        }
      }
      break;


▼ソースコード末尾(末行のした)に追加▼

/* 関数 DeleteCharByNum( st, p1, p2 ) */
  // 各行の先頭/末尾からの指定文字数を削除
function DeleteCharByNum( str, p1, p2 ) {
  var a = str.split( "\n" );
  for ( var i = 0; i < a.length; i ++ )
    a[i] = a[i].slice( p1, a[i].length - p2 );
  return a.join( "\n" );
}


/* 関数 quote( str ) */
// 『JavaScript/正規表現 - Wikibooks』より
// ref. https://ja.wikibooks.org/wiki/JavaScript/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE
// PerlのquotemetaやRubyのRegExp.quoteのように、()や[]など正規表現のメタ文字と解釈される可能性のある文字をエスケープして返す関数は、Stringオブジェクトのreplaceメソッドを使用して簡単に作成することができます。

function Quote( str ) {
    return str.replace( /\W/g, function( $0 ) {
        return '\\' + $0;
    } );
}


/**
 * 全角から半角への変革関数 toHalfWidth( strVal )
 * 入力値の英数記号を半角変換して返却
 * [引数]   strVal: 入力値
 * [返却値] String(): 半角変換された文字列
 */
// ref. https://webllica.com/add-comma-as-thousands-separator/ より

function ToHalfWidth( strVal ){
  // 半角変換
  var halfVal = strVal.replace( /[!-~]/g,
    function( tmpStr ) {
      // 文字コードをシフト
      return String.fromCharCode( tmpStr.charCodeAt(0) - 0xFEE0 );
    }
  );
  return halfVal;
}


メモ

  • 2018/08/24 (sukemaru)
ページを新規作成
  • 2018/08/26 (sukemaru)
「カッコで囲う (ポップアップメニューなし)」の節を追加
  • 2018/08/27 (sukemaru)
・「カッコで囲う (ポップアップメニューあり)」のソースコードを修正
・case1~8 の "s.CharLeft( false, p2[r].length );" を "s.SetActivePos( s.GetActivePos() - p2[r].length );" に変更
  • 2018/10/12 (sukemaru)
「カッコで囲う (ポップアップメニューあり)」のソースコードに "3文字ずつ前後を削除" を追加
組みこみ用コード「wiki用 文字列装飾」と「挿入型コメントアウト」の節を追加
「カッコで囲う.zip」のダウンロードリンクを追加
  • 2018/10/13 - 2018/10/16 (sukemaru)
・マクロのコードを微修正
・「カッコで囲う.zip」を差し替え
  • 2018/10/19 (sukemaru)
・「引用符を追加/削除」の節を追加
・「カッコで囲う.zip」を差し替え
  • 2018/10/26 (sukemaru)
・コードの体裁を修正 (※変数名を変更したので、追加コードは最新の「カッコで囲う」でないとエラーになる)
・各マクロの動作コードを変更し、実行後の文字列に変化なしになる場合に undo 履歴を残さないようにした
・追加コード「任意の文字列」の項目を追加
・追加コードの「JS コメントアウト1」と「XML コメントアウト」のコードをまとめた
・追加コードの「JS アンコメント」で先頭/末尾のコメントマーク /* */ がある行では中間行の行頭記号を削除しないようにした
・「引用符を追加/削除」の終了後の動作コードを変更し、不自然な位置にキャレットが移動する不具合を修正した
・「カッコで囲う.zip」を差し替え
  • 2018/10/29 (sukemaru)
・「カッコで囲う (ポップアップメニューあり)」の節を更新(本体のソースコードに追加コードを包摂)
・「カッコで囲う (ポップアップメニューあり)」のメニュー項目に「任意の文字列2」を追加
・「カッコで囲う (ポップアップメニューあり)」のソースコードをまとめてページ下部に移動
・「カッコで囲う.zip」を差し替え
  • 2018/11/19 (sukemaru)
・「カッコで囲う (ポップアップメニューあり)」用の人柱版追加コード「行頭/行末から任意の 文字数 を削除」「行頭/行末から任意の 文字列 を削除」を追加
スポンサーリンク