Clojureにヒアドキュメント的な機能を追加しつつ、compojureでコードを埋め込んでsyntax highlightを効かせる

タイトルが長い。compojure(clojureでsinatra likeなことができる)でwebサイトを作っていたが、RubyやらClojureやらのコードを埋め込みたい。要ははてなのsuperpre記法っぽいものが欲しかったのである。

clojureに標準でヒアドキュメント的なことはできないが、リーダーマクロで怪しいことをすればそれっぽいことができるようになる。

これでclojureのコード内にrubyやらなんやらのコードを埋め込めるようになった。

syntax highlightにはSyntaxHighlighterが有名そうなのでこれを使うことにする。compojureでcssやらjsを扱うためにはrootディレクトリにpublicというディレクトリを作って、その中に入れていけばよい。syntaxhighlighterをダウンロードして(リネームして)、compojureを使っているコードのヘッダに相当するところでこんな感じに書く。

(defn head [title]
  [:head
   [:meta{:charset "utf-8"}]
   [:title title]
   [:link{:rel "stylesheet"
	  :href "stylesheet.css"
	  :type "text/css"}]
   [:script{:type "text/javascript"
	    :src "/syntaxhighlighter/scripts/shCore.js"}]
   [:script{:type "text/javascript"
	    :src "/syntaxhighlighter/scripts/shBrushRuby.js"}]
   [:script{:type "text/javascript"
	    :src "/syntaxhighlighter/scripts/shBrushClojure.js"}]
   [:script{:type "text/javascript"
	    :src "/syntaxhighlighter/scripts/shBrushCpp.js"}]
   [:link{:type "text/css"
	  :rel "stylesheet"
	  :href "/syntaxhighlighter/styles/shCore.css"}]
   [:link{:type "text/css"
	  :rel "stylesheet"
	  :href "/syntaxhighlighter/styles/shThemeEclipse.css"}]
   [:script {:type "text/javascript"}
    "SyntaxHighlighter.all()"]])

ちなみにsyntaxhighlighterにはダウンロードした状態だとclojure用のものは入っていない。が、公開してくれている人がいるので、syntaxhighlighter/scripts以下にjsファイルを放り込んでおく。

はてな記法のsuper pre記法っぽく使えるように適当に関数を用意しておく。gutterなんとかっていうのは行番号を表示しない、というやつのようだ。

(defn spre [lang body]
  (vector :pre
	  (hash-map :class (str "brush: " lang "; gutter: false"))
	  body))
   (spre "ruby" (str #-EOM
#!/usr/bin/ruby
require 'enumerator'

STDIN.each_line do |line|
  words = line.split(/\s/)
  words.each_cons(2) do |word|
    unless word.empty?
      a, b = word
      printf("%s\s%s\t1\n", a, b)
    end
  end
end
EOM))

するとこんな感じできれいに埋め込めて幸せになれる。
Publication
うほほい。