ぺーぱーふぇいす

雑記と備忘録。私はプログラマ。

Mery 自作マクロ「初回起動時にいつものファイルを開く.js」

個人用のマクロ紹介。
その日初めてMeryを起動したら所定のファイルを開くよ、というマクロ。

説明

私はMeryを使ってMarkdownで2種類の日報を書いている。
いつも所定のファイルに追記していくだけなんだけど、毎朝Meryを立ち上げた時に2ファイル開くのがめんどくさい。
なので、Meryがその日初めて起動した時のみ、所定のファイルを開くマクロを作った。需要はあんまり無いと思う。もしかしたら「Meryの初回起動のみやらせたい処理がある」って人にとっては参考になるか……な?

マクロ本体と設定

初回起動時にいつものファイルを開く.js

// -----------------------------------------------------------------------------
// Meryがその日初めて起動されたら、所定のファイルを開く。
// about:  マクロと同一のディレクトリ配下のlogsフォルダに最終起動日(初回起動.log)
//         を保存します。
//         このマクロが呼び出された時、ログに記載されている最終日が本日と一致
//         しなかった場合、所定のファイルをMery上で開きます。
// create: 2018/03/30 PaperFace1000
// update: 
// -----------------------------------------------------------------------------

// 初回起動判定
var quit_flg = true;
var docs = Editor.Documents;

if(docs.Count == 1){
    if(docs.Item(0).Name == ""){
        quit_flg = false;
    }
}

if(quit_flg){
    Quit();
}

// 日付フォーマット
function dateToString(date)
{
    var result = "yyyyMMdd";
    result = result.replace(/yyyy/g, date.getFullYear());
    result = result.replace(/MM/g, ('0' + (date.getMonth() + 1)).slice(-2));
    result = result.replace(/dd/g, ('0' + date.getDate()).slice(-2));
    
    return result;
}

// 開くファイルたち
var files = [
    "C:\\work\日報.md"
   ,"C:\\Users\\user\\Documents\\日報(提出用).md"
];

// 以下、メイン処理
var fso = new ActiveXObject( "Scripting.FileSystemObject" );

var dir_path = fso.GetParentFolderName(ScriptFullName);
var log_dir = fso.BuildPath(dir_path, "logs");
var log_path = fso.BuildPath(log_dir, "初回起動.log");

var file;
var line = "";

if(fso.FileExists(log_path)){
    file = fso.OpenTextFile(log_path);
    
    while(!file.AtEndOfStream){
        // 1行しか書き込まないファイルだけど、一応ReadAll()じゃなくてReadLine()で読み込む。
        line = file.ReadLine();
        line = line.replace("\n", "");
        break;
    }
    
    file.Close();
}

var today = dateToString(new Date());

if(line != today){
    for(var i = 0; i < files.length; i++){
        if(i >= 1){
            Editor.NewFile();
        }
        Editor.OpenFile(files[i]);
    }
    docs.Item(0).Activate();
}

if(!fso.FolderExists(log_dir)){
    fso.CreateFolder(log_dir);
}

file = fso.CreateTextFile(log_path, true);
file.Write(today);
file.Close();

fso = null;

マクロはイベント起動とし、「フォーカスを受け取った時」に実行されるようにしている。

f:id:PaperFace:20180429210142p:plain

f:id:PaperFace:20180429210204p:plain

Meryがフォーカスを得た時、まずは新規作成でMeryが開かれているかを確認している。Meryをタブ表示にしているのであれば、「無題-1」といったタブが表示されているような状態。
この時、<このマクロが入っているフォルダ>\logs\初回起動.logを参照する。
初回起動.logにはyyyyMMdd形式の前回起動した年月日が記載されており、この年月日が本日と一致していなかった場合は、「Meryが今日始めて起動された」とみなす。files(文字列配列)に記載されているファイルを開き(ここでは例としてそれっぽい名前の日報.md日報(提出用).mdとした)、初回起動.logの中身を本日に書き換えて更新する。

余談

Mery自体のスタンスはシンプルであることなようなので、ニッチな機能はマクロやプラグインによって解決することになっている。
そんなこんなで、ニッチな機能を実現すべくマクロを書く場合は、こうしてテキストベースのログとか設定ファイルを利用することになると思う。今回は前回Meryが起動された年月日を記録する際に、1行のみ記載される平文のテキストファイルを用いているが、これが複雑な設定ファイルとなってきた時にどう扱うかが課題かもしれない。
なにせ、JScriptで動いていることを考慮した上で、「設定INIか、XMLか、JSONか…」とフォーマットを考える必要があり、それでいてそれに合ったパーサを最悪は自分で用意しなければならない場合もある。
まあ、おそらくそのレベルまでの機能を必要としたら、マクロではなくプラグインを作ってC#.NETの力を借りたほうが良いということなのだと思う。

また、今回はMeryで用意されているイベントの中に「Meryをその日初めて起動した時」みたいなド直球のイベントは無かったので、前項で解説した通り、Meryがフォーカスを得た時に新規作成で開いている(=Meryそのものを単体で起動した)時、ログファイルを読み込んで最終起動日と比較するなんて処理を行っている。
なので、なるべくファイル入出力を減らすように工夫してはいるが、Meryがフォーカスを得る度にこうしたマクロが実行されているというのも神経質な人は気になるかもしれないなぁ……

細々としたマクロを書いているけど、こんなことを考え始めてる時点でそろそろMeryプラグインも作るころかな……?