2016年7月24日日曜日

WindowsのEmacsからエクセルのファイルはエクセルで開くようにしたいんだよ

 たとえば、Macだと下記のようなコードをinit.elに放りこんでおくと、dired-modeでWで、指定したファイルをopenコマンドで呼び出してくれる。これはファインダーでダブルクリックしたときと同じ動きをしてくれるもので——pdfファイルだったらpdfビュアーで開いてくれる。これでエクセルのようなEmacsで開いてもしかたがないようなファイルを対応したアプリケーションで開くことができるようになる。

(require 'deferred)

;; diredで外部プロセス起動
(add-hook 'dired-mode-hook
   (lambda ()
     (define-key dired-mode-map
       "W" 'dired-open)))

(defun dired-open ()
  (interactive)
    (deferred:process "open" (dired-get-filename)))

 元々、このコードはMeadowがらみで知った1。Meadowにはfiberという、Macのopenコマンドに相当するものが同梱されていたのだ。そのMeadowも今はメンテされていない。
 Windowsで動くEmacsはいくつか、あるのだけれど、さすがにfiberはなくてかわりにstartコマンドがある。でもこいつを呼び出すにはどうしたらいいのかなぁ、なんかstartコマンドが見つからないんですけど、と思っていたら内部コマンドだということを知った。そうか。2
 ところがEmacsのパス構文がちがうため、フルパスでstartコマンドを渡すとうまく動作しない。前記のサイト2でもディレクトリの部分をのぞいたファイル名だけにしていた。MeadowはWindowsのパス構文の変換ができた。もしかしたらEmacsに取り込まれているんじゃないか、とelispを漁って、見つけた。

 w32-convert-standard-filename

 で、前記サイトのコードを元にこうした。

(defun my-x-open (file)
  "open file."
  (interactive "FOpen File: ")
  (message "Opening %s..." file)
  (call-process "cmd.exe" nil 0 nil "/c" "start" "" (w32-convert-standard-filename file))
  (message "Opening %s...done" file))

 これを使ってbookmarkの一覧バッファや、orgのハイパーリンクから外部コマンドで立ち上げることができるようになる。良きことかな。

追記:2016年7月31日(日)
cmd.exeをcall-processなどしなくてw32-shell-executeで呼び出せることが判明……。

Footnotes:

1

もちろんもうすこしちがうコードだった。当時はdeferredとか、なかったし。

2

サイトはググっても見つからなくなってしまった……。