Emacs Lisp 製の CMS の詳細

トップページでも述べているように、このサイトは Emacs Lisp で書かれた CMS が Emacs の上で動いているというふうになっています。Emacs を知らない人がいたらいけないので 一応説明しておくと、Emacs は LISP というプログラミング言語の方言である Emacs Lisp という 言語で拡張できるというテキストエディタです。最近は CoffeeScript で拡張できる某エディタだったり JavaScript で拡張できるなんとかかんとかコードだったり拡張可能なテキストエディタがあふれているので 機能を拡張できるからといって何ということもありませんが、その昔はテキストエディタを 何らかの機能で拡張できるってのは革新的だったとかいうのはどうでもいい話なのでここには書きません。

一応ソースコードは ここ に。

まだ開発中なので不満なところが多々ありますが、今後直していけたらな、と。

一応現時点 (2019/7/27) での機能と実装について書いておきます。

Emacs に入ってくるまで

Emacs に Web サーバーをさせるのは不可能ではないかもしれないんですが、 単なるテキストエディタをネットの海にさらしておくのはちょっと怖いので、 Web サーバーが受け取ったリクエストを CGI で Emacs に渡すという感じになってます。 で、Web サーバーには Nginx を使っているんですが、これはおそらく CGI を直接扱えないので、 fcgiwrap というソフトウェア経由で Emacs にリクエストが飛ぶって感じになってます。 で、CGI スクリプトとして .el ファイルを実行するには、ファイルが実行可能で、かつ 先頭の shebang 行で Emacs をスクリプトインタプリタとして起動する必要があるんですが、 ここでひとつ問題があって、 .el ファイルを

$ emacs foo.sh

という感じに実行すると普通にファイルを開こうとして、かつ、 stdout が tty じゃないので tty じゃないぞ、って感じのエラーを吐いて終わってしまいます。 で、 Linux の実装では、

#!/bin/foo bar baz

みたいな shebang を書くと、それは、

argv[0] = "/bin/foo";
argv[1] = "bar baz";

みたいに渡されてしまうので、ここには引数は一つしか渡すことができません。

一方で、Emacs をスクリプトインタープリタとして実行したい場合、

$ emacs --script <なんかファイル名>

という感じに実行する必要があって、「これなら引数ひとつで足りる」と思う方もいらっしゃる かもしれませんが、Emacs のインストール場所に依存せずに使いたいというのが個人的 にあったりして、そうなると env 経由で呼ぶ必要があったりして、結局使える引数の数が足りません。 そういう訳で、Emacs をラップするやつを書いて対処してます。 まあ、Emacs をビルドしてデフォルトの場所にインストールした環境でしか使わないと思われるので おそらくこんなことをする必要はなかったんですが。

ルーティング

ルーティングってのはネットワークのルーティングじゃないです。アプリケーションサーバーによくある URL によるルーティングです。有名どころの Rails だったり Laravel だったりは、ルーティング用 の .rb ファイルだったり .php ファイルだったりが1個あって、その中で完全一致だったり正規表現 だったりでルーティングできるようになってたりするんですが、この CMS ではちょっと違う実装になっていて、 エントリポイントである このファイル でリクエストの PATH を LISP のリストに分割して、 その後のことは全部そのディレクトリを担当するファイルに任せるという実装になっています。といっても、現状 entry ディレクトリのことしか考える必要はないんですが。ただし、リクエストされたファイル名とディレクトリ名 を等価に扱うという実装になっているので、実装としては entryindex があるみたいな実装になってます。

エントリ

ブログのエントリのデータは posts というディレクトリ以下に入っているので、そこから持ってきて返すという感じになってます。 ここで、それぞれのエントリは Org Mode のファイルなので、それを HTML に変換する必要があります。 ここは Org Mode が普通に Emacs で使えるのでそれを使ってます。スタイルを自分好みにしたいのでいろいろいじってますが、 そこはまあどうでもいいところです。見た目と HTML の構造の不一致は CSS でなんとかなります (HTML の合理的な 構造を CSS で破壊するアンチパターン (?))。 また、現状一つのエントリは Org Mode ファイルで構成されているので、それ用にディレクトリをつくる必要はないんですが、 エントリのリストを作るのが面倒だったのと、今後何か他のデータを入れる可能性があるってことでそういう感じになっています。

また、Org Mode の HTML エクスポートがローカルでやると遅延が感じられるくらい遅かったのですが、 さくらの VPS が意外と速いらしく、そこそこ動いてるな、という感じがしています。

今後やりたいこと

まだエントリのリストのページングが未実装なのでそこを早く実装したいです。 あとはエントリのリストの日付の実装が適当なので修正したいです。

追記

今は elisp の CMS は動いてないです。Hugo で生成してます。