« ^ »

Emacsのorg-modeのorg-babel-load-fileで出力されるファイル名を指定したい

所要時間: 約 3分

TL;DR

  • Emacsの設定をOrg Modeで記述していたが、設定の変更でファイルを開くときにorg-babel-load-fileで出力されたファイルが選択の上部に表示されていた。
  • org-babel-load-fileはorg-babel-tangleを用いてファイルを出力しそれを読み込んでいたが、そのファイル名を外から変更することは難しい実装となっていた。
  • org-babel-load-fileを用いず直接org-babel-tangleを用いるように修正した。

Emacsの設定をOrg Modeを使って記述している

Emacsの設定をOrg Modeを用いて記述している。Org Modeのドキュメント内に コードブロックで設定となるEmacs Lispを記述しそれをinit.elで org-babel-load-fileを用いて読み込んでいる。

org-babel-load-fileはorg-babel-tangleを用いてOrg Modeのドキュメント内 のEmacs Lispを抜き出して拡張子を.elに変更したファイルを生成する。その 後その生成したファイルをload-fileで読み込んでいる。

設定の変更のためファイルを開くときにDiredで一時的なファイルが選択肢の上部に表示されてしまう

README.orgを読み込んだ場合、README.elが生成される。もし設定を編集した ければ元のファイルであるREADME.orgを編集するから、通常このREADME.elは 直接編集しない。しかしDiredなどでファイルを開こうとするとファイル名の 先頭が同じであるためREADME.orgとREADME.elが表示される。しかも.orgと.el では.elのほうがアルファベット順で早い順番で表示されるため、毎回ファイ ル選択を移動させなければならない。

org-babel-load-fileで出力されるファイル名を変更できないか?

org-babel-load-fileで出力されるファイル名を変更できればよいが外からファ イル名を変更することが難しい実装となっていた。

;;;###autoload
(defun org-babel-load-file (file &optional compile)
  "Load Emacs Lisp source code blocks in the Org FILE.
This function exports the source code using `org-babel-tangle'
and then loads the resulting file using `load-file'.  With
optional prefix argument COMPILE, the tangled Emacs Lisp file is
byte-compiled before it is loaded."
  (interactive "fFile to load: \nP")
  (let ((tangled-file (concat (file-name-sans-extension file) ".el")))
    ;; Tangle only if the Org file is newer than the Elisp file.
    (unless (org-file-newer-than-p
	     tangled-file
	     (file-attribute-modification-time
	      (file-attributes (file-truename file))))
      (org-babel-tangle-file file tangled-file "emacs-lisp\\|elisp"))
    (if compile
	(progn
	  (byte-compile-file tangled-file)
	  (load tangled-file)
	  (message "Compiled and loaded %s" tangled-file))
      (load-file tangled-file)
      (message "Loaded %s" tangled-file))))
/Applications/Emacs.app/Contents/Resources/lisp/org/org.el.gz

file-name-sans-extensionをこの関数を実行するときだけモンキーパッチすれ ば挙動は変更できそうではあるがこの関数で実施している内容がそれほど多く ない事がわかった。主にやっていることは以下の2点だ。

  1. org-babel-tangleでコードブロックを抽出する。
  2. 抽出したコードブロックをload-fileで読み込む。

この程度であればモンキーパッチすることなく直接実装するほうが見通しは良さそうだ。

一時的なファイルが選択肢の上部に表示されないように一時的なファイルの名前を変更する

そのためorg-babel-load-fileを使わずorg-tangleを直接使用しファイルを出力し、 それをload-fileで読み込むように変更を行った。

(save-window-excursion
  ;; Almost the same as org-babel-load-file, But the tangled filenames
  ;; are added dot to prefix for make it easier to choose in dired.
  (let ((tangled-file (org-babel-tangle-file
		       (expand-file-name "README.org" user-emacs-directory)
		       ".README.el"
		       "emacs-lisp\\|elisp")))
    (load-file tangled-file)))

https://github.com/TakesxiSximada/emacs.d/commit/4faa7f47d0a9909171579f977ab4cafe1e48ec19