Macro/投稿/203

http://sakura.qp.land.to/?Macro%2F%C5%EA%B9%C6%2F203


Top > Macro > 投稿 > 203

1つ上のネストレベルの括弧に移動

  • ページ: Macro/投稿
  • 作者: jj?
  • カテゴリー: js
  • 投稿日: 2009-05-01 (金) 07:40:23

メッセージ

1つ上のネストレベルの括弧にカーソルを移動します。
C言語系の文法での使用を意図しています。

 if(a){    ←(3)ここの "{" に移動します。
   if(b){  ←(2)ここの "{" に移動します。更にマクロ実行すると、
     c;    ←(1)ここでマクロ実行すると、
   }
 }

デフォルトでは波括弧 "{ }" のみが対象ですが、
定義値を変更すれば 丸括弧 "( )"、角括弧 "[ ]" も対象にできます。


(2014/05/31) sakura:2.1.0.0以降:ちらつき抑止・速度Up。 / 2.0.6.0以降:検索キーを履歴に登録しない(しかし検索ボックスには残る)。 / プラグイン[Command]からの呼び出しに対応。
(2012/08/05) Unicode版対応。(ANSI版1.6.6.0/Unicode版2.0.5.0にて動作確認。)

fileExitNestedBracket.js
  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
/*
 [概要]
	1つ上のネストレベルの括弧にカーソルを移動します。
	括弧は "{}" (波括弧)が対象です。(→ bCOUNT_xxxxx で変更可。)
	
	移動方向:
		デフォルトのカーソルの移動方向(検索方向)は上方向ですが、
		本マクロのファイル名の拡張子(.js)が大文字(.JS)の場合、下方向になります。
		マクロ登録の File 名の設定により、方向が指定可能です。
		例:[共通設定] - [マクロ] タブ
			番号	マクロ名					ファイル名
			1		上方向:1つ上の括弧に移動	ExitNestedBracket.js
			2		下方向:1つ上の括弧に移動	ExitNestedBracket.JS (←大文字の.JS)
		
		プラグイン[Command]の場合も同様です。ハンドラ(マクロのパス)の設定で、
		拡張子を大文字(.JS)にすると下方向になります。
		例: plugin.def: [Command] セクション - "C[nnn]" キー
				[Command]
				; 上方向
				C[1]=..\..\macro\ExitNestedBracket.js
				C[1].Label=↑1つ上の括弧に移動
				; 下方向
				C[2]=..\..\macro\ExitNestedBracket.JS (←大文字の.JS)
				C[2].Label=↓1つ上の括弧に移動
		
		(サクラエディタの仕様変更によりこの方法が使えなくなる可能性もあります。)
 [制限]
	・括弧の対応が取れていない場合(コメントや文字列などで)、うまく動作しません。
 [変更履歴]
	2014/05/30	sakura:2.1.0.0:SetDrawSwitch()でちらつき抑止・速度Up、
				StatusMsg()で「見つかりませんでした」表示。
				sakura:2.0.6.0:検索キーを履歴に登録しない。(しかし検索ボックスには残る。)
				プラグイン[Command]からの呼び出しに対応。
	2012/07/28	Unicode版対応
	2009/04/22	新規
*/
 
//2012/07/28 Unicode版対応
// ANSI版/Unicode版の区別
var bUNICODE_VER = (Editor.ExpandParameter("$V").split(".")[0] == "1") ? false : true;
    //  false=ANSI版 / true=Unicode版
    // "$V":サクラエディタのバージョン (例:ANSI版="1.6.6.0" / Unicode版="2.0.5.0")
    // とりあえず、先頭が "1" ならANSI版とする。
 
// 「検索ダイアログを自動的に閉じる」チェックをONにするか。
// (チェックOFFで使用されている方はfalseにして下さい。)
var bSEARCHDIALOG_AUTOCLOSE = true;
 
// 括弧の検索回数の上限。
// (とりあえずの値。あまり大きくしたくはないが、長いプログラムだと足りなくなる。)
var nBRACKET_SEARCHCOUNT_MAX = 2000;
 
// 行頭(桁位置=1)にある括弧を最上位のネストレベル(上のネストレベル無し)とみなすか。
//var bSTOP_SEARCH_WHEN_BRACKET_FOUND_AT_TOPOFLINE = false;
var bSTOP_SEARCH_WHEN_BRACKET_FOUND_AT_TOPOFLINE = true;
 
