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

提供: MeryWiki
ナビゲーションに移動 検索に移動

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

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

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

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


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


ダウンロード[編集]

ファイル:さいごに閉じたファイル.zip」(アイコン入り)
最終更新: 2019/11/30


ソースコード[編集]

#title = "さいごに閉じたファイル..."
#tooltip = "「さいごに閉じたファイル」をポップアップメニューから開く"
#icon = "restore[3].ico"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",8

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

/**
 * sukemaru (2019/04/28 - 2019/11/30)
 * 「最近閉じたファイル」で現在開かれていないものをポップアップメニューに表示する
 * 
 * ・Mery の「オプション」設定で「カーソル位置とブックマークを保存する」が無効、
 *   または「カーソル位置とブックマーク」の履歴が削除されたときは
 *   ポップアップメニューを表示しない(Mery.his ファイルがない)。
 * ・Mery.his を下から順にチェックするだけなので、マクロなどで閉じられたファイルは
 *   Mery.his の並び順に反映されていないことがあるかも。
 * ・ブックマークなしのドキュメントの場合、
 *   文書の先頭(pos=0)にキャレットを置いて閉じると Mery.his から消えるので、
 *   Mery の再起動後に「さいごに閉じたファイル」に表示されない。
 */

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

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

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


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

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

  var width = String( lCount ).length;
  for ( var i = 0, num, label, id; i < lCount; i ++ ) {
    if ( i % 10 == 0 ) {
      menu.Add( "", 0, meMenuSeparator );
    }
    id = i + 1;
    // 「連番: 親フォルダ名¥ ファイル名」に切りつめる
    num   = ( "   " + id ).slice( - width ).replace( /\d$/ , "&$&" );
    label = lFiles[i].replace( /(?:.+\\)*([^\\]+\\)([^\\]+)$/ , "$1 $2" )
                     .replace( /&/g, "&&" );
    menu.Add( num + ":\t" + label, id );
  }

  // ポップアップメニューを表示
  Status = " 「さいごに閉じたファイル」 "
         + lCount + " 件 表示  [ "
         + ( ( new Date() - start ) / 1000 ).toFixed( 3 )
                                            .replace( /\./, ". " )
         + " 秒 ]";
  var r = menu.Track( mePosMouse );

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


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

// if ( editor.ActiveDocument.FullName || editor.ActiveDocument.Text ) {
//   editor.NewFile();
// }
// editor.OpenFile( LatestClosedFile()[0] );


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

/**
 * 関数 LatestClosedFile( num )
 * Mery.his を読み込んで「さいごに閉じたファイル」のフルパスの配列を返す
 * 
 * 引数:  「さいごに閉じたファイル」の件数を指定
 *         0 または省略した場合は1件と見做す
 * 戻り値: 配列 [ fullpath1, fullpath2, fullpath3, ... ] 
 */
function LatestClosedFile( num ) {
  var num             = ( num > 0 ) ? num : 1;
  var closedFile      = "";
  var closedFileArray = [];

  // Mery.his をさがす (ポータブル / %AppData%\Mery )
  var Fso        = new ActiveXObject( "Scripting.FileSystemObject" );
  var meryPath   = editor.FullName;
  var mery       = Fso.GetBaseName( meryPath );
  var meryhis    = meryPath.replace( /\.exe$/i , ".his" );
  if ( ! Fso.FileExists( meryhis ) ) {
    var WshShell = new ActiveXObject( "WScript.Shell" );
    meryhis      = WshShell.SpecialFolders( "APPDATA" )
                 + "\\Mery\\" + mery + ".his";
  }
  if ( ! Fso.FileExists( meryhis ) ) {
    Status = " " + mery + ".his ファイルがありません。";
    return [];
  }

  // Mery.his を読みこむ
  var Adodb = new ActiveXObject( "ADODB.Stream" );
  var adTypeText = 2;
  var adReadAll  = -1;
  Adodb.Type     = adTypeText
  Adodb.Charset  = "UTF-8";
  Adodb.Open();
  Adodb.LoadFromFile( meryhis );
  var hisText	 = Adodb.ReadText( adReadAll );
  Adodb.Close();
  
  // Mery.his からファイルパスを抽出する
  var hisArray = hisText.match( /^\[.+\]$/gm );
  if ( ! hisArray ) {
    Status = " " + mery + ".his に履歴がありません。";
    return [];
  }

  // 履歴のファイルパスをうしろから順にチェックして
  // 現在開いているファイルにないものを「さいごに閉じたファイル」とする
  hisArray.reverse();
  var hCount = hisArray.length;
  var eCount = Editors.Count;
  var docus,  dCount,  file;
  outerLoop:
  for ( var i = 0; i < hCount && closedFileArray.length < num; i ++ ) {
    closedFile = hisArray[i].slice( 1, -1 );
    for ( var ee = 0; ee < eCount; ee ++ ) {
      docus  = Editors.Item( ee ).Documents;
      dCount = docus.Count;
      for ( var dd = 0; dd < dCount; dd ++ ) {
        file = docus.Item( dd ).FullName.toLowerCase();
        if ( closedFile.toLowerCase() == file ) {
          continue outerLoop;
        }
      }
    }
    if ( Fso.FileExists( closedFile ) ) {
      closedFileArray.push( closedFile );
    }
  }
  if ( ! closedFileArray.length ) {
    Status = " 有効な「閉じたファイル」の履歴がありません。";
  }
  return closedFileArray;
}


メモ[編集]

  • 2019/04/28 (sukemaru)
  • 2019/04/29 (sukemaru)
  • Mery.his が空だった場合など処理の修正(length = 0 の "" か [] を返すように)。
  • ループ処理に break を追加 ( ← 2019/11/30 削除)。
  • 2019/04/30 (sukemaru)
(組み込み関数 LatestClosedFile() のコードはおなじ)
  • 2019/04/30 (sukemaru)
  • 組み込み関数のコード変更(エラー回避とループ処理の最適化)。
  • 1件だけの場合でも戻り値を配列に収納して返すように変更。
  • ポップアップメニューに表示するファイルパス内の "&" を補完。
  • 表示数の初期値を 25 件に変更。
スポンサーリンク