対応する括弧に移動

提供: MeryWiki
2024年12月30日 (月) 04:42時点におけるMSY-07 (トーク | 投稿記録)による版 (with文を使用しないソースコードに修正)
ナビゲーションに移動 検索に移動

このマクロはMery Ver 3.6.1で追加されたコマンド「対応する括弧へ移動」と同機能です。

概要

カーソル右側に括弧がある場合、対応する括弧に移動します。

「shift」変数を「true」に書き換えると、選択しながら移動します。

Kuro, Kurama 版

// -----------------------------------------------------------------------------
// 対応する括弧に移動
//
// Copyright (c) Kuro. All Rights Reserved.
// www:    https://www.haijin-boys.com/
// Special Thanks for Kurama さん, Take さん
// -----------------------------------------------------------------------------

// シフトの状態(オンの場合は選択、オフの場合は移動)
var shift = false;
// 括弧として認識する文字
var lp = "(<[{「『【(";
var rp = ")>]}」』】)";
// 描画停止
Redraw = false;
// ステータスバーを消去
Status = "";
var sel = document.selection;
// カーソル位置を保存
var ax = sel.GetActivePointX(mePosLogical);
var ay = sel.GetActivePointY(mePosLogical);
// スクロール位置を保存
var sx = ScrollX;
var sy = ScrollY;
// カーソル位置を復元
sel.SetActivePoint(mePosLogical, ax, ay, false);
// 単語を選択
sel.SelectWord();
// 現在位置の括弧を取得
var c1 = sel.Text;
// 選択範囲を解除
sel.Collapse();
var l = lp.indexOf(c1);
var r = rp.indexOf(c1);
var st = 0;
if (l > -1) {
	// 対応する括弧の種類を取得
	var c2 = rp.charAt(l);
	sel.EndOfDocument(true);
	var s = sel.Text;
	// カーソル位置を復元
	sel.SetActivePoint(mePosLogical, ax, ay, false);
	// スクロール位置を復元
	ScrollX = sx;
	ScrollY = sy;
	var x = ax;
	var y = ay;
	for (var i = 0; i < s.length; i++) {
		x++;
		if (s.charAt(i) == c1) {
			st++;
		}
		if (s.charAt(i) == c2) {
			st--;
		}
		if (st == 0) {
			y = sel.GetActivePointY(mePosLogical);
			// カーソル位置を復元
			sel.SetActivePoint(mePosLogical, ax, ay, false);
			sel.SetActivePoint(mePosLogical, x, y, shift);
			// 左に戻る
			sel.CharLeft(shift, 1);
			break;
		}
		if (s.charAt(i) == "\n") {
			x = 1;
			y = sel.GetActivePointY(mePosLogical) + 1;
			sel.SetActivePoint(mePosLogical, x, y, false);
			sel.StartOfLine(false, mePosLogical);
			x = sel.GetActivePointX(mePosLogical);
		}
	}
} else if (r > -1) {
	// 対応する括弧の種類を取得
	var c2 = lp.charAt(r);
	sel.CharRight(false, 1);
	sel.StartOfDocument(true);
	var s = sel.Text;
	// カーソル位置を復元
	sel.SetActivePoint(mePosLogical, ax, ay, false);
	// スクロール位置を復元
	ScrollX = sx;
	ScrollY = sy;
	var x = ax;
	for (var i = s.length - 1; i >= 0; i--) {
		x--;
		if (s.charAt(i) == c1) {
			st++;
		}
		if (s.charAt(i) == c2) {
			st--;
		}
		if (st == 0) {
			y = sel.GetActivePointY(mePosLogical);
			// カーソル位置を復元
			sel.SetActivePoint(mePosLogical, ax, ay, false);
			sel.SetActivePoint(mePosLogical, x, y, shift);
			// 右に進む
			sel.CharRight(shift, 1);
			break;
		}
		if (s.charAt(i) == "\n") {
			x = 1;
			y = sel.GetActivePointY(mePosLogical) - 1;
			sel.SetActivePoint(mePosLogical, x, y, false);
			sel.EndOfLine(false, mePosLogical);
			x = sel.GetActivePointX(mePosLogical);
		}
	}
} else {
	// 括弧が無い場合は元の位置に戻す
	sel.SetActivePoint(mePosLogical, ax, ay, false);
	Status = "カーソル位置に括弧が見つかりませんでした";
}
if (st != 0) {
	sel.SetActivePoint(mePosLogical, ax, ay, false);
	Status = "対応する括弧が見つかりませんでした";
}
// 描画開始
Redraw = true;

Masme 版

  • ステータスバーに括弧間の文字数を表示するようにしました。
  • Kuro, kurama 版の不安定な挙動を調整しました。
    • カーソル右側が改行か[EOF]の場合、左側の括弧に反応するのを修正。例外なく右側のみ反応するようにした。
    • 開き括弧の直前ではなく、直後に移動する場合※があるのを修正。直前に移動するよう統一した。
      ※カーソル右側が改行か[EOF]の場合。改行をまたぐ移動になる場合。対応する括弧が行頭にある場合。

変更履歴

  • 1.0.2 (2019-04-12)
    • Quit() → break ラベル文に変更
  • 1.0.1 (2017-05-27)
    • 処理方法を正規表現検索 → 文字列検索に変更し、高速化
    • 対応する括弧が見つからなかった場合、選択解除する → しない仕様に変更
  • 1.0.0 (2014-02-05)
    • 初版公開

ソースコード

//■対応する括弧に移動
// 2014-02-05 - 2019-04-12

//■括弧の定義(0+2n:開き/1+2n:閉じ)
var BRACKET = "()<>[]{}「」『』【】()";
//■範囲選択(true:する/false:しない)
var SHIFT = false;

quit: {
var Sel = Document.Selection;
var txt = Document.Text;
var sPos = Sel.GetActivePos(), ePos = sPos; //カーソル始点, 探索位置&終点
var sBrc = txt.charAt(sPos); //カーソル右側の文字を取得
var iBrc = BRACKET.indexOf(sBrc);
if (iBrc===-1 || sBrc==="") { Status = "カーソル右側に括弧がありません"; break quit; }
var nest = 1, s, e;
if (iBrc % 2) { //◆閉じ括弧の場合、先頭方向へ探す
	var eBrc = BRACKET.charAt(iBrc-1); //対応する開き括弧を取得
	while (nest) {
		s = txt.lastIndexOf(sBrc,ePos-1);
		e = txt.lastIndexOf(eBrc,ePos-1);
		if (e===-1 || ePos<=0) break;
		if (e<s) {nest++; ePos=s;} else {nest--; ePos=e;}
	}
} else { //◆開き括弧の場合、末尾方向へ探す
	var eBrc = BRACKET.charAt(iBrc+1); //対応する閉じ括弧を取得
	while (nest) {
		s = txt.indexOf(sBrc,ePos+1);
		e = txt.indexOf(eBrc,ePos+1);
		if (e===-1) break;
		if (s<e && s!==-1) {nest++; ePos=s;} else {nest--; ePos=e;}
	}
}
if (nest!==0) { Status = "対応する括弧が見つかりませんでした"; break quit; }
Sel.SetActivePos(sPos);
Sel.SetActivePos(ePos, SHIFT);
Status = "対応する括弧の距離: "+(Math.abs(ePos - sPos)-1)+"文字";
}
スポンサーリンク