「検索ジャンプの include版」の版間の差分

提供: MeryWiki
ナビゲーションに移動 検索に移動
Sukemaru (トーク | 投稿記録)
ソースコードを修正
Sukemaru (トーク | 投稿記録)
修正と更新
8行目: 8行目:
includeライブラリを使用し、設定内容を外部ファイルに保存します(◆settingEnable 変数で設定。デフォルト: 有効)。
includeライブラリを使用し、設定内容を外部ファイルに保存します(◆settingEnable 変数で設定。デフォルト: 有効)。


設定内容の読み込み/書き出しが可能になったので、設定の変更はポップアップメニュー内の項目のチェック ON/OFF でできるようになります。
設定内容の読み込み/書き出しが可能になったので、<span style="color:#c00;">設定の変更はポップアップメニュー内の項目のチェック ON/OFF でできるようになります。 </span><br>
 
[[ファイル:Mery_ジャンプ_SS_2.png|link=https://www.haijin-boys.com/wiki/images/0/0f/Mery_ジャンプ_SS.png|スクリーンショット]]


<div class="warningbox">
<div class="warningbox">
28行目: 30行目:
* 検索のさいに「英単語のみ検索」するかしないかを選択できます(◆変数で設定)。
* 検索のさいに「英単語のみ検索」するかしないかを選択できます(◆変数で設定)。


:* ただし、このオプションを有効にして検索できるのは英単語のみです (日本語不可)。<br> 欧文でも ascii 範囲外のアルファベットを使った単語では正常に機能しません。
:* ただし、このオプションを有効にして検索できるのは英単語のみです。<br> 欧文でも ascii 範囲外のアルファベットを使った単語では正常に機能しません。<br><span style="color:#c00;">このオプションを有効にすると日本語の文字列は検索できません。</span>
:* 有効にした場合は正規表現を使用しての検索になるので、処理がやや遅くなります。
:* 有効にした場合は正規表現を使用しての検索になるので、処理がやや遅くなります。


36行目: 38行目:


== ソースコード ==
== ソースコード ==
新規追加: 2018/12/17
最終更新: 2018/12/20
 
※ポップアップメニューの表示に unicode 文字を使用していますので、シフトJISなどで保存しないでください。
<source lang="javascript">
<source lang="javascript">
#title = "ジャンプ"
#title = "ジャンプ"
43行目: 47行目:
#include "include/MeryInfo.js"
#include "include/MeryInfo.js"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",229
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",229
// ※※ メニューに検索ヒットした行が表示されないときは、メニューの「英単語のみ」のチェックをはずしてください ※※
// ※※ メニューから設定の変更ができないときは、メニューの「JSON ファイルを開く」から設定ファイルの実在確認をしてください ※※


/**
/**
*
* ※※ メニューに検索ヒットした行が表示されないときは、メニューの「英単語のみ」のチェックをはずしてください ※※
*
  * ------------------------------------------------------------
  * ------------------------------------------------------------
  * "ポップアップメニューで検索先にジャンプ"
  * "ポップアップメニューで検索先にジャンプ"
  * Original Copyright: 手石 (2014/04/04)
  * Original Copyright: 手石 (2014/04/04)
  * ------------------------------------------------------------
  * ------------------------------------------------------------
  * Modified by: sukemaru (2018/11/12 - 2018/12/17)
  * Modified by: sukemaru (2018/11/12 - 2018/12/20)
  * ------------------------------------------------------------
  * ------------------------------------------------------------
*
* ◆ include版 ◆
* 「includeライブラリ」を使用
*  設定内容を外部 JSON ファイルに書き出し/読み込み
*  設定項目はポップアップメニューから変更可
* 「英単語のみ検索する」に対応
*  選択範囲が何件目のヒットかを表示
*
  */
  */
// ◆ include版 ◆
// 「includeライブラリ」を使用
//  設定内容を外部 JSON ファイルに書き出し/読み込み
//  設定項目はポップアップメニューから変更可
// 「英単語のみ検索する」に対応
// ◆ 人柱版 ◆
// 「大文字/小文字の区別」に対応(■通常版へ逆移植済み)
// 「空行+空白行」の検索に対応
// 「ヒット件数(出現回数)」を表示
//  スペースキーでポップアップメニューをキャンセル可
// 「検索履歴に残さない」を追加(■通常版へ逆移植済み)
// 「行の表示方法」を Mery.ini から取得
// 「自動マーカー」オプションを廃止(デフォルト: 自動マーカー有効)
// 「検索所要時間」の表示(■通常版へ逆移植済み)
//  検索ジャンプ後のスクロールの挙動を調整(■通常版へ逆移植済み)
// 「変数/関数の定義行」のマーキング


var start = new Date(); // 所要時間の計測開始
var start = new Date(); // 所要時間の計測開始
var setting = {}; // ← ※この "var setting = {}" の行を削除・書き換えしないこと!!
var setting = {};


// ---------- ▼ include版 追加設定項目 ▼ ----------
// ---------- ▼ include版 追加設定項目 ▼ ----------
82行目: 76行目:
   setting.settingEnable = true; // ◆初期値 = true; (表示しない)
   setting.settingEnable = true; // ◆初期値 = true; (表示しない)


 
 
// ◆英単語のみを検索する? (true; する / false; しない)
// ◆英単語のみを検索する? (true; する / false; しない)
   setting.wholeWordEnable = false; // ◆初期値 = false; (しない)
   setting.wholeWordEnable = false; // ◆初期値 = false; (しない)
91行目: 85行目:
// ※ ◆人柱版◆ の追加設定で autoLineModeEnable が true の場合は無効(自動設定)
// ※ ◆人柱版◆ の追加設定で autoLineModeEnable が true の場合は無効(自動設定)
   setting.logical = true; // ■初期値 = true;  (論理座標)
   setting.logical = true; // ■初期値 = true;  (論理座標)
 
 
// ■検索文字列の強調表示を残すか? (true; 残す / false; 残さない)
// ■検索文字列の強調表示を残すか? (true; 残す / false; 残さない)
// ※ ◆人柱版◆ の追加設定で historyDisable が true の場合は無効(強調表示しない)
// ※ ◆人柱版◆ の追加設定で historyDisable が true の場合は無効(強調表示しない)
101行目: 95行目:
// ◆検索処理の所要時間を表示するか? (true; する / false; しない)
// ◆検索処理の所要時間を表示するか? (true; する / false; しない)
   setting.timerEnable = true; // ◆初期値 = true; (する)
   setting.timerEnable = true; // ◆初期値 = true; (する)
 
 
// ◆行の表示方法を Mery.ini から自動で読み込むか? (true; 読み込む /false; 読み込まない)
// ◆行の表示方法を Mery.ini から自動で読み込むか? (true; 読み込む /false; 読み込まない)
   setting.autoLineModeEnable = false; // ◆初期値 = false; (読み込まない)
   setting.autoLineModeEnable = false; // ◆初期値 = false; (読み込まない)
 
 
// ◆検索文字列を「検索履歴」に残さない? (true; 残さない / false; 残す)
// ◆検索文字列を「検索履歴」に残さない? (true; 残さない / false; 残す)
// ※ historyDisable が true の場合、通常版の設定 highliteEnable は無効になります(強調表示しない)
   setting.historyDisable = false; // ◆初期値 = true; (残す)
   setting.historyDisable = false; // ◆初期値 = true; (残す)
 
 
// ◆検索文字列の「大文字/小文字」を区別するか? (true; 区別する / false; 区別しない)
// ◆検索文字列の「大文字/小文字」を区別するか? (true; 区別する / false; 区別しない)
   setting.caseEnable = false; // ◆初期値 = false; (区別しない)
   setting.caseEnable = false; // ◆初期値 = false; (区別しない)
 
 
// ◆空行/空白行を検索対象にするか? (true; する / false; しない)
// ◆空行/空白行を検索対象にするか? (true; する / false; しない)
   setting.blankEnable = false; // ◆初期値 = true; (します)
   setting.blankEnable = false; // ◆初期値 = true; (します)
 
 
// ◆ヒット件数(出現回数)を表示するか? (true; 表示する / false; 表示しない)
// ◆ヒット件数(出現回数)を表示するか? (true; 表示する / false; 表示しない)
   setting.countEnable = false; // ◆初期値 = true; (表示します)
   setting.countEnable = false; // ◆初期値 = true; (表示します)
123行目: 118行目:


// ---------- ▲ 設定項目 ここまで ▲ ----------
// ---------- ▲ 設定項目 ここまで ▲ ----------


var initialSettings = setting;
var initialSettings = setting;
var json = ScriptName.replace( /\.js$/i , "" );
var json = ScriptName.replace( /\.js$/i , "" );
// ◆ JSON ファイルの初期化 / 実在確認 ◆
// CheckJsonFile();


// JSON ファイルから設定を読み込む
// JSON ファイルから設定を読み込む
136行目: 129行目:


/* ポップアップメニューの「行番号の表示方法」 */
/* ポップアップメニューの「行番号の表示方法」 */
// Mery.ini から「行の表示方法」を取得する
if ( setting.autoLineModeEnable ) {
if ( setting.autoLineModeEnable ) {
   var iniText = IO.LoadFromFile( MeryInfo.GetIniPath(), "utf-8" );
   var iniText = IO.LoadFromFile( MeryInfo.GetIniPath(), "utf-8" );
   $LineColumnView = Number( iniText.match( /^LineColumnView=[01]$/m ).shift().slice( -1 ) );
   $LineColumnView = Number( iniText.match( /^LineColumnView=[01]$/m ).shift().slice( -1 ) );
   setting.logical = Math.abs( $LineColumnView - 1 );
   setting.logical = ! $LineColumnView;
}
}
// 「行番号の表示方法」の定数を変数に
var posMode = setting.logical ? mePosLogical : mePosView;
var posMode = setting.logical ? mePosLogical : mePosView;
var lineMode = setting.logical ? 0 : meGetLineView;
var lineMode = setting.logical ? 0 : meGetLineView;
146行目: 141行目:
var d = document,  s = document.selection;
var d = document,  s = document.selection;
var sx = ScrollX,  sy = ScrollY;
var sx = ScrollX,  sy = ScrollY;
// 選択範囲の先頭位置(行番号)と、文書全体の行数(論理行/表示行)
var ty = s.GetTopPointY( posMode );
var ty = s.GetTopPointY( posMode );
var lines = d.GetLines( lineMode );
var lines = d.GetLines( lineMode );
var lineStatus = "全体の行数: " + SeparateNum( lines )
                + ( setting.logical ? " 行 ( 論理行 )" : " 行 ( 表示行 )" );
// メニューにピン止めする固定アイテムの字下げ = EN SPACE * ( 文書全体の行数のケタ数 / 2 )
var linesWidth = lines.toString().length; // 全体の行数のケタ数
var menuIndent = "          ".slice( 0 - Math.round( linesWidth / 2 ) );


/* 検索文字列の準備 */
/* 検索文字列の準備 */
var blank = new RegExp( "^[\t  ]*$" , "" );
var blank = new RegExp( "^[\t  ]*$" , "" ); // 空白行の正規表現
var re;
var re; // "空白行の正規表現検索" フラグ
// 選択範囲なしならキャレット位置の単語を選択する
if ( s.IsEmpty ) {
if ( s.IsEmpty ) {
   var pos = s.GetActivePos();
   var pos = s.GetActivePos(); // "選択範囲なし" のフラグ
   s.SelectWord();
   s.SelectWord();
}
}
var st = s.Text;
var st = s.Text; // 検索文字列


// 選択範囲の末尾が改行 "\n" なら検索文字列から除外する
// 選択範囲の末尾が改行 "\n" なら検索文字列から除外する
if ( ! st || st.charAt( st.length - 1 ) == "\n" ) {
if ( ! st || st.charAt( st.length - 1 ) == "\n" ) {
   st = st.replace( /\n$/g , "" );
   st = st.replace( /\n$/g , "" );
  // 自動マーカーを効かせるために選択範囲も調整する
   var anc = s.GetAnchorPos();
   var anc = s.GetAnchorPos();
   var act = s.GetActivePos();
   var act = s.GetActivePos(); // "末尾調整" フラグ
   if ( anc < act && ! ( setting.blankEnable && st.match( blank ) ) )
   if ( anc < act && ! ( setting.blankEnable && st.match( blank ) ) ) {
     s.SetActivePos( act - 1, true );
     s.SetActivePos( act - 1, true );
  }
   if ( act < anc && ! ( setting.blankEnable && st.match( blank ) ) ) {
   if ( act < anc && ! ( setting.blankEnable && st.match( blank ) ) ) {
     s.SetAnchorPos( anc - 1 );
     s.SetAnchorPos( anc - 1 );
     s.SetActivePos( act, true );
     s.SetActivePos( act, true );
   }
   }
   if ( setting.blankEnable && st.match( blank ) )
   if ( setting.blankEnable && st.match( blank ) ) {
     re = true;
     re = true; // "空白行の正規表現検索" フラグ
  }
}
}
// 文書末尾の空白行の場合でも "空白行の正規表現検索" フラグ
else if ( ty == lines && st == d.GetLine( ty, lineMode )
else if ( ty == lines && st == d.GetLine( ty, lineMode )
       && setting.blankEnable && st.match( blank ) )
       && setting.blankEnable && st.match( blank ) ) {
   re = true;
   re = true;
}


var cancel = 5; // "キャンセル" フラグ
// "キャンセル" フラグ
if ( ! setting.blankEnable && ! st )
var cancel = 5;
   cancel = 1;
if ( ! setting.blankEnable && ! st ) {
else if ( st.match( /\n/g ) )
   cancel = 1; // 検索文字列がないとき(空行)
   cancel = 2;
}
else if ( st.match( /\n/g ) ) {
   cancel = 2; // 検索条件エラー(選択範囲に改行あり)
}


// ポップアップメニューでジャンプ先リスト
else {
else {
/* ポップアップメニューの準備 */
/* ポップアップメニューの準備 */
   var m = CreatePopupMenu(),  flags;
   var m = CreatePopupMenu(),  flags;


   // include 版の設定変更メニュー
   // include 版の設定変更メニュー
   if ( setting.settingEnable )
   if ( setting.settingEnable ) {
     SettingsMenu();
     SettingsMenu();
  }


   // 「文字列」の検索では先頭に「キャンセル」のアイテムを表示
   // 「文字列」の検索では先頭に「キャンセル」のアイテムを表示
   if ( ! re ) {
   if ( ! re ) {
     m.Add( "         キャンセル & ", 0 );
     m.Add( menuIndent + "キャンセル & ", 0 ); // Space キーでキャンセル可
     m.Add( "", 0, meMenuSeparator );
     m.Add( "", 0, meMenuSeparator );
     // Hit, Grand total, Variables
     // Grand total, Hit, Variables
     var mArray = [], hit = 0,  t,  gt = 0,  v = 0,  check = "";
     var mArray = [], rArray = [],  t ,  me ,  gt = 0,  hit = 0,  v = 0,  check = "";
     if ( setting.countEnable )
    var stQuote = st.replace( /\W/g , "\\$&" );
     if ( setting.countEnable ) {
      // アクティブ行(検索開始行)全体の文字列を取得
       var activeLine = d.GetLine( ty, lineMode );
       var activeLine = d.GetLine( ty, lineMode );
       var stQuote = st.replace( /\W/g , "\\$&" );
       var tx = s.GetTopPointX( posMode );
       var reg = new RegExp( stQuote , setting.caseEnable ? "g" : "gi" );
      // 行内のヒット数とヒット総数カウント用
       var reg = new RegExp(
          ( setting.wholeWordEnable ? ( "\\b" + stQuote + "\\b" ) : stQuote )
        , ( setting.caseEnble ? "g" : "gi" ) );
    }
   }
   }
  // 「空行+空白行」の検索ではパターンごとの配列を使用する
   else {
   else {
     var hArray = [],  nArray = [],  wArray = [];
     var hArray = [],  nArray = [],  wArray = [];
    // Hit ( match completely ), Blank line ( n + w ), New line ( ^$ ), White space ( ^[\s ]+$ )
     var h = 0,  b = 0,  n = 0,  w = 0;
     var h = 0,  b = 0,  n = 0,  w = 0;
   }
   }


/* 文書全体を行単位で分割し、配列に */
/* 文書全体を行単位で分割し、配列に */
   for ( var a = [ "" ], i = 1; i <= lines ; i ++ )
   for ( var a = [ "" ], i = 1; i <= lines ; i ++ ) { // a[0] = "" / i = 行番号
     a.push( d.GetLine( i, lineMode ) );
     a.push( d.GetLine( i, lineMode ) );
  }


/* 検索文字列がヒットした行をポップアップメニューのアイテムとして取得する */
/* 検索文字列がヒットした行をポップアップメニューのアイテムとして取得する */
   for ( var i = 1, len = a.length; i < len; i ++ ) {
   for ( var i = 1, len = a.length; i < len; i ++ ) { // a[0] = 空要素、i = 行番号 => y
    // アクティブ行は左に ✓ チェックマーク付き
     flags = ( i == ty ) ? meMenuChecked : 0; // + meMenuGrayed
     flags = ( i == ty ) ? meMenuChecked : 0; // + meMenuGrayed
     // 「検索文字列」がヒットしたら(「大文字/小文字」「英単語のみ」オプションに対応)
     // 「検索文字列」がヒットしたら(「大文字/小文字」「英単語のみ」オプションに対応)
     if ( ! re && findCaseTF( a[i], st ) >= 0 ) {
     if ( ! re && FindCaseTF( a[i] ) >= 0 ) {
       // 行内でのヒット回数
       // 総ヒット数フラグが有効の場合
       if ( setting.countEnable ) {
       if ( setting.countEnable ) {
        rArray.push( [ i, gt ] );
        // 行内でのヒット回数
         t = a[i].match( reg );
         t = a[i].match( reg );
         gt += t.length;
        // 選択範囲が「何件目のヒット」か
        if ( i == ty ) {
          me = ( t.length > 1 && a[i].substr( 0, tx - 1 ).match( RegExp( reg ) ) )
                  ? gt + 1 + a[i].substr( 0, tx - 1 ).match( RegExp( reg ) ).length
                  : gt + 1;
        }
         gt += t.length; // 総ヒット回数(大文字/小文字を区別できる)
         check = Marking(); // 右側につけるマーキング
         check = Marking(); // 右側につけるマーキング
         // 変数/関数の定義行はメニューの先頭にも置く
         // 変数/関数の定義行はメニューの先頭にも置く
         if ( check.match( /←/ ) ) {
         if ( check.match( /←/ ) ) {
228行目: 262行目:
       // 行頭空白を除去、空白文字を半角スペースに置換、文字数を圧縮
       // 行頭空白を除去、空白文字を半角スペースに置換、文字数を圧縮
       // 「検索文字列がヒットした行」を配列に格納
       // 「検索文字列がヒットした行」を配列に格納
       mArray.push( [ Labeling( a[i], i ) + check, i, flags ] );
       mArray.push( [ Labeling( a[i], i ) + check, i, flags ] ); // ヒットした行
       hit ++;
       hit ++; // ヒットした行数
     }
     } // end if () { 検索文字列がヒットしたら }
 
     // 「空行+空白行」の検索ではサブメニュー用の配列に分別
     // 「空行+空白行」の検索ではサブメニュー用の配列に分別
     else if ( re && a[i].match( blank ) ) {
     else if ( re && a[i].match( blank ) ) {
       b ++;
       b ++; // 空行+空白行の総数: Blank line ( n + w )
       if ( a[i] == st ) {
       if ( a[i] == st ) {
         hArray.push( [ Labeling( a[i], i ), i, flags ] );
         hArray.push( [ Labeling( a[i], i ), i, flags ] ); // 一致した行
         h ++;
         h ++; // 一致した行数: Hit ( match completely )
       }
       }
       if ( st && ! a[i] ) {
       if ( st && ! a[i] ) {
         nArray.push( [ Labeling( a[i], i ), i, flags ] );
         nArray.push( [ Labeling( a[i], i ), i, flags ] ); // 空行 a[i] == ""
         n ++;
         n ++; // 空行数: New line ( /^$/ )
       }
       }
       else if ( a[i] ) {
       else if ( a[i] ) {
         wArray.push( [ Labeling( a[i], i ), i, flags ] );
         wArray.push( [ Labeling( a[i], i ), i, flags ] ); // 空白行 a[i].length > 0
         w ++;
         w ++; // 空白行数: White space ( /^\s+$/ )
       }
       }
     }
     } // end else if () { 「空行+空白行」の検索 }
   }
   } // end for () { ヒットした行を取得する }
 
   // 配列から「検索文字列がヒットした行」をポップアップメニューに追加する
   // 配列から「検索文字列がヒットした行」をポップアップメニューに追加する
   if ( ! re && hit ) {
   if ( ! re && hit ) {
     if ( v )
     if ( v )
       m.Add( "", 0, meMenuSeparator );
       m.Add( "", 0, meMenuSeparator );
     for ( var i = 0; i < hit; i ++ ) {
     if ( v < hit ) {
      if ( v && v == hit )
      for ( var i = 0; i < hit; i ++ ) {
         break;
        // 10件ごとにセパレータ、30件ごとに「キャンセル」行を追加
      AddCancelLines( m, i ); // 10件ごとにセパレータ、30件ごとに「キャンセル」行
         AddCancelLines( m, i );
      m.Add( mArray[i][0], mArray[i][1], mArray[i][2] );
        m.Add( mArray[i][0], mArray[i][1], mArray[i][2] );
      }
     }
     }
   }
   }
   // 配列から「空行+空白行」をポップアップメニューに追加する
   // 配列から「空行+空白行」をポップアップメニューに追加する
   if ( re && b ) {
   if ( re && b ) {
     if ( b != h ) { // ( n + w ) > h
     if ( b != h ) { // ( n + w ) > h
       m.Add( " すべての空行+空白行: " + SeparateNum( b ) + " 行", 0 );
       m.Add( menuIndent + "すべての空行+空白行: " + SeparateNum( b ) + " 行", 0 ); // , meMenuGrayed
       m.Add( "", 0, meMenuSeparator );
       m.Add( "", 0, meMenuSeparator );
     }
     }
     if ( n && st ) {
     if ( n && st ) { // ( nArray.length > 0 ) && ( st.length > 0 )
       var sm1 = CreatePopupMenu();
       var sm1 = CreatePopupMenu();
       m.AddPopup( " すべての空行: " + SeparateNum( n ) + " 行 (&N)", sm1 );
       m.AddPopup( menuIndent + "すべての空行: " + SeparateNum( n ) + " 行 (&N)", sm1 );
       for ( var i = 0; i < n; i ++ ) {
       for ( var i = 0; i < n; i ++ ) {
         AddCancelLines( sm1, i ); // 30件ごとに「キャンセル」行を追加
         AddCancelLines( sm1, i ); // 30件ごとに「キャンセル」行を追加
273行目: 311行目:
       }
       }
     }
     }
     if ( w && n + h != b ) {
     if ( w && n + h != b ) { // ( wArray.length > 0 ) && ( n + h != b )
       var sm2 = CreatePopupMenu();
       var sm2 = CreatePopupMenu();
       m.AddPopup( " すべての空白行: " + SeparateNum( w ) + " 行 (&W)", sm2 );
       m.AddPopup( menuIndent + "すべての空白行: " + SeparateNum( w ) + " 行 (&W)", sm2 );
       for ( var i = 0; i < w; i ++ ) {
       for ( var i = 0; i < w; i ++ ) {
         AddCancelLines( sm2, i ); // 30件ごとに「キャンセル」行を追加
         AddCancelLines( sm2, i ); // 30件ごとに「キャンセル」行を追加
281行目: 319行目:
       }
       }
     }
     }
     if ( ( n && st ) || ( w && n + h != b ) )
     if ( ( n && st ) || ( w && n + h != b ) ) {
       m.Add( "", 0, meMenuSeparator );
       m.Add( "", 0, meMenuSeparator );
     // キャンセルを兼ねる(Space キーでキャンセル可)
    }
     m.Add( " ▼    一致した行: " + SeparateNum( h ) + " 行  ▼\t& ", 0 );
     // キャンセルを兼ねる(Space キーでキャンセル可) , meMenuGrayed
     m.Add( " ▼  一致した行: " + SeparateNum( h ) + " 行  ▼\t& ", 0 );
     for ( var i = 0; i < h; i ++ ) { // h == hArray.length
     for ( var i = 0; i < h; i ++ ) { // h == hArray.length
       AddCancelLines( m, i ); // 30件ごとに「キャンセル」行を追加
       AddCancelLines( m, i ); // 30件ごとに「キャンセル」行を追加
       m.Add( hArray[i][0], hArray[i][1], hArray[i][2] );
       m.Add( hArray[i][0], hArray[i][1], hArray[i][2] );
     }
     }
   }
   } // end if () { 配列から「空行+空白行」をポップアップメニューに追加する }


/* 検索開始からポップアップメニューを表示するまでの所要時間を取得 */
/* 検索開始からポップアップメニューを表示するまでの所要時間を取得 */
   if ( setting.timerEnable )
   if ( setting.timerEnable ) {
     var timerStatus = TimerElapsed( new Date(), start );
     var timerStatus = TimerElapsed( new Date(), start );
  }


/* ポップアップメニューを表示するのは、検索ヒット行が複数のとき */
/* ポップアップメニューを表示するのは、検索ヒット行が複数のとき */
   if ( hit > 1 || b > 1 || setting.settingEnable ) {
   if ( hit > 1 || b > 1 || setting.settingEnable ) {
     var findStatus = (
 
      ( re ? " 一致した行数: " + SeparateNum( h ) + " 行"
    // ポップアップメニューを出すまえにステータスバー表示させること
              + " / すべての空(白)行数: " + SeparateNum( b ) + " 行 / " :
     var findStatus = FindStatus( me );
    /*!re*/ ( gt ? ( " ヒット数: " + SeparateNum( gt ) + " 件 ・ " ) : " ヒットした行数: " )
              + SeparateNum( hit ) + " 行 / "
      )
      + "全体の行数: " + SeparateNum( lines )
      + ( setting.logical ? " 行 (論理行)" : " 行 (表示行)" )
      + ( setting.timerEnable ? timerStatus : "" )
    );
    // ポップアップメニューを出すまえにステータスバー表示
     Status = findStatus;
     Status = findStatus;


316行目: 348行目:
     if ( y >= 100000 ) {
     if ( y >= 100000 ) {
       SettingsChange( y );
       SettingsChange( y );
       var isChanged = true;
       var isChanged = true; // 選択範囲復旧のためのフラグ
     }
     }


322行目: 354行目:
     else if ( y ) {
     else if ( y ) {
       s.SetActivePoint( posMode, 1, y );
       s.SetActivePoint( posMode, 1, y );
       // 空白行でジャンプしたときは検索履歴に残さない
       // 空白行でジャンプしたときは検索履歴に残さない
       if ( re && d.GetLine( y, lineMode ) )
       if ( re && d.GetLine( y, lineMode ) ) {
         // 行(空白文字列)全体を範囲選択する(※完全な空行 ^\n では範囲選択しない)
         // 行(空白文字列)全体を範囲選択する(※完全な空行 ^\n では範囲選択しない)
         s.SetAnchorPoint( posMode, 1, y + 1 );
         s.SetAnchorPoint( posMode, 1, y + 1 );
      }
       // 文字列でジャンプしたとき
       // 文字列でジャンプしたとき
       else if ( ! re ) {
       else if ( ! re ) {
         if ( setting.historyDisable ) {
         if ( setting.historyDisable ) {
           // 検索履歴に残さない ※「検索文字列の強調表示」なし
           // 検索履歴に残さない ※「検索文字列の強調表示」なし
           s.SetActivePos( s.GetActivePos() + findCaseTF( d.GetLine( y, lineMode ), st ) );
           s.SetActivePos( s.GetActivePos() + FindCaseTF( d.GetLine( y, lineMode ) ) );
           s.SetAnchorPos( s.GetActivePos() + st.length );
           s.SetAnchorPos( s.GetActivePos() + st.length );
         }
         }
337行目: 371行目:
           s.Find( st, meFindNext );
           s.Find( st, meFindNext );
           d.HighlightFind = setting.highlightEnable; // 「検索文字列の強調表示」を解除する/しない
           d.HighlightFind = setting.highlightEnable; // 「検索文字列の強調表示」を解除する/しない
        }
        // ジャンプ後の選択範囲が何件目のヒットかを取得する
        if ( setting.countEnable ) {
          for ( i = 0; i < rArray.length; i ++ ) {
            if ( rArray[i][0] == y ) {
              var im = rArray[i][1] + 1;
              break;
            }
          }
         }
         }
       }
       }
       ScrollY = ( ScrollY == sy ) ? ScrollY
       ScrollY = ( ScrollY == sy ) ? ScrollY
                                   : s.GetActivePointY( mePosView );
                                   : s.GetActivePointY( mePosView );
       Quit();
       cancel = 0;
    } // end else ( ジャンプして、検索文字列を範囲選択 )
 
/* キャンセルした場合 */
    else {
      cancel = 3; // ポップアップメニューをキャンセル ( y == 0 )
     }
     }
  } // end if () { ポップアップメニューを表示 }


/* キャンセルした場合 */
  else {
     else  cancel = 3; // ポップアップメニューをキャンセル ( y == 0 )
     cancel = 4; // ほかの行でヒットなし ( hit == 1 || b == 1 )
   }
   }
  else  cancel = 4; // ほかの行でヒットなし ( hit == 1 || b == 1 )
} // end else { ポップアップメニューでジャンプ先リスト }
}


/* ジャンプしなかったときは、キャレット位置/選択範囲を復帰 */
/* ジャンプしなかったときは、キャレット位置/選択範囲を復帰 */
if ( cancel || isChanged ) {
if ( cancel || isChanged ) {
   if ( pos || pos === 0 )
   if ( pos || pos === 0 ) {
     s.SetActivePos( pos );
     s.SetActivePos( pos );
   else if ( act ) {
  }
   else if ( act || act === 0 ) {
     s.SetAnchorPos( anc );
     s.SetAnchorPos( anc );
     s.SetActivePos( act, true );
     s.SetActivePos( act, true );
   }
   }
   ScrollX = sx;  ScrollY = sy;
   ScrollX = sx;  ScrollY = sy;
}


/* ステータスバーにキャンセルメッセージを表示 */
// キャンセルフラグの値が 1 or 2 のとき、所要時間の計測終了
  if ( setting.timerEnable && ! timerStatus )
timerStatus = ( setting.timerEnable )
    var timerStatus = TimerElapsed( new Date(), start );
                  ? ( ! timerStatus )
  Status = (
                        ? TimerElapsed( new Date(), start )
     ( isChanged || cancel == 3 ) ? findStatus : // ヒット数表示のまま
                        : timerStatus
     ( ( cancel == 1 ) ? " 検索文字列がありません(空行)。 " :
                  : "";
      ( cancel == 2 ) ? " 検索文字列に【 改行 】を含めることはできません。 " :
 
      ( cancel == 4 ) ? " ヒットなし。 " :
/* ステータスバーに終了メッセージを表示 */
      /*  else  */    " 無効な検索文字列。 " // ← 使われないはず
Status =
    )
     ( isChanged || cancel == 3 ) ? findStatus : // ヒット数表示のまま
    + "全体の行数: " + SeparateNum( lines )
     ( cancel == 0 ) ? FindStatus( im ) : // ヒット数表示
    + ( setting.logical ? " 行 (論理行)" : " 行 (表示行)" )
  ( ( cancel == 1 ) ? " 検索文字列がありません ( 空行 )。 " :
    + ( setting.timerEnable ? timerStatus : "" )
    ( cancel == 2 ) ? " 無効な検索文字列 ( 改行 )。 " :
  );
    ( cancel == 4 ) ? " ヒットなし。 " :
}
    /*  else  */    " 無効な検索文字列。 " // ← 使われないはず
  ) + lineStatus + timerStatus;
Quit();
Quit();


// ------------------------------------------------------------
// ------------------------------------------------------------
389行目: 439行目:
}
}


/* 関数 FindCaseTF( str, st ) */
/* 関数 FindCaseTF( str ) */
// 文字列 str 内で st を検索するさいに「大文字/小文字を区別」する/しない
// 文字列 str 内で st を検索するさいに「大文字/小文字を区別」する/しない
// および 「英単語のみ検索」する/しない オプションにに対応
// および 「英単語のみ検索」する/しない オプションに対応
function FindCaseTF( str, st ) {
function FindCaseTF( str ) {
   return setting.wholeWordEnable
   return setting.wholeWordEnable
             ? str.search( RegExp( "\\b" + stQuote + "\\b" , setting.caseEnable ? "g" : "gi" ) )
             ? str.search( RegExp( "\\b" + stQuote + "\\b" , setting.caseEnable ? "g" : "gi" ) )
406行目: 456行目:
     // 変数の宣言の行: "var st" ... / "var hoge = piyo , st " ...
     // 変数の宣言の行: "var st" ... / "var hoge = piyo , st " ...
     a[i].match( RegExp( "\\b(?:var |let |const )(?:\\s*|[^\(]+[,]\\s+)[$]?"
     a[i].match( RegExp( "\\b(?:var |let |const )(?:\\s*|[^\(]+[,]\\s+)[$]?"
                         + stQuote + "(?=\\s*(?:[=,;]|$))" , "" ) ) ? "\t ← v a r" :
                         + stQuote + "(?=\\s*(?:[=,;]|$))" , "" ) )
        ? "\t ← v a r" : // ※カッコの員数あわせ→)※
 
     // 変数の宣言の行: "var hoge = fuga(), " + st
     // 変数の宣言の行: "var hoge = fuga(), " + st
     ( a[i].match( RegExp( "\\b(?:var |let |const ).*?\\(.*?[,]\\s*[$]?"
     ( a[i].match( RegExp( "\\b(?:var |let |const ).*?\\(.*?[,]\\s*[$]?"
                          + stQuote + "(?=\\s*(?:[=,;]|$))" , "" ) )
                        + stQuote + "(?=\\s*(?:[=,;]|$))" , "" ) ) // ※員数あわせ→)※
       // 閉じていないカッコがあるかの簡易的なチェック // ※カッコの員数あわせ→)※
       // 閉じていないカッコがあるかの簡易的なチェック
       && SearchCloseBrc( a[i], stQuote ) ) ? "\t ← v a r" :
       && SearchCloseBrc( a[i], stQuote ) )
        ? "\t ← v a r" :
 
     // 変数に値を代入している行 st + " = fuga"
     // 変数に値を代入している行 st + " = fuga"
     a[i].match( RegExp( "\\b" + stQuote + "(?=\\s*=(?!=))" , "" ) ) ? "\t ← s u b" :
     ( ! st.match( blank ) &&
      a[i].match( RegExp( "\\b" + stQuote + "(?=\\s*(?:\\+=|\\+\\+|-=|--|=(?!=)))" , "" ) ) )
        ? "\t ← s u b" :
 
     // 関数の定義の行
     // 関数の定義の行
     a[i].match( RegExp( "\\bfunction +[$]?" + stQuote + "(?=[\\s(])" , "" ) ) ? "\t ← f n" :
     a[i].match( RegExp( "\\bfunction +[$]?" + stQuote + "(?=[\\s(])" , "" ) )
    // ※カッコの員数あわせ→)※
        ? "\t ← f n" : // ※員数あわせ→)※
 
     ( i != ty && a[i] == activeLine ) ? "\t **" : // ①アクティブ行と完全一致する行(重複行)
     ( i != ty && a[i] == activeLine ) ? "\t **" : // ①アクティブ行と完全一致する行(重複行)
     ( t && t.length > 1 )    ? "\t x" + t.length : // ②検索文字列が複数ヒットした行
     ( t && t.length > 1 )    ? "\t x" + t.length : // ②検索文字列が複数ヒットした行
     ( i == ty && a[i] == st ) ? "\t ⏎" : // ③アクティブ行(行検索のとき)✓↵
     ( i == ty && a[i] == st ) ? "\t ⏎" : // ③アクティブ行(行検索のとき)✓↵
     ( i != ty && a[i] == st ) ? "\t *" : // ④検索文字列と完全一致する行
     ( i != ty && a[i] == st ) ? "\t *" : // ④検索文字列と完全一致する行
                                 "" // ⑤検索文字列を含む行
                                 "" // ⑤検索文字列を含む行
   );
   );
   return _check;
   return _check;
444行目: 502行目:
                                   /* else */  label
                                   /* else */  label
   );
   );
   return ( "   " + i ).slice( -4 ) + " : " + label;
   return ( "          " + i ).slice( 0 - linesWidth ) + " : " + label;
}
}


