マクロイベント「ファイルを開いた時」に開かれたdocument取得

  1. マクロイベント「ファイルを開いた時」を利用して、マクロを実行しています。
    マクロでは開かれたファイルに対して処理を行いたいので、先頭で
    var doc = editor.ActiveDocument;
    として取得しています。

    ここで、複数のファイルをMeryアイコンにドラッグすると、イベントマクロそれぞれが必ずしも開かれたdocumentを取得できないようです。
    以前はうまく動いていた気がするのですが....

    複数のファイルを開きますし、マクロ実行時に必ずしも開いたファイルがアクティブとは限らないと言われれば、確かにそのとおりなのですが、そうすると「ファイルを開いた時」イベントがほとんど役に立たなくなってしまいそうです。

    他の方法でも、マクロから開かれたdocumentを取得できればいいのですが、何か方法は無いでしょうか?
    ご助言お願いいたします。

     |  pizz  |  返信
  2. 何をやっているかも書いておきますね。
    ファイルの拡張子が二重になっている場合に、前方の拡張子に従った編集モードにしています。
    “hogehoge.ps1.bat”
    のような場合に、編集モードを"Bat"ではなく、"PowerShell"にします。
    ダブルクリックで実行できるように.batにしているけど、中身は実質PowerShellなファイルです。

    var doc = editor.ActiveDocument;
    var fileName = doc.Name;
    var dot1 = fileName.lastIndexOf(".");
    if(dot1 > 0){
    	var dot2 = fileName.lastIndexOf(".", dot1 - 1);
    	if(dot2 > 0){
    		var fileExt = fileName.substring(dot2 + 1, dot1).trim().toLowerCase();
    		if(fileExt != ""){
    			for(var i = 0; i < editor.ReadSettingInteger("Modes", "Count", 0); i++){
    				var modeExts = editor.ReadSettingString("Modes\\Mode" + i.toString(), "Extensions", "").toLowerCase().split(",");
    				if(modeExts.indexOf(fileExt) >= 0){
    					doc.mode = Editor.ReadSettingString("Modes\\Mode" + i.toString(), "Caption", "");
    					break;
    				}
    			}
    		}
    	}
    }
    

    Mery: 3.7.8 (x64, Portable)
    Onigmo: 6.2.0
    C/Migemo: 1.3
    Tidy: 5.8.0
    Hunspell: 1.7.1
    検索 バー: 1.0.6 (FindBar.dll)
    アウトライン: 3.2.2 (Outline.dll)
    OS: Windows 10 (Version 22H2, OS Build 19045.5131, 64-bit Edition)

     |  pizz  |  返信
  3. ご愛用いただきありがとうございます。

    現在の仕様では、[ファイルを開いた時] イベントは、ファイルを開く処理がすべて終わってから呼び出されます。

    そのため、複数のファイルを開いている途中でdocumentを取得することはできないんですよね。

    > 以前はうまく動いていた気がするのですが…

    私もちょっと気になったので、Ver 2.6.7 と Ver 3.2.8 で試してみましたが、やっぱり動きませんでした。

    そもそも、複数のファイルを開く途中でマクロが実行されると、処理が終わっていない状態でdocument.Close();みたいな操作をされた場合などは、プログラム的に危険ですよね。

    この仕様は、そういった問題を避けるための意図的な設計だと思われます。

    > 複数のファイルを開きますし、マクロ実行時に必ずしも開いたファイルがアクティブとは限らないと言われれば、確かにそのとおりなのですが、そうすると「ファイルを開いた時」イベントがほとんど役に立たなくなってしまいそうです。

    おっしゃるとおりです。このイベントの用途が、1 つのファイルを開く場合に限定されてしまうのは確かに惜しいですね。

    ちなみに、Ver 3.7.7 では、ファイルを閉じたあとに呼ばれる、[ファイルを閉じた時] イベントでファイル名を取得できるようになりました。

    この仕組みを応用すれば、[ファイルを開いた時] イベントでも同様の対応が可能かもしれません。

    もちろん、複数のファイルを開いている途中でマクロが動くようになるわけではありませんが、すべてのファイルを開き終わった後にマクロが実行される仕様は維持しつつ、[ファイルを開いた時] イベントでdocumentが呼び出し元を指すようにすれば、もう少し便利になるのではと思います。

    次のバージョンでこれが実装できるか、ちょっと検討してみますね。

     |  Kuro  |  返信
  4. >Kuro さん

    毎回のわがまま、聞いていただきありがとうございます。
    無理を言っているのはわかっていますので、無理しない程度でお願いしますね。

     |  pizz  |  返信
  5. 力技だけど、ファイル一覧の保持と比較で、新しく開いたファイルを特定する方法。
    取り敢えずこれなら?

    「ファイルを開いた時」のイベントマクロ

    var edicnt = editors.Count;
    var flist = [];
    for( let i=0; i<edicnt; i++ ){
    	let dcol = editors.Item(i).Documents;
    	for( let didx=0, dend=dcol.Count; didx<dend; didx++ ){
    		let cdoc = dcol.Item(didx);
    		flist.push({path:cdoc.FullName, doc:cdoc});
    	}
    }
    var flist_aldy, flist_opnd;
    if( (flist_aldy = Tag("OpenedFileList")) ){
    	flist_opnd = [];
    	var se = flist_aldy.length;
    	for( let i=0, e=flist.length; i<e; i++ ){
    		let si = 0, path = flist[i].path;
    		for( ; si<se; si++ ){
    			if( flist_aldy[si]===path ) break
    		}
    		if( si==se ) flist_opnd.push( flist[i] );
    	}
    }else{
    	flist_opnd = flist;
    }
    Tag("OpenedFileList") = flist.map(function(item){ return item.path; });
    for( let opidx=0, oplen=flist_opnd.length; opidx<oplen; opidx++ ){
    
    	var doc = flist_opnd[opidx].doc;
    	...同処理
    }

    「文書を閉じた時」のイベントマクロ

    var edicnt = editors.Count;
    var flist = [];
    for( let i=0; i<edicnt; i++ ){
    	let dcol = editors.Item(i).Documents;
    	for( let didx=0, dend=dcol.Count; didx<dend; didx++ ){
    		let cdoc = dcol.Item(didx);
    		flist.push( cdoc.FullName );
    	}
    }
    Tag("OpenedFileList") = flist;
     |  MM  |  返信
  6. > 力技だけど、ファイル一覧の保持と比較で、新しく開いたファイルを特定する方法。
    > 取り敢えずこれなら?

    アイディアありがとうございます。
    なかなかの力技ですねww
    現状そこまで困っているわけでもないので、管理の煩雑さも考え、今回はやめておきます。
    わざわざ考えていただいたのにすみません...

     |  pizz  |  返信
  7. MM さん、サポートのご協力ありがとうございます!

    pizz さん、Ver 3.7.9 で対応してみました。

    editor.ActiveDocumentではなく、documentで、[ファイルを開いた時] イベントが発生した文書にアクセスできるようになっていると思います。お試しくださいませ。

     |  Kuro  |  返信
  8. Kuro さん

    対応ありがとうございます。
    ver.3.7.9にして、document参照に変更し、無事思い通りの動作になりました。

     |  pizz  |  返信
  9. > Kuro さん

    そういえば、Tagプロパティって、だんだん皆さん使うようになってきたようで...
    アイディア出した側としては、うれしい限りです。
    shell.GetKeyState() ファンクションも実装されましたし、Meryさん進化してますね!

     |  pizz  |  返信
  10. > ver.3.7.9にして、document参照に変更し、無事思い通りの動作になりました。

    ご確認いただきありがとうございます。うまく動作しているようで、安心しました。

    > そういえば、Tagプロパティって、だんだん皆さん使うようになってきたようで…
    > アイディア出した側としては、うれしい限りです。

    そうですね。Tagプロパティは開発においても苦労した部分なので、こうして活用されていると聞くと、とても嬉しいです。

    Ver 3.7.9 では、マクロの非同期処理もかなり安定してきましたし、shell.GetKeyState()と組み合わせれば、ノベルゲームみたいなものも作れるかもしれませんね。(作る意味は別として…w)

     |  Kuro  |  返信
スポンサーリンク