「さいごに閉じたファイルを開く」の版間の差分

提供: MeryWiki
ナビゲーションに移動 検索に移動
Sukemaru (トーク | 投稿記録)
Sukemaru (トーク | 投稿記録)
更新
4行目: 4行目:
[[ヘルプ:ファイル#最近のファイル|ファイルメニュー]] では「最近開いたファイルの履歴」が表示されますが、タブをたくさん並べているときには「現在開いているファイル」ばかりが表示されがちです。
[[ヘルプ:ファイル#最近のファイル|ファイルメニュー]] では「最近開いたファイルの履歴」が表示されますが、タブをたくさん並べているときには「現在開いているファイル」ばかりが表示されがちです。


このマクロでは、Mery.ini ファイルに記録されている「最近開いたファイルの履歴」ではなく、<b style="color:#0000c0;"> Mery.his </b> ファイルに記録されている履歴情報を読み込み、'''「現在開いているファイル」を除いて、さいごに閉じた順にファイルを表示します。'''
このマクロでは、Mery.ini ファイルに記録されている「最近開いたファイルの履歴」ではなく、<b style="color:#0000c0;"> Mery.his </b> ファイルに記録されている履歴情報を読み込み、「現在開いているファイル」を除いて、「最近閉じたファイル ('''さいごに閉じたファイル''')」のみを表示します。
 
<br><br>
*表示する件数は、ソースコード内の設定変数 '''volume = n''' (初期値 5)で変更できます。
*表示する件数は、ソースコード内の設定変数 <syntaxhighlight lang="javascript" inline>volume = n</syntaxhighlight> (初期値 25)で変更できます。


*ファイルの実在確認の処理を入れてあるので、削除・移動・リネームされたファイルは表示されません。
*ファイルの実在確認の処理を入れてあるので、削除・移動・リネームされたファイルは表示されません。
18行目: 18行目:


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


== ダウンロード ==
== ダウンロード ==
「[[ファイル:さいごに閉じたファイル.zip]]」(アイコン入り)
「[[ファイル:さいごに閉じたファイル.zip]]」(アイコン入り)<br>
[[#メモ|最終更新]]: 2019/11/30
 


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


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


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


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




// 「さいごに閉じたファイル」の配列を取得する
// 「さいごに閉じたファイル」の配列を取得する
var _latestClosedFile = LatestClosedFile( volume );
var lFiles = LatestClosedFile( volume );
 
var lCount = lFiles.length;
if ( _latestClosedFile.length ) {
  // 1件なら [ 配列 ] のかたちに
  if ( volume == 1 ) {
    _latestClosedFile = [ _latestClosedFile ];
  }


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


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


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


   // ファイルを開く
   // ファイルを開く
   if ( r > 0 ) {
   if ( r > 0 ) {
     if ( document.FullName || document.Text ) {
    var d = editor.ActiveDocument;
      editor.NewFile();
     if ( d.FullName || d.Text ) { editor.NewFile(); }
    }
     editor.OpenFile( lFiles[ r - 1 ] );
     editor.OpenFile( _latestClosedFile[ r - 1 ] );
   }
   }
}
}
88行目: 97行目:
// ---------- ▼ ポップアップメニューなしで開くなら ▼ ----------
// ---------- ▼ ポップアップメニューなしで開くなら ▼ ----------


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




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


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


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


   // 履歴のファイルパスをうしろから順にチェックして
   // 履歴のファイルパスをうしろから順にチェックして
137行目: 156行目:
   var hCount = hisArray.length;
   var hCount = hisArray.length;
   var eCount = Editors.Count;
   var eCount = Editors.Count;
   var dCount, cCount, file, hit;
   var docus,  dCount, file;
   outerLoop:
   outerLoop:
   for ( var i = 0; i < hCount; i ++ ) {
   for ( var i = 0; i < hCount && closedFileArray.length < num; i ++ ) {
     closedFile = hisArray[i].replace( /^\[|\]$/g, "" );
     closedFile = hisArray[i].slice( 1, -1 );
     for ( var ee = 0; ee < eCount; ee ++ ) {
     for ( var ee = 0; ee < eCount; ee ++ ) {
       dCount = Editors.Item( ee ).Documents.Count;
       docus  = Editors.Item( ee ).Documents;
       for ( var dd = 0, hit = 0; dd < dCount; dd ++ ) {
      dCount = docus.Count;
         file = Editors.Item( ee ).Documents.Item( dd ).FullName;
       for ( var dd = 0; dd < dCount; dd ++ ) {
         if ( closedFile == file ) { hit ++; }
         file = docus.Item( dd ).FullName.toLowerCase();
         if ( closedFile.toLowerCase() == file ) {
          continue outerLoop;
        }
       }
       }
      cCount = closedFileArray.length;
    }
      if ( ! hit && cCount < num && Fso.FileExists( closedFile ) ) {
    if ( Fso.FileExists( closedFile ) ) {
        closedFileArray.push( closedFile );
      closedFileArray.push( closedFile );
      }
      if ( cCount == num ) { break outerLoop; }
     }
     }
   }
   }
   // Status = ( ( new Date() - start ) /1000 ).toFixed( 3 ).replace( /\./, ". " ) +" 秒";
   if ( ! closedFileArray.length ) {
   return num == 1 ? ( closedFileArray[0] || "" ) : closedFileArray;
    Status = " 有効な「閉じたファイル」の履歴がありません。";
  }
   return closedFileArray;
}
}
</source>
</source>
163行目: 185行目:
*2019/04/28 (sukemaru)  
*2019/04/28 (sukemaru)  
:*「[[さいごに閉じたファイル を参照する]]」のページを作成
:*「[[さいごに閉じたファイル を参照する]]」のページを作成
*2019/04/29 (sukemaru)  
*2019/04/29 (sukemaru)  
:*Mery.his が空だった場合など処理の修正(length = 0 の "" か [] を返すように)。
:*Mery.his が空だった場合など処理の修正(length = 0 の "" か [] を返すように)。
:*ループ処理に break を追加。
:*ループ処理に break を追加 ( ← 2019/11/30 削除)。
:*ロースペックの win xp (32bit, cpu 1コア, JScript 5.8) でテストしたかぎりでは、処理時間はそれほどかからないようだった(ポップアップメニューの表示までで 0.02 ~ 0.04 秒)。
 
*2019/04/30 (sukemaru)
:*「[[さいごに閉じたファイル を参照する]]」のページからこのページに移設。
::(組み込み関数 LatestClosedFile() のコードはおなじ)


*2019/04/30 (sukemaru)  
*2019/04/30 (sukemaru)  
:*「[[さいごに閉じたファイル を参照する]]」のページからこのページに移設
:*組み込み関数のコード変更(エラー回避とループ処理の最適化)。
:*(組み込み関数 LatestClosedFile() のコードはおなじ)
:*1件だけの場合でも戻り値を配列に収納して返すように変更。
:*ポップアップメニューに表示するファイルパス内の "&" を補完。
:*表示数の初期値を 25 件に変更。

2019年11月30日 (土) 19:35時点における版

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

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

このマクロでは、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 件に変更。
スポンサーリンク