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

Project German-style

同人、Github、その他活動の記録と報告

Emacs org-modeでdrawerのエクスポート方法をカスタマイズ

emacs org-mode Hack

Evernoteが可愛く見えると評判の、emacserにとって究極のライフハックツールorg-modeについて。

org-modeは単なる高性能メモツールに留まらず、htmlやTeXへのエクスポートを駆使することでドキュメント作成ツールとしても活用できるわけですが、ちょっと凝ったことをしようとすると、どうしても出力のカスタマイズが必要になり、その作法は基本的に関数ヘルプ(C-h f)とソースしかドキュメントがない。という訳で、調べた事はなるべく共有していきましょう。

さしあたって、今回はドローワの出力をカスタマイズしてみた。


モチベーションとして、TeXで数式を書くと非常に長くなるので、org-modeとしては折り畳み表示がしたい所。ところが、ドローワ内にequation環境を入れても、デフォルトではエクスポート時にverbatim環境に入れられてしまうので上手くいかない。加えてそもそも、:XXX:で囲んでさらにequation環境で囲むというのは二度手間感が。なので、どうせカスタマイズ必須ならドローワをそのまま\begin{...}〜\end{...}環境に置き換えるというソリューションを探してみましょう。

とりあえず、C-h fやC-h vでorg-export-まで入れてdrawer関係について調べてみると、org-export-format-drawer-functionなる変数を発見。次いで、ソースにて以下のような部分がある事を確認。

	   (setq content (funcall (or org-export-format-drawer-function
				      'org-export-format-drawer)

オーケイ、org-export-format-drawerの実装を見ながら、それっぽい動きをする関数を作ってorg-export-format-drawer-functionにセットすれば良い訳か。ヘルプにもそんな感じで書いてありますけど、最終的にはソースを見ないと安心してコードを書き始められないですね。あと、エクスポート形式に依存する部分はorg-export-current-backendを見て分岐。これは逆にドキュメント読まないと分からない(というか、これで良いという確信が得られない)ですね。

という訳で、最終的に出来上がったソースは以下の通り。

(setq my-export-latex-block-drawer
      '*1

	   ;begin, endを付加
	   (content (concat (format "\\begin{%s}\n" (cdr latexblock))
			    content
			    (format "\\end{%s}\n" (cdr latexblock))))

	   ;属性を設定
	   (content (org-add-props content nil 'org-protected t)))
	content))
     (t 
      ;デフォルト処理
      (org-export-format-drawer name content)))))

(setq org-export-format-drawer-function 'my-export-format-drawer)

(org-add-props content nil 'org-protected t)はたぶんこの後のプロセスでの余計な変換を抑制すると思われ。直接エクスポート先のソースを出力するなら付けておいて安定じゃないかな。

ついでなのでインライン数式も対応したい所ですけど、インライン数式自体現在使用していないので今後の課題として。org-latex-regexpsを弄ればいけるかも。

おっと忘れる所だった。ドローワをエクスポートするなら、ファイル中に以下の表記が必要です。

#+DRAWERS: EQUATION EQNARRAY
#       もしくはorg-drawers
#+OPTIONS: d:t

*1:"EQUATION" . "equation") ("EQNARRAY" . "eqnarray"))) (defun my-export-format-drawer (name content) (let* ((latexblock ;drawerの名称がlatex-blockに該当すればnon-nil (assoc name my-export-latex-block-drawer))) (cond ((and (equal org-export-current-backend 'latex) latexblock) (let* (;インデントを消去 (content (org-remove-indentation content