読者です 読者をやめる 読者になる 読者になる

blechmusikの日記

キー・カスタマイズ・ソフトウェア "DvorakJ" の覚え書きをはじめとして様々なことを書いています。

emacs.exe と emacsclient.exe を自動的に使い分ける AutoHotkey のスクリプトを作成した (gnupack 向け)

後日追記

emacs.exe と emacsclient.exe を自動的に使い分ける AutoHotkey のスクリプトを改良した (gnupack 向け) - blechmusik2の日記を公開した。


Emacs.exe が既に起動していたら emacsclient.exe (EmacsWiki: Emacs Client)で、そうでなければ emacs.exe (gnupack用)でファイルを開くスクリプトを作った。ただし、ここでいう emacs.exe とは emacsclientw.exeと同一のフォルダ以外に入っている emacs.exe のことではなく、 gnupack の配布パッケージにおいて特別に配布されているものだ(gnupackのインストールディレクトリ直下のemacs.exe)。emacs.exe が起動していないときに emacsclientw.exe を起動したり emacsclientw.exeを単独で起動するとエラーになるのだが、そういうエラーをAutoHotkeyのスクリプトによって抑制できるようになる。これによって、emacs.exe が起動中か否かに注意を払わなくてよくなるから、ファイルの編集作業が大分快適になるだろう。
具体的には以下の表のとおり動作する。

編集対象のファイルが渡された場合 そうでないとき
emacs.exeが起動中 emacsclientw.exeでファイルを開く emacs.exeにフォーカスを移す
emacs.exeは未起動 gnupackのインストールディレクトリ直下のemacs.exeを使ってファイルを開く gnupackのインストールディレクトリ直下のemacs.exeを起動

ソースは以下の通りだ。スクリプトと同じフォルダに"emacs_file_paths.ini"を置き、各種実行ファイルへのパスを記述しておくこと。

;; 引数の内容を取得する
arg_file := get_command_argument()[1]

;; ----------------------------------------
ini_file := "emacs_file_paths.ini"

;; ini のファイルの存否を確認する
if ( not( FileExist(ini_file) )) {
	MsgBox, % "ini file is not found."
	ExitApp
}

;; ----------------------------------------
;; ini から各種実行ファイルのパスを読み取る
IniRead, emacs_exe_path, %ini_file%, emacs_path, emacs_exe_path
IniRead, emacsclientw_path, %ini_file%, emacs_path, emacsclientw_path
IniRead, gnupack_emacs_exe_path, %ini_file%, emacs_path, gnupack_emacs_exe_path
IniRead, server_file_path, %ini_file%, emacs_path, server_file_path


;; 各種実行ファイルのパスの存否を確認する
for index, file in [emacs_exe_path, emacsclientw_path, gnupack_emacs_exe_path] {
	if ( not( FileExist(file))) {
		MsgBox, % "the file is not found.`n" . file
	}
}

;; ----------------------------------------
;; emacs.exe が起動中かどうかを調べる
;; 起動中ならば emacs.exe のパスを取得する
for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
{
    if ("emacs.exe" = process.Name)
       process_of_emacs_exists := True
}



;; emacs が起動中のとき
if (process_of_emacs_exists) {
	if (arg_file)
		Run, %emacsclientw_path% --server-file %server_file_path% %arg_file%
	else
		WinActivate, ahk_class Emacs
	
	ExitApp
}


;; Emacs がまだ起動していないとき
if (arg_file)
	Run, %gnupack_emacs_exe_path% %arg_file%
else
	Run, %gnupack_emacs_exe_path%
return


;; ----------------------------------------
;; 引数の内容をまとめて取得する関数

get_command_argument(){
    global
    local arg_list := []
    
    Loop,100
    {
        if ("" != Trim(%A_Index%)){
            arg_list.insert(%A_Index%)
        }
    }
    
    return arg_list
}

また、gnupackのemacsを使用している人向けに、emacs_file_paths.iniに各種パスの設定を自動的に書き出すスクリプトを作っておいた。gnupackの初期設定が維持されているならば、正常に動作するだろう。

ini_file := "emacs_file_paths.ini"

MsgBox, 4, , gnupack に収録されている Emacs の設定を`n%ini_file% に書き出しますか?
IfMsgBox, No
	ExitApp


gnupack_dir_path := ""
emacs_dir_path := ""

gnupack_emacs_exe_path := ""
server_file_path := ""
emacs_exe_path := ""
emacsclientw_path := ""



;; emacs.exe が起動中かどうかを調べる
;; 起動中ならば emacs.exe のパスを取得する
for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
{
    if ("emacs.exe" = process.Name) {
    	process_of_emacs_exists := True
       emacs_exe_path := RegExReplace(process.CommandLine, "(""|\s.+$)")
    }
}


if not (process_of_emacs_exists) {
	ExitApp
}

;; emacs.exe が起動中のときには
;; emacsclientw.exe のパスと
;; gnupack のインストールディレクトリ直下の emacs.exe のパス、
;; Emacs の server file のパスを取得する
emacs_dir_path := RegExReplace(emacs_exe_path, "(?!\\)[^\\]+?$")
gnupack_dir_path := RegExReplace(emacs_dir_path, "app\\emacs\\emacs\\bin\\")


gnupack_emacs_exe_path := gnupack_dir_path . "emacs.exe"
emacsclientw_path := emacs_dir_path . "emacsclientw.exe"


IniWrite, %emacs_exe_path%, %ini_file%, emacs_path, emacs_exe_path
IniWrite, %emacsclientw_path%, %ini_file%, emacs_path, emacsclientw_path
IniWrite, %gnupack_emacs_exe_path%, %ini_file%, emacs_path, gnupack_emacs_exe_path

server_file_path := gnupack_dir_path . "home\.emacs.d\server\server"
IniWrite, %server_file_path%, %ini_file%, emacs_path, server_file_path