Hacking on coleslaw

Posted on 2013-04-19
Tagged with hack, common-lisp, coleslaw, github, pages

In this post, I document how I hacked coleslaw to add Github’s pages integration.

What is coleslaw?

coleslaw is a static blog generator written in Common Lisp, much like Jekyll, albeit with less features.

I’ve been using Octopress to generate this site. Since I don’t know Ruby, and have to intention to learn it, I can’t hack on Octopress’s code nor on Jekyll’s, which is a shame. As I am learning Common Lisp, and wanting to work on something in it, switching to coleslaw seems perfect for me.

Trying coleslaw out

Here’s how I set up and use coleslaw.

cd /path/to/repo # this is where the post-receive script is put
git --bare init
wget -c https://raw.github.com/redline6561/coleslaw/master/examples/single-site.coleslawrc \
     -O ~/.coleslawrc
(:author "Example Setter"
 :deploy "/path/to/deploy" ; this is where coleslaw writes its output
 :domain "http://blog.example.com"
 :feeds ("lisp")
 :plugins ((mathjax)
           (disqus :shortname "my-site-name")
           (analytics :tracking-code "foo"))
 ;; this is where coleslaw writes its temporary output, which gets moved
 ;; into :DEPLOY
 :repo "/path/to/some/temporary/folder/"
 :sitenav ((:url "http://example.com/" :name "Home")
           (:url "http://twitter.com/example" :name "Twitter")
           (:url "http://github.com/example" :name "Code"))
 :title "Blog title"
 :theme "hyde")
wget -c https://raw.github.com/redline6561/coleslaw/master/examples/example.post-receive \
     -O /path/to/repo/hooks/post-receive
# edit the file
chmod +x /path/to/repo/hooks/post-receive
cd /path/to/posts
git init
git remote add prod file:///path/to/repo/
cd /path/to/deploy/.curr/
php -S localhost:8080


As I want to put my blog on Github’s pages with my custom domain, I need the generator to put a file named CNAME, whose content is my custom domain name, in the root of the generated site. However, currently coleslaw only recognizes files with post extension, along with files in the static folder, and does not allow putting custom files in the root of the site. I need to hack up a way to generate that CNAME file under the root of the site.

Forking the code

The usual workflow on Github is to fork the code, hack on it, commit and then send a pull request to the original author.

After forking the code and cloning it to my machine, I need to setup Quicklisp’s quickproject according to this so that it sees my code.

Since I have generated the posts using coleslaw, Quicklisp must have pulled the code from its repository. For safety, I uninstall Quicklisp’s coleslaw.

;; start sbcl and load Quicklisp's setup.lisp
(use-package :ql-dist)
(uninstall (release "coleslaw"))
; instructions gotten from
;   https://groups.google.com/forum/?fromgroups=#!topic/quicklisp/CvB3mwsL7l4

Hack on it

I add a property to class blog in order to capture user’s intent to integrate with Github’s pages.

; in src/config.lisp
(defclass blog ()
   ; [...]
   (github :initarg :github :initform nil :accessor github)
   ; [...]

And then the code to actually generate the CNAME file

(defgeneric deploy (staging)
        ; [...]
        (run-program "mv ~a ~a" staging new-build)
        (when (github *config*)
          (let ((cname-filename (rel-path "" "~a/CNAME" new-build))
                (stripped-url (subseq (domain *config*)
                                      (+ 2 (position #\/ (domain *config*))))))
            (with-open-file (cname cname-filename
                                   :direction :output
                                   :if-exists :supersede)
              (format cname "~a~%" stripped-url))))
        (when (probe-file prev)
        ; [...]

(Not) Send a pull request to the original author

Since the way I pulled out the domain name from the blog object is very ad-hoc, I don’t think this code is production quality yet. I should write a separate library to parse the url and then use that to robustly extract the domain name. Until then, I won’t send a pull request to the original author.