eclipse+eclipsemonkey+AutoHotkeyでHTMLなどをeclipseのエディタで保存した時にブラウザをリロードする方法

http://la.ma.la/blog/diary_200608281736.htm
のエントリのeclipse版をやってみました。今回は、最新Verのganymedeを使いました。
eclipseのエディタでファイルを保存したとき、あらかじめ設定しておいたファイル名または拡張子にマッチした際に、AutoHotkeyで作ったブラウザリロード用exeを呼び出す仕組みです。
検索の仕方が悪いのか、ほかにやっている人を見つけられなかったので、試行錯誤してやってみました。というメモです。
以前書いた、greasemonkeyスクリプト開発をAptanaのEclipse Monkeyで便利にする - T氏の(非)日常記のを改造しています。

準備1:Firefoxリロード用exeを用意する

http://la.ma.la/blog/diary_200608281736.htm
に置いてある、ma.laさん作成のreload_firefox.exeを入手するか、AutoHotkeyをダウンロードして、次のスクリプトからFirefoxをリロードするexeを作ります。私はreload_firefox.exeをそのまま使わせていただきました(ma.laさんありがとうございます:ペコリ)

#NoTrayIcon
SetTitleMatchMode, 2
WinGet, FF,, Mozilla Firefox
ControlSend,, {F5}, ahk_id %FF%

AutoHotkeyは以下のサイトからダウンロード、

日本語の情報は以下から。情報量多くて参考になります。

入手したFirefoxリロード用exeを保存します。
以下、c:\dev\フォルダに、reload_firefox.exeとして保存したとして記載します。

準備2:eclipsemonkeyを導入する

  1. Help -> Software Updates を選択して、Software Updates and Add-onsを表示
  2. Available Softwareのタブ -> Add Siteで、以下の更新サイトを登録
  3. Eclipse Monkeyを開いて、Installボタンを押してインストールする


準備3:eclipsemonkeyスクリプトを配置する

以下のスクリプトを、適当なプロジェクトにmonkeyというフォルダを作ってその中に保存します。
こんなイメージです。(Aptanaの画像ですが、以前のエントリの使い回しですので、あしからず)

  • reloadFirefox.js
/*
 * Kudos: tomo.snowbug
 * License: EPL 1.0
 * DOM: http://download.eclipse.org/technology/dash/update/org.eclipse.eclipsemonkey.lang.javascript
 * Listener: commandService().addExecutionListener(this);
 * requre monkeyLogger.js
 */

//include("monkeyLogger.js");

var Setting = {
	targetFileName: "", //for multiple selection, using delimiter as comma.
	targetFileExtension: "html,js,css", //for multiple selection, using delimiter as comma.
	reloadFilefoxExe: "c:\\dev\\reload_firefox.exe",
};

function commandService(){
    var commandServiceClass = Packages.org.eclipse.ui.commands.ICommandService;
    var commandService = Packages.org.eclipse.ui.PlatformUI.getWorkbench().getAdapter(commandServiceClass);
    return commandService;
}

function preExecute(commandId, event){
}

/* Add in all methods required by the interface, even if they are unused */
function postExecuteSuccess(commandId, returnValue){
    // if we see a save command
    if (commandId == "org.eclipse.ui.file.save") {
    	execReloadFirefox();
    }
}

function notHandled(commandId, exception){
}

function postExecuteFailure(commandId, exception){
}

function wait(seconds) {
	var thread = java.lang.Thread.currentThread();
	var waitFor = seconds * 1000;
	thread.sleep(waitFor);
}

function execReloadFirefox(){
    var savedFile = editors.activeEditor.title;
//    Logger.debug("call reloadFilefox :" + savedFile);
    if (!isTargetFile(savedFile) ) return;
    wait(2);
//    Logger.debug("exectue reload:" + Setting.reloadFilefoxExe); 
    var runtime = java.lang.Runtime.getRuntime();
    var process = runtime.exec(Setting.reloadFilefoxExe);
}

function isTargetFile(fileName) {
	var targetFileNames = Setting.targetFileName.split(",");
	var targetFileExtensions = Setting.targetFileExtension.split(",");
	var fileExtension = "";
	var flagment = fileName.split(".");
	if (flagment.length > 1) {
		fileExtension = flagment[flagment.length - 1];
	}
	for (var i = 0; i < targetFileNames.length; i++ ) {
		if (targetFileNames[i] == fileName) return true;
	}
	if (fileExtension == "") return false;
	for (var i = 0; i < targetFileExtensions.length; i++) {
		if (targetFileExtensions[i] == fileExtension) return true;
	}
	return false;
}

Settingの中を環境に合わせて書き換えてください。

