さいごに閉じたファイルを開く

提供: MeryWiki
移動先: 案内検索

「さいごに閉じたファイル」ポップアップメニュー[編集]

ファイルメニュー では「最近開いたファイルの履歴」が表示されますが、タブをたくさん並べているときには「現在開いているファイル」ばかりが表示されがちです。

このマクロでは、Mery.ini ファイルに記録されている「最近開いたファイルの履歴」ではなく、 Mery.his ファイルに記録されている履歴情報を読み込み、「現在開いているファイル」を除いて、さいごに閉じた順にファイルを表示します。

  • 表示する件数は、ソースコード内の設定変数 volume = n (初期値 5)で変更できます。
  • ファイルの実在確認の処理を入れてあるので、削除・移動・リネームされたファイルは表示されません。
  • Mery の「オプション」設定の「履歴」グループで「カーソル位置とブックマークを保存する」が無効の場合は、Mery.his ファイルを参照できないので、ポップアップメニューが表示されません。
  • Mery 本体(エディタエンジン)の仕様上、「閉じたときのキャレット位置が文書の先頭」×「ブックマークなし」×「横書き表示」で閉じたファイルは、Mery を終了したときに Mery.his から記録が削除されます。履歴に残したいファイルを閉じるさいは、キャレットの位置を文頭からズラすか、任意の行にブックマークをつけておくようにしてください。
  • 通常の操作でタブを閉じず、「すべて閉じる」マクロなどでタブを閉じた場合、Mery.his ファイルの並び順が「保存された順 または 閉じた順」にならないことがあるので、このマクロで取得できる履歴の順番の正確さについては保証できません。


  • 「さいごに閉じたファイル」ポップアップメニューは、別のポップアップメニューマクロ「ファイルを読み直す・開きなおす」に組みこんである機能を独立させたものです。

ダウンロード[編集]

ファイル:さいごに閉じたファイル.zip」(アイコン入り)

ソースコード[編集]

#title = "さいごに閉じたファイル"
#tooltip = "「さいごに閉じたファイル」をポップアップメニューから開く"
// #icon = "restore[3].ico"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",8
var start = new Date();	// 所要時間計測(開始)

/**
 * 最近閉じたファイルで現在開かれていないものをポップアップメニューに表示する
 * 
 * Mery の「オプション」設定で「カーソル位置とブックマークを保存する」が無効なら
 * ポップアップメニューを表示しない(Mery.his がない)。
 * Mery.his を下から順にチェックするだけなので、マクロなどで閉じられたファイルは
 * Mery.his の並び順に反映されていないことがあるかも。
 */


// ■「さいごに閉じたファイル」の件数を指定
var volume = 5;


// 「さいごに閉じたファイル」の配列を取得する
var _latestClosedFile = LatestClosedFile( volume );

if ( _latestClosedFile.length ) {
  // 1件なら [ 配列 ] のかたちに
  if ( volume == 1 ) {
    _latestClosedFile = [ _latestClosedFile ];
  }

  // ポップアップメニューの準備
  var menu = CreatePopupMenu();
  menu.Add( "\t▼ さいごに閉じたファイル ▼", 0, meMenuGrayed );
  menu.Add( "", 0, meMenuSeparator );

  for ( var i = 0, num, label; i < _latestClosedFile.length; i ++ ) {
    // 「連番: 親フォルダ名\ ファイル名」に切りつめる
    num = ( " " + ( i + 1 ) ).slice( -2 ).replace( /\d$/, "&$&" );
    label = _latestClosedFile[i].replace( /(?:.+\\)*([^\\]+\\)([^\\]+)$/, "$1 $2" );
    menu.Add( num + ":\t" + label, i + 1 );
  }
  menu.Add( "", 0, meMenuSeparator );
  menu.Add( "\tキャンセル & ", 0 );

  Status = " さいごに閉じたファイル "
         + Math.min( volume, _latestClosedFile.length ) + " 件 [ "
         + ( ( new Date() - start ) /1000 ).toFixed( 3 )
                                           .replace( /\./, ". " )
         + " 秒 ]";

  // ポップアップメニューを表示
  var r = menu.Track( mePosMouse );

  // ファイルを開く
  if ( r > 0 ) {
    if ( document.FullName || document.Text ) {
      editor.NewFile();
    }
    editor.OpenFile( _latestClosedFile[ r - 1 ] );
  }
}


