「対応する括弧に移動」の版間の差分

提供:MeryWiki
ナビゲーションに移動 検索に移動
(誤記修正(カーソル右側が改行→改行か[EOF]))
(masme版を更新。)
1行目: 1行目:
カーソル右側に括弧がある場合、対応する括弧に移動します。
「shift」変数を「true」に書き換えると、選択しながら移動します。
<div>__TOC__</div>
<div>__TOC__</div>


= Kuro, kurama 版 (2009/08) =
= Kuro, kurama 版 (2009/08) =
* 「shift」変数を「true」に書き換えると、選択しながら移動します。


<source lang="javascript">
<source lang="javascript">
127行目: 124行目:
</source>
</source>


= masme 版 (2014/02) =
= masme 版 =
Get/SetActivePos メソッドと正規表現検索を活用したバージョンです。
* ステータスバーに括弧間の文字数を表示するようにしました。
* 正規表現検索を利用することで、より高速に動作するようになりました。
* Kuro, kurama 版の不安定な挙動を調整しました。
* ステータスバーに括弧間の距離(文字数)を表示するようにしました。
** カーソル右側が改行か[EOF]の場合、左側の括弧に反応するのを修正。例外なく右側のみ反応するようにした。
* Kuro, kurama 版に存在するバグっぽい挙動を修正しました。
** 開き括弧の直前ではなく、直後に移動する場合<sup>※</sup>があるのを修正。直前に移動するよう統一した。<br>※カーソル右側が改行か[EOF]の場合。改行をまたぐ移動になる場合。対応する括弧が行頭にある場合。
** カーソル右側が改行か[EOF]の場合に限り、左側の括弧に反応するのを修正。例外なく、右側の括弧にのみ反応するようにした。
** 開き括弧の「直前」ではなく「直後」に移動する場合があるのを修正。括弧の「直前」に移動するよう統一した。


== 更新履歴 ==
* 2017/05/27
** 処理方法を正規表現検索 → 文字列検索に変更し、高速化。
** 対応する括弧が見つからなかった場合、選択解除する → しない仕様に変更。
* 2014/02/05
** 初版公開。
== ソースコード ==
<source lang="javascript">
<source lang="javascript">
//■対応する括弧に移動
//■対応する括弧に移動
// 2014/02/05
// 2014/02/05-2017/05/27


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


(function(){
(function(){
  var sel = Document.Selection;
var Sel = Document.Selection;
  var pos = sel.GetActivePos(); //カーソル位置を記憶
var txt = Document.Text;
  var $br1 = Document.Text.charAt(pos) || -1; //右側の文字を取得/[EOF]の場合、-1 に
var sPos = Sel.GetActivePos(), ePos = sPos; //カーソル始点, 探索位置&終点
  var $bri = br.indexOf($br1);
var sBrc = txt.charAt(sPos); //カーソル右側の文字を取得
  switch (true) { //括弧の判定、探索準備
var iBrc = BRACKET.indexOf(sBrc);
  case ($bri == -1): //◆括弧でない場合
if (iBrc===-1 || sBrc==="") { Status = "カーソル右側に括弧がありません"; Quit(); }
    Status = "カーソル右側に括弧がありません";
var nest = 1, s, e;
    Quit();
if (iBrc % 2) { //◆閉じ括弧の場合、先頭方向へ探す
  case ($bri % 2 == 0): //◆開き括弧の場合
  var eBrc = BRACKET.charAt(iBrc-1); //対応する開き括弧を取得
    var $br2 = br.charAt($bri+1); //対応する閉じ括弧を取得
  while (nest) {
     var $text = Document.Text.slice(pos+1);
     s = txt.lastIndexOf(sBrc,ePos-1);
     //※探索範囲は括弧の直後から文末まで
     e = txt.lastIndexOf(eBrc,ePos-1);
     break;
     if (e===-1 || ePos<=0) break;
  case ($bri % 2 == 1): //◆閉じ括弧の場合
     if (e<s) {nest++; ePos=s;} else {nest--; ePos=e;}
    var $br2 = br.charAt($bri-1); //対応する開き括弧を取得
     var $text = Document.Text.slice(0,pos).split("").reverse().join("");
    //※探索範囲は括弧の直前から文頭まで
    break;
   }
   }
  //対応する括弧を探索し、距離を測定
} else { //◆開き括弧の場合、末尾方向へ探す
   var nest= 1, dist= i= 0, re= new RegExp("["+"\\"+$br1+"\\"+$br2+"]");
   var eBrc = BRACKET.charAt(iBrc+1); //対応する閉じ括弧を取得
   while (nest) { //ネストが無くなるまで探す
   while (nest) {
     i = $text.search(re);
     s = txt.indexOf(sBrc,ePos+1);
     if (i == -1) break; //括弧が見当たらない場合、探索終了
    e = txt.indexOf(eBrc,ePos+1);
     if ($text.charAt(i) == $br1) nest++; else nest--;
     if (e===-1) break;
    $text = $text.slice(i+1); //探索した範囲を除去
     if (s<e && s!==-1) {nest++; ePos=s;} else {nest--; ePos=e;}
    dist += i+1; //距離を加算
   }
   }
  switch (true) { //結果の判定、移動処理
}
  case (nest != 0): //◆ネストが残る場合
if (nest!==0) { Status = "対応する括弧が見つかりませんでした"; Quit(); }
    Status = "対応する括弧が見つかりませんでした";
Sel.SetActivePos(sPos);
    sel.SetActivePos(pos); //カーソル位置を復元、選択解除
Sel.SetActivePos(ePos, SHIFT);
    Quit();
Status = "対応する括弧の距離: "+(Math.abs(ePos - sPos)-1)+"文字";
  case ($bri % 2 == 0): //◆開き括弧の場合
}());
    sel.SetAnchorPos(pos);
    sel.SetActivePos(pos + dist, shift); //閉じ括弧の直前に移動
    break;
  case ($bri % 2 == 1): //◆閉じ括弧の場合
    sel.SetAnchorPos(pos);
    sel.SetActivePos(pos - dist, shift); //開き括弧の直前に移動
    break;
  }
  Status = "対応する括弧間の距離: "+(dist - 1)+"文字";
})();
</source>
</source>

2017年5月27日 (土) 17:03時点における版

Kuro, kurama 版 (2009/08)

  • 「shift」変数を「true」に書き換えると、選択しながら移動します。
// -----------------------------------------------------------------------------
// 対応する括弧に移動
//
// Copyright (c) Kuro. All Rights Reserved.
// www:    http://www.haijin-boys.com/
// Special Thanks for Kurama さん, Take さん
// -----------------------------------------------------------------------------

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

masme 版

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

更新履歴

  • 2017/05/27
    • 処理方法を正規表現検索 → 文字列検索に変更し、高速化。
    • 対応する括弧が見つからなかった場合、選択解除する → しない仕様に変更。
  • 2014/02/05
    • 初版公開。

ソースコード

//■対応する括弧に移動
// 2014/02/05-2017/05/27

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

(function(){
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 = "カーソル右側に括弧がありません"; 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 = "対応する括弧が見つかりませんでした"; Quit(); }
Sel.SetActivePos(sPos);
Sel.SetActivePos(ePos, SHIFT);
Status = "対応する括弧の距離: "+(Math.abs(ePos - sPos)-1)+"文字";
}());
スポンサーリンク