var Setting = {
targetFileName: "",
targetFileExtension: "html,js,css",
reloadFilefoxExe: "c:\\dev\\reload_firefox.exe",
};

  • targetFileName
    • 指定したファイルを保存したときにブラウザをリロードする。カンマ区切りで複数指定。
  • targetFileExtension
    • 指定した拡張子をもつファイルを保存したときにブラウザをリロードする。カンマ区切りで複数指定。
  • reloadFilefoxExe
    • Firefoxリロード用exeファイルへのパスを指定する。\記号は\\というようにひとつダブらせて記述します。

使う

  1. Eclipseで編集するHTMLを開きます。
  2. Firefoxを開いて、上記のHTMLを開きます。そのタブを開きっぱなしにしておきます。
  3. EclipseでHTMLを編集して、Cntl+sなどで保存します。
  4. ブラウザがリロードされます。しあわせ〜。

おまけ

reloadFirefox.jsで、eclipseのコンソールへのログ出力をするmonkeyLogger.jsです。
他のeclipsemonkeyスクリプトからも使えます。reloadFirefox.jsの

//include("monkeyLogger.js");や
// Logger.debug("call reloadFilefox :" + savedFile);

コメントアウトをはずすと、eclipseのコンソールにメッセージ出力されます。

  • monkeyLogger.js
/*
 * Kudos: tomo.snowbug
 * License: EPL 1.0
 * DOM: http://download.eclipse.org/technology/dash/update/org.eclipse.eclipsemonkey.lang.javascript
 * OnLoad: initialize()
 * Logger for EclipseMonkey
 */

var Logger = {
    loglevel: 0, //0=debug, 1=info, 2=warn, 3=error
    _name: "Eclipse Monkey Logger",
    init: function(){
        this._p("Start " + this._name);
    },
    debug: function(str){
        if (this.loglevel < 1) 
            this._p(this._logFormat("DEBUG", str));
    },
    info: function(str){
        if (this.loglevel < 2) 
            this._p(this._logFormat("INFO ", str));
    },
    warn: function(str){
        if (this.loglevel < 3) 
            this._p(this._logFormat("WARN ", str));
    },
    error: function(str){
        if (this.loglevel < 4) 
            this._p(this._logFormat("ERROR", str));
    },
    destory: function(){
        var consoleName = this._name;
        var ConsoleMgr = Packages.org.eclipse.ui.console.ConsolePlugin.getDefault().getConsoleManager();
        var nowConsoles = ConsoleMgr.getConsoles();
        var target = null;
        for (var i in nowConsoles) {
            if (nowConsoles[i].getName() == consoleName) {
                target = nowConsoles[i];
            }
        }
        if (target == null) 
            return;
        var MessageConsole = Packages.org.eclipse.ui.console.MessageConsole;
        var console = new MessageConsole(consoleName, null);
        var consoles = java.lang.reflect.Array.newInstance(MessageConsole, 1)
        consoles[0] = target;
        ConsoleMgr.removeConsoles(consoles);
    },
    _p: function(str){
        this._prepareConsole().newMessageStream().println(str);
    },
    _prepareConsole: function(){
        var consoleName = this._name;
        var ConsoleMgr = Packages.org.eclipse.ui.console.ConsolePlugin.getDefault().getConsoleManager();
        var nowConsoles = ConsoleMgr.getConsoles();
        for (var i in nowConsoles) {
            if (nowConsoles[i].getName() == consoleName) {
                return nowConsoles[i];
            }
        }
        var MessageConsole = Packages.org.eclipse.ui.console.MessageConsole;
        var console = new MessageConsole(consoleName, null);
        var consoles = java.lang.reflect.Array.newInstance(MessageConsole, 1)
        consoles[0] = console
        ConsoleMgr.addConsoles(consoles);
        return console;
    },
    _logFormat: function(level, str){
        var now = new Date();
        var h = this._heading;
        var formattedDate = "[" + now.getFullYear() + "/" + h(now.getMonth() + 1, 2) +
        "/" +
        h(now.getDate(), 2) +
        " " +
        h(now.getHours(), 2) +
        ":" +
        h(now.getMinutes(), 2) +
        ":" +
        h(now.getSeconds(), 2) +
        "." +
        h(now.getMilliseconds(), 3) +
        "]";
        return formattedDate + " " + level + " " + str;
    },
    _heading: function(str, length){
        var heading = "";
        var amount = length - new String(str).length;
        for (var i = 0; i < amount; i++) {
            heading += " ";
        }
        return heading + str;
    },
};
function initialize(){
    Logger.init();
}

最後に

IEでもできそうですが、なんかできてません><。
何かのお役に立てれば良いです〜
(2008-08-10追記)AutoHotkeyからIEにF5キーを送りつける場合、ウィンドウをアクティブにしないと受け付けないようです。次回のエントリに書こうと思います