// ---------- ▼ ポップアップメニューなしで開くなら ▼ ----------

// if ( document.FullName || document.Text ) {
//   editor.NewFile();
// }
// editor.OpenFile( LatestClosedFile() );


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

/**
 * 関数 LatestClosedFile( num )
 * Mery.his を読み込んで「さいごに閉じたファイル」のフルパスを返す
 * 
 * 引数: 「さいごに閉じたファイル」の件数を指定
 *     1 を指定した場合または省略した場合は、1件のフルパスを文字列で返す
 *     2 以上の数値を指定した場合は、配列で返す
 */
function LatestClosedFile( num ) {
  // var start = new Date();	// 所要時間計測(開始)
  var closedFile = "",  closedFileArray = [];
  var num = num ? num : 1;

  // Mery.his をさがす (ポータブル / %AppData%\Mery )
  var meryhis = editor.FullName.replace( /\.exe$/i , ".his" );
  var Fso = new ActiveXObject( "Scripting.FileSystemObject" );
  if ( ! Fso.FileExists( meryhis ) ) {
    var WshShell = new ActiveXObject( "WScript.Shell" );
    meryhis = WshShell.ExpandEnvironmentStrings( "%APPDATA%" )
            + "\\Mery\\Mery.his";
  }
  if ( ! Fso.FileExists( meryhis ) ) { return closedFile; }

  // Mery.his を読みこむ
  var Adodb = new ActiveXObject( "ADODB.Stream" );
  var adTypeText = 2,  adReadAll = -1;
  Adodb.Type = adTypeText,  Adodb.Charset = "UTF-8";
  Adodb.Open();
  Adodb.LoadFromFile( meryhis );
  var hisText = Adodb.ReadText( adReadAll ).replace( /\r\n?/g, "\n" );
  Adodb.Close();
  
  // Mery.his からファイルパスを抽出する
  var hisArray = hisText.match( /^\[.+\]$/gm );
  if ( ! hisArray ) { return closedFile; }

  // 履歴のファイルパスをうしろから順にチェックして
  // 現在開いているファイルにないものを「さいごに閉じたファイル」とする
  hisArray.reverse();
  var hCount = hisArray.length;
  var eCount = Editors.Count;
  var dCount, cCount, file, hit;
  outerLoop:
  for ( var i = 0; i < hCount; i ++ ) {
    closedFile = hisArray[i].replace( /^\[|\]$/g, "" );
    for ( var ee = 0; ee < eCount; ee ++ ) {
      dCount = Editors.Item( ee ).Documents.Count;
      for ( var dd = 0, hit = 0; dd < dCount; dd ++ ) {
        file = Editors.Item( ee ).Documents.Item( dd ).FullName;
        if ( closedFile == file ) { hit ++; }
      }
      cCount = closedFileArray.length;
      if ( ! hit && cCount < num && Fso.FileExists( closedFile ) ) {
        closedFileArray.push( closedFile );
      }
      if ( cCount == num ) { break outerLoop; }
    }
  }
  // Status = ( ( new Date() - start ) /1000 ).toFixed( 3 ).replace( /\./, ". " ) +" 秒";
  return num == 1 ? ( closedFileArray[0] || "" ) : closedFileArray;
}


メモ[編集]

  • 2019/04/28 (sukemaru)
  • 2019/04/29 (sukemaru)
  • Mery.his が空だった場合など処理の修正(length = 0 の "" か [] を返すように)。
  • ループ処理に break を追加。
  • ロースペックの win xp (32bit, cpu 1コア, JScript 5.8) でテストしたかぎりでは、処理時間はそれほどかからないようだった(ポップアップメニューの表示までで 0.02 ~ 0.04 秒)。
  • 2019/04/30 (sukemaru)
スポンサーリンク