451行目: 509行目:
function AddCancelLines( menu, num ) {
function AddCancelLines( menu, num ) {
   // 「文字列の検索」では10件ごとにセパレータを追加
   // 「文字列の検索」では10件ごとにセパレータを追加
   if ( ! re && num > 0 && num % 10 == 0 && num % 30 != 0 )
   if ( ! re && num > 0 && num % 10 == 0 && num % 30 != 0 ) {
     menu.Add( "", 0, meMenuSeparator );
     menu.Add( "", 0, meMenuSeparator );
  }
  // 30件ごとに「キャンセル」行を追加
   if ( num % 30 == 0 ) {
   if ( num % 30 == 0 ) {
     if ( num != 0 )
     if ( num != 0 ) {
       menu.Add( "", 0, meMenuSeparator );
       menu.Add( "", 0, meMenuSeparator );
    }
     if ( num != 0 || menu != m) {
     if ( num != 0 || menu != m) {
       menu.Add( "   キャンセル", 0 );
       menu.Add( menuIndent + "キャンセル", 0 );
       menu.Add( "", 0, meMenuSeparator );
       menu.Add( "", 0, meMenuSeparator );
     }
     }
   }
   }
}
/* 関数 FindStatus( num ) */
// ステータスバーに表示するヒット数や所要時間の情報など
function FindStatus( num ) {
  var statusStr =
    ( re ? " 一致: " + SeparateNum( h ) + " 行" + " / 空白行数: " + SeparateNum( b ) + " 行 / "
        : ( gt ? " ヒット数: " + SeparateNum( gt ) + " 件 ( " + SeparateNum( num ) + " 件目 ) ・ "
                : " ヒット: " )
          + SeparateNum( hit ) + " 行 / "
    ) + lineStatus + timerStatus;
    return statusStr;
}
}


