org-mode で記事が書けるようになりました
1. org-mode で記事を書きたい
今までの記事は全て SXML
で直書きしていました。 しかし、ここ最近、
org-mode
を本格的に使用するようになって、
いくらS式が好きだといってもさすがに SXML
でブログを書くのは苦行であると気づきました。 今後 Guix
の紹介記事のような重要な記事を書く予定があるので、 org-mode
の強力なタスク管理を利用して記事を作成したいと考えています。
このブログは Haunt
という、GNU Guile
製の静的サイトジェネレータを使用して生成しているのですが、
サポートしている文書の形式は, SXML
, Texinfo
, Skribe
, CommonMark
の4つのみであったため、 デフォルトでは org-mode
は使用できませんでした。
既に org-mode
に依存してしまっているので、 org-mode
で記事が書けないのは致命的です。 この問題を、 Haunt
を拡張することによって解決します。
2. Haunt の紹介
Haunt は GNU Guile (Scheme の処理系の一つ)で実装された静的サイトジェネレータで、 サイトの生成の仕方などを Guile で割と自由に拡張できるのが特徴的です。 このサイトでもブログ記事から対応する GitLab 上のソースコードにアクセスしたり、 記事の変更履歴を閲覧する機能が追加されています。 ソースコードは公開されているので、興味のある方は確認してみてください。
Haunt の基本的な使い方については
公式ドキュメント
を参照していただくことにして、 今回の説明に必要なところだけ解説します。
haunt.scm
というファイルでサイトをどのように生成するのかという設定を書き、 posts
ディレクトリに記事を配置して haunt build
というコマンドを実行すると良い感じにブログが生成されます。
haunt.scm
で記事の reader
を指定することができるので、 今回は
org-reader
という org-mode
用の reader
を追加することで、
org-mode
の記事を書けるように拡張します。
3. org-reader の実装について
commonmark-reader
の実装を確認したところ、
記事のファイルからメタデータと SXML
形式のコンテンツに変換できれば良いことが分かりました。
Guile
だけで org-mode
の文書を SXML
に変換するのは骨が折れそうなので、 Pandoc
を使用して HTML
に変換して、それを SXML
に変換することで実現することにしました。
Pandoc
を使用して HTML
に変換する部分は
org-string->html-string
という手続きで実現しているのですが、 Guile
でパイプの入出力を行なうプログラムを書くのが意外と難しかったです。
(ice-9 popen)
が公式に提供している open-pipe*
だと入力用のポートのみをクローズすることができないために、
エクスポートされていない手続きである open-process
を使用しています。
(define (org-port->html-string port) (receive (read-port write-port pid) (open-process OPEN_BOTH "pandoc" "-f" "org") (put-string write-port (get-string-all port)) (close-port write-port) (let ((result (get-string-all read-port))) (close-port read-port) (let ((status (cdr (waitpid pid)))) (unless (zero? status) (error "pandoc return a non-zero status-code:" status))) result)))
非公開の手続きを使用しているので、正直微妙な気持ちになっていますが、
shell
の代替として Guile
が使えそうな雰囲気ですね。
org-reader
本体は下記のように実装しています。
(define org-reader (make-reader (make-file-extension-matcher "org") (lambda (file) (call-with-input-file file (lambda (port) (let* ((metadata (read-metadata-headers port)) (html-string (org-string->html-string (get-string-all port)))) (values metadata ((sxpath '(dummy *)) (xml->sxml (string-append "<dummy>" html-string "</dummy>"))))))))))
4. まとめ
org-mode
でブログを書けるようになりました。
Haunt は Hackable な静的サイトジェネレータで、Guile を使って簡単にカスタマイズできて結構楽しいです。 自分でブログを作成する予定のある人は一度検討してみてください。