「ブックマーク一覧ジャンプ」の版間の差分

提供: MeryWiki
ナビゲーションに移動 検索に移動
Sukemaru (トーク | 投稿記録)
編集の要約なし
MSY-07 (トーク | 投稿記録)
変数の宣言を追加
 
(2人の利用者による、間の15版が非表示)
1行目: 1行目:
 
== 概要 ==
= goat 版 =
 
ポップアップメニューでジャンプ先を選択。範囲指定中はジャンプ先まで選択範囲を拡大します。
ポップアップメニューでジャンプ先を選択。範囲指定中はジャンプ先まで選択範囲を拡大します。
Mery Ver.1.1.2.2840 および Ver.2.0.9.3936 での動作を確認しています。
(2012.09.24)
<source lang="javascript">
#title="ブックマーク一覧"
/*
* ブックマーク一覧をポップアップメニューにして選択ジャンプ
* Mery標準のブックマークが対象
* 範囲選択中の場合は選択範囲を拡大
*/
(function(){
  // 描画停止
  Redraw = false;
  with(document.selection){
    var flgBlock = !isEmpty;
    //カーソル位置の保存
    var activePos = GetActivePos();
    var anchorPos = GetAnchorPos();
    var sX = ScrollX;
    var sY = ScrollY;
    var bookmarks = new Array();
    StartOfDocument(false);
    // 先頭行がブックマークされてないか
    var isTopMarked = false;
    CharRight(false);
    if(PreviousBookmark()){
      isTopMarked = true;
      SelectLine();
      menuKey = Text.slice(0,24).replace(/\t/g, "\\t");
      Collapse();
      bookmarks.push("Line " + GetActivePointY(mePosLogical) + ":\t" + menuKey);
    } else {
      StartOfDocument(false);
    }
    while(NextBookmark()){
      SelectLine();
      menuKey = Text.slice(0, 24).replace(/\t/g, "\\t");
      Collapse();
      bookmarks.push("Line " + GetActivePointY(mePosLogical) + ":\t" + menuKey);
    }
    var bmcount = bookmarks.length;
    if(bmcount == 0){
      //カーソル位置の復帰
      SetActivePos(activePos);
      SetAnchorPos(anchorPos);
      ScrollX = sX;
      ScrollY = sY;
    } else {
      var BookmarkMenu = CreatePopupMenu();
      for(var i = 0; i < bmcount; i++){
        //メニューのアクセスキーも1から始まるほうが便利
        BookmarkMenu.Add("&" + (i+1) + " " + bookmarks[i], i+1)
      }
      var ret = BookmarkMenu.Track(0);
      if(ret == 0){
        //カーソル位置の復帰
        SetActivePos(activePos);
        SetAnchorPos(anchorPos);
        ScrollX = sX;
        ScrollY = sY;
      } else {
        StartOfDocument(false);
        if(isTopMarked)ret--;
        for(i = 0; i < ret; i++){ NextBookmark(); }
      }
    }
    if(flgBlock){
      //ジャンプ前の選択開始位置からジャンプ後のカーソル位置まで範囲選択
      SetAnchorPos(anchorPos);
    }
  }
  // 描画再開
  Redraw = true;
})()
</source>
== Mery ver 2.7.0 以降への対応 ==
<span style="color:#c00;"> goat 版を '''Mery ver 2.7.0 以降'''で使用する場合は、'''20''' 行目付近を以下のように書き換えてください。</span><br>
変更しない場合、ドキュメントの 1 行目がブックマークされていてもポップアップメニューに表示されなくなります。 (2019/04/16 sukemaru)
; 変更前
18.    var bookmarks = new Array();
19.    <span style="color:#c00;">StartOfDocument(false);</span>
20.    <i style="color:#408080;">// 先頭行がブックマークされてないか</i>
21.    var isTopMarked = false;
22.    <span style="color:#c00;">CharRight(false);</span>
23.    if(PreviousBookmark()){
24.      isTopMarked = true;
; 変更後
18.    var bookmarks = new Array();
19.    <span style="color:#c00;">'''//''' StartOfDocument(false);</span>
20.    <i style="color:#408080;">// 先頭行がブックマークされてないか</i>
21.    var isTopMarked = false;
22.    <b style="color:#c00;">SetActivePoint(mePosLogical, 1, 2);</b>
23.    if(PreviousBookmark()){
24.      isTopMarked = true;
= sukemaru 版 =
goat 版を元にして、ポップアップメニューを表示するまでの速度をすこしだけ改善しました。
;▼ goat 版からの変更点 ▼
* ソースコード内の設定項目から "表示行" / "論理行" の選択可(初期値は "論理行")
* 設定項目で "ジャンプ先までの範囲選択" はしない状態を初期値にした
* ブックマーク行の検索 ~ ポップアップメニューの表示 までの速度を改善
* ポップアップメニューの体裁を変更(「[[ポップアップメニューで検索先にジャンプ#sukemaru_版|検索ジャンプ]]」マクロにあわせた)
* ステータスバーにブックマーク件数などの情報を表示
* 「ブックマークがありません」メニュー(先頭行か最終行にジャンプ可)。
* ジャンプしたときのスクロール位置を調整。
* ジャンプ先まで範囲選択するときの先頭/末尾を調整。
* 「先頭行/最終行 へジャンプ」をメニューにピン止め表示。
Mery でプログラミング用のフォントを使っている人だと、ポップアップメニュー内で半角 '''¥''' 記号 (U+005C) が'''バックスラッシュ''' (U+005C) にならないのは気落ち悪いかも? ということで、ソースコード内の関数 MenuKey() のコードのコメントアウトしてある行を有効化すると "擬似的に" '''バックスラッシュ'''化できます <br> (※「∖」(U+2216) に置換して表示します)。
== ダウンロード ==
'''ダウンロード:''' 「[[ファイル:ブックマークジャンプ.zip]]」(アイコン入り) 
<br> 最終更新: 2019/04/16(Mery 2.7.0 以降への対応と [[#include版|include版]] を追加)


== ソースコード ==
== ソースコード ==
<syntaxhighlight lang="javascript" copy>
#title="ブックマーク一覧"
/*
* ブックマーク一覧をポップアップメニューにして選択ジャンプ
* Mery標準のブックマークが対象
* 範囲選択中の場合は選択範囲を拡大
*/
(function(){
// 描画停止
Redraw = false;
var sel = document.selection;
var flgBlock = !sel.IsEmpty;
//カーソル位置の保存
var activePos = sel.GetActivePos();
var anchorPos = sel.GetAnchorPos();
var sX = ScrollX;
var sY = ScrollY;


* このマクロではポップアップメニューの表示に EN SPACE「 」(U+2002) などを使用します。ファイルに保存するさいは、文字コードをシフト JIS にしないでください('''UTF-8''' や Unicode で保存する)。
var bookmarks = [];
<source lang="javascript" style="height:60em; overflow:auto;">
var menuKey = "";
#title = "ブックマーク一覧ジャンプ"
// 先頭行がブックマークされてないか
#tooltip = "ポップアップメニューでブックマーク行にジャンプ"
var isTopMarked = false;
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",243
sel.SetActivePoint(mePosLogical, 1, 2);
// または 244
if(sel.PreviousBookmark()){
 
isTopMarked = true;
/* ---------------------------------------------------------
sel.SelectLine();
* 「ブックマーク一覧ジャンプ」
menuKey = sel.Text.slice(0,24).replace(/\t/g, "\\t");
*  Orginal created by:  goat (Last update:  2012/09/24)
sel.Collapse();
*  Modified by: sukemaru (2018/08/08 - 2019/04/16)
bookmarks.push("Line " + sel.GetActivePointY(mePosLogical) + ":\t" + menuKey);
* --------------------------------------------------------- */
} else {
 
sel.StartOfDocument(false);
var start = new Date(); // 所要時間計測(開始)
}
 
while(sel.NextBookmark()){
// ---------- ▼ 設定項目 ▼ ----------
sel.SelectLine();
 
menuKey = sel.Text.slice(0, 24).replace(/\t/g, "\\t");
// ■ ジャンプする前に選択範囲があったときはジャンプ先の行まで範囲選択する?
sel.Collapse();
var flgBlockEnable = false; // (true 範囲選択する / false 範囲選択しない)
bookmarks.push("Line " + sel.GetActivePointY(mePosLogical) + ":\t" + menuKey);
 
}
  // ■ 下の行にジャンプしたとき、ジャンプ先の行全体(論理行)を選択範囲に含める?
var bmcount = bookmarks.length;
  var endOfBookmarkLine = false; // (true 含める / false 含めない)
if(bmcount == 0){
 
//カーソル位置の復帰
// ■ 行の表示方法を Mery.ini から「自動」で読み込むか?
sel.SetActivePos(activePos);
var autoLineModeEnable = false; // (true 読み込む / false 読み込まない)
sel.SetAnchorPos(anchorPos);
 
ScrollX = sX;
  // ■ 行の表示方法(手動設定用)
ScrollY = sY;
  var lineColumnView = 0; // ( 0 論理行 / 1 表示行 )
} else {
 
var BookmarkMenu = CreatePopupMenu();
// ■ 「ブックマークがありません」メニューを表示する?
for(var i = 0; i < bmcount; i++){
var extraMenuEnable = true; // (true する / false しない)
//メニューのアクセスキーも1から始まるほうが便利
 
BookmarkMenu.Add("&" + (i+1) + " " + bookmarks[i], i+1);
// ■ ポップアップメニューに「先頭行/最終行 へジャンプ」をピン止め表示する?
}
var menuPinEnable = true; // (true する / false しない)
var ret = BookmarkMenu.Track(0);
 
if(ret == 0){
// ■ ポップアップメニューに表示する文字数
//カーソル位置の復帰
var menuWidth = 65; // (全角/半角の区別なし)
sel.SetActivePos(activePos);
 
sel.SetAnchorPos(anchorPos);
// ---------- ▲ 設定項目 ▲ ----------
ScrollX = sX;
 
ScrollY = sY;
 
} else {
// Mery.ini から「行の表示方法」を取得する( 表示行 = 1 / 論理行 = 0
sel.StartOfDocument(false);
if ( autoLineModeEnable ) {
if(isTopMarked){
  lineColumnView = GetIniOptionNum( "LineColumnView" );
ret--;
}
}
// 表示行/論理行 の定数
for(i = 0; i < ret; i++){
var posMode = lineColumnView ? mePosView : mePosLogical;
sel.NextBookmark();
var lineMode = lineColumnView ? meGetLineView : 0;
}
// 全体の行数
}
var d = editor.ActiveDocument;
}
var lines = d.GetLines( lineMode );
if(flgBlock){
var linesWidth = lines.toString().length;
//ジャンプ前の選択開始位置からジャンプ後のカーソル位置まで範囲選択
// カーソルと選択範囲の位置を保存
sel.SetAnchorPos(anchorPos);
var s = editor.ActiveDocument.selection;
}
var aY = s.GetActivePointY( posMode );
// 描画再開
var act = s.GetActivePos();
Redraw = true;
var anc = s.GetAnchorPos();
})();
var sX = ScrollX,  sY = ScrollY;
</syntaxhighlight>
// ブックマーク行の変数
var bmY;
var bmStr;
var bmArray = [];
 
// ブックマーク行を検索
Redraw = false;
s.SetActivePoint( mePosLogical, 1, 2 );
if ( s.PreviousBookmark() ) {
  bmY = s.GetActivePointY( posMode );
  bmStr = d.GetLine( bmY, lineMode );
  bmArray.push( [ MenuKey( bmStr, bmY ), bmY ] );
}
s.SetActivePos( 0 );
while ( s.NextBookmark() ) {
  bmY = s.GetActivePointY( posMode );
  bmStr = d.GetLine( bmY, lineMode );
  bmArray.push( [ MenuKey( bmStr, bmY ), bmY ] );
}
// ブックマークの件数
var bmCount = bmArray.length;
 
// カーソル位置と選択範囲を復帰
s.SetActivePos( act );
s.SetAnchorPos( anc );
ScrollX = sX,  ScrollY = sY;
 
// ポップアップメニューの準備
var bmMenu = CreatePopupMenu();
var Check = function( num ) {
  return num == aY ? meMenuChecked : 0;
}
if ( bmCount ) {
  var cancelPin = ( "          " ).slice( - linesWidth )
                + "  キャンセル\t& ";
}
if ( menuPinEnable ) {
  var topPin = ( "          " + 1 ).slice( - linesWidth )
            + ":  ** 先頭行へジャンプ (&T) **";
  var endPin = ( "          " + lines ).slice( - linesWidth )
            + ":  ** 最終行へジャンプ (&E) **";
  var actPin = ( "          " + aY ).slice( - linesWidth )
            + ":     行頭へジャンプ (&A)";
}
// ステータスラベル
var bmStatus1 = bmCount
              ? " ブックマーク: " + bmCount + " 件 /"
              : " ブックマークがありません。";
var bmStatus2 = " 全体の行数: "
              + lines.toString()
                    .replace( /(\d)(?=(?:\d{3})+$)/g, "$1," )
              + ( lineColumnView ? " 行 (表示行)"
                                : " 行 (論理行)" );
 
// 「ブックマーク一覧」ポップアップメニュー
if ( bmCount ) {
  bmMenu.Add( cancelPin, 0 );
  if ( menuPinEnable && bmArray[0][1] > 1 ) {
    bmMenu.Add( "", 0, meMenuSeparator );
    bmMenu.Add( topPin, 1, Check( 1 ) );
  }
  for ( var i = 0, flags; i < bmCount; i ++ ) {
    if ( i % 10 == 0 ) {
      bmMenu.Add( "", 0, meMenuSeparator );
    }
    bmMenu.Add( bmArray[i][0], bmArray[i][1], Check( bmArray[i][1] ) );
  }
  if ( menuPinEnable && bmArray[ bmCount - 1 ][1] !== lines ) {
    bmMenu.Add( "", 0, meMenuSeparator );
    bmMenu.Add( endPin, lines, Check( lines ) );
  }
}
// 「ブックマークがありません」ポップアップメニュー
else if ( extraMenuEnable ) {
  bmMenu.Add( "※" + bmStatus1 + "& ※", 0 );
  if ( ! menuPinEnable ) {
    bmMenu.Add( bmStatus2 + "& ", 0 );
  }
  else if ( lines > 1 ) {
    bmMenu.Add( "", 0, meMenuSeparator );
    bmMenu.Add( topPin, 1, Check( 1 ) );
    bmMenu.Add( endPin, lines, Check( lines ) );
  }
  else if ( lines == 1 ) {
    bmMenu.Add( actPin, aY, meMenuChecked );
  }
}
// ステータスバーとポップアップメニューを表示
Status = bmStatus1 + bmStatus2
      + TimerElapsed( new Date(), start );
var y = bmMenu.Track( mePosMouse );
 
// ジャンプ
if ( y > 0 ) {
  if ( y == aY ) {
    s.StartOfDocument();
    s.EndOfDocument();
  }
  s.SetActivePoint( posMode, 1, y );
 
  // ジャンプ前の選択範囲からジャンプ先の行まで範囲選択
  if ( flgBlockEnable && act !== anc ) {
    var tp = ( anc < act ) ? anc : act;
    var bp = ( anc < act ) ? act : anc;
    var jumpDown = ( aY < y );
    s.SetAnchorPos( jumpDown ? tp : bp );
    if ( jumpDown && endOfBookmarkLine ) {
      s.EndOfLine( true, mePosLogical );
      ScrollX = 1;
    }
  }
  ScrollY = ( ScrollY == sY )
          ? sY : s.GetActivePointY( mePosView );
}
Redraw = true;
 
// ---------- ▼ 関数 ▼ ----------
 
/**
* 関数 MenuKey( str, num )
* ポップアップメニューに表示するラベルを生成する
*
* ・行頭空白を除去
* ・空白文字を圧縮
* ・削られてしまう「&」を補完
* ・判別しづらいメタ文字を全角に置換
* ・文字数を切り詰め
* ・行番号をケタ埋め: EN SPACE「 」(U+2002)
*  ▼ 2019/03/30 追加 ▼
* ・「¥」(U+005C) を「∖」に置換:「∖」(U+2216) または「╲」(U+2572) 「﹨」(U+FE68)
* ・「a-z」を全角に置換
*/
function MenuKey( str, num ) {
  var menuKey = str.replace( /^[\t  ]+/, "" )
                  .replace( /(?:\t|[ ]{3,}|[ ]{2,})+/g, " › " )
                  .replace( /&/g, "&&" )
                // .replace( /[\\]/g, "∖" )
                // .replace( /([^∖!"',.:;`|\t  ])([∖]+)/g, "$1 $2" )
                  .replace( /[!"%'(),.:;@\[\]`a-z{|}]/g,
                    function( $0 ) {
                      return String.fromCharCode( $0.charCodeAt( 0 ) + 0xFEE0 )
                    } );
  menuKey = ( menuKey.length > menuWidth )
          ? menuKey.slice( 0, menuWidth ) + " ..."
          : menuKey;
  return ( "          &" + num ).slice( - linesWidth - 1 ) + ":  " + menuKey;
}
 
/**
* 関数 TimerElapsed( end, start )
* start からの経過時間計測
* [ s.sss 秒 ] で返す
*/
function TimerElapsed( end, start ) {
  var elapsed = ( end - start ) / 1000;
  return " [ "
        + ( elapsed + "000" ).replace( /(\.)(\d{3})(0*)/, "$1 $2" )
        + " 秒 ]";
}
 
/**
* 関数 GetIniOptionNum( key )
* 引数で指定された設定項目の「値」を返す(※数値1ケタ)
*/
function GetIniOptionNum( key ) {
  var regIniKey = new RegExp( "^" + key + "=\\d+$", "m" );
  var Fso = new ActiveXObject( "Scripting.FileSystemObject" );
  // Mery.ini を探す
  var iniPath = editor.FullName.replace( /\.exe$/i, ".ini" );
  if ( ! Fso.FileExists( iniPath ) ) {
    var WshShell = new ActiveXObject( "WScript.Shell" );
    iniPath = WshShell.ExpandEnvironmentStrings( "%APPDATA%" )
            + "\\Mery\\Mery.ini";
  }
  // Mery.ini を読み込む
  var iniFile = Fso.OpenTextFile( iniPath, 1 );
  var iniText = iniFile.ReadAll();
  iniFile.Close();
  // 項目の値を取得する
  var dist = + iniText.match( regIniKey )
                      .shift()
                      .replace( /^.+=(\d+)$/, "$1" );
  return dist;
}
</source>
 
 
== include版 ==
 
[[ダウンロード|ZIP 書庫]]内の「'''include版'''」フォルダの JS ファイルを使用すると、「[[ポップアップメニューで検索先にジャンプ#include版|ポップアップメニューで検索先にジャンプ]]」マクロと同様に、<span style="color:#c00;">マクロの動作設定の変更をポップアップメニュー内の項目のチェック ON/OFF でできるようになります。 </span><br>
[[includeライブラリ]] を使用し、設定内容は外部ファイルに保存します(◆settingEnable 変数で設定。デフォルト: 有効)。<br>
 
<div id="注1" class="warningbox">
* あらかじめ [[includeライブラリ]] をインストールしてください。
* 設定内容の保存場所は '''Mery\Macros\MacroSettings\<ブックマーク一覧ジャンプ>.json''' <br> または '''%AppData%\Mery\MacroSettings\<ジャンプ>.jso'''n です。<br> (※ <ブックマーク一覧ジャンプ> の部分はこのマクロのファイル名)
</div>
 
* 「▼ 通常版 設定項目 ▼」以降の設定項目は『初期値』としてのみ利用され、ソースコード内の設定項目を直接書き換えする必要はありません。<br> ただし、settingEnable 変数を完全に無効にする場合は、ソースコード内で変更する必要があります。<br> → settingEnable を無効にした場合は「通常版」と同じ状態になり、「設定変更」サブメニューがひょうじされなくなります。
 
 
<source lang="javascript" style="height:60em; overflow:auto;">
#title = "ブックマーク一覧ジャンプ"
#tooltip = "ポップアップメニューでブックマーク行にジャンプ"
#icon = "bookmark_list.ico"
#include "include/IO.js"
#include "include/MeryInfo.js"
// ▲ includeライブラリを導入していない場合は #include の2行をコメントアウトすること▲
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",243
 
/**
* ---------------------------------------------------------
* 「ブックマーク一覧ジャンプ」
*  Orginal created by:  goat  (Last update:  2012/09/24)
*  Modified by:  sukemaru    (2018/08/08 - 2019/04/15)
*  【include版】              (2019/04/15 - )
* ---------------------------------------------------------
* 【include版】
* ・「設定変更」サブメニューを表示
* ・ 設定内容を外部ファイル(JSON)に保存
*/
 
var start = new Date(); // 所要時間計測(開始)
 
// ---------- ▼ 【include版】 初期設定項目 ▼ ----------
 
// ◆ 「設定変更」サブメニューを表示するか?
//(includeライブラリを導入していない場合は false にすること)
var settingEnable = true; // (true する / false しない)
 
// ◆ JSON ファイルのベース名
var jsonName = ScriptName.replace( /\.js$/i, "" ); // 既定値
 
// 任意の名前に変更する場合はアンコメントして書き換える
// jsonName = "ブックマーク一覧ジャンプ";
 
// ---------- ▼ 通常版 設定項目 ▼ ----------
 
// 【include版】ではポップアップメニューから変更すること
var flgBlockEnable = false;
var endOfBookmarkLine = false;
var autoLineModeEnable = false;
var lineColumnView = 0;
var extraMenuEnable = true;
var menuPinEnable = true;
var menuWidth = 65;
 
// ---------- ▲ 設定項目 ▲ ----------
 
 
/* ▼ 【include版】の追加コード ▼ */
var initialSettings = { settingEnable: false };
if ( settingEnable ) {
  // ソースコードの「設定項目」内の初期値を保存する
  var setting = {
    settingEnable: settingEnable,
    flgBlockEnable: flgBlockEnable,
    endOfBookmarkLine: endOfBookmarkLine,
    extraMenuEnable: extraMenuEnable,
    menuPinEnable: menuPinEnable,
    autoLineModeEnable: autoLineModeEnable,
    lineColumnView: lineColumnView,
    menuWidth: menuWidth
  };
  // 「設定変更」メニューの表示許可や JSON の初期化に使用する初期設定
  initialSettings = setting;
  // JSON ファイルから設定を読み込む
  jsonName = jsonName || ScriptName.replace( /\.js$/i, "" );
  setting = IO.Deserialize( setting, jsonName );
  // 通常版の設定変数に再代入
  settingEnable = setting.settingEnable;
  flgBlockEnable = setting.flgBlockEnable;
  endOfBookmarkLine = setting.endOfBookmarkLine;
  extraMenuEnable = setting.extraMenuEnable;
  menuPinEnable = setting.menuPinEnable;
  autoLineModeEnable = setting.autoLineModeEnable;
  lineColumnView = setting.lineColumnView;
  menuWidth = setting.menuWidth;
}
/* ▲ 【include版】の追加コード ▲ */
 
// Mery.ini から「行の表示方法」を取得する( 表示行 = 1 / 論理行 = 0 )
if ( autoLineModeEnable ) {
  lineColumnView = GetIniOptionNum( "LineColumnView" );
}
// 表示行/論理行 の定数
var posMode = lineColumnView ? mePosView : mePosLogical;
var lineMode = lineColumnView ? meGetLineView : 0;
// 全体の行数
var d = editor.ActiveDocument;
var lines = d.GetLines( lineMode );
var linesWidth = lines.toString().length;
// カーソルと選択範囲の位置を保存
var s = editor.ActiveDocument.selection;
var aY = s.GetActivePointY( posMode );
var act = s.GetActivePos();
var anc = s.GetAnchorPos();
var sX = ScrollX,  sY = ScrollY;
var isBookmarked = false;
// ブックマーク行の変数
var bmY;
var bmStr;
var bmArray = [];
 
// ブックマーク行を検索
Redraw = false;
// アクティブ行がブックマークされているか
s.SetActivePoint( mePosLogical, 1, aY + 1 );
if ( s.PreviousBookmark()
    && s.GetActivePointY( posMode ) == aY ) {
  isBookmarked = true;
}
// 先頭行がブックマークされているか
s.SetActivePoint( mePosLogical, 1, 2 );
if ( s.PreviousBookmark() ) {
  bmY = s.GetActivePointY( posMode );
  bmStr = d.GetLine( bmY, lineMode );
  bmArray.push( [ MenuKey( bmStr, bmY ), bmY ] );
}
// 2行目以降のブックマークを探す
s.SetActivePos( 0 );
while ( s.NextBookmark() ) {
  bmY = s.GetActivePointY( posMode );
  bmStr = d.GetLine( bmY, lineMode );
  bmArray.push( [ MenuKey( bmStr, bmY ), bmY ] );
}
// ブックマークの件数
var bmCount = bmArray.length;
 
// カーソル位置と選択範囲を復帰
s.SetActivePos( act );
s.SetAnchorPos( anc );
ScrollX = sX,  ScrollY = sY;
 
// ポップアップメニューの準備
var bmMenu = CreatePopupMenu();
var Check = function( num ) {
  return num == aY ? meMenuChecked : 0;
}
if ( bmCount ) {
  var cancelPin = ( "          " ).slice( - linesWidth )
                + "  キャンセル\t& ";
}
if ( menuPinEnable ) {
  var topPin = ( "          " + 1 ).slice( - linesWidth )
            + ":  ** 先頭行へジャンプ (&T) **";
  var endPin = ( "          " + lines ).slice( - linesWidth )
            + ":  ** 最終行へジャンプ (&E) **";
  var actPin = ( "          " + aY ).slice( - linesWidth )
            + ":     行頭へジャンプ (&A)";
}
// ステータスラベル
var bmStatus1 = bmCount
              ? " ブックマーク: " + bmCount + " 件 /"
              : " ブックマークがありません。";
var bmStatus2 = " 全体の行数: "
              + lines.toString()
                    .replace( /(\d)(?=(?:\d{3})+$)/g, "$1," )
              + ( lineColumnView ? " 行 (表示行)"
                                : " 行 (論理行)" );
 
/* 【include版】の設定変更サブメニュー */
if ( initialSettings.settingEnable
    && ( bmCount || extraMenuEnable ) ) {
  SettingsMenu( bmMenu );
}
 
// 「ブックマーク一覧」ポップアップメニュー
if ( bmCount ) {
  bmMenu.Add( cancelPin, 0 );
  if ( menuPinEnable && ( bmArray[0][1] > 1
      || ! isBookmarked && aY > 1 && aY < lines ) ) {
    bmMenu.Add( "", 0, meMenuSeparator );
    if ( bmArray[0][1] > 1 ) {
      bmMenu.Add( topPin, 1, Check( 1 ) );
    }
    if ( ! isBookmarked && aY > 1 && aY < lines ) {
      bmMenu.Add( actPin, aY, meMenuChecked );
    }
  }
  for ( var i = 0, flags; i < bmCount; i ++ ) {
    if ( i % 10 == 0 ) {
      bmMenu.Add( "", 0, meMenuSeparator );
    }
    bmMenu.Add( bmArray[i][0], bmArray[i][1], Check( bmArray[i][1] ) );
  }
  if ( menuPinEnable && bmArray[ bmCount - 1 ][1] !== lines ) {
    bmMenu.Add( "", 0, meMenuSeparator );
    bmMenu.Add( endPin, lines, Check( lines ) );
  }
}
// 「ブックマークがありません」ポップアップメニュー
else if ( extraMenuEnable ) {
  bmMenu.Add( "※" + bmStatus1 + " ※\t& ", 0 );
  if ( ! menuPinEnable ) {
    bmMenu.Add( bmStatus2, 0 );
  }
  if ( menuPinEnable && lines > 1 ) {
    bmMenu.Add( "", 0, meMenuSeparator );
    bmMenu.Add( topPin, 1, Check( 1 ) );
    if ( aY > 1 && aY < lines ) {
      bmMenu.Add( actPin, aY, meMenuChecked );
    }
    bmMenu.Add( endPin, lines, Check( lines ) );
  }
  else if ( menuPinEnable && lines == 1 ) {
    bmMenu.Add( actPin, aY, meMenuChecked );
  }
}
 
// ステータスバーとポップアップメニューを表示
Status = bmStatus1 + bmStatus2
      + TimerElapsed( new Date(), start );
var y = bmMenu.Track( mePosMouse );
 
/* 【include版】の設定変更サブメニュー項目を選択した場合 */
if ( y >= 10000000 ) {
  SettingsChange( y );
}
 
// ジャンプ
else if ( y > 0 ) {
  if ( y == aY ) {
    s.StartOfDocument();
    s.EndOfDocument();
  }
  s.SetActivePoint( posMode, 1, y );
 
  // ジャンプ前の選択範囲からジャンプ先の行まで範囲選択
  if ( flgBlockEnable && act !== anc ) {
    var tp = ( anc < act ) ? anc : act;
    var bp = ( anc < act ) ? act : anc;
    var jumpDown = ( aY < y );
    s.SetAnchorPos( jumpDown ? tp : bp );
    if ( jumpDown && endOfBookmarkLine ) {
      s.EndOfLine( true, mePosLogical );
      ScrollX = 1;
    }
  }
  ScrollY = ( ScrollY == sY )
          ? sY : s.GetActivePointY( mePosView );
}
Redraw = true;
 
// ---------- ▼ 関数 ▼ ----------
 
/**
* 関数 MenuKey( str, num )
* ポップアップメニューに表示するラベルを生成する
*
* ・行頭空白を除去
* ・空白文字を圧縮
* ・削られてしまう「&」を補完
* ・判別しづらいメタ文字を全角に置換
* ・文字数を切り詰め
* ・行番号をケタ埋め: EN SPACE「 」(U+2002)
* ・「¥」(U+005C) を「∖」に置換:「∖」(U+2216) または「╲」(U+2572) 「﹨」(U+FE68)
* ・「a-z」を全角に置換
*/
function MenuKey( str, num ) {
  var menuKey = str.replace( /^[\t  ]+/, "" )
                  .replace( /(?:\t|[ ]{3,}|[ ]{2,})+/g, " › " )
                  .replace( /&/g, "&&" )
                // .replace( /[\\]/g, "∖" )
                // .replace( /([^∖!"',.:;`|\t  ])([∖]+)/g, "$1 $2" )
                  .replace( /[!"%'(),.:;@\[\]`a-z{|}]/g,
                    function( $0 ) {
                      return String.fromCharCode( $0.charCodeAt( 0 ) + 0xFEE0 )
                    } );
  menuKey = ( menuKey.length > menuWidth )
          ? menuKey.slice( 0, menuWidth ) + " ..."
          : menuKey;
  return ( "          &" + num ).slice( - linesWidth - 1 ) + ":  " + menuKey;
}
 
/**
* 関数 TimerElapsed( end, start )
* start からの経過時間計測
* [ s.sss 秒 ] で返す
*/
function TimerElapsed( end, start ) {
  var elapsed = ( end - start ) / 1000;
  return " [ "
        + ( elapsed + "000" ).replace( /(\.)(\d{3})(0*)/, "$1 $2" )
        + " 秒 ]";
}
 
/**
* 関数 GetIniOptionNum( key )
* 引数で指定された設定項目の「値」を返す(※数値1ケタ)
*/
function GetIniOptionNum( key ) {
  var regIniKey = new RegExp( "^" + key + "=\\d+$", "m" );
  var Fso = new ActiveXObject( "Scripting.FileSystemObject" );
  // Mery.ini を探す
  var iniPath = editor.FullName.replace( /\.exe$/i, ".ini" );
  if ( ! Fso.FileExists( iniPath ) ) {
    var WshShell = new ActiveXObject( "WScript.Shell" );
    iniPath = WshShell.ExpandEnvironmentStrings( "%APPDATA%" )
            + "\\Mery\\Mery.ini";
  }
  // Mery.ini を読み込む
  var iniFile = Fso.OpenTextFile( iniPath, 1 );
  var iniText = iniFile.ReadAll();
  iniFile.Close();
  // 項目の値を取得する
  var dist = + iniText.match( regIniKey )
                      .shift()
                      .replace( /^.+=(\d+)$/, "$1" );
  return dist;
}
 
// ---------- ▼ 【include版】 関数 ▼ ----------
 
/**
* 関数 SettingsMenu( objPopupMenu )
* ポップアップメニューに「設定変更」サブメニューを表示する
* 引数: メインコードのポップアップメニューオブジェクト
*/
function SettingsMenu( objMenu ) {
  var subMenu = CreatePopupMenu();
  var menuIndent = ( "          " ).slice( - linesWidth );
  // メニューのオプションフラグ
  var settingFlag = settingEnable ? 0 : meMenuChecked;
  var grayFlag = ! settingEnable ? meMenuGrayed : 0;
  var flgBlockFlag = flgBlockEnable ? meMenuChecked : 0;
  var grayFlag_1 = ( ! flgBlockEnable || ! settingEnable )
                ?  meMenuGrayed : 0;
  var endOfBookmarkLineFlag = ( endOfBookmarkLine && flgBlockEnable )
                            ? meMenuChecked : 0;
  var extraMenuFlag = extraMenuEnable ? meMenuChecked : 0;
  var menuPinFlag = menuPinEnable ? meMenuChecked : 0;
  var autoLineModeFlag = autoLineModeEnable ? meMenuChecked : 0;
  var grayFlag_2 = ( autoLineModeEnable || ! settingEnable )
                ?  meMenuGrayed : 0;
  var viewFlag = lineColumnView ? meMenuChecked : 0;
  var logicalFlag = lineColumnView ? 0 : meMenuChecked;
  var maxWidthFlag = menuWidth > 100 ? meMenuGrayed : 0;
  var minWidthFlag = menuWidth < 30 ? meMenuGrayed : 0;
 
  // 「設定変更」サブメニューのアイテム
  // objMenu.Add( "", 0, meMenuSeparator );
  objMenu.AddPopup( menuIndent + "  設定を変更する (&S)", subMenu );
  objMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "  ジャンプ先の行まで 範囲選択する (&B)",
              10000001, flgBlockFlag + grayFlag );
  subMenu.Add( "  下の行にジャンプしたときに 行全体を選択 (&D)",
              10000002, endOfBookmarkLineFlag + grayFlag_1 );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "  ブックマークがなくても メニューを表示する (&N)",
              10000003, extraMenuFlag + grayFlag );
  subMenu.Add( "「先頭行/最終行/行頭 へジャンプ」を表示 (&P)",
              10000004, menuPinFlag + grayFlag );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "「行の表示方法」 を自動設定する (&A)",
              10000005, autoLineModeFlag + grayFlag );
  subMenu.Add( "  行数を 「論理行」 で表示する (&L)",
              10000006, logicalFlag + grayFlag_2 );
  subMenu.Add( "  行数を 「表示行」 で表示する (&V)",
              10000007, viewFlag + grayFlag_2 );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "  メニューの表示幅を 10文字 増やす (&+)\t"
            + menuWidth
            + ( menuWidth > 100 ? "" : " → " + ( menuWidth + 10 ) ),
              10000008, maxWidthFlag + grayFlag );
  subMenu.Add( "  メニューの表示幅を 10文字 減らす (&-)\t"
            + menuWidth
            + ( menuWidth < 30 ? "" : " → " + ( menuWidth - 10 ) ),
              10000009, minWidthFlag + grayFlag );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "  設定内容をロックする (&S)", 10000000, settingFlag );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "「ジャンプ」マクロの JS ファイルを開く (&O)", 10000013 );
  subMenu.Add( "「ジャンプ」マクロの JSON ファイルを開く (&J)", 10000014 );
  subMenu.Add( "", 0, meMenuSeparator );
  subMenu.Add( "  設定内容を初期化する (&I)", 10000015, grayFlag );
  subMenu.Add( "  キャンセル\t& ", 0 );
}
 
/**
* 関数 SettingsChange( num )
* ポップアップメニューで選択した項目の設定状態を変更する
*/
function SettingsChange( num ) {
  var setting = IO.Deserialize( setting, jsonName );
  var sIsChanged = true;
  switch ( num ) {
    case 10000000:
      setting.settingEnable = ! settingEnable;
      break;
    case 10000001:
      setting.flgBlockEnable = ! flgBlockEnable;
      break;
    case 10000002:
      setting.endOfBookmarkLine = ! endOfBookmarkLine;
      break;
    case 10000003:
      setting.extraMenuEnable = ! extraMenuEnable;
      break;
    case 10000004:
      setting.menuPinEnable = ! menuPinEnable;
      break;
    case 10000005:
      setting.autoLineModeEnable = ! autoLineModeEnable;
      break;
    case 10000006:
    case 10000007:
      setting.lineColumnView = ! lineColumnView;
      break;
    case 10000008:
      setting.menuWidth += 10;
      break;
    case 10000009:
      setting.menuWidth -= 10;
      break;
    case 10000013:
      sIsChanged = false;
      Status = " " + ScriptFullName;
      OpenJumpJS( "var settingEnable = " );
      break;
    case 10000014:
      sIsChanged = false;
      OpenJumpJson( jsonName );
      break;
    case 10000015:
      sIsChanged = false;
      CheckJsonFile( jsonName );
      break;
    default:
      sIsChanged = false;
      break;
  }
  if ( sIsChanged ) {
    IO.Serialize( setting, jsonName );
    Status = "  設定の変更を保存しました。";
  }
}
 
/**
* 関数 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() {
  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;
}
</source>

2025年11月25日 (火) 16:53時点における最新版

概要[編集]

ポップアップメニューでジャンプ先を選択。範囲指定中はジャンプ先まで選択範囲を拡大します。

ソースコード[編集]

#title="ブックマーク一覧"
/*
* ブックマーク一覧をポップアップメニューにして選択ジャンプ
* Mery標準のブックマークが対象
* 範囲選択中の場合は選択範囲を拡大
*/
(function(){
	// 描画停止
	Redraw = false;
	var sel = document.selection;
	var flgBlock = !sel.IsEmpty;
	//カーソル位置の保存
	var activePos = sel.GetActivePos();
	var anchorPos = sel.GetAnchorPos();
	var sX = ScrollX;
	var sY = ScrollY;

	var bookmarks = [];
	var menuKey = "";
	// 先頭行がブックマークされてないか
	var isTopMarked = false;
	sel.SetActivePoint(mePosLogical, 1, 2);
	if(sel.PreviousBookmark()){
		isTopMarked = true;
		sel.SelectLine();
		menuKey = sel.Text.slice(0,24).replace(/\t/g, "\\t");
		sel.Collapse();
		bookmarks.push("Line " + sel.GetActivePointY(mePosLogical) + ":\t" + menuKey);
	} else {
		sel.StartOfDocument(false);
	}
	while(sel.NextBookmark()){
		sel.SelectLine();
		menuKey = sel.Text.slice(0, 24).replace(/\t/g, "\\t");
		sel.Collapse();
		bookmarks.push("Line " + sel.GetActivePointY(mePosLogical) + ":\t" + menuKey);
	}
	var bmcount = bookmarks.length;
	if(bmcount == 0){
		//カーソル位置の復帰
		sel.SetActivePos(activePos);
		sel.SetAnchorPos(anchorPos);
		ScrollX = sX;
		ScrollY = sY;
	} else {
		var BookmarkMenu = CreatePopupMenu();
		for(var i = 0; i < bmcount; i++){
			//メニューのアクセスキーも1から始まるほうが便利
			BookmarkMenu.Add("&" + (i+1) + " " + bookmarks[i], i+1);
		}
		var ret = BookmarkMenu.Track(0);
		if(ret == 0){
			//カーソル位置の復帰
			sel.SetActivePos(activePos);
			sel.SetAnchorPos(anchorPos);
			ScrollX = sX;
			ScrollY = sY;
		} else {
			sel.StartOfDocument(false);
			if(isTopMarked){
				ret--;
			}
			for(i = 0; i < ret; i++){
				sel.NextBookmark();
			}
		}
	}
	if(flgBlock){
		//ジャンプ前の選択開始位置からジャンプ後のカーソル位置まで範囲選択
		sel.SetAnchorPos(anchorPos);
	}
	// 描画再開
	Redraw = true;
})();
スポンサーリンク