466行目: 539行目:
// 数値を3ケタ区切りに
// 数値を3ケタ区切りに
function SeparateNum( num ) {
function SeparateNum( num ) {
   if ( ! num ) { num = ""; }
   if ( ! num ) {
    num = "";
  }
   return num.toString().replace( /(\d)(?=(?:\d{3})+$)/g , "$1," );
   return num.toString().replace( /(\d)(?=(?:\d{3})+$)/g , "$1," );
}
}
499行目: 574行目:
   var maxWidthFlag = setting.menuWidth > 100 ? meMenuGrayed : 0;
   var maxWidthFlag = setting.menuWidth > 100 ? meMenuGrayed : 0;
   var minWidthFlag = setting.menuWidth < 30 ? meMenuGrayed : 0;
   var minWidthFlag = setting.menuWidth < 30 ? meMenuGrayed : 0;
   m.Add( "", 0, meMenuSeparator );
   m.Add( "", 0, meMenuSeparator );
   m.AddPopup( "         設定を変更する (&S)", subMenu );
   m.AddPopup( menuIndent + "設定を変更する (&S)", subMenu );
   m.Add( "", 0, meMenuSeparator );
   m.Add( "", 0, meMenuSeparator );
   subMenu.Add( "「大文字/小文字」 を区別する (&C)", 100007, caseFlag );
   subMenu.Add( "「大文字/小文字」 を区別する (&C)", 100007, caseFlag );
509行目: 585行目:
   subMenu.Add( "「検索文字列の強調表示」 を残す (&F)", 100003, highlightFlag + grayOut2 );
   subMenu.Add( "「検索文字列の強調表示」 を残す (&F)", 100003, highlightFlag + grayOut2 );
   subMenu.Add( "", 0, meMenuSeparator );
   subMenu.Add( "", 0, meMenuSeparator );
   subMenu.Add( "「行の表示方法」 を自動設定する (&A))", 100005, autoLineModeFlag );
   subMenu.Add( "「行の表示方法」 を自動設定する (&A)", 100005, autoLineModeFlag );
   subMenu.Add( "  行数を 「論理行」 で表示する (&L)", 100001, logicalFlag + grayOut1 );
   subMenu.Add( "  行数を 「論理行」 で表示する (&L)", 100001, logicalFlag + grayOut1 );
   subMenu.Add( "  行数を 「表示行」 で表示する (&V)", 100002, viewFlag1 );
   subMenu.Add( "  行数を 「表示行」 で表示する (&V)", 100002, viewFlag );
   subMenu.Add( "", 0, meMenuSeparator );
   subMenu.Add( "", 0, meMenuSeparator );
   subMenu.Add( "「検索処理の所要時間」 を表示する (&T)", 100004, timerFlag );
   subMenu.Add( "「検索処理の所要時間」 を表示する (&T)", 100004, timerFlag );
532行目: 608行目:
function SettingsChange( num ) {
function SettingsChange( num ) {
   var setting = IO.Deserialize( setting, json );
   var setting = IO.Deserialize( setting, json );
   var isChanged = true;
   var sIsChanged = true;
   switch ( num ) {
   switch ( num ) {
     case 100001:  case 100002:
     case 100001:  case 100002:
568行目: 644行目:
       break;
       break;
     case 100013:
     case 100013:
       isChanged = false;
       sIsChanged = false;
       OpenJumpJS();
       OpenJumpJS();
       break;
       break;
     case 100014:
     case 100014:
       isChanged = false;
       sIsChanged = false;
       OpenJumpJson();
       OpenJumpJson();
       break;
       break;
     case 100015:
     case 100015:
       isChanged = false;
       sIsChanged = false;
       CheckJsonFile();
       CheckJsonFile();
       break;
       break;
     default:
     default:
       isChanged = false;
       sIsChanged = false;
       break;
       break;
   }
   }
   if ( isChanged )
   if ( sIsChanged ) {
     IO.Serialize( setting, json );
     IO.Serialize( setting, json );
  }
}
}


590行目: 667行目:
// このマクロを開いて設定項目の行にジャンプする
// このマクロを開いて設定項目の行にジャンプする
function OpenJumpJS() {
function OpenJumpJS() {
   var docusCount = editor.documents.Count;
  // Count は 1 からの整数値、Item は 0 からの整数値
   var isOpen = false,  c;
   var eCount = editors.Count;
   for ( var i = 0; i <= docusCount; i ++ ) {
   var isOpen = false,  ee ,  dd;
     if ( ! editor.documents.Item( i ) )
  OuterLoop:
       continue;
   for ( var j = 0; j < eCount; j ++ ) {
    if ( editor.documents.Item( i ).FullName == ScriptFullName ) {
     var dCount = editors.Item( j ).documents.Count;
      isOpen = true;
    for ( var i = 0; i < dCount; i ++ ) {
      c = i;
       if ( editors.Item( j ).documents.Item( i ).FullName == ScriptFullName ) {
      break;
        isOpen = true;
        ee = j;
        dd = i;
        break OuterLoop;
      }
     }
     }
   }
   }
   if ( isOpen )
   if ( isOpen ) {
     editor.documents.Item( c ).Activate();
     editors.Item( ee ).documents.Item( dd ).Activate();
  }
   else {
   else {
     editor.NewFile();
     editor.NewFile();
     editor.OpenFile( ScriptFullName );
     ee = ( editors.Count == 1 ) ? 0 : eCount;
    editors.Item( ee ).OpenFile( ScriptFullName );
   }
   }
   var js = editor.ActiveDocument.Text.split( "\n" );
   var js = editors.Item( ee ).ActiveDocument;
   var settingsSection = "var setting = {}";
  var settingPos = js.Text.indexOf( "setting.settingEnable" );
   var yy = 21;
   js.selection.SetActivePos( settingPos );
   for ( var i = 1, len = js.length; i < len; i ++ ) {
   // 狙った行にスクロールしないようなので、強引にやる
    if ( js[i].indexOf( settingsSection ) >= 0 ) {
   var yy = js.selection.GetActivePointY( mePosLogical );
      yy = i + 3;
   new ActiveXObject( "WScript.Shell" ).Run( '"' + editor.FullName + '" /l ' + yy + ' "' + ScriptFullName + '"' );
      break;
    }
   }
  editor.ActiveDocument.selection.SetActivePoint( mePosLogical, 1, yy )
}
}


622行目: 701行目:
// JSON ファイルを開く
// JSON ファイルを開く
function OpenJumpJson() {
function OpenJumpJson() {
   var jsonPath = IO.Path.Add( MeryInfo.GetMacroFolderPath(),
   var jsonPath = IO.Path.Add( MeryInfo.GetMacroFolderPath(), "MacroSettings", json + ".json" );
                            "MacroSettings", json + ".json" );
   IO.Serialize( setting, json );
   IO.Serialize( setting, json );
   Sleep( 500 );
   Sleep( 500 );
   if ( IO.Path.IsExist( jsonPath ) ) {
   if ( IO.Path.IsExist( jsonPath ) ) {
     if ( Confirm( "設定ファイルは正常です\n"
     var confirmMessage = Confirm( "設定ファイルは正常です\n"
                  + jsonPath + "\n\n"
                                  + jsonPath + "\n\n"
                  + IO.LoadFromFile( jsonPath ).replace( /^\{|\}$/g , "  " )
                                  + IO.LoadFromFile( jsonPath ).replace( /^\{|\}$/g , "  " )
                                              .replace( /,/g , ",\n  " )
                                                              .replace( /,/g , ",\n  " )
                  + "\n\n設定ファイルを開きますか?" ) )
                                  + "\n\n設定ファイルを開きますか?" );
    if ( confirmMessage ) {
       new ActiveXObject( "WScript.Shell" ).Run( '"' + editor.FullName + '" "' + jsonPath + '"' );
       new ActiveXObject( "WScript.Shell" ).Run( '"' + editor.FullName + '" "' + jsonPath + '"' );
    }
   }
   }
   else
   else {
     Alert( "設定ファイルがありません\n"  
     Alert( "設定ファイルがありません\n"
           + IO.Path.Add( MeryInfo.GetMacroFolderPath(), "MacroSettings" ) );
           + IO.Path.Add( MeryInfo.GetMacroFolderPath(), "MacroSettings" ) );
  }
}
}


/* 関数 CheckJsonFile() */
/* 関数 CheckJsonFile() */
644行目: 724行目:
function CheckJsonFile() {
function CheckJsonFile() {
   if ( Confirm( "設定ファイルを初期化しますか?" ) ) {
   if ( Confirm( "設定ファイルを初期化しますか?" ) ) {
     var jsonPath = IO.Path.Add( MeryInfo.GetMacroFolderPath(),
     var jsonPath = IO.Path.Add( MeryInfo.GetMacroFolderPath(), "MacroSettings", json + ".json" );
                              "MacroSettings", json + ".json" );
     IO.Serialize( initialSettings, json );
     IO.Serialize( initialSettings, json );
     Sleep( 500 );
     Sleep( 500 );
     Alert( IO.Path.IsExist( jsonPath ) ? "設定ファイルは正常です\n" + jsonPath + "\n\n"
     Alert(
                                        + IO.LoadFromFile( jsonPath ).replace( /^\{|\}$/g , "  " )
      IO.Path.IsExist( jsonPath )
                                                                      .replace( /,/g , ",\n  " )
          ? "設定ファイルは正常です\n" + jsonPath + "\n\n"
                                      : "設定ファイルがありません\n"  
            + IO.LoadFromFile( jsonPath ).replace( /^\{|\}$/g , "  " )
                                        + IO.Path.Add( MeryInfo.GetMacroFolderPath(), "MacroSettings" )
                                        .replace( /,/g , ",\n  " )
          : "設定ファイルがありません\n"
            + IO.Path.Add( MeryInfo.GetMacroFolderPath(), "MacroSettings" )
     );
     );
     Quit();
     Quit();
664行目: 745行目:
: 新規アップロード
: 新規アップロード
* 2018/12/17
* 2018/12/17
: ソースコードのミスを修正
: ・ソースコードのミスを修正
: ・設定用 JSON ファイルをポップアップメニューから初期化し、内容を参照できるようにした
* 2018/12/20
: ・ソースコードのミスを修正
: ・文字列の検索のさいに「選択範囲が何件目のヒットか」を表示
: ・行番号の表示桁数の制限をなくした(5000行以上のファイルにはあまり適さないとおもう… 処理速度的に)
 
行の表示方法が「表示座標」のとき、折り返し部分にかかった文字列にはマッチしないままです。<br> 実装すると動作速度が遅くなり、実用に適さなくなってしまいます…

2018年12月20日 (木) 21:57時点における版

>> もとのページ

ポップアップメニューで検索先にジャンプ(sukemaru 版)


include版

includeライブラリを使用し、設定内容を外部ファイルに保存します(◆settingEnable 変数で設定。デフォルト: 有効)。

設定内容の読み込み/書き出しが可能になったので、設定の変更はポップアップメニュー内の項目のチェック ON/OFF でできるようになります。

スクリーンショット

  • あらかじめ includeライブラリ をインストールしてください。
  • 設定内容の保存場所は Mery\Macros\MacroSettings\ジャンプ.json です
    ※ <ジャンプ> の部分はこのマクロのファイル名)。
  • 「▼ 通常版 初期設定項目 ▼」以降の設定項目は『初期値』としてのみ利用され、ソースコード内の設定項目を直接書き換えする必要はありません。
    ただし、settingEnable 変数をを無効にする場合は、ソースコード内で変更する必要があります。
    settingEnable を無効にした場合は「人柱版」と同じ状態になるので、設定変更はソースコードの直接編集(変数の true/false の変更)でおこなう必要があります。


  • はじめての設定変更のさいにエラーが発生する場合は、
  1.  ポップアップメニューの「設定内容を初期化する」を実行して、ファイルを確認してください( → JSON ファイルを新規作成して設定値を書き出します)。
  2.  ポップアップメニューの「JSON ファイルを開く」を実行して、ファイルを確認してください。
  3.  JSON ファイルが正常に作成されない場合は、同梱の「ジャンプ.json」を Mery\Macros\MacroSettings\ フォルダに配置してください。


▼ 追加オプション ▼

  • 検索のさいに「英単語のみ検索」するかしないかを選択できます(◆変数で設定)。
  • ただし、このオプションを有効にして検索できるのは英単語のみです。
    欧文でも ascii 範囲外のアルファベットを使った単語では正常に機能しません。
    このオプションを有効にすると日本語の文字列は検索できません。
  • 有効にした場合は正規表現を使用しての検索になるので、処理がやや遅くなります。


>> もとのページ


ソースコード

最終更新: 2018/12/20

※ポップアップメニューの表示に unicode 文字を使用していますので、シフトJISなどで保存しないでください。

#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 - 2018/12/20)
 * ------------------------------------------------------------
 *
 * ◆ include版 ◆
 * 「includeライブラリ」を使用
 *   設定内容を外部 JSON ファイルに書き出し/読み込み
 *   設定項目はポップアップメニューから変更可
 * 「英単語のみ検索する」に対応
 *   選択範囲が何件目のヒットかを表示
 *
 */

var start = new Date();	// 所要時間の計測開始
var setting = {};

// ---------- ▼ include版 追加設定項目 ▼ ----------

// ◆このマクロの「設定を変更するための項目」をポップアップメニューに表示するか?
  setting.settingEnable = true;		// ◆初期値 = true; (表示しない)


// ◆英単語のみを検索する? (true; する / false; しない)
  setting.wholeWordEnable = false;	// ◆初期値 = false; (しない)

// ---------- ▼ 通常版 初期設定項目 ▼ ----------

// ■行の表示方法 (true; 論理座標 /false; 表示座標)
// ※ ◆人柱版◆ の追加設定で autoLineModeEnable が true の場合は無効(自動設定)
  setting.logical = true;		// ■初期値 = true;  (論理座標)

// ■検索文字列の強調表示を残すか? (true; 残す / false; 残さない)
// ※ ◆人柱版◆ の追加設定で historyDisable が true の場合は無効(強調表示しない)
  setting.highlightEnable = true;	// ■初期値 = true; (残す)

// ---------- ▼ 人柱版 初期設定項目 ▼ ----------
// ◆人柱版のオプションを有効にすると処理が遅くなります

// ◆検索処理の所要時間を表示するか? (true; する / false; しない)
  setting.timerEnable = true;		// ◆初期値 = true; (する)

// ◆行の表示方法を Mery.ini から自動で読み込むか? (true; 読み込む /false; 読み込まない)
  setting.autoLineModeEnable = false;	// ◆初期値 = false; (読み込まない)

// ◆検索文字列を「検索履歴」に残さない? (true; 残さない / false; 残す)
// ※ historyDisable が true の場合、通常版の設定 highliteEnable は無効になります(強調表示しない)
  setting.historyDisable = false;	// ◆初期値 = true; (残す)

// ◆検索文字列の「大文字/小文字」を区別するか? (true; 区別する / false; 区別しない)
  setting.caseEnable = false;		// ◆初期値 = false; (区別しない)

// ◆空行/空白行を検索対象にするか? (true; する / false; しない)
  setting.blankEnable = false;		// ◆初期値 = true; (します)

// ◆ヒット件数(出現回数)を表示するか? (true; 表示する / false; 表示しない)
  setting.countEnable = false;		// ◆初期値 = true; (表示します)

// ---------- ▼ 手石版 初期設定項目 ▼ ----------

// ●ポップアップメニューに表示する文字数
  setting.menuWidth = 65;

// ---------- ▲ 設定項目 ここまで ▲ ----------


var initialSettings = setting;
var json = ScriptName.replace( /\.js$/i , "" );

// JSON ファイルから設定を読み込む
if ( setting.settingEnable ) {
  setting = IO.Deserialize( setting, json );
}

/* ポップアップメニューの「行番号の表示方法」 */
// Mery.ini から「行の表示方法」を取得する
if ( setting.autoLineModeEnable ) {
  var iniText = IO.LoadFromFile( MeryInfo.GetIniPath(), "utf-8" );
  $LineColumnView = Number( 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 ty = s.GetTopPointY( posMode );
var lines = d.GetLines( lineMode );
var lineStatus = "全体の行数: " + SeparateNum( lines )
                 + ( setting.logical ? " 行 ( 論理行 )" : " 行 ( 表示行 )" );
// メニューにピン止めする固定アイテムの字下げ = EN SPACE * ( 文書全体の行数のケタ数 / 2 )
var linesWidth = lines.toString().length;	// 全体の行数のケタ数
var menuIndent = "          ".slice( 0 - Math.round( linesWidth / 2 ) );

/* 検索文字列の準備 */
var blank = new RegExp( "^[\t  ]*$" , "" );	// 空白行の正規表現
var re;						// "空白行の正規表現検索" フラグ
// 選択範囲なしならキャレット位置の単語を選択する
if ( s.IsEmpty ) {
  var pos = s.GetActivePos();	// "選択範囲なし" のフラグ
  s.SelectWord();
}
var st = s.Text;	// 検索文字列

// 選択範囲の末尾が改行 "\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 && st.match( blank ) ) ) {
    s.SetActivePos( act - 1, true );
  }
  if ( act < anc && ! ( setting.blankEnable && st.match( blank ) ) ) {
    s.SetAnchorPos( anc - 1 );
    s.SetActivePos( act, true );
  }
  if ( setting.blankEnable && st.match( blank ) ) {
    re = true;		// "空白行の正規表現検索" フラグ
  }
}
// 文書末尾の空白行の場合でも "空白行の正規表現検索" フラグ
else if ( ty == lines && st == d.GetLine( ty, lineMode )
       && setting.blankEnable && st.match( blank ) ) {
  re = true;
}

// "キャンセル" フラグ
var cancel = 5;
if ( ! setting.blankEnable && ! st ) {
  cancel = 1;		// 検索文字列がないとき(空行)
}
else if ( st.match( /\n/g ) ) {
  cancel = 2;		// 検索条件エラー(選択範囲に改行あり)
}

// ポップアップメニューでジャンプ先リスト
else {

/* ポップアップメニューの準備 */
  var m = CreatePopupMenu(),  flags;

  // include 版の設定変更メニュー
  if ( setting.settingEnable ) {
    SettingsMenu();
  }

  // 「文字列」の検索では先頭に「キャンセル」のアイテムを表示
  if ( ! re ) {
    m.Add( menuIndent + "キャンセル	& ", 0 );	// Space キーでキャンセル可
    m.Add( "", 0, meMenuSeparator );
    // Grand total, Hit, Variables
    var mArray = [], rArray = [],  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 reg = new RegExp(
          ( setting.wholeWordEnable ? ( "\\b" + stQuote + "\\b" ) : stQuote )
        , ( setting.caseEnble ? "g" : "gi" ) );
    }
  }
  // 「空行+空白行」の検索ではパターンごとの配列を使用する
  else {
    var hArray = [],  nArray = [],  wArray = [];
    // Hit ( match completely ), Blank line ( n + w ), New line ( ^$ ), 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 ) {
        rArray.push( [ i, gt ] );
        // 行内でのヒット回数
        t = a[i].match( reg );
        // 選択範囲が「何件目のヒット」か
        if ( i == ty ) {
          me = ( t.length > 1 && a[i].substr( 0, tx - 1 ).match( RegExp( reg ) ) )
                  ? gt + 1 + a[i].substr( 0, tx - 1 ).match( RegExp( reg ) ).length
                  : gt + 1;
        }
        gt += t.length;		// 総ヒット回数(大文字/小文字を区別できる)
        check = Marking();	// 右側につけるマーキング

        // 変数/関数の定義行はメニューの先頭にも置く
        if ( check.match( /←/ ) ) {
          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 && a[i].match( blank ) ) {
      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 ( 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 ) + " 行", 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 ) + " 行  ▼\t& ", 0 );
    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 () { 配列から「空行+空白行」をポップアップメニューに追加する }

/* 検索開始からポップアップメニューを表示するまでの所要時間を取得 */
  if ( setting.timerEnable ) {
    var timerStatus = TimerElapsed( new Date(), start );
  }

/* ポップアップメニューを表示するのは、検索ヒット行が複数のとき */
  if ( hit > 1 || b > 1 || setting.settingEnable ) {

    // ポップアップメニューを出すまえにステータスバー表示させること
    var findStatus = FindStatus( me );
    Status = findStatus;

/* カーソル位置にポップアップメニューを表示 */
    var y = m.Track( mePosMouse );	// Track( 0 ) ならキャレット位置

/* include 版の設定変更サブメニュー項目を選択した場合 */
    if ( y >= 100000 ) {
      SettingsChange( y );
      var isChanged = true;		// 選択範囲復旧のためのフラグ
    }

/* 選択した行番号(行頭)にジャンプして、検索文字列を範囲選択 */
    else if ( y ) {
      s.SetActivePoint( posMode, 1, y );

      // 空白行でジャンプしたときは検索履歴に残さない
      if ( re && d.GetLine( y, lineMode ) ) {
        // 行(空白文字列)全体を範囲選択する(※完全な空行 ^\n では範囲選択しない)
        s.SetAnchorPoint( posMode, 1, y + 1 );
      }
      // 文字列でジャンプしたとき
      else if ( ! re ) {
        if ( setting.historyDisable ) {
          // 検索履歴に残さない ※「検索文字列の強調表示」なし
          s.SetActivePos( s.GetActivePos() + FindCaseTF( d.GetLine( y, lineMode ) ) );
          s.SetAnchorPos( s.GetActivePos() + st.length );
        }
        else {
          // 検索履歴に残す ※ Mery の検索機能で文字列を範囲選択
          s.Find( st, meFindNext );
          d.HighlightFind = setting.highlightEnable;	// 「検索文字列の強調表示」を解除する/しない
        }
        // ジャンプ後の選択範囲が何件目のヒットかを取得する
        if ( setting.countEnable ) {
          for ( i = 0; i < rArray.length; i ++ ) {
            if ( rArray[i][0] == y ) {
              var im = rArray[i][1] + 1;
              break;
            }
          }
        }
      }
      ScrollY = ( ScrollY == sy ) ? ScrollY
                                  : s.GetActivePointY( mePosView );
      cancel = 0;
    }	// end else ( ジャンプして、検索文字列を範囲選択 )

/* キャンセルした場合 */
    else {
      cancel = 3;	// ポップアップメニューをキャンセル ( y == 0 )
    }
  }	// end if () { ポップアップメニューを表示 }

  else {
    cancel = 4;	// ほかの行でヒットなし ( 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 or 2 のとき、所要時間の計測終了
timerStatus = ( setting.timerEnable )
                  ? ( ! timerStatus )
                        ? TimerElapsed( new Date(), start )
                        : timerStatus
                  : "";

/* ステータスバーに終了メッセージを表示 */
Status =
    ( isChanged || cancel == 3 ) ? findStatus :	// ヒット数表示のまま
    ( cancel == 0 ) ? FindStatus( im ) :		// ヒット数表示
  ( ( cancel == 1 ) ? " 検索文字列がありません ( 空行 )。 " :
    ( cancel == 2 ) ? " 無効な検索文字列 ( 改行 )。 " :
    ( cancel == 4 ) ? " ヒットなし。 " :
     /*  else  */     " 無効な検索文字列。 "		// ← 使われないはず
  ) + lineStatus + timerStatus;
Quit();

// ------------------------------------------------------------

/* 関数 TimerElapsed( end, start ) */
// start からの経過時間を [ s.sss 秒 ] で返す
function TimerElapsed( end, start ) {
  var elapsed = end - start;
  return "  [ "
         + ( ( elapsed / 1000 ) + "000" ).replace( /(\.)(\d{3})(0*)/, "$1 $2" )
         + " 秒 ]";
}

/* 関数 FindCaseTF( str ) */
// 文字列 str 内で st を検索するさいに「大文字/小文字を区別」する/しない
// および 「英単語のみ検索」する/しない オプションに対応
function FindCaseTF( str ) {
  return setting.wholeWordEnable
            ? str.search( RegExp( "\\b" + stQuote + "\\b" , setting.caseEnable ? "g" : "gi" ) )
            : setting.caseEnable
                ? str.indexOf( st )
                : str.toLowerCase().indexOf( st.toLowerCase() );
}

/* 関数 Marking() */
// ポップアップメニューの右側に表示するマーキング
function Marking() {
  var _check = (
    // 変数の宣言の行:	"var st" ... / "var hoge = piyo , st " ...
    a[i].match( RegExp( "\\b(?:var |let |const )(?:\\s*|[^\(]+[,]\\s+)[$]?"
                        + stQuote + "(?=\\s*(?:[=,;]|$))" , "" ) )
        ? "\t ← v a r" :	// ※カッコの員数あわせ→)※

    // 変数の宣言の行:	"var hoge = fuga(), " + st
    ( a[i].match( RegExp( "\\b(?:var |let |const ).*?\\(.*?[,]\\s*[$]?"
                        + stQuote + "(?=\\s*(?:[=,;]|$))" , "" ) )	// ※員数あわせ→)※
      // 閉じていないカッコがあるかの簡易的なチェック
      && SearchCloseBrc( a[i], stQuote ) )
        ? "\t ← v a r" :

    // 変数に値を代入している行	st + " = fuga"
    ( ! st.match( blank ) &&
      a[i].match( RegExp( "\\b" + stQuote + "(?=\\s*(?:\\+=|\\+\\+|-=|--|=(?!=)))" , "" ) ) )
        ? "\t ← s u b" :

    // 関数の定義の行
    a[i].match( RegExp( "\\bfunction +[$]?" + stQuote + "(?=[\\s(])" , "" ) )
        ? "\t ← f n" :	// ※員数あわせ→)※

    ( i != ty && a[i] == activeLine ) ? "\t **" :	// ①アクティブ行と完全一致する行(重複行)
    ( t && t.length > 1 )     ? "\t x" + t.length :	// ②検索文字列が複数ヒットした行
    ( i == ty && a[i] == st ) ? "\t ⏎" :			// ③アクティブ行(行検索のとき)✓↵
    ( i != ty && a[i] == st ) ? "\t *" :			// ④検索文字列と完全一致する行
                                ""					// ⑤検索文字列を含む行
  );
  return _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 + 1 ) ? label.slice( 0, setting.menuWidth ) + "..." :
                                   /* else */  label
  );
  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( num ) */
// ステータスバーに表示するヒット数や所要時間の情報など
function FindStatus( num ) {
  var statusStr =
    ( re ? " 一致: " + SeparateNum( h ) + " 行" + " / 空白行数: " + SeparateNum( b ) + " 行 / "
         : ( gt ? " ヒット数: " + SeparateNum( gt ) + " 件 ( " + SeparateNum( num ) + " 件目 ) ・ "
                : " ヒット: " )
           + SeparateNum( hit ) + " 行 / "
    ) + lineStatus + timerStatus;
    return statusStr;
}

/* 関数 SeparateNum( num ) */
// 数値を3ケタ区切りに
function SeparateNum( num ) {
  if ( ! num ) {
    num = "";
  }
  return num.toString().replace( /(\d)(?=(?:\d{3})+$)/g , "$1," );
}

/* 関数 SearchCloseBrc( str, word ) */
// 閉じていないカッコがないかを簡易的にチェックする(閉じていなければ false )
function SearchCloseBrc( str, word ) {
  var txt = str.substr( str.search( /\b(?:var |let |const )/ ),
                        str.search( 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 grayOut1 = setting.autoLineModeEnable ?  meMenuGrayed : 0;
  var logicalFlag = setting.logical ? meMenuChecked : 0;
  var viewFlag = setting.logical ? 0 : meMenuChecked;
  var grayOut2 = setting.historyDisable ?  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 wholeWordFlag = setting.wholeWordEnable ? meMenuChecked : 0;
  var blankFlag = setting.blankEnable ? meMenuChecked : 0;
  var countFlag = setting.countEnable ? meMenuChecked : 0;
  var maxWidthFlag = setting.menuWidth > 100 ? meMenuGrayed : 0;
  var minWidthFlag = setting.menuWidth < 30 ? meMenuGrayed : 0;

  m.Add( "", 0, meMenuSeparator );
  m.AddPopup( menuIndent + "設定を変更する (&S)", subMenu );
  m.Add( "", 0, meMenuSeparator );
  subMenu.Add( "「大文字/小文字」 を区別する (&C)", 100007, caseFlag );
  subMenu.Add( "「英単語のみ」 検索する (&W)", 100008, wholeWordFlag );
  subMenu.Add( "「空行/空白行」 を検索対象にする (&B)", 100009, blankFlag );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "「検索履歴」 に残さない (&H)", 100006, historyFlag );
  subMenu.Add( "「検索文字列の強調表示」 を残す (&F)", 100003, highlightFlag + grayOut2 );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "「行の表示方法」 を自動設定する (&A)", 100005, autoLineModeFlag );
  subMenu.Add( "  行数を 「論理行」 で表示する (&L)", 100001, logicalFlag + grayOut1 );
  subMenu.Add( "  行数を 「表示行」 で表示する (&V)", 100002, viewFlag );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "「検索処理の所要時間」 を表示する (&T)", 100004, timerFlag );
  subMenu.Add( "「ヒット件数」(出現総数)を表示する (&G)", 100010, countFlag );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "  メニューの表示幅を 10文字 増やす (&P) \t" + setting.menuWidth
    + ( setting.menuWidth > 100 ? "" : " → " + ( setting.menuWidth + 10 ) ), 100011, maxWidthFlag );
  subMenu.Add( "  メニューの表示幅を 10文字 減らす (&M) \t" + setting.menuWidth
    + ( setting.menuWidth < 30 ? "" : " → " + ( setting.menuWidth - 10 ) ), 100012, minWidthFlag );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "  このマクロの JS ファイルを開く (&O)", 100013 );
  subMenu.Add( "  このマクロの JSON ファイルを開く (&J)", 100014 );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "  設定内容を初期化する (&I)", 100015 );
}

/* 関数 SettingsChange( num ) */
// ポップアップメニューで選択した項目の設定状態を変更する
function SettingsChange( num ) {
  var setting = IO.Deserialize( setting, json );
  var sIsChanged = true;
  switch ( num ) {
    case 100001:  case 100002:
      setting.logical = ! setting.logical;
      break;
    case 100003:
      setting.highlightEnable = ! setting.highlightEnable;
      break;
    case 100004:
      setting.timerEnable = ! setting.timerEnable;
      break;
    case 100005:
      setting.autoLineModeEnable = ! setting.autoLineModeEnable;
      break;
    case 100006:
      setting.historyDisable = ! setting.historyDisable;
      break;
    case 100007:
      setting.caseEnable = ! setting.caseEnable;
      break;
    case 100008:
      setting.wholeWordEnable = ! setting.wholeWordEnable;
      break;
    case 100009:
      setting.blankEnable = ! setting.blankEnable;
      break;
    case 100010:
      setting.countEnable = ! setting.countEnable;
      break;
    case 100011:
      setting.menuWidth += 10;
      break;
    case 100012:
      setting.menuWidth -= 10;
      break;
    case 100013:
      sIsChanged = false;
      OpenJumpJS();
      break;
    case 100014:
      sIsChanged = false;
      OpenJumpJson();
      break;
    case 100015:
      sIsChanged = false;
      CheckJsonFile();
      break;
    default:
      sIsChanged = false;
      break;
  }
  if ( sIsChanged ) {
    IO.Serialize( setting, json );
  }
}

/* 関数 OpenJumpJS() */
// このマクロを開いて設定項目の行にジャンプする
function OpenJumpJS() {
  // Count は 1 からの整数値、Item は 0 からの整数値
  var eCount = editors.Count;
  var isOpen = false,  ee ,  dd;
  OuterLoop:
  for ( var j = 0; j < eCount; j ++ ) {
    var dCount = editors.Item( j ).documents.Count;
    for ( var i = 0; i < dCount; i ++ ) {
      if ( editors.Item( j ).documents.Item( i ).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( "setting.settingEnable" );
  js.selection.SetActivePos( settingPos );
  // 狙った行にスクロールしないようなので、強引にやる
  var yy = js.selection.GetActivePointY( mePosLogical );
  new ActiveXObject( "WScript.Shell" ).Run( '"' + editor.FullName + '" /l ' + yy + ' "' + ScriptFullName + '"' );
}

/* 関数 OpenJumpJson() */
// JSON ファイルを開く
function OpenJumpJson() {
  var jsonPath = IO.Path.Add( MeryInfo.GetMacroFolderPath(), "MacroSettings", json + ".json" );
  IO.Serialize( setting, json );
  Sleep( 500 );
  if ( IO.Path.IsExist( jsonPath ) ) {
    var confirmMessage = Confirm( "設定ファイルは正常です\n"
                                  + jsonPath + "\n\n"
                                  + IO.LoadFromFile( jsonPath ).replace( /^\{|\}$/g , "  " )
                                                               .replace( /,/g , ",\n  " )
                                  + "\n\n設定ファイルを開きますか?" );
    if ( confirmMessage ) {
      new ActiveXObject( "WScript.Shell" ).Run( '"' + editor.FullName + '" "' + jsonPath + '"' );
    }
  }
  else {
    Alert( "設定ファイルがありません\n"
           + IO.Path.Add( MeryInfo.GetMacroFolderPath(), "MacroSettings" ) );
  }
}

/* 関数 CheckJsonFile() */
// JSON ファイルの初期化/実在確認
function CheckJsonFile() {
  if ( Confirm( "設定ファイルを初期化しますか?" ) ) {
    var jsonPath = IO.Path.Add( MeryInfo.GetMacroFolderPath(), "MacroSettings", json + ".json" );
    IO.Serialize( initialSettings, json );
    Sleep( 500 );
    Alert(
      IO.Path.IsExist( jsonPath )
          ? "設定ファイルは正常です\n" + jsonPath + "\n\n"
            + IO.LoadFromFile( jsonPath ).replace( /^\{|\}$/g , "  " )
                                         .replace( /,/g , ",\n  " )
          : "設定ファイルがありません\n"
            + IO.Path.Add( MeryInfo.GetMacroFolderPath(), "MacroSettings" )
    );
    Quit();
  }
}


メモ

  • 2018/12/16
新規アップロード
  • 2018/12/17
・ソースコードのミスを修正
・設定用 JSON ファイルをポップアップメニューから初期化し、内容を参照できるようにした
  • 2018/12/20
・ソースコードのミスを修正
・文字列の検索のさいに「選択範囲が何件目のヒットか」を表示
・行番号の表示桁数の制限をなくした(5000行以上のファイルにはあまり適さないとおもう… 処理速度的に)

行の表示方法が「表示座標」のとき、折り返し部分にかかった文字列にはマッチしないままです。
実装すると動作速度が遅くなり、実用に適さなくなってしまいます…

スポンサーリンク