// "{}" (波括弧)を対象にするか。
var bCOUNT_BRACES = true;
 
// "()" (丸括弧)を対象にするか。
var bCOUNT_PARENTHESES = false;
 
// "[]" (角括弧)を対象にするか。
var bCOUNT_SQUAREBRACKETS = false;
 
 
 
//--------------
// メイン
Main();
 
function Main()
{
    var ext;            // マクロのファイル名の拡張子。
    var bUpward;        // true=上方向 / false=下方向 に移動。
    var nNestLevel;        // ネストレベル。(配列)
    var nLevelIncDec;    // ネストレベルの増減。
    var sSearch;        // 検索文字列。
    var nSearchOption;    // 検索オプション。(検索ダイアログの状態)
    var bFound;            // 1つ上のネストレベルの括弧が見つかったか。
    var y0;
    var nLoopCount;
    var s;
    var x;
    //2014/05/30 sakura:2.1.0.0、プラグイン対応。
    var sMacroPath;        // 本マクロのパス
    var x0;
    var sSakuraVer;        // 各4桁 (例:sakura:1.6.6.0 → "0001.0006.0006.0000")
    var bSakuraVer2_1;    // true=sakura:2.1.0.0以降 / false=2.1.0.0より前のVer
    
    //2014/05/30 sakura:2.1.0.0。
    // とりあえず4桁にして比較 (例:"1.23.456.7890" → "0001.0023.0456.7890")
    sSakuraVer = Editor.ExpandParameter("$V").replace( /\d+/g,
        function($0){return ("000"+$0).slice(-4);} );
    bSakuraVer2_1 = (sSakuraVer >= "0002.0001.0000.0000");
    
    //2014/05/30 プラグイン[Command]からの呼び出しに対応。
    //	ext = Editor.ExpandParameter("$M");
    //	ext = ext.substring( ext.lastIndexOf(".") + 1 );
    sMacroPath = Editor.ExpandParameter("$M");
    if( (sMacroPath == "") && (typeof Plugin != "undefined") ){
        // プラグインではExpandParameter("$M")=""(空文字列)が返る。
        sMacroPath = Plugin.GetDef( "Command", "C[" + Plugin.GetCommandNo() + "]" );
    }
    ext = sMacroPath.replace( /.*\./, "" );
    
    // マクロの拡張子が大文字(="JS")なら下方向。
    bUpward = ((ext != "") && (ext == ext.toUpperCase())) ? false : true;
    
    nNestLevel = new Array();
    nNestLevel["{}"] = 0;
    nNestLevel["()"] = 0;
    nNestLevel["[]"] = 0;
    nLevelIncDec = (bUpward) ? +1 : -1;
    sSearch = "";
    if( bCOUNT_BRACES         ) sSearch += "|\\{|\\}";
    if( bCOUNT_PARENTHESES    ) sSearch += "|\\(|\\)";
    if( bCOUNT_SQUAREBRACKETS ) sSearch += "|\\[|\\]";
    if( sSearch == "" ) return;                // bCOUNT_BRACES等がすべてfalseだった。
    sSearch = sSearch.substring( 1 );        // 先頭の "|" を消す。
    nSearchOption = 1<<2;
    //2014/05/30 sakura:2.0.6.0:検索キーを履歴に登録しない。
    nSearchOption |= 0x800;            // bit11:検索キーを履歴に登録しない(2.0.6.0 以降)。
    if( bSEARCHDIALOG_AUTOCLOSE ){
        nSearchOption |= 1<<4;        // bit4:検索ダイアログを自動的に閉じる。
    }
    bFound = false;
    y0 = Editor.ExpandParameter("$y") -0;    // (-0:文字列→数値)
    if( bSakuraVer2_1 ){
        x0 = Editor.ExpandParameter("$x") -0;    // (-0:文字列→数値)
        Editor.SetDrawSwitch( 0 );                // 画面描画を非表示に。
    }
    Editor.CancelMode();        // 範囲選択中なら取り消し。
    for(nLoopCount=0;  nLoopCount < nBRACKET_SEARCHCOUNT_MAX;  nLoopCount++)
    {
        // 括弧を検索。
        if( bUpward ){
            Editor.SearchPrev( sSearch, nSearchOption );
        }else{
            Editor.SearchNext( sSearch, nSearchOption );
        }
        if( Editor.IsTextSelected() == 0 ) break;    // 見つからない。
        
        // コメント内やクォート内の括弧は無視。(簡易。1行内のみ対応。)
        s = Editor.GetLineStr( 0 );
        x = getCursorColumn();        // 括弧の文字位置(0開始)。
        // 1行内で "//" を探す。(ダブルクォート文字列の外にある "//")
        if( s.search( /^([^"]*"[^"]*")*?[^"]*?\/\// ) != -1 ){
			if( x >= RegExp.lastIndex ){
				continue;	// 括弧は "//" の後ろにある。
            }
        }
        // 1行内で "/*"〜"*/"、他を探す。
        if( isInsideOf( s, x, "/*", "*/" ) ) continue;    // 括弧は "/*"〜"*/" の間にある。
        if( isInsideOf( s, x, '"', '"' ) ) continue;    // 括弧は '"'〜'"' の間にある。
        if( isInsideOf( s, x, "'", "'" ) ) continue;    // 括弧は "'"〜"'" の間にある。
        
        // ネストレベルの増減。
        switch( Editor.GetSelectedString(0) ){        // 検索された文字列。
        case "{":    nNestLevel["{}"] -= nLevelIncDec;    break;
        case "}":    nNestLevel["{}"] += nLevelIncDec;    break;
        case "(":    nNestLevel["()"] -= nLevelIncDec;    break;
        case ")":    nNestLevel["()"] += nLevelIncDec;    break;
        case "[":    nNestLevel["[]"] -= nLevelIncDec;    break;
        case "]":    nNestLevel["[]"] += nLevelIncDec;    break;
        default:    break;
        }
        if(    (nNestLevel["{}"] == -1)
            || (nNestLevel["()"] == -1)
            || (nNestLevel["[]"] == -1)
        ){
            bFound = true;        // 1つ上のネストレベルの括弧が見つかった。
            break;
        }
        
        if( bSTOP_SEARCH_WHEN_BRACKET_FOUND_AT_TOPOFLINE ){
            // 行頭に括弧があった場合、上のネストレベルは見つからないとみなす。
            if( Editor.ExpandParameter("$x") == 1 ){
                break;
            }
        }
    } //for
    if( bFound ){
        // カーソルが画面外にあれば画面内にスクロールさせる役目もあり。
        if( bUpward ){
            Editor.Left();        // 開き括弧("{")の左に移動。
        }else{
            Editor.Right();        // 閉じ括弧("}")の右に移動。
        }
        Editor.SearchClearMark();
        if( bSakuraVer2_1 ){
            Editor.SetDrawSwitch( 1 );            // 画面描画を(非表示から)非表示に。
            Editor.ReDraw();
            // 画面描画を非表示にすると括弧が強調表示されなかったので移動履歴で対処。
            Editor.MoveHistSet();
            Editor.MoveHistPrev();
        }
    }else{
        Editor.CancelMode();
        Editor.SearchClearMark();
        if( bSakuraVer2_1 ){
            Editor.MoveCursor( y0, x0, 0 );        // 開始前の位置に戻る。
            Editor.SetDrawSwitch( 1 );            // 画面描画を(非表示から)非表示に。
            Editor.ReDraw();
            Editor.StatusMsg( ((bUpward) ? "△" : "▽") + "見つかりませんでした" );
            Editor.MsgBeep();
        }else{
            sSearch = "\x03NotFound\x02";        // 検索に失敗させる。(失敗するはず…)
            nSearchOption &= ~(1<<2);
            // マクロ実行時の行に戻る。(桁位置も戻したいがちょっと苦しい。)
            if( bUpward ){
                // とりあえず行頭へ。
                Editor.Jump( y0, 1 );
                // 「△見つかりませんでした」をステータスバーに表示。
                Editor.SearchPrev( sSearch, nSearchOption );
            }else{
                // とりあえず行末へ。
                Editor.Jump( y0 +1, 1 );
                if( Editor.ExpandParameter("$y") == y0 +1 ) Editor.Left();
                // 「▽見つかりませんでした」をステータスバーに表示。
                Editor.SearchNext( sSearch, nSearchOption );
            }
        }
    }
    //Editor.TraceOut("nLoopCount=" + ("   "+nLoopCount).slice(-4) );	//デバッグ用
}
 
 
// 文字列 sSrc 中の位置 nPos (0開始)が、文字列 sFrom と sTo の間にあるかを調べる。
// 戻り値:
//		true = nPosはsFrom〜sToの間にある / false = ない
// 例:	sSrc="012/*5*/89/*2*/56/*9" のとき:
//			isInsideOf(sSrc, 12, "/*", "*/") → true
//			isInsideOf(sSrc, 19, "/*", "*/") → false
//		sSrc="012'4'6789" のとき:
//			isInsideOf(sSrc, 4, "'", "'") → true
function isInsideOf( sSrc, nPos, sFrom, sTo )
{
    var sta, end;
    end = 0;
    while( (sta = sSrc.indexOf( sFrom, end )) != -1 ){
        sta += sFrom.length;
        if( nPos < sta ) break;
        if( (end = sSrc.indexOf( sTo, sta )) == -1 ) break;
        if( nPos < end ) return true;    // sFrom〜sTo の間にある
        end += sTo.length;
    }
    return false;
}
 
 
// カーソル行の、カーソルのある文字の位置(先頭からの文字数(桁位置)、0開始)を返す。
// 日本語のみ対応。
// 戻り値:
//		文字位置(0開始)。
// 例:	カーソル行の文字列が「abcあいう」で、カーソルが「い」の位置 → 4 を返す。
function getCursorColumn()
{
    var str;    // カーソル行の文字列。
    var x;        // カーソルの桁位置(先頭からのバイト数)。
    var len, i, c;
    
    //2012/07/28 Unicode版対応
    if( bUNICODE_VER ){
        // Unicode版では "$x" は(行頭からの)バイト数ではなく文字数が返る。
        return Editor.ExpandParameter("$x") -1;        // 文字列→数値、0開始にする。
    }
    
    str = Editor.GetLineStr( 0 );
    x = Editor.ExpandParameter("$x") - 1;    // 文字列→数値、0開始にする。
    len = 0;
    for(i=0;  i < str.length;  i++){
        if( len >= x ) break;
        // Shift_JIS: 0x0 〜 0x80, 0xa0, 0xa1 〜 0xdf, 0xfd 〜 0xff
        // Unicode  : 0x0 〜 0x80, 0xf8f0, 0xff61 〜 0xff9f, 0xf8f1 〜 0xf8f3
        c = str.charCodeAt( i );
        if( (c>=0x0 && c<=0x80) || (c>=0xf8f0 && c<=0xf8f3) || (c>=0xff61 && c<=0xff9f) ){
            len++;
        }else{
            len += 2;
        }
    }
    return i;
}


参考: plugin.def の例

fileplugin.def
  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
[Plugin]
;IdはMSのGUIDGEN.EXEで発生。
Id={F9FA0481-A4D9-4537-90D0-D0A16B3F5128}
Name=1つ上の括弧に移動
Description=ExitNestedBracket.js
Type=wsh
Author=
Version=1.0
Url=
 
[Plug]
 
[Command]
; 上方向 (拡張子 js は小文字で登録)
C[1]=..\..\macro\ExitNestedBracket.js
C[1].Label=↑1つ上の括弧に移動
; 下方向 (拡張子 JS は大文字で登録)
C[2]=..\..\macro\ExitNestedBracket.JS
C[2].Label=↓1つ上の括弧に移動
 
[Option]
 
[Wsh]
;UseCache=0
 

旧版:
fileExitNestedBracket.20120805.zip
fileExitNestedBracketOLD.zip (ANSI版のみ対応2009/05/01)



URL B I U SIZE Black Maroon Green Olive Navy Purple Teal Gray Silver Red Lime Yellow Blue Fuchsia Aqua White

添付ファイル: fileExitNestedBracket.js 218件 [詳細] fileExitNestedBracket.20120805.zip 169件 [詳細] fileplugin.def 207件 [詳細] fileExitNestedBracketOLD.zip 218件 [詳細]

リロード   新規 編集 凍結 差分 添付 複製 名前変更   ホーム 一覧 単語検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS
Last-modified: 2015-11-24 (火) 22:59:03 (998d)