Pages
あるいはCommonLisp製github.pages用コンパイラ。

Meta info

対象読者

Github.pagesを使ってのブログ運営をしてみようかしら、と思ってるCLer。

Introduction

CommonLispの勉強を初めて数年経ち、様々な知見を蓄えてきました。 そのような知見はブログという形で共有されれば有意義であるというのが、大方の見方です。 僕自身もその意見には比較的賛成なのですが、僕は非常にものぐさな人間ですので、これまでそのような発表を一切と言って差し支えないレベルで行ってきませんでした。

まぁ、でも、そろそろなんか書こうかなぁ、と。

2017年現在、技術系ブログは、僕の観測範囲内では大きく4つに別れる印象です。^1

自サバはハードルが高い。 hatenaはべつに技術系に特化したサービスというわけではない。 qiitaはなんかいろいろアレ。 という訳でgithub.pagesが良いかなぁ、と。

Github.pagesでのブログ運営は簡単で、cloneしてきたディレクトリにhtmlを置いてpushしたらいいだけみたいです。 管理にはjekyllを使うのが本家推奨です。

ですがここで大きな問題がありまして、僕はhtml/css/jsに関してズブの素人なのです。 これからブログを運営しながら少しずつ学んでいくとして、それにプラスしてjekyllなどというツールの使い方まで学んでいかなくてはならないというのはいかにもハードルが高い。

そこで慣れ親しんだCommonLispでそれ用のスクリプトを自作すれば、jekyllの使い方を学ばなくて良いという意味合いでハードルが一つ減りますし、やりたいことはmarkdownで記事を書いたらいい具合にhtmlにコンパイルしてくれるというだけのものですので作るのは簡単そうですし、自作するとなれば嫌でも生のhtmlやcssを見ないわけにはいかなくなりますのでその辺の学習も進むだろうと安直に考えたわけです。

なによりCommonLispを書くのは楽しいですからね。

そうしてできたのがPagesです。

[1] 2022年現在はzennが一大勢力となっております。

How to use

Clone してきたディレクトリに行って、、、

cd to/your/name.github.io

'src'ディレクトリをほって、、、

mkdir src

記事を書いて、、、

vim src/first-blog.md

pagesを呼ぶだけ。

pages

Pagesはだいたい以下のようにディレクトリを構築します。

yourname.github.io/
 +--- archives/
 |    +--- blog.html
 |
 |--- archives.html
 +--- css/
 |    +---css.css
 |
 +--- img/
 +--- indexes/
      +---index.html
 +--- src/
      +--- blog.md

srcディレクトリにあるmarkdown(note 拡張子はmdでなくてはなりません。)からarchives下のhtmlを生成し、それらへのリンクをまとめたarchives.htmlを生成、最後に最新記事をindex.htmlとして生成します。

markdownからhtmlへのコンパイルはmarkdownがindex.htmlより新しいもののみ行われます。 (すなわち、アップデートされたもののみ再コンパイルされます。) また、archives.htmlは新しい順にソートされた形でコンパイルされます。

Installation

Rosスクリプトが書かれているのでROSWELL経由でインストールするのが推奨です。

ros install hyotang666/markup-functions
ros install hyotang666/pages

たぶんこれでインストールできるはず(試してない)。

なお、shellから叩きたくない人はREPLから(PAGES:COMPILE)を評価していただければ良いです。

現在はmarkdownしか対応していませんし、今後もtexやorgといった他の物に対応する気はありませんが、PAGES:COMPILEのキーワード引数:PATTERNに拡張子のパターン文字列を(規定値は"*.md")、:COMPILERにパスネームを引数に受け取り*STANDARD-OUTPUT*<body>の中身を出力する無引数関数(ようするにthunk)を返す関数を渡してあげればそれで動きますので拡張は簡単だろうと思います。

以下にhtmlを受け取ってhtmlへコンパイルするIDENTITY的なものの例を書いときますね。

(pages:compile :pattern "*.html"
               :compiler (lambda(pathname)
                           (lambda()
                             (write-string (uiop:read-file-string pathname)))))

作ってみて。

デバッグしやすいように副作用を分離していったらTHUNKの嵐になってちょっと混乱したw

関数を返す関数をこんなにも書いたのは初めてかもしれない。

htmlのマークアップにはCL-WHOを使っています。(特に不満がないので。) 深町氏のcl-markupや2017/5のquicklisp-updateで入ってきたCl-whyも気になるっちゃ気になりますが。
htmlのマークアップには自作のHTMLgeneratorであるmarkup-functionsを使っています。 プリティプリントのサポートとコンパイル時のHTML文法チェックに力を入れてあります。

cssのコンパイルにはcl-cssを使っています。

markdownからhtmlへのコンパイルには3bmdを使っています。 (3bmdはclispで動かないバグがあるのでpagesもclispでは動きません。) (3bmdがclispで動こないバグはPRを送ったので多分動くようになってます。テストはしてません) 2017/5のquicklisp-updateで入ってきたmarkdown.clも気になりますが、まだアルファクオリティとのこで敬遠しました。 cl-markdown? そんな子いましたかねぇ?

なお前回の記事で書いたDYNAMIC-PACKAGEを試験的に使用しています。(試験の結果使いづらいという結論に達したので依存は外しました)

今後。

ご覧の通りのへっぽこCSSなので、見た目をもう少し何とかしたいかなぁとは思いつつ、必要充分だよなぁとも思いつつ。 ここから先はデザイナの領域だなぁ、とも思いつつ。 CSSはpicoをお試しで導入してみました。

JSは、べつに、いらない、、かなぁ?

今はそんなことより手元のオレオレライブラリ群をちまちまとgithubに上げてはブログを書くという方に専念したほうがよさそげ、かとも思っております。

将来的にアレコレしたくなったときに、このPagesを拡張していくのか、さっさと捨てて作りなおすのか、それともjekyllなどに鞍替えするのか、何もかも未定です。

という訳でPagesの使用は非推奨です。

Common Lispで静的サイトジェネレータが欲しいならcoleslawがいいかもしれません。

2021年追記

なんだかんだで使い続けてはいます。 リファクタリング等でコードの内容と記事が噛み合わなくなって来たので修正。

2022年追記

なんだかんだで使い続けてはいます。 リファクタリング等でコードの内容と記事が噛み合わなくなって来たので修正。