「
検索ジャンプの include版
」を編集中 (節単位)
ナビゲーションに移動
検索に移動
警告:
ログインしていません。編集を行うと、あなたの IP アドレスが公開されます。
ログイン
または
アカウントを作成
すれば、あなたの編集はその利用者名とともに表示されるほか、さまざまなメリットもあります。
スパム攻撃防止用のチェックです。 決して、ここには、値の入力は
しない
でください!
== ソースコード == 最終更新: 2019/04/16 (Quitメソッドを削除/JSON ファイルの初期化のコードを修正) ※ポップアップメニューの表示に unicode 文字を使用していますので、シフトJISなどで保存しないでください。 <syntaxhighlight lang="javascript"> #title = "ジャンプ" #tooltip = "ポップアップメニューで検索先にジャンプ" #include "include/IO.js" #include "include/MeryInfo.js" // #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",229 /** * ------------------------------------------------------------ * "ポップアップメニューで検索先にジャンプ" * Original Copyright: 手石 (2014/04/04) * ------------------------------------------------------------ * Modified by: sukemaru (2018/11/12 - 2019/04/16) * ------------------------------------------------------------ * * 【include版】での追加機能 * 「includeライブラリ」を使用 * 検索設定はポップアップメニューから変更可 * 設定内容を外部 JSON ファイルに書き出し/読み込み * 「英単語のみ検索する」に対応 * 選択範囲が何件目のヒットかを表示可 * ヒットした行が 30 より多いときはメニューに「※さいごの行※」へのショートカットを追加 * * 【人柱版】からの追加機能 * 「大文字/小文字の区別」に対応(→ ■通常版へ逆移植済み) * 「空行+空白行」の検索に対応 * 「ヒット件数(出現回数)」を表示可 * スペースキーでポップアップメニューをキャンセル可 * 「検索履歴に残さない」を追加(→ ■通常版へ逆移植済み) * 「行の表示方法」を Mery.ini から取得可 * 「自動マーカー」オプションを廃止(デフォルト: 自動マーカー有効) * 「検索所要時間」の表示可(→ ■通常版へ逆移植済み) * 検索ジャンプ後のスクロールの挙動を調整(→ ■通常版へ逆移植済み) * 「変数/関数の定義行」のマーキング * (※2019/03/12 編集モードを限定 "JavaScript", "MeryMacroJS") * */ var start = new Date(); // 所要時間の計測開始 var setting = {}; // ---------- ▼ 【include版】 追加設定項目 ▼ ---------- // ◆このマクロの「設定を変更するための項目」をポップアップメニューに表示するか? setting.settingEnable = true; // ◆初期値 = true; (表示する) // ◆英単語のみを検索する? (true; する / false; しない) setting.wholeWordEnable = false; // ◆初期値 = false; (しない) // ---------- ▼ 【通常版】 初期設定項目 ▼ ---------- setting.logical = true; setting.highlightEnable = true; // ---------- ▼ 【人柱版 → 通常版 逆移植】 設定項目 ▼ ---------- setting.timerEnable = true; setting.historyDisable = false; setting.caseEnable = false; // ---------- ▼ 【人柱版】 初期設定項目 ▼ ---------- setting.autoLineModeEnable = false; setting.blankEnable = true; setting.countEnable = true; // ---------- ▼ 【手石版】 初期設定項目 ▼ ---------- setting.menuWidth = 65; // ---------- ▲ 設定項目 ここまで ▲ ---------- var initialSettings = setting; var json = ScriptName.replace( /\.js$/i , "" ); // JSON ファイルから設定を読み込む if ( initialSettings.settingEnable ) { setting = IO.Deserialize( setting, json ); } /* ■ポップアップメニューの「行番号の表示方法」 */ // Mery.ini から「行の表示方法」を取得する if ( setting.autoLineModeEnable ) { var iniText = IO.LoadFromFile( MeryInfo.GetIniPath(), "utf-8" ); var $LineColumnView = + iniText.match( /^LineColumnView=[01]$/m ).shift().slice( -1 ); setting.logical = ! $LineColumnView; } // 「行番号の表示方法」の定数を変数に var posMode = setting.logical ? mePosLogical : mePosView; var lineMode = setting.logical ? 0 : meGetLineView; var d = document, s = document.selection; var sx = ScrollX, sy = ScrollY; // 文書全体の行数(論理行/表示行) var lines = d.GetLines( lineMode ); var lineStatus = "全体の行数: " + SeparateNum( lines ) + ( setting.logical ? " 行 ( 論理行 )" : " 行 ( 表示行 )" ); // 9,999,999行 制限オーバーのときは終了 if ( lines >= 10000000 ) { Status = "9,999,999行 制限オーバー。 文書" + lineStatus + TimerElapsed( new Date(), start ); } else { // メニューにピン止めする固定アイテムの字下げ = EN SPACE * ( 文書全体の行数のケタ数 / 2 ) var linesWidth = lines.toString().length; // 全体の行数のケタ数 var menuIndent = " ".slice( 0 - Math.round( linesWidth / 2 ) ); // (U+2002) /* 検索文字列の準備 */ var blank = new RegExp( "^[\t ]*$" , "" ); // 空白行の正規表現 var re; // "空白行の正規表現検索" フラグ // 「英単語のみ」オプションが有効のときは、選択範囲の有無によらず // キャレット付近の単語を自動選択する(キャンセルしても単語選択のまま残す) if ( setting.wholeWordEnable && ! s.Text.match( /^[\t ]*\n/ ) ) { if ( s.GetActivePos() < s.GetAnchorPos() ) { s.Collapse( meCollapseEnd ); } s.SelectWord(); } // 選択範囲なしならキャレット位置の単語を自動選択する if ( s.IsEmpty ) { var pos = s.GetActivePos(); // "選択範囲なし" のフラグ s.SelectWord(); // 先頭部分に $ があるならそれも含める (JavaScript の $変数名 の検索に使用) if ( d.Text.charAt( s.GetAnchorPos() - 1 ) == "$" ) { var $act = s.GetActivePos(); s.SetAnchorPos( s.GetAnchorPos() - 1 ); s.SetActivePos( $act, true ); } } var st = s.Text; // 検索文字列 var ty = s.GetTopPointY( posMode ); // 選択範囲の先頭位置(行番号) var by = s.GetBottomPointY( posMode ); // 選択範囲の末尾位置(行番号) // 選択範囲の末尾が改行 "\n" なら検索文字列から除外する if ( ! st || st.charAt( st.length - 1 ) == "\n" ) { st = st.replace( /\n$/g , "" ); // 自動マーカーを効かせるために選択範囲も調整する var anc = s.GetAnchorPos(); var act = s.GetActivePos(); // "末尾調整" フラグ if ( anc < act && ! ( setting.blankEnable && blank.test( st ) ) ) { s.SetActivePos( act - 1, true ); } if ( act < anc && ! ( setting.blankEnable && blank.test( st ) ) ) { s.SetAnchorPos( anc - 1 ); s.SetActivePos( act, true ); } if ( setting.blankEnable && blank.test( st ) ) { re = true; // "空白行の正規表現検索" フラグ } } // 文書末尾の空白行の場合でも "空白行の正規表現検索" フラグ else if ( ty == lines && st == d.GetLine( ty, lineMode ) && setting.blankEnable && blank.test( st ) ) { re = true; } /* "キャンセル" フラグ */ var cancel = 7; // 検索文字列がないとき(空行) if ( ! setting.blankEnable && ! st ) { cancel = 1; } // 検索条件エラー(複数行: 選択範囲に改行あり) else if ( new RegExp( "\\n" , "" ).test( st ) ) { cancel = 2; } // 検索条件エラー(複数行: 「表示行」& 選択範囲に折り返しあり) else if ( ty != by && ! setting.logical ) { cancel = 3; } // 検索条件エラー(「英単語のみ」有効で検索文字列が非・英単語のとき) else if ( ! re && setting.wholeWordEnable && st.match( /\W/ ) ) { cancel = 4; } // ポップアップメニューでジャンプ先リスト else { /* ポップアップメニューの準備 */ var m = CreatePopupMenu(), flags; // 【include版】の設定変更メニュー if ( initialSettings.settingEnable ) { SettingsMenu(); } // 「文字列」の検索では先頭に「キャンセル」のアイテムを表示 if ( ! re ) { m.Add( menuIndent + "キャンセル & ", 0 ); // Space キーでキャンセル可 m.Add( "", 0, meMenuSeparator ); // Menu Array, Total, Grand Total, Hit, Variables, Me var mArray = [], gtArray = [], t , me , gt = 0, hit = 0, v = 0, check = ""; var stQuote = st.replace( /\W/g , "\\$&" ); if ( setting.countEnable ) { // アクティブ行(検索開始行)全体の文字列を取得 var activeLine = d.GetLine( ty, lineMode ); var tx = s.GetTopPointX( posMode ); // 「行内のヒット数」と「ヒット総数」カウント用の正規表現 var countReg = new RegExp( ( setting.wholeWordEnable ? ( "\\b" + stQuote + "\\b" ) : stQuote ) , ( setting.caseEnable ? "g" : "gi" ) ); } } // 「空行+空白行」の検索ではパターンごとの配列を使用する else { var hArray = [], nArray = [], wArray = []; // Hit (match completely), Blank line ( n + w ), New line ( ^\n ), White space ( ^[\s ]+$ ) var h = 0, b = 0, n = 0, w = 0; } /* 文書全体を行単位で分割し、配列に */ for ( var a = [ "" ], i = 1; i <= lines ; i ++ ) { // a[0] = ""、 i = 行番号 a.push( d.GetLine( i, lineMode ) ); } /* 検索文字列がヒットした行をポップアップメニューのアイテムとして取得する */ for ( var i = 1, len = a.length; i < len; i ++ ) { // a[0] = 空要素、i = 行番号 → y // アクティブ行は左に ✓ チェックマーク付き flags = ( i == ty ) ? meMenuChecked : 0; // + meMenuGrayed // 「検索文字列」がヒットしたら(「大文字/小文字」「英単語のみ」オプションに対応) if ( ! re && FindCaseTF( a[i] ) >= 0 ) { // 「ヒット総数」フラグが有効の場合 if ( setting.countEnable ) { gtArray.push( [ i, gt ] ); t = a[i].match( countReg ); // 行内でのヒット回数 // 選択範囲の検索文字列が「何件目のヒット」か if ( i == ty ) { me = ( t.length > 1 && a[i].substr( 0, tx - 1 ).match( countReg ) ) ? gt + 1 + a[i].substr( 0, tx - 1 ).match( countReg ).length : gt + 1; } gt += t.length; // 総ヒット回数(大文字/小文字を区別できる) check = Marking(); // 右側につけるマーキング // 変数/関数の定義行はメニューの先頭にも置く if ( new RegExp( "←" , "" ).test( check ) ) { m.Add( Labeling( a[i], i ) + check, i, flags ); v ++; // "変数/関数の定義行" のフラグ } } // 行頭空白を除去、空白文字を半角スペースに置換、文字数を圧縮 // 「検索文字列がヒットした行」を配列に格納 mArray.push( [ Labeling( a[i], i ) + check, i, flags ] ); // ヒットした行 hit ++; // ヒットした行数 } // end if () { 検索文字列がヒットしたら } // 「空行+空白行」の検索ではサブメニュー用の配列に分別 else if ( re && blank.test( a[i] ) ) { b ++; // 空行+空白行の総数: Blank line ( n + w ) if ( a[i] == st ) { hArray.push( [ Labeling( a[i], i ), i, flags ] ); // 一致した行 h ++; // 一致した行数: Hit ( match completely ) } if ( st && ! a[i] ) { nArray.push( [ Labeling( a[i], i ), i, flags ] ); // 空行 a[i] == "" n ++; // 空行数: New line ( /^$/ ) } else if ( a[i] ) { wArray.push( [ Labeling( a[i], i ), i, flags ] ); // 空白行 a[i].length > 0 w ++; // 空白行数: White space ( /^\s+$/ ) } } // end else if () { 「空行+空白行」の検索 } } // end for () { ヒットした行を取得する } // 配列から「検索文字列がヒットした行」をポップアップメニューに追加する if ( ! re && hit ) { if ( v ) { m.Add( "", 0, meMenuSeparator ); } if ( hit > 30 ) { // ヒットした行が 30 より多いときは「※さいごの行※」を追加 m.Add( " ※ さいごの行 ( 行番号: " + mArray[ hit - 1 ][1] + " 行目 ) ※", mArray[ hit - 1 ][1] ); m.Add( "", 0, meMenuSeparator ); } if ( v < hit ) { for ( var i = 0; i < hit; i ++ ) { // 10件ごとにセパレータ、30件ごとに「キャンセル」行を追加 AddCancelLines( m, i ); // 配列から「検索文字列がヒットした行」をポップアップメニューに追加 m.Add( mArray[i][0], mArray[i][1], mArray[i][2] ); } } } // 配列から「空行+空白行」をポップアップメニューに追加する if ( re && b ) { if ( b != h ) { // ( n + w ) > h // 「すべての空行+空白行」の総数をピン止め m.Add( menuIndent + "すべての空行+空白行: " + SeparateNum( b.toString() ) + " 行", 0 ); // , meMenuGrayed m.Add( "", 0, meMenuSeparator ); } if ( n && st ) { // ( nArray.length > 0 ) && ( st.length > 0 ) var sm1 = CreatePopupMenu(); m.AddPopup( menuIndent + "すべての空行: " + SeparateNum( n ) + " 行 (&N)", sm1 ); for ( var i = 0; i < n; i ++ ) { AddCancelLines( sm1, i ); // 30件ごとに「キャンセル」行を追加 // 「空行」を「すべての空行」サブメニューに追加 sm1.Add( nArray[i][0], nArray[i][1], nArray[i][2] ); } } if ( w && n + h != b ) { // ( wArray.length > 0 ) && ( n + h != b ) var sm2 = CreatePopupMenu(); m.AddPopup( menuIndent + "すべての空白行: " + SeparateNum( w ) + " 行 (&W)", sm2 ); for ( var i = 0; i < w; i ++ ) { AddCancelLines( sm2, i ); // 30件ごとに「キャンセル」行を追加 // 「空白行」を「すべての空白行」サブメニューに追加 sm2.Add( wArray[i][0], wArray[i][1], wArray[i][2] ); } } if ( ( n && st ) || ( w && n + h != b ) ) { m.Add( "", 0, meMenuSeparator ); } // キャンセルを兼ねる(Space キーでキャンセル可) , meMenuGrayed m.Add( " ▼ 一致した行: " + SeparateNum( h.toString() ) + " 行 ▼\t& ", 0 ); if ( h > 30 ) { // ヒットした行が 30 より多いときは「※さいごの行※」を追加 m.Add( " ※ さいごの行 ( 行番号: " + hArray[ h - 1 ][1] + " 行目 ) ※", hArray[ h - 1 ][1] ); } for ( var i = 0; i < h; i ++ ) { // h == hArray.length AddCancelLines( m, i ); // 30件ごとに「キャンセル」行を追加 // 「一致した行」をメニューに追加 m.Add( hArray[i][0], hArray[i][1], hArray[i][2] ); } } // end if () { 配列から「空行+空白行」をポップアップメニューに追加する } // 空白行なしで \s*\n を検索にかけた場合(一致する「空行+空白行」が 0 行) if ( re && ! b && ! h ) { m.Add( menuIndent + "キャンセル\t& ", 0 ); } /* 検索開始からポップアップメニューを表示するまでの所要時間を取得 */ var timerStatus = setting.timerEnable ? TimerElapsed( new Date(), start ) : ""; /* ポップアップメニューを表示するのは、検索ヒット行が複数のとき */ if ( hit > 1 || b > 1 || setting.settingEnable ) { // ポップアップメニューを出すまえにステータスバー表示させること var findStatus = FindStatus(); Status = findStatus; /* カーソル位置にポップアップメニューを表示 */ var y = m.Track( mePosMouse ); // Track( 0 ) ならキャレット位置 /* 【include版】の設定変更サブメニュー項目を選択した場合 */ if ( y >= 10000000 ) { SettingsChange( y ); var isChanged = true; // 選択範囲復旧のためのフラグ } /* 選択した行番号(行頭)にジャンプして、検索文字列を範囲選択 */ else if ( y ) { s.SetActivePoint( posMode, 1, y ); // 文字列でジャンプしたとき if ( ! re ) { if ( setting.historyDisable ) { // 検索履歴に残さない ※「検索文字列の強調表示」なし s.SetActivePos( s.GetActivePos() + FindCaseTF( d.GetLine( y, lineMode ) ) ); s.SetAnchorPos( s.GetActivePos() + st.length ); d.HighlightFind = false; } else { // 検索履歴に残す ※ Mery の検索メソッドで文字列を範囲選択 s.Find( st, meFindNext ); // 「検索文字列の強調表示」を解除する/しない d.HighlightFind = setting.highlightEnable; } // ジャンプ後の選択範囲が何件目のヒットかを取得する if ( setting.countEnable ) { for ( i = 0; i < gtArray.length; i ++ ) { if ( gtArray[i][0] == y ) { var im = gtArray[i][1] + 1; break; } } } } // 空白行でジャンプしたときは検索履歴に残さない else if ( re && d.GetLine( y, lineMode ) ) { // 行(空白文字列)全体を範囲選択する(※完全な空行 ^\n では範囲選択しない) s.SetAnchorPoint( posMode, 1, y + 1 ); } ScrollY = ( ScrollY == sy ) ? ScrollY : s.GetActivePointY( mePosView ); cancel = 0; } // end else ( ジャンプして、検索文字列を範囲選択 ) /* キャンセルした場合 */ else { cancel = 5; // ポップアップメニューをキャンセル ( y == 0 ) } } // end if () { ポップアップメニューを表示 } else { cancel = 6; // ほかの行でヒットなし ( hit == 1 || b == 1 ) } } // end else { ポップアップメニューでジャンプ先リスト } /* ジャンプしなかったときは、キャレット位置/選択範囲を復帰 */ if ( cancel || isChanged ) { if ( pos || pos === 0 ) { s.SetActivePos( pos ); } else if ( act || act === 0 ) { s.SetAnchorPos( anc ); s.SetActivePos( act, true ); } ScrollX = sx; ScrollY = sy; } // キャンセルフラグが 1 ~ 4 (検索条件エラー)のとき、所要時間の計測終了 timerStatus = ( setting.timerEnable ) ? ( ! timerStatus ) ? TimerElapsed( new Date(), start ) : timerStatus : ""; /* ステータスバーに終了メッセージを表示 */ Status = ( // メニュー表示後にジャンプしなかったときと、設定を変更したとき ( cancel == 5 || isChanged ) ? findStatus : // ヒット数表示のまま // メニュー表示後にジャンプしたとき ( cancel == 0 ) ? FindStatus() : // ヒット数表示を更新 // 検索条件エラーでメニューを表示しなかったとき ( ( cancel == 1 ) ? " 検索文字列がありません ( 空行 ); " : ( cancel == 2 ) ? " 無効な検索文字列 ( 改行 ); " : ( cancel == 3 ) ? " 無効な検索文字列 ( 折り返し ); " : ( cancel == 4 ) ? " 無効な検索文字列 ( 非・英単語 ); " : ( cancel == 6 ) ? " ヒットなし。 " : /* else */ " 無効な検索文字列。 " // ← 使われないはず ) + lineStatus + timerStatus ); } // ------------------------------------------------------------ /* 関数 SeparateNum( num ) */ // 数値を3ケタ区切りに function SeparateNum( num ) { // if ( num === 0 ) { // num = "0"; // } return num.toString().replace( /(\d)(?=(?:\d{3})+$)/g , "$1," ); } /* 関数 TimerElapsed( end, start ) */ // start からの経過時間を [ s.sss 秒 ] で返す // (Javascript 時間計測のマクロでの分解能は 16ms とのこと) function TimerElapsed( end, start ) { var elapsed = end - start; return " [ " + ( ( elapsed / 1000 ) + "000" ).replace( /(\.)(\d{3})(0*)/, "$1 $2" ) + " 秒 ]"; } /* 関数 FindCaseTF( str ) */ // 文字列 str 内で st を検索するさいに「大文字/小文字を区別」する/しない // および 「英単語のみ検索」する/しない オプションに対応 // ヒットすればヒットした位置( 0 ~ )、ヒットしなければ -1 を返す function FindCaseTF( str ) { return setting.wholeWordEnable ? str.search( new RegExp( "\\b" + stQuote + "\\b" , setting.caseEnable ? "g" : "gi" ) ) : setting.caseEnable ? str.indexOf( st ) : str.toLowerCase().indexOf( st.toLowerCase() ); } /* 関数 Marking() */ // ポップアップメニューの右側に表示するマーキング function Marking() { var _stQuote = stQuote.replace( /(?:^\\ |\\ $)/g , "" ); var _check = ( ( i == ty && a[i] == st ) ? "\t ⏎" : // ①アクティブ行(行検索のとき)✓↵ ( t.length > 1 ) ? "\t x" + t.length : // ②検索文字列が複数ヒットした行 ( i != ty && a[i] == activeLine ) ? "\t **" : // ③アクティブ行と完全一致する重複行 ( a[i] == st ) ? "\t *" : // ④検索文字列と完全一致する行 "\t " // ⑤検索文字列を含む行; ); var JS_check = ( // 編集モードが "JavaScript" か "MeryMacroJS" のとき ( d.Mode.match( /javascript|mery[ _]?macros?[ _]?js/i ) ? new RegExp( "\\b(?:var |let |const )(?:\\s*|[^(]+[,]\\s*)[$]?" // ※)※ + _stQuote + "(?=\\s*(?:[=,;]|$))" , "" ).test( a[i] ) // 変数の宣言の行: "var st" ... / "var hoge = piyo , st " ... ? "\t ← var" : ( new RegExp( "\\b(?:var |let |const ).*?\\(.*?[,]\\s*[$]?" + _stQuote + "(?=\\s*(?:[=,;]|$))" , "" ).test( a[i] ) // ※)※ && SearchCloseBrc( a[i], stQuote ) ) // 閉じていないカッコのチェック // 変数の宣言の行: "var hoge = fuga(), st " ... ? "\t ← var" : ( ! blank.test( st ) && new RegExp( "\\b" + _stQuote + "(?=\\s*(?:\\+=|\\+\\+|-=|--|=(?!=)))" , "" ).test( a[i] ) ) // 変数に値を代入している行: "st = fuga" ? "\t ← sub" : new RegExp( "\\bfunction +[$]?" + _stQuote + "(?=[\\s(])" , "" ).test( a[i] ) // ※)※ // 関数の定義の行: "function st" ... ? "\t ← fn" : "" : "" ) ); return _check + JS_check; } /* 関数 Labeling( str, num ) */ // ポップアップメニューに表示する文字列の整形 function Labeling( line, i ) { // Labeling( a[i], i ) ※ line = a[i] ヒットした行全体 // 行頭空白を除去、空白文字は全角スペースに置換、文字数を圧縮して取得 var label = line.replace( /^[\t ]+/ , "" ) .replace( /(?:\t|[ ]{3,}|[ ]{2,})+/g , " › " ) .replace( /[.,:;(){}]/g , // 判別しづらい半角メタ文字を全角に置換 function( $0 ) { return String.fromCharCode( $0.charCodeAt( 0 ) + 0xFEE0 ) } ); label = ! line.length ? "( 空行 )" : ! label.length ? ( line == st ) ? "( 空白行 " + line.length + " 文字 * )" : "( 空白行 " + line.length + " 文字 )" : ( label.length > setting.menuWidth ) ? label.slice( 0, setting.menuWidth ) + "..." : label; // 行番号の右寄せは EN SPACE " " (U+2002) でケタ埋め return ( " " + i ).slice( 0 - linesWidth ) + " : " + label; } /* 関数 AddCancelLines( menu, num ) */ // 30行ごとに「キャンセル」行を追加する function AddCancelLines( menu, num ) { // 「文字列の検索」では10件ごとにセパレータを追加 if ( ! re && num > 0 && num % 10 == 0 && num % 30 != 0 ) { menu.Add( "", 0, meMenuSeparator ); } // 30件ごとに「キャンセル」行を追加 if ( num % 30 == 0 ) { if ( num != 0 ) { menu.Add( "", 0, meMenuSeparator ); } if ( num != 0 || menu != m) { menu.Add( menuIndent + "キャンセル", 0 ); menu.Add( "", 0, meMenuSeparator ); } } } /* 関数 FindStatus() */ // ステータスバーに表示するヒット数や所要時間の情報など function FindStatus() { var statusStr = ( ( re ? " 一致: " + SeparateNum( h ) + " 行 / 空白行数: " + SeparateNum( b ) + " 行 / " : ( gt ? " ヒット数: " + SeparateNum( gt ) + " 件 ( " // me: ジャンプする前の位置 / im: ジャンプした後の位置 + SeparateNum( im ? im : me ) + " 件目 ) ・ " : " ヒット: " ) + SeparateNum( hit ) + " 行 / " ) + lineStatus + timerStatus ); return statusStr; } /* 関数 SearchCloseBrc( str, word ) */ // 閉じていないカッコがないかを簡易的にチェックする(閉じていなければ false ) function SearchCloseBrc( str, word ) { var txt = str.substr( str.search( /\b(?:var |let |const )/ ) , str.search( new RegExp( "\\b" + word + "\\b" , "" ) ) ); var oBrc = txt.match( /\(/g ); // 開きカッコの数 var cBrc = txt.match (/\)/g ); // 閉じカッコの数 return ( ! cBrc || oBrc.length > cBrc.length ) ? 0 : 1; } /* 関数 SettingsMenu() */ // ポップアップメニューに設定変更用のサブメニューを表示する function SettingsMenu() { var subMenu = CreatePopupMenu(); var grayFlag_1 = ( setting.autoLineModeEnable || ! setting.settingEnable ) ? meMenuGrayed : 0; var logicalFlag = setting.logical ? meMenuChecked : 0; var viewFlag = setting.logical ? 0 : meMenuChecked; var grayFlag_2 = ( setting.historyDisable || ! setting.settingEnable ) ? meMenuGrayed : 0; var highlightFlag = ( setting.highlightEnable && ! setting.historyDisable ) ? meMenuChecked : 0; var timerFlag = setting.timerEnable ? meMenuChecked : 0; var autoLineModeFlag = setting.autoLineModeEnable ? meMenuChecked : 0; var historyFlag = setting.historyDisable ? meMenuChecked : 0; var caseFlag = setting.caseEnable ? meMenuChecked : 0; var blankFlag = setting.blankEnable ? meMenuChecked : 0; var countFlag = setting.countEnable ? meMenuChecked : 0; var wholeWordFlag = setting.wholeWordEnable ? meMenuChecked : 0; var maxWidthFlag = setting.menuWidth > 100 ? meMenuGrayed : 0; var minWidthFlag = setting.menuWidth < 30 ? meMenuGrayed : 0; var settingFlag = setting.settingEnable ? meMenuChecked : 0; var grayFlag = ! setting.settingEnable ? meMenuGrayed : 0; m.Add( "", 0, meMenuSeparator ); m.AddPopup( menuIndent + "設定を変更する (&S)", subMenu ); m.Add( "", 0, meMenuSeparator ); subMenu.Add( "「大文字/小文字」 を区別する (&C)", 10000007, caseFlag + grayFlag ); subMenu.Add( "「英単語のみ」 検索する (&W)", 10000008, wholeWordFlag + grayFlag ); subMenu.Add( "「空行/空白行」 を検索対象にする (&B)", 10000009, blankFlag + grayFlag ); subMenu.Add( "", 0, meMenuSeparator ); subMenu.Add( "「検索履歴」 に残さない (&H)", 10000006, historyFlag + grayFlag ); subMenu.Add( "「検索文字列の強調表示」 を残す (&F)", 10000003, highlightFlag + grayFlag_2 ); subMenu.Add( "", 0, meMenuSeparator ); subMenu.Add( "「行の表示方法」 を自動設定する (&A)", 10000005, autoLineModeFlag + grayFlag ); subMenu.Add( " 行数を 「論理行」 で表示する (&L)", 10000001, logicalFlag + grayFlag_1 ); subMenu.Add( " 行数を 「表示行」 で表示する (&V)", 10000002, viewFlag + grayFlag_1 ); subMenu.Add( "", 0, meMenuSeparator ); subMenu.Add( "「検索処理の所要時間」 を表示する (&T)", 10000004, timerFlag + grayFlag ); subMenu.Add( "「ヒット件数」(出現総数)を表示する (&G)", 10000010, countFlag + grayFlag ); subMenu.Add( "", 0, meMenuSeparator ); subMenu.Add( " メニューの表示幅を 10文字 増やす (&P) \t" + setting.menuWidth + ( setting.menuWidth > 100 ? "" : " → " + ( setting.menuWidth + 10 ) ) , 10000011, maxWidthFlag + grayFlag ); subMenu.Add( " メニューの表示幅を 10文字 減らす (&M) \t" + setting.menuWidth + ( setting.menuWidth < 30 ? "" : " → " + ( setting.menuWidth - 10 ) ) , 10000012, minWidthFlag + grayFlag ); subMenu.Add( "", 0, meMenuSeparator ); subMenu.Add( "", 0, meMenuSeparator ); subMenu.Add( " 設定変更を許可する (&S)", 10000000, settingFlag ); subMenu.Add( " 設定内容を初期化する (&I)", 10000015, grayFlag ); subMenu.Add( "", 0, meMenuSeparator ); subMenu.Add( " このマクロの JS ファイルを開く (&O)", 10000013 ); subMenu.Add( " このマクロの JSON ファイルを開く (&J)", 10000014, grayFlag ); } /* 関数 SettingsChange( num ) */ // ポップアップメニューで選択した項目の設定状態を変更する function SettingsChange( num ) { var setting = IO.Deserialize( setting, json ); var sIsChanged = true; switch ( num ) { case 10000000: setting.settingEnable = ! setting.settingEnable; break; case 10000001: case 10000002: setting.logical = ! setting.logical; break; case 10000003: setting.highlightEnable = ! setting.highlightEnable; break; case 10000004: setting.timerEnable = ! setting.timerEnable; break; case 10000005: setting.autoLineModeEnable = ! setting.autoLineModeEnable; break; case 10000006: setting.historyDisable = ! setting.historyDisable; break; case 10000007: setting.caseEnable = ! setting.caseEnable; break; case 10000008: setting.wholeWordEnable = ! setting.wholeWordEnable; break; case 10000009: setting.blankEnable = ! setting.blankEnable; break; case 10000010: setting.countEnable = ! setting.countEnable; break; case 10000011: setting.menuWidth += 10; break; case 10000012: setting.menuWidth -= 10; break; case 10000013: sIsChanged = false; OpenJumpJS( "setting.settingEnable = " ); break; case 10000014: sIsChanged = false; OpenJumpJson( json ); break; case 10000015: sIsChanged = false; CheckJsonFile( json ); break; default: sIsChanged = false; break; } if ( sIsChanged ) { IO.Serialize( setting, json ); } } /** * 関数 OpenJumpJS( str ) * このマクロの JS ファイルを開いて設定項目の行にジャンプする * 引数: 検索文字列(設定項目の行の文字列) * ※引数がないときは文頭 */ function OpenJumpJS( str ) { Redraw = false; var targetStr = str || ""; // Count は 1 からの整数値、Item は 0 からの整数値 var eCount = editors.Count; var dCount, dItem, ee , dd; var isOpen = false; OuterLoop: for ( var j = 0; j < eCount; j ++ ) { dCount = editors.Item( j ).documents.Count; for ( var i = 0; i < dCount; i ++ ) { dItem = editors.Item( j ).documents.Item( i ); if ( dItem.FullName == ScriptFullName ) { isOpen = true; ee = j; dd = i; break OuterLoop; } } } if ( isOpen ) { editors.Item( ee ).documents.Item( dd ).Activate(); } else { editor.NewFile(); ee = ( editors.Count == 1 ) ? 0 : eCount; editors.Item( ee ).OpenFile( ScriptFullName ); } var js = editors.Item( ee ).ActiveDocument; var settingPos = js.Text.indexOf( targetStr ); js.selection.SetActivePos( settingPos + targetStr.length ); js.selection.WordRight( true ); // true を範囲選択 var vy = js.selection.GetActivePointY( mePosView ); ScrollY = vy; // 狙った行にスクロールしないようなら、強引にやる var ly = js.selection.GetActivePointY( mePosLogical ); var WshShell = new ActiveXObject( "WScript.Shell" ); WshShell.Run( '"' + editor.FullName + '" /l ' + ly + ' "' + ScriptFullName + '"' ); ScrollY = vy; Redraw = true; } /** * 関数 OpenJumpJson( jsonName ) * JSON ファイルを開く */ function OpenJumpJson( jsonName ) { var Fso = new ActiveXObject( "Scripting.FileSystemObject" ); var jsonDir = JsonDir(); var jsonPath = jsonDir + "\\" + jsonName + ".json"; IO.Serialize( setting, jsonName ); Sleep( 500 ); if ( Fso.FileExists( jsonPath ) && JsonContents( jsonPath ).length ) { var confirmStr = "設定ファイルは正常です \n\n" + JsonContents( jsonPath ) + "設定ファイルを開きますか? "; if ( Confirm( confirmStr ) ) { var WshShell = new ActiveXObject( "WScript.Shell" ); WshShell.Run( '"' + editor.FullName + '" "' + jsonPath + '"' ); } } else { Alert( "設定ファイルがありません \n" + jsonDir + " " ); } } /** * 関数 CheckJsonFile( jsonName ) * JSON ファイルの初期化/実在確認 */ function CheckJsonFile( jsonName ) { var jsonDir = JsonDir(); var jsonPath = jsonDir + "\\" + jsonName + ".json"; var confirmStr = jsonPath + " \n\n" + "設定ファイルを初期化しますか? " if ( Confirm( confirmStr ) ) { IO.Serialize( initialSettings, jsonName ); Sleep( 500 ); var alertStr = ( IO.Path.IsExist( jsonPath ) && JsonContents( jsonPath ).length ) ? "設定ファイルは正常です \n\n" + JsonContents( jsonPath ) : "設定ファイルがありません \n" + jsonDir + " "; Alert( alertStr ); } } /** * 関数 JsonDir() * JSON ファイルの親フォルダのパス */ function JsonDir() { var Fso = new ActiveXObject( "Scripting.FileSystemObject" ); var jsonDir; if ( Fso.FileExists( editor.FullName.replace( /\.exe$/i, ".ini" ) ) ) { jsonDir = editor.FullName.replace( /Mery\.exe$/i, "" ) + "Macros\\MacroSettings"; } else { var WshShell = new ActiveXObject( "WScript.Shell" ); jsonDir = WshShell.ExpandEnvironmentStrings( "%APPDATA%" ) + "\\Mery\\MacroSettings"; } return jsonDir; } /** * 関数 JsonContents( jsonPath ) * JSON ファイルの文字列をメッセージボックス用に整形する */ function JsonContents( jsonPath ) { var contents = ( jsonPath + " \n" + IO.LoadFromFile( jsonPath ) .replace( /^\{/, "\n{\n " ) .replace( /\}$/g, "\n}\n\n" ) .replace( /,/g, " ,\n " ) .replace( /:/g, ": " ) // .replace( /[a-z]/g, // function( $0 ) { // return String.fromCharCode( $0.charCodeAt( 0 ) + 0xFEE0 ) // } ) ); return contents; } </syntaxhighlight>
編集内容の要約:
MeryWikiへの投稿はすべて、他の投稿者によって編集、変更、除去される場合があります。 自分が書いたものが他の人に容赦なく編集されるのを望まない場合は、ここに投稿しないでください。
また、投稿するのは、自分で書いたものか、パブリック ドメインまたはそれに類するフリーな資料からの複製であることを約束してください(詳細は
MeryWiki:著作権
を参照)。
著作権保護されている作品は、許諾なしに投稿しないでください!
このページを編集するには、下記の数式を計算してその答えを欄に入力してください (
ヘルプ
):
いちたすには =
キャンセル
編集ヘルプ
(新しいウィンドウで開きます)
スポンサーリンク
ナビゲーション メニュー
個人用ツール
ログインしていません
トーク
投稿記録
アカウント作成
ログイン
名前空間
ページ
議論
日本語
表示
閲覧
編集
履歴表示
その他
検索
スポンサーリンク
スポンサーリンク
案内
メインページ
ヘルプ
よくある質問
マクロリファレンス
マクロライブラリ
プラグインライブラリ
構文ファイル
テーマ
寄付・開発支援
練習用ページ
開発室
開発者のブログ
ツール
スポンサーリンク