カッコをはずす
選択範囲の "最初の1文字" と "最後の1文字" が「対になるカッコ」のとき、カッコ囲いをはずします。
それにくわえて
- 「カッコをはずす」マクロでは、選択範囲の外側 (前と後) の各1文字が「対になるカッコ」のときにも、カッコ囲いをはずします。
- 「カッコを追加/削除」マクロは、「さいごに削除したカッコ」と同種のカッコで選択範囲を囲います。
任意のタイミングで「さいごに削除したカッコ」を記憶・更新することができるので、ソースコードや散文の校正のさいに使うと便利です。
削除できるカッコの種類は、ソースコード内で定義したもののみとなります。
- カッコの種類(開き/閉じ それぞれ「1文字」ずつ)
- 各種のカッコ(半角/全角/縦書き)のペア
- ( ) 「 」 < > [ ] { } ⦅ ⦆
( ) 「 」 『 』 < > [ ] { } 【 】 〖 〗 ⦅ ⦆ 〚 〛 〔 〕 〘 〙 〈 〉 《 》
﹁﹂ ﹃﹄ ︵︶ ︿﹀ ︽︾ ︹︺ ︷︸ ︻︼ ︗︘
- 各種の引用符(半角/全角)のペア
- " " ' ' ” ” ’ ’ 〝 〞 〝 〟 ‘ ’ “ ”
- ーダーシー、〜波ダーシ〜、~全角チルダ~
- ␣半角空白␣、全角空白 のペア
- 各種記号のペア
- + + - - * * / / # # = = % % : : : : @ @ @ @ ※ ※
● ● ■ ■ ◆ ◆ ▼ ▼ ▲ ▲ ☆ ☆ ★ ★ † †
← → → ← ↑ ↓ ↓ ↑ ← ← → → ↑ ↑ ↓ ↓
- など...
- 設定項目内の定義要配列
var brackets2 = [ ... ];
をカスタマイズすると、HTML タグなど「複数文字ずつのペア」も登録することができます。
- ※
"===", "==="
と"==", "=="
のように同一文字列をふくむペア(半角空白 あり/なし の差分なども)を登録する場合は、文字列の長さが大きいものが先になるようにしてください。
c.f. 「カッコで囲う」マクロ: ポップアップメニューから任意のカッコを追加する
「引用符を追加/削除」マクロ: 特定のカッコまたは引用符の追加/削除トグル
- ダウンロード >> 「ファイル:カッコを削除/追加.zip」(アイコン入り)
- 最終更新:2020/06/28
- マルチカーソル/複数選択範囲に対応
- 「カッコを削除/追加」マクロを削除
- ダウンロード >> 「ファイル:カッコを削除/追加.zip」(アイコン入り)
カッコをはずす[編集]
選択範囲の "最初の1文字" と "最後の1文字" が「対になるカッコ」のとき、または選択範囲の外側 (前と後) の各1文字が「対になるカッコ」のときに、カッコ囲いをはずします。
- 1回の実行につき1組のカッコ囲いをはずします(※内側の両端が優先。半角空白のペアも除去対象)。
- 例. 以下の行で [ "hoge" ] を範囲選択して連続で実行した場合、次のように作用します。
( [ "hoge" ] ) // 元の文字列(下線部が選択範囲) ( "hoge" ) // 1回目 実行後: [ と ] を削除しました。 ( "hoge" ) // 2回目 実行後: ␣ と ␣ を削除しました。 ( hoge ) // 3回目 実行後: " と " を削除しました。 (hoge) // 4回目 実行後: ␣ と ␣ を削除しました。 ※選択範囲の外側 hoge // 5回目 実行後: ( と ) を削除しました。 ※選択範囲の外側
- ( [ "hoge" ] ) 全体を範囲選択して連続で実行した場合は選択範囲内の外側から、
( [ "hoge" ] ) の hoge だけを範囲選択して連続で実行した場合は選択範囲外の内側から
順にカッコ囲いを解除します。
- ( [ "hoge" ] ) 全体を範囲選択して連続で実行した場合は選択範囲内の外側から、
ソースコード[編集]
※ Mery ver 3.0.1 以降では「マルチカーソル/複数選択範囲」にも対応します。
#title="カッコをはずす"
#tooltip="対になるカッコを除去する"
// #icon="brackets(delete)[1].ico"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",286
/**
* ------------------------------------------------------------
* カッコをはずす
* sukemaru, 2019/03/14 - 2020/06/28
* ------------------------------------------------------------
* 選択範囲の最初の1文字と最後の1文字が「対になるカッコ」のとき、
* または選択範囲の外側 (前と後) の各1文字が「対になるカッコ」のときに、
* カッコ囲いをはずします。
*/
// ---------- ▼ 設定項目 ▼ ---------- //
// ■ 選択範囲の『外側』(前と後ろ) の各1文字がカッコのときも除去する? ■
// (※ 選択範囲の前後を1文字ずつ拡張してカッコを除去する)
var outerEnable = true; // true:する / false:しない
// ▼「対になるカッコ」の種類 (始)と(終) のペアを列挙する ▼
// ※ brackets に列挙する開き/閉じカッコのペアはそれぞれ「1文字」ずつでないとダメ
var brackets = "()「」<>[]{}\"\"''()「」『』<>[]{}【】〖〗﹁﹂﹃﹄︵︶︿﹀︽︾︹︺︷︸︻︼︗︘⦅⦆⦅⦆〚〛〔〕〘〙〈〉《》””’’〝〞〝〟‘’“”――~~〜〜 ";
brackets += "++--**\/\/##==%%::::@@@@※※○○●●□□■■◇◇◆◆▽▽▼▼△△▲▲☆☆★★††||←→→←↑↓↓↑←←→→↑↑↓↓……¿?¡!‚‘‚’„“„”“„‘‚‹››‹«»»«——‐‐--␣␣__≪≫";
// ▼ HTML タグなど複数文字の要素での (始)と(終) のペアを列挙 ▼
var brackets2 = [
"<i>" , "</i>" , "<u>" , "</u>" , "<s>" , "</s>" ,
"<b>" , "</b>" , "<q>" , "</q>" ,
"</" , ">" , "<" , "/>" ,
"<li>" , "</li>" , "<h>" , "</h>" ,
"<span>" , "</span>" , "<div>" , "</div>" ,
"<pre>" , "</pre>" , "<code>" , "</code>" ,
"===== " , " =====" , "=====" , "=====" , "==== " , " ====", "====" , "====",
"=== " , " ===" , "===" , "===" , "== " , " ==" , "==" , "==" , "= " , " =",
"'''''" , "'''''" , "'''" , "'''" , "''" , "''",
"――" , "――" ,
"/** \n" , "\n */" , "/** \n" , "\n*/" , "/**\n" , "\n */" , "/**\n" , "\n*/" ,
"/* \n" , "\n */" , "/* \n" , "\n*/" , "/*\n" , "\n */" , "/*\n" , "\n*/" ,
"/** " , " */" , "/* " , " */" , "/*" , "*/" ,
"( ", " )" , " (", ") " , ' "' , '" ' ,
"<!-- " , " -->" , "<!--" , "-->"
];
// ---------- ▲ 設定項目 ▲ ---------- //
// brackets2 が先、brackets が後
brackets = brackets2.concat( brackets.split( "" ) );
var d = editor.ActiveDocument;
if ( d.ReadOnly ) {
Status = " ドキュメントは書き換え禁止です。";
}
else {
var s = d.selection;
var sx = ScrollX, sy = ScrollY;
// マルチカーソル/複数選択に対応
var arg = [ outerEnable, brackets ];
// 選択範囲が1つで矩形選択ではないとき
if ( ! s.Mode || s.Mode === 1 ) {
DeleteBrackets_Main( arg );
}
// 矩形選択または複数選択のとき
else {
var dt = d.Text;
BeginUndoGroup();
AddUndo();
MultiFunction( DeleteBrackets_Main, arg );
EndUndoGroup();
if ( d.Text === dt ) { d.Undo(); }
}
ScrollX = sx; ScrollY = sy;
}
/**
* 関数 DeleteBrackets_Main()
* 「カッコをはずす」マクロ
*/
function DeleteBrackets_Main( arg ) {
var outerEnable = arg[0];
var brackets = arg[1];
var d = editor.ActiveDocument;
var s = d.selection;
var st = s.Text;
var act = s.GetActivePos();
var anc = s.GetAnchorPos();
var tp = ( anc < act ) ? anc : act;
var bp = ( anc < act ) ? act : anc;
var $del = false;
var o, c;
// 選択範囲内の最初と最後の各1文字がカッコのとき
for ( var i = 0, len = brackets.length - 1; i < len; i ++ ) {
o = brackets[i]; // 開きカッコ
c = brackets[ i + 1 ] // 閉じカッコ
if ( st.length >= o.length + c.length
&& i % 2 === 0
&& st.slice( 0, o.length ) === o
&& st.slice( - c.length ) === c ) {
// 先頭と末尾の各1文字ずつを削除し、選択範囲を復帰する
s.Text = st.slice( o.length, - c.length );
s.SetAnchorPos( tp );
$del = true;
break;
}
}
// 選択範囲の外側 (前と後) がカッコのとき
if ( outerEnable && ! $del ) {
for ( var i = 0, len = brackets.length - 1; i < len; i ++ ) {
o = brackets[i]; // 開きカッコ
c = brackets[ i + 1 ] // 閉じカッコ
if ( i % 2 === 0
&& d.Text.slice( tp - o.length, tp ) === o
&& d.Text.slice( bp, bp + c.length ) === c ) {
// 選択範囲の先頭/末尾をカッコの文字数ぶんだけ拡張
s.SetAnchorPos( tp - o.length );
s.SetActivePos( bp + c.length, true );
st = s.Text;
// 先頭と末尾のカッコを削除し、選択範囲を復帰する
s.Text = st.slice( o.length, - c.length );
s.SetAnchorPos( tp - o.length );
$del = true;
break;
}
}
}
// 終了ステータス
Status = ( $del )
? " " + ( o == " " ? "␣" : o ) + " と "
+ ( c == " " ? "␣" : c ) + " を削除しました。"
: " カッコがありません。";
}
/**
* 関数 MultiFunction( Fn, arg1 )
* マルチカーソル(複数選択範囲)に対応させる
* 第1引数: Function; 選択範囲ごとに適用する処理の関数
* 第2引数: Function に渡す引数をまとめた配列
*/
function MultiFunction( Fn, arg ) {
var d = editor.ActiveDocument;
var s = d.selection;
// 矩形選択範囲は行に分ける
s.Mode = meModeMulti;
// 選択範囲の座標を取得
var sCount = s.Count;
var Sel = [];
for ( var i = 0; i < sCount; i ++ ) {
Sel[i] = {
act: s.GetActivePos( i ),
anc: s.GetAnchorPos( i )
};
}
// 各選択範囲を処理;
for ( var i = 0, diff = 0, dl; i < sCount; i ++ ) {
dl = d.TextLength;
s.SetActivePos( Sel[i].act + diff );
s.SetAnchorPos( Sel[i].anc + diff );
Fn( arg ); // DeleteBrackets_Main() 関数でカッコを削除
// Fn() の残した選択範囲(またはキャレット位置)を回収
Sel[i].act = s.GetActivePos();
Sel[i].anc = s.GetAnchorPos();
diff += d.TextLength - dl; // 文字数の増減量(累積)
}
// マルチカーソル(複数選択範囲)を復帰
for ( var i = 0; i < sCount; i ++ ) {
s.AddPos( Sel[i].anc, Sel[i].act );
}
}
カッコを追加/削除[編集]
マクロライブラリで公開・配布されている pizz 氏作成の「GetKeyState」を利用して、「カッコをはずす」マクロに「カッコを追加」の機能を加えたマクロです。
- マクロ実行時に Ctrl キー が押されているときは、選択範囲を「さいごに削除したカッコ」で囲います。
- マクロ実行時に Ctrl キーが押されていないとき、選択範囲の最初の1文字と最後の1文字が「対になるカッコ」の場合か、または選択範囲の外側 (前と後) の各1文字が「対になるカッコ」の場合には、カッコ囲いをはずします(→ 詳細は「カッコをはずす」マクロの項を参照)。
※ 設定項目 var ctrlToDel = true;
にすると、Ctrl キーが押されているときは「カッコを削除」、押されていないときは「カッコを追加」になります。
- 外部実行ファイル GetKeyState.exe を利用して Ctrl キーと Alt キーの押し下げ状態を取得します。
- あらかじめ "GetKeyState.zip" をダウンロードして、書庫内の「GetKeyState.exe」を Macros フォルダに配置してください。
- includeライブラリ を利用して「さいごに 追加/削除 したカッコ」を外部ファイルに保存します。
- あらかじめ「includeライブラリ」を Macros フォルダに配置してください。
- 外部ファイルの保存場所は Mery\Macros\MacroSettings\<カッコを追加/削除>.json
または %AppData%\Mery\MacroSettings\<カッコを追加/削除>.json です。
(<カッコを追加/削除>
の部分はこのマクロのファイル名と同一になります)
- 外部ファイルの保存場所は Mery\Macros\MacroSettings\<カッコを追加/削除>.json
※ Mery ver 3.0.0 以降では「includeライブラリ」なしでも動作します。
- 「カッコを追加」の動作
- 定義されたカッコのペアを削除したときに「さいごに削除したカッコ」を更新しますので、「カッコを削除」の動作をしたことがない場合には、設定項目の
defaultOpenBrc
とdefaultCloseBrc
で定義されたカッコのペアで選択範囲を囲います。
- ※ Mery ver 3.0.0 以降で「includeライブラリ」を導入していない場合は、Mery の再起動ごとに「さいごに 追加/削除 したカッコ」の一時記憶内容が破棄されます。
- カッコの追加に使用する前に、一度「使いたいカッコ」の削除を実行して、設定ファイルの「さいごに 追加/削除 したカッコ」を更新する必要があります。
e.g. "削除" → "追加" → "追加" …… (削除) → (追加) → (追加) ……
- Ctrl キーによる動作の切り替え
- ツールバーにアイコンを置いて実行する場合、アイコンをクリックするときの Ctrl キーの押し下げ状態(Ctrl+クリックか、ただのクリックか)で機能を切り替えます
- [マクロ]メニューや右クリックメニュー内から実行する場合も、実行するときの Ctrl キーの押し下げ状態(Ctrl+クリック or ただの左クリック、または Ctrl+Enter or Enter)で機能を切り替えます
- 外部リソースからの読み込みコストがあるため、ショートカットキー( e.g. Ctrl+F8)や Ctrl+クリックが速すぎると Ctrl キーの押し下げ状態を正しく取得できないことがあります。
「カッコを追加/削除」がうまく機能しないときは、Ctrl キーを放すタイミングを遅らせてください
(マクロが発動するまで、またはマクロの処理が終了するまで Ctrl キーを押し下げたままにする)。
- Alt キーによる動作の切り替え
- Ctrl キーが押されていないときで、Alt キーを押しながら実行したときは「さいごに削除したカッコ」ではなく、「つねに特定のカッコ」(設定項目
altOpenBrc
とaltCloseBrc
で指定)で選択範囲を囲います。
- ※ 設定項目で
var altOpenBrc = "";
,var altCloseBrc = "";
にすると「GetKeyState.exe」による Alt キーの状態取得処理がなくなるので、処理速度がすこし速くなります。
- マルチカーソル/複数選択範囲への対応
Mery ver 3.0.1 以降 の「マルチカーソル/複数選択範囲」にたいしても、それぞれの選択範囲ごとに「カッコを追加/削除」できます。
※ (小カッコで囲われた選択範囲)
と 「カギカッコで囲われた選択範囲」
のカッコを同時に削除できます。
- 「カッコを削除」での注意事項
- カッコで囲われていない選択範囲は無視されます。
- 複数選択範囲や矩形選択範囲からカッコを削除したときは「さいごに削除したカッコ」を外部ファイルに保存しません(外部ファイルへの連続アクセス・書き込みによるエラー抑止のための仕様)。
- Mery ver 3.0.1 以降で「includeライブラリ」を導入していない環境では、複数選択範囲や矩形選択範囲からカッコを削除したときに「さいごに削除したカッコ」を一時記憶させることができますが、保存されるカッコは「いちばん後ろの選択範囲から削除したカッコ」になります(複数範囲選択したときの順番を考慮しない)。
ソースコード[編集]
※ Mery ver 3.0.0 以降では #include "include/IO.js"
を削除しても動作します。
※ Mery ver 3.0.1 以降では「マルチカーソル/複数選択範囲」にも対応します。
#title="カッコを追加/削除"
#tooltip="対になるカッコを追加/削除する"
#include "include/IO.js"
// #icon="brackets(delete)[3].ico"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",288
var start = new Date();
editor.ExecuteCommandByID( MEID_WINDOW_ACTIVE_PANE = 2189 );
/**
* ------------------------------------------------------------
* カッコを追加/削除
* sukemaru, 2019/03/19 - 2020/06/28
* ------------------------------------------------------------
* ※ 以下の外部実行ファイルが必要です。
* ・pizz 氏作成の "GetKeySatate.exe(キー状態取得実行ファイル)" を Macros フォルダに配置してください。
* https://www.haijin-boys.com/wiki/GetKeyState.exe(キー状態取得実行ファイル)
* ------------------------------------------------------------
* ※ Mery ver 2.x では、以下の外部ライブラリが必要です。
* ・ks 氏作成の "includeライブラリ" を Macros フォルダに配置してください。
* https://www.haijin-boys.com/wiki/includeライブラリ
* ------------------------------------------------------------
*/
// ---------- ▼ 設定項目 ▼ ---------- //
// ■ Ctrl キーを押しながら実行したときの動作モード
var ctrlToDel = false; // true:カッコを追加 / false:カッコを削除
// ■ 選択範囲の『外側』(前と後ろ) の各1文字がカッコのときも削除する? ■
// (※ 選択範囲の前後を1文字ずつ拡張してカッコを削除する)
var outerEnable = true; // true:する / false:しない
// ■ 追加するカッコの初期値(Tag プロパティや JSON がないとき)
var defaultOpenBrc = "「";
var defaultCloseBrc = "」";
// ■ Alt キー押し下げ時は指定したカッコを追加(※強制)
var altOpenBrc = "(";
var altCloseBrc = ")";
// ■ JSON ファイルのベース名(要:include ライブラリ)
var jsonName = ScriptName.replace( /\.js$/i, "" );
// var jsonName = "カッコを追加/削除";
// ■ 削除したカッコの一時記憶方法(要:Mery ver 3.0.0 以上)
var tagType = 1;
// 0 : 一時記憶なし
// 1 : タブ(文書)ごとに一時記憶する(Document.Tag)
// 2 : ウインドウごとに一時記憶する(Editor.Tag)
// 3 : すべてのタブとウインドウ共通で一時記憶する(window.Tag)
// ▼「対になるカッコ」の種類 (始)と(終) のペアを列挙する ▼
// ※ brackets に列挙する開き/閉じカッコのペアはそれぞれ「1文字」ずつでないとダメ
var brackets = "()「」<>[]{}\"\"''()「」『』<>[]{}【】〖〗﹁﹂﹃﹄︵︶︿﹀︽︾︹︺︷︸︻︼︗︘⦅⦆⦅⦆〚〛〔〕〘〙〈〉《》””’’〝〞〝〟‘’“”――~~〜〜 ";
brackets += "++--**\/\/##==%%::::@@@@※※○○●●□□■■◇◇◆◆▽▽▼▼△△▲▲☆☆★★††||←→→←↑↓↓↑←←→→↑↑↓↓……¿?¡!‚‘‚’„“„”“„‘‚‹››‹«»»«——‐‐--␣␣__≪≫";
// ▼ HTML タグなど複数文字の要素での (始)と(終) のペアを列挙 ▼
var brackets2 = [
"<i>" , "</i>" , "<u>" , "</u>" , "<s>" , "</s>" ,
"<b>" , "</b>" , "<q>" , "</q>" ,
"</" , ">" , "<" , "/>" ,
"<li>" , "</li>" , "<h>" , "</h>" ,
"<span>" , "</span>" , "<div>" , "</div>" ,
"<pre>" , "</pre>" , "<code>" , "</code>" ,
"===== " , " =====" , "=====" , "=====" , "==== " , " ====", "====" , "====",
"=== " , " ===" , "===" , "===" , "== " , " ==" , "==" , "==" , "= " , " =",
"'''''" , "'''''" , "'''" , "'''" , "''" , "''",
"――" , "――" ,
"/** \n" , "\n */" , "/** \n" , "\n*/" , "/**\n" , "\n */" , "/**\n" , "\n*/" ,
"/* \n" , "\n */" , "/* \n" , "\n*/" , "/*\n" , "\n */" , "/*\n" , "\n*/" ,
"/** " , " */" , "/* " , " */" , "/*" , "*/" ,
"( ", " )" , " (", ") " , ' "' , '" ' ,
"<!-- " , " -->" , "<!--" , "-->"
];
// ---------- ▲ 設定項目 ▲ ---------- //
brackets = brackets2.concat( brackets.split( "" ) ); // brackets2 が先、brackets が後
// OutputBar.Writeln( ( brackets.length / 2 ) + " pairs of brckets" );
// OutputBar.Writeln( brackets.toString().replace( /\n/g , "\\n" ).replace( /\t/g , "\\t" ).replace( /[ ]/g , "▯" ) + "\n" );
var d = editor.ActiveDocument;
var $end = false; // 完了フラグ
var $ctrl = $alt = false;
var gks = editor.FullName.replace( /[^\\]+$/, "" )
+ "Macros\\GetKeyState.exe";
if ( d.ReadOnly ) {
Status = " ドキュメントは書き換え禁止です。";
$end = true;
}
else if ( ! new ActiveXObject( "Scripting.FileSystemObject" ).FileExists( gks ) ) {
Status = " GetKeyState.exe がありません。";
$end = true;
}
else {
var WshShell = new ActiveXObject( "WScript.Shell" );
// Ctrl, Alt キーの状態を取得
$ctrl = ( WshShell.Run( "\"" + gks + "\" ctrl", 0, true ) === 1 );
if ( ! $ctrl && altOpenBrc && altCloseBrc ) {
$alt = ( WshShell.Run( "\"" + gks + "\" alt" , 0, true ) === 1 );
}
}
// メインコード
if ( ! $end ) {
$ctrl = $alt ? false : ( ctrlToDel ? $ctrl : ! $ctrl );
var s = d.selection;
var sMode = s.Mode || 0;
var setting = {
openBracket: defaultOpenBrc,
closeBracket: defaultCloseBrc,
altOpenBrc: altOpenBrc,
altCloseBrc: altCloseBrc,
defaultOpenBrc: defaultOpenBrc,
defaultCloseBrc: defaultCloseBrc
};
// Tag プロパティに対応
var ioEnable = ( typeof IO === "object" );
var tagEnable = ( "Tag" in window );
var tagKey = "addDeleteBrackets";
// JSON ファイルから「最後に使用したカッコ」を読みこむ
if ( ioEnable ) {
jsonName = jsonName || ScriptName.replace( /\.js$/i, "" );
setting = IO.Deserialize( setting, jsonName ); // JSON 読み込み
}
// Tag プロパティから「最後に使用したカッコ」を読みこむ
else if ( tagEnable ) {
setting = GetTag( tagType, tagKey ) || setting;
}
var sx = ScrollX, sy = ScrollY;
// マルチカーソル/複数選択に対応
// ※ マルチカーソル/複数選択では削除したカッコを外部 JSON ファイルに保存しない
var arg = [
tagType, jsonName, outerEnable, brackets, $ctrl, $alt, sMode,
setting, ioEnable, tagEnable, tagKey, start
];
// 選択範囲が1つで矩形選択ではないとき
if ( ! s.Mode || s.Mode === 1 ) {
AddDeleteBrackets_Main( arg );
}
// 矩形選択または複数選択のとき
else {
var dt = d.Text;
BeginUndoGroup();
AddUndo();
MultiFunction( AddDeleteBrackets_Main, arg );
EndUndoGroup();
if ( d.Text === dt ) { d.Undo(); }
}
ScrollX = sx; ScrollY = sy;
}
/**
* 関数 AddDeleteBrackets_Main()
* 「カッコを追加/削除」マクロ
*/
function AddDeleteBrackets_Main( arg ) {
var tagType = arg[0];
var jsonName = arg[1];
var outerEnable = arg[2];
var brackets = arg[3];
var $ctrl = arg[4];
var $alt = arg[5];
var sMode = arg[6];
var setting = arg[7];
var ioEnable = arg[8];
var tagEnable = arg[9];
var tagKey = arg[10];
var start = arg[11];
var d = editor.ActiveDocument;
var s = d.selection;
var act = s.GetActivePos();
var anc = s.GetAnchorPos();
var tp = Math.min( anc, act );
var bp = Math.max( anc, act );
var $end = $del = $add = false; // 削除フラグ/追加フラグ/完了フラグ
var len = brackets.length;
var tmp = {};
// 選択範囲を「最後に使用したカッコ」で囲う
// Alt キーありで「指定したカッコを強制追加」モード(※優先)
// ショートカットキー [ Alt+F8 ] or [ Shift+F8 ]
if ( $alt || ! $ctrl ) {
AddBrackets( setting, tp, $alt );
$add = $end = true;
}
// 選択範囲の先頭と末尾から「対になるカッコ」を削除
// ショートカットキー [ Ctrl+F8 ]
if ( ! $end && $ctrl ) {
tmp = DeleteBrackets(
brackets, setting, sMode, ioEnable, jsonName, tagEnable, tagKey, tagType, tp
);
setting = tmp.setting;
$end = tmp.$end; $del = tmp.$del;
}
// 選択範囲内の先頭と末尾が「対になるカッコ」ではなかったとき
if ( ! $end && outerEnable ) {
tmp = RemoveOuterBrackets(
brackets, setting, sMode, ioEnable, jsonName, tagEnable, tagKey, tagType, tp, bp
);
setting = tmp.setting;
$end = tmp.$end; $del = tmp.$del;
}
var o = $alt ? setting.altOpenBrc
: setting.openBracket;
var c = $alt ? setting.altCloseBrc
: setting.closeBracket;
// 終了ステータス
Status = $add ? " " + o.replace( /[ ]+/g , "␣" ) + " カッコ "
+ c.replace( /[ ]+/g , "␣" ) + " で囲いました。"
: $del ? " " + o.replace( /[ ]+/g , "␣" ) + " と "
+ c.replace( /[ ]+/g , "␣" ) + " を削除しました。"
: $end ? " カッコの 追加/削除 なし。 "
/* else */ : " カッコがありません。 ( searched for "
+ ( ( len / 2 ) + " pairs of brckets )" );
Status += TimerElapsed( new Date(), start );
}
/**
* 関数 TimerElapsed( end, start )
* start からの経過時間を [ s.sss 秒 ] で返す
*/
function TimerElapsed( end, start ) {
var elapsedSec = ( end - start ) / 1000;
// start からの経過時間を [ s.sss 秒 ] で返す
return " [ "
+ elapsedSec.toFixed( 3 ).replace( /\./, ". " )
+ " 秒 ]";
}
/**
* 関数 AddBrackets( setting )
* 選択範囲をカッコで囲う
*/
function AddBrackets( setting, tp, $alt ) {
// 追加するカッコ ( Alt強制 > 「最後に使用したカッコ」 > 初期値 )
var o = $alt ? setting.altOpenBrc
: setting.openBracket;
var c = $alt ? setting.altCloseBrc
: setting.closeBracket;
var s = editor.ActiveDocument.selection;
// カッコを追加
s.Text = o + s.Text + c;
s.SetAnchorPos( tp ); // 選択範囲を復帰
return true;
}
/**
* 関数 DeleteBrackets( brackets, setting, jsonName )
* 選択範囲の先頭と末尾からカッコを削除する
*/
function DeleteBrackets( brackets, setting, sMode, ioEnable, jsonName, tagEnable, tagKey, tagType, tp ) {
var $del = $end = false;
var s = editor.ActiveDocument.selection, st = s.Text;
var o = c = "", oLen = cLen = 0;
// ループ処理で「対になるカッコ」と一致するかチェック
for ( var i = 0, len = brackets.length; i < len; i += 2 ) {
if ( i % 2 == 1 ) { continue; }
o = brackets[ i ]; oLen = o.length; // 開きカッコ
c = brackets[ i + 1 ]; cLen = c.length; // 閉じカッコ
// 選択範囲内の先頭と末尾が「対になるカッコ」のとき
if ( st.length >= oLen + cLen
&& st.slice( 0, oLen ) === o
&& st.slice( - cLen ) === c ) {
// 先頭・末尾のカッコを削除して選択範囲を復帰
s.Text = st.slice( oLen, - cLen );
s.SetAnchorPos( tp ); // 選択範囲を復帰
$del = $end = true;
// ヒットしたカッコを JSONファイル/Tagプロパティ に保存
if ( ( o !== setting.openBracket || c !== setting.closeBracket ) ) {
setting.openBracket = o;
setting.closeBracket = c;
if ( ioEnable && jsonName && sMode < 2 ) { // JSON 書き込み
IO.Serialize( setting, jsonName );
}
else if ( tagEnable ) { // Tag 書き込み
SetTag( setting, tagType, tagKey );
}
}
break;
}
}
return { setting : setting, $del : $del, $end : $end };
}
/*
* 関数 RemoveOuterBrackets( brackets, setting, jsonName )
* 選択範囲の外側(前と後ろ)にあるカッコを削除する
*/
function RemoveOuterBrackets( brackets, setting, sMode, ioEnable, jsonName, tagEnable, tagKey, tagType, tp, bp ) {
var $del = $end = false;
var d = editor.ActiveDocument, s = d.selection;
var dt = d.Text, st = s.Text;
var o = c = "", oLen = cLen = 0;
for ( var i = 0, len = brackets.length; i < len; i += 2 ) {
if ( i % 2 === 1 ) { continue; }
o = brackets[ i ]; oLen = o.length; // 開きカッコ
c = brackets[ i + 1 ]; cLen = c.length; // 閉じカッコ
// 選択範囲の外側 (前と後) の各1文字がカッコのとき
// カッコの文字数だけ選択範囲を拡張してカッコを削除
if ( dt.slice( tp - oLen, tp ) === o
&& dt.slice( bp, bp + cLen ) === c ) {
s.SetAnchorPos( tp - oLen );
s.SetActivePos( bp + cLen, true );
s.Text = s.Text.slice( oLen, - cLen );
s.SetAnchorPos( tp - oLen ); // 選択範囲を復帰
$del = $end = true;
// ヒットしたカッコを Tag プロパティ/JSON ファイル に保存
if ( o !== setting.openBracket || c !== setting.closeBracket ) {
setting.openBracket = o;
setting.closeBracket = c;
if ( ioEnable && jsonName && sMode < 2 ) { // JSON 書き込み
IO.Serialize( setting, jsonName );
}
else if ( tagEnable ) { // Tag 書き込み
SetTag( setting, tagType, tagKey );
}
}
break;
}
}
return { setting : setting, $del : $del, $end : $end };
}
/**
* 関数 GetTag( tagType, tagKey, property )
* 指定された Tag の値を返す
*/
function GetTag( tagType, tagKey, property ) {
try {
var obj = ( typeof tagType === "object" ) ? tagType
: ( tagType === 1 ) ? editor.ActiveDocument
: ( tagType === 2 ) ? editor
: ( tagType === 3 ) ? window
: window;
return ( obj.Tag.Exists( tagKey )
&& ( property ? property in obj.Tag( tagKey ) : true ) )
? property
? obj.Tag( tagKey )[ property ]
: obj.Tag( tagKey )
: null;
} catch( e ) { Status = e; return null; }
}
/**
* 関数 SetTag( value, tagType, tagKey, property )
* 指定された値を Tag に書き込む
*/
function SetTag( value, tagType, tagKey, property ) {
try {
var obj = ( typeof tagType === "object" ) ? tagType
: ( tagType === 1 ) ? editor.ActiveDocument
: ( tagType === 2 ) ? editor
: ( tagType === 3 ) ? window
: window;
if ( property ) {
if ( obj.Tag.Exists( tagKey ) ) {
obj.Tag( tagKey )[ property ] = value;
}
else { obj.Tag( tagKey ) = { property: value }; }
}
else { obj.Tag( tagKey ) = value; }
}
catch( e ) { Status = e; }
finally { return; }
}
/**
* 関数 MultiFunction( Fn, arg1 )
* マルチカーソル(複数選択範囲)に対応させる
* 第1引数: Function; 選択範囲ごとに適用する処理の関数
* 第2引数: Function に渡す引数をまとめた配列
*/
function MultiFunction( Fn, arg ) {
var d = editor.ActiveDocument;
var s = d.selection;
// 矩形選択範囲は行に分ける
s.Mode = meModeMulti;
// 選択範囲の座標を取得
var sCount = s.Count;
var Sel = [];
for ( var i = 0; i < sCount; i ++ ) {
Sel[i] = {
act: s.GetActivePos( i ),
anc: s.GetAnchorPos( i )
};
}
// 各選択範囲を処理;
for ( var i = 0, diff = 0, dl; i < sCount; i ++ ) {
dl = d.TextLength;
s.SetActivePos( Sel[i].act + diff );
s.SetAnchorPos( Sel[i].anc + diff );
Fn( arg ); // AddDeleteBrackets_Main() 関数でカッコを追加/削除
// Fn() の残した選択範囲(またはキャレット位置)を回収
Sel[i].act = s.GetActivePos();
Sel[i].anc = s.GetAnchorPos();
diff += d.TextLength - dl; // 文字数の増減量(累積)
}
// マルチカーソル(複数選択範囲)を復帰
for ( var i = 0; i < sCount; i ++ ) {
s.AddPos( Sel[i].anc, Sel[i].act );
}
}
メモ[編集]
- (2019/03/14 sukemaru)
- 「カッコをはずす」マクロの初版
- (2019/03/18 sukemaru)
- 「カッコを削除/追加」マクロを追加
- (2019/03/19 sukemaru)
- 「カッコを追加/削除」マクロを追加
- ZIP をアップロード
- (2019/04/07 sukemaru)
- Quit() メソッドを削除して ZIP を更新(ソースコード内の年月日の表記はまま)
- (2019/05/03 sukemaru)
- 「カッコを追加/削除」の変数の記述ミスによるエラーを修正
- (2020/06/28 sukemaru)
- 「カッコを削除/追加」マクロを削除
- マルチカーソル/複数選択範囲に対応