emacsでロード時にも現在のディレクトリを元にパスを設定する。

通常、emacsが立ち上がっているとき、現在開いているバッファのディレクトリの値が欲しければ、`default-directory`を使えば良い。

(insert default-directory);; -> /home/podmo/up/

バッファ上で直接`eval-buffer`をした場合には問題ないが、`load`を利用して読み込んだ時に失敗する。

具体例

現在のディレクトリは"/home/podhmo/up"。これでeval-bufferを使った場合とloadを使った場合でのdefault-directoryの値を見る。
現状の位置から、"./tmp/test.buf"を作成し、test.bufから見た相対的なファイルパスを取得したい。
得られる値が"/home/podhmo/up/tmp/"になることを期待している。

(defun show-me-default-directory (mes)
  (message "default-directory: %s (%s)" default-directory mes))

;; eval-buffer
(let ((file "tmp/test.buf"))
  (with-temp-file file
    (insert "(show-me-default-directory \"eval-buffer\")"))
  (with-current-buffer (find-file-noselect file)
    (eval-buffer)))

;; load
(let ((file "tmp/test.buf"))
  (with-temp-file file
    (insert "(show-me-default-directory \"load\")"))
  (load (concat default-directory file)))

結果は以下のよう。

;; eval-buffer
default-directory: /home/podhmo/up/tmp/ (eval-buffer)
nil
Loading /home/podhmo/up/tmp/test.buf...
;; load
default-directory: /home/podhmo/up/ (load)
Loading /home/podhmo/up/tmp/test.buf...done
t

本当は、default-directory=/home/podhmo/up/tmpであって欲しかったかったのだけれどloadで失敗。

対応

load時にはload-file-nameのディレクトリ名を取ると良い。これを使ったcurrent-directoryという関数を用意する。

(defun current-directory ()
  (cond ((and load-in-progress (stringp load-file-name))
         (file-name-directory load-file-name))
        (default-directory default-directory)
        (t nil)))

(defun show-me-default-directory (mes)
  (message "default-directory: %s (%s)" (current-directory) mes))

show-me-default-directoryもcurrent-directoryを使った形に変更。
上の式を評価した結果は以下の通り。

default-directory: /home/nao/up/tmp/ (eval-buffer)
nil
Loading /home/nao/up/tmp/test.buf...
default-directory: /home/nao/up/tmp/ (load)
Loading /home/nao/up/tmp/test.buf...done

うまく取得できている。

追記

emacs --load <file>

という形で読み込むとload-in-progressがtにならないみたい。
こういう形に変更した方が実用的かも。

(defun current-directory ()
  (cond ((stringp load-file-name)
         (file-name-directory load-file-name))
        (default-directory default-directory)
        (t nil)))