ブックマーク一覧ジャンプ

提供: MeryWiki
2019年4月8日 (月) 21:19時点におけるSukemaru (トーク | 投稿記録)による版 (sukemaru版のソースコードと ZIP を更新)
ナビゲーションに移動 検索に移動

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

goat 版

Mery Ver.1.1.2.2840 および Ver.2.0.9.3936 での動作を確認しています。 (2012.09.24)

 #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;
 })()


sukemaru 版

goat 版のソースコードを元にして、ポップアップメニューを表示するまでの速度をすこしだけ改善しました。


▼ goat 版からの変更点 ▼
  • ソースコード内の設定項目から "表示行" / "論理行" の選択可(初期値は "論理行")
  • 設定項目で "ジャンプ先までの範囲選択" はしない状態を初期値にした
  • ブックマーク行の検索 ~ ポップアップメニューの表示 までの速度を改善
  • ポップアップメニューの体裁を変更(「検索ジャンプ」マクロにあわせた)
  • ステータスバーにブックマーク件数などの情報を表示
  • 「ブックマークがありません」メニュー(先頭行か最終行にジャンプ可)。
  • ジャンプしたときのスクロール位置を調整。

Mery でプログラミング用のフォントを使っている人だと、ポップアップメニュー内で半角 ¥ 記号 (U+005C) がバックスラッシュ (U+005C) にならないのは気落ち悪いかも? ということで、ソースコード内の関数 MenuKey() のコードのコメントアウトしてある行を有効化すると "擬似的に" バックスラッシュ化できます
(※「∖」(U+2216) に置換して表示します)。


ソースコード

ダウンロード:ファイル:ブックマークジャンプ.zip」(アイコン入り) 
最終更新: 2019/04/08


  • このマクロではポップアップメニューの表示に EN SPACE「 」(U+2002) などを使用します。ファイルに保存するさいは、文字コードをシフト JIS にしないでください(UTF-8 や Unicode で保存する)。
#title = "ブックマーク一覧ジャンプ"
#tooltip = "ポップアップメニューでブックマーク行にジャンプ"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",243
// または 244

/**
 * ---------------------------------------------------------
 * 「ブックマーク一覧ジャンプ」
 *   Orginal created by:  goat  (Last update:  2012/09/24)
 *   Modified by:  sukemaru  (2018/08/08 - 2019/04/08)
 * ---------------------------------------------------------
 */

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


// ---------- ▼ 設定項目 ▼ ----------

// ■ ジャンプする前に選択範囲があったときはジャンプ先の行まで範囲選択する?
var flgBlockEnable = false;	// (true; 範囲選択する/false; 範囲選択しない)

// ■ 行の表示方法を Mery.ini から「自動」で読み込むか?
var autoLineModeEnable = false;	// (true; 読み込む /false; 読み込まない)

// ■ 行の表示方法(手動設定)
var $LineColumnView = 0;	// ( 0: 論理行 / 1: 表示行 )

// ■ ポップアップメニューに表示する文字数(全角/半角の区別なし)
var menuWidth = 65;

// ---------- ▲ 設定項目 ▲ ----------


// Mery.ini から「行の表示方法」を取得する( 表示行 = 1 / 論理行 = 0 )
if ( autoLineModeEnable ) {
  lineColumnView = GetIniOptionNum( "LineColumnView" );
}
// 表示行/論理行 の定数
var posMode = lineColumnView ? mePosView : mePosLogical;
var lineMode = lineColumnView ? meGetLineView : 0;

var d = editor.ActiveDocument;
var s = editor.ActiveDocument.selection;
var lines = d.GetLines( lineMode ).toString();	// 全体の行数
var linesWidth = lines.length;			// 全体の行数のケタ数

//カーソル位置の保存
var act = s.GetActivePos();
var anc = s.GetAnchorPos();
var sx = ScrollX,  sy = ScrollY;
var ay = s.GetActivePointY( posMode );
var by;
var flgBlock = ! s.isEmpty;

var lineStr = "";
var menuKey = "";
var bmArray = new Array();	// ブックマーク行の文字列を収納する

Redraw = false;

// 先頭行がブックマークされているか
s.SetActivePos( 1 );
if ( s.PreviousBookmark() ) {
  by = s.GetActivePointY( posMode );
  lineStr = d.GetLine( by, lineMode );	// 文字列を取得
  // メニュー用ラベルを生成して配列に収納する
  bmArray.push( [ MenuKey( lineStr, by ), by ] );
}
// 2行目以降のブックマークを探す
s.SetActivePos( 0 );
while ( s.NextBookmark() ) {
  by = s.GetActivePointY( posMode );
  lineStr = d.GetLine( by, lineMode );	// 文字列を取得
  // メニュー用ラベルを生成して配列に収納する
  bmArray.push( [ MenuKey( lineStr, by ), by ] );
}
// カーソル位置を復帰
s.SetActivePos( act );
s.SetAnchorPos( anc );
ScrollX = sx;
ScrollY = sy;

// ブックマークの件数
var bmCount = bmArray.length;

// 「ブックマークがありません」ポップアップメニュー
if ( ! bmCount ) {
  var statusStr1 = " ブックマークがありません。"
  var statusStr2 = " 全体の行数: " 
                 + lines.replace( /(\d)(?=(?:\d{3})+$)/g , "$1," ) 
                 + ( lineColumnView ? " 行 (表示行)" : " 行 (論理行)" );
  Status = statusStr1 + statusStr2 + TimerElapsed( new Date(), start );

  var menu = CreatePopupMenu();
  menu.Add( "※" + statusStr1 + "& ※", 0 );
  menu.Add( statusStr2 + "& ", 0 );
  menu.Add( "", 0, meMenuSeparator );
  menu.Add( "   先頭行へジャンプ (&S)", 1 );
  menu.Add( "   最終行へジャンプ (&E)", + lines );

  var y = menu.Track( mePosMouse );
  if ( y > 0 ) {
    s.SetActivePoint( posMode, 1, y );
  }
}

// 「ブックマーク一覧」ポップアップメニュー
else {	// if ( bmCount )
  var BookmarkMenu = CreatePopupMenu();

  // メニューの上部に「キャンセル」行をピン止め
  BookmarkMenu.Add( ( "          " ).slice( - linesWidth - 1 )
                  + " キャンセル& ", 0 );
  var flags;
  for ( var i = 0; i < bmCount; i ++ ) {
    // 10行ごとにセパレータ
    if ( i % 10 == 0 ) {
      BookmarkMenu.Add( "", 0, meMenuSeparator );
    }
    // アクティブ行にチェックマークフラグ
    flags = ( bmArray[i][1] == ay ) ? meMenuChecked : 0;
    // ブックマーク行をポップアップメニューに追加
    BookmarkMenu.Add( bmArray[i][0], bmArray[i][1], flags );
  }

  Status = " ブックマーク:" + bmCount
         + " 件  / 全体の行数: " 
         + lines.replace( /(\d)(?=(?:\d{3})+$)/g , "$1," )  
         + ( lineColumnView ? " 行 (表示行)" : " 行 (論理行)" )
         + TimerElapsed( new Date(), start );

  // ポップアップメニューを表示
  var y = BookmarkMenu.Track( mePosMouse );
  // ジャンプ
  if ( y > 0 ) {
    s.SetActivePoint( posMode, 1, y );
    ScrollY = ( ScrollY == sy ) ? sy
                                : s.GetActivePointY( mePosView );

    // ジャンプ前の選択開始位置からジャンプ後の行まで範囲選択
    if ( flgBlockEnable && flgBlock ) {
      s.SetAnchorPos( anc );
      if ( ay < s.GetActivePointY( posMode ) ) {
        s.EndOfLine( true, posMode );
      }
    }
  }
}

Redraw = true;


// ---------- ▼ 関数 ▼ ----------

/**
 * 関数 MenuKey( str, num )
 * ポップアップメニューに表示するラベルを生成する
 * ・行頭空白を除去
 * ・空白文字を圧縮
 * ・削られてしまう「&」を補完
 * ・判別しづらいメタ文字を全角に置換
 * ・文字数を切り詰め
 * ・行番号をケタ埋め:		EN SPACE「 」(U+2002)
 *  ▼ 2019/03/30 追加 ▼
 * ・「\」を「∖」に置換:	「∖」(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().slice( - 1 );
  iniFile.Close();
  return dist;
}
スポンサーリンク