Scriptjure, Static, and Disqus

06 Apr 2011

The blogging engine I use is written in clojure. I am now using scriptjure, a clojure library for generating javascript, for the javascript in my page templates.

I included scriptjure in my fork of static (clojure static site generator that runs this blog). I have modified my default.clj and now use hiccup and scriptjure for the disqus integration as follows. To adapt this code for your own use, you need only to change the string after forums – in this case: apocalispnow – to the name of your site.

I rewrote the following section to use hiccup:

Without Hiccup:

[:div {:id "disqus"} 
 (if (= (:type metadata) :post) 
 "<div id=\"disqus_thread\"></div><script type=\"text/javascript\" src=\"http://disqus.com/forums/nakkaya/embed.js\"></script><noscript><a href=\"http://disqus.com/forums/nakkaya/?url=ref\">View the discussion thread.</a></noscript><a href=\"http://disqus.com\" class=\"dsq-brlink\">blog comments powered by <span class=\"logo-disqus\">Disqus</span></a>")]]

With Hiccup:

[:div {:id "disqus"}
 (if (= (:type metadata) :post)
   (html
    [:div#disqus_thread]
    [:script {:type "text/javascript" :src "http://disqus.com/forums/apocalispnow/embed.js"}]
    [:noscript
     [:a {:href "http://disqus.com/forums/apocalispnow/?url=ref"} "View the discussion thread."]]
    [:a {:href "http://disqus.com" :class "dsq-brlink"} "blog comments powered by" [:span {:class "logo-disqus"} "Disqus"]]))]

I think this is easier to read, more idiomatic, and makes embedding disqus in clojure web applications easier. Likewise for embedding javascript, though scriptjure may be overkill.

Without scriptjure & hiccup:

  (if (= (:type metadata) :post) 
    "<script type=\"text/javascript\">
//<![CDATA[
(function() {
             var links = document.getElementsByTagName('a');
             var query = '?';
             for(var i = 0; i < links.length; i++) {
                     if(links[i].href.indexOf('#disqus_thread') >= 0) {
                                                                       query += 'url' + i + '=' + encodeURIComponent(links[i].href) + '&';
                                                                       }
                     }
             document.write('<script charset=\"utf-8\" type=\"text/javascript\" src=\"http://disqus.com/forums/nakkaya/get_num_replies.js' + query + '\"></' + 'script>');
             })();
//]]>
</script>")
[:script {:type "text/javascript"}
 "$(document).ready(function() {
      $(\"pre\").wrapInner(\"<code></code>\");
      hljs.initHighlightingOnLoad();
  });"]

With scriptjure & hiccup:

(if (= (:type metadata) :post)
  (html
   [:script {:type "text/javascript" :charset "utf-8" :src
             (str "http://disqus.com/forums/apocalispnow/get_num_replies.js"
                  (js (do
                        (var links (.getElementsByTagName document "a"))
                        (var query "?")
                        (var i 0)
                        (while (< i (.length links))
                          (if (>= (.href.indexOf (aget links i) "#disqus_thread") 0)
                            (set! query
                                  (+ query "url" i "="
                                     (encodeURIComponent (.href (aget links i))) "&")))
                          (inc i))
                        (return query))))}])

Above I use the (html) function to wrap everything so if doesn't complain.

[:script {:type "text/javascript"}
 (js (. ($ document) ready 
        (fn []
          (. ($ "pre") wrapInner (clj (html [:code])))
          (.initHighlightingOnLoad hljs))))]

I do have some comments on scriptjure. First let me say that I think it's an awesome project and opens up possibilities for a dynamic web frontend to clojure apps. Hiccup and Scriptjure are a great example of how to create web pages from within clojure. However, scriptjure is still in early development. If you've taken a look at my code above you may notice some strange choices in terms of representing the javascript in scriptjure. I had to tweak my solution to work around what is currently supported in scriptjure, which was not much of a hassle but may be a deterrent for some.

For instance, I was unable to figure out how to represent a js for loop in scriptjure. After some research I realized it was because for isn't currently in the scriptjure special forms, which you can browse to here. Another issue was working around set! with scriptjure. set! performs basic javascript assignment, as seen below:

> (js (set! x 5))
"x = 5;\n" 

Attempts at manual assignment seem to fail:

> (js (= x 5))
"(x === 5)"
> (js (== x 5))
"(x == 5)"
> (js (+= x 5))
"(x += 5)"

I would like to be able to use (= 1 1) for tests and (== x y), (+= x y) for javascript assignment in scriptjure. Oh well…

All in all, I'm excited to see how scripture progresses. I think one of the cool things about the project is interoperability between clojure and javascript. Coupled with enlive, I see some cool projects in the near future.

Lein 5.0 out

24 Mar 2011

Lein 5.0 is out. Upgrade.

How not to parse the modeline in stumpwm:

10 Mar 2011

This is one of those where you look back on what you've written and cringe.

(defparameter *strip-newline* " | xargs echo -n"
  "command to strip newline from shell commands")
(defparameter *mode-line-spacer* " | "
  "string that seperates *mode-line-contents*")
(defparameter GRP-WIN-ML-FMT "%g %v^>"
  "group & window mode-line format")
(defparameter DATE-COMMAND "date"
  "date mode-line shell-command")
(defparameter POWER-COMMAND "acpi | awk '{print $4}'"
  "power mode-line shell-command")
(defparameter MUSIC-COMMAND "mpc status | head -n 1"
  "music mode-line shell-command")
(defparameter *mode-line-contents* (list GRP-WIN-ML-FMT DATE-COMMAND POWER-COMMAND MUSIC-COMMAND)
  "list of mode-line variables and shell-commands") 

(defmacro parse-mode-line (mode-text)
  "macro for applying shell command wrapper to *mode-line-contents*. Strip newline with *strip-newline*"
  `(eval (stumpwm:run-shell-command (concatenate 'string ,mode-text *strip-newline*) t)))

(setf stumpwm:*screen-mode-line-format*
      `(:eval (mapcar #'(lambda (x) (concatenate 'string x *mode-line-spacer*)) 
                      (cons (car *mode-line-contents*) 
                            (mapcar (lambda (x) (macroexpand-1 (parse-mode-line x)))
                                    (cdr *mode-line-contents*))))))

A Naive Gnus Setup

08 Mar 2011

Use Gnus as MUA

Overview

I switched over from mutt to gnus a few months back and thought I'd share my setup. I'm pulling from a remote server where I run dovecot, procmail, and postfix (a setup I've been happy and maybe I'll post on it later). On the remote server, I pull from all my mail accounts using getmail into the maildir hierarchy which is the mailstore for my user in dovecot (~/mail). The reason I use getmail instead of offlineimap at this stage is I don't want bidirectional mail syndication upstream to my other accounts.

Getting the mail

I pull my mail using offlineimap to my local machine. If I move mail on the local machine in gnus, then my changes are reflected back to the server due to offlineimap's bidirectional syndication. Sweet. I use maildir format on the local machine as well.

Running a local imap server

I know what you're thinking: (take 3 (repeat "why?!")). The answer is simple: emacs is not multithreaded. The bottom line is that I try to stick to the unix philosophy while still doing everything from within emacs. Emacs is a frontend for other services on my machine, which reduces the load on the text editor. Without this approach, you'll be using elisp to do tasks which should be done by something else.

Pandoc is awesome

25 Feb 2011

I have just started to use pandoc and am blown away. I haven't really used many tools written in haskell, but I've always been impressed. Pandoc is no different. It converts one markup format into another and is able to convert to and from org files, which is a huge plus.

However, a warning: do not install pandoc from the debian repos!

At the time of this writing, Pandoc is v. 1.8.1.1 (2011-02-13). Org writer was included in v. 1.8 (2011-01-30). The current version in sid (unstable) is 1.5.11. The current version in experimental is 1.6-1.

This is a little too ridiculous if you ask me.

If you're on a debian system, do the following:

  • Install cabal
$ sudo aptitude install cabal-install
  • Update cabal
$ cabal update

The next step is not required, but it is just an easy way to get the most recent version of cabal and ditch the debian package in the process. Because you will have to add ~/.cabal to your path to run pandoc, it makes sense to do this in my opinion. If you don't do this step, cabal will whine about everything being deprecated (probably fine).

  • If it prints that there is a new version of cabal available, run the following:
$ cabal install cabal-install
  • If it whines about zlib, install the following with aptitude:
$ sudo aptitude install libghc6-zlib-dev zlibc
  • Install pandoc through cabal:
$ cabal install pandoc
  • Add cabal bin directory to your path, you can do this two ways:

– Temporary add:

$ export PATH=$PATH:~/.cabal/bin/

– Permanent add (for those using bash):

$ echo 'export PATH=$PATH:~/.cabal/bin/' >> .bashrc
$ source ~/.bashrc

Now go grab a markdown readme off of github or something and try the following:

$ pandoc -f markdown -t org README

You should have a nice org mode file!

For anybody who would like to compare version disparity between pandoc-debian and pandoc in cabal, here are the links:

debian: http://packages.debian.org/search?keywords=pandoc

pandoc: http://johnmacfarlane.net/pandoc/releases.html

fpc

My Blog

25 Feb 2011

Welcome

This is my personal blog that is still a work in progress. I've been looking for a good blogging setup for a while and I think I've finally found what I've been looking for with static. So here is what I'm talking about:

Blog like you code

Use the tools you know

This is a big one for me. I want to be able to blog in emacs. Why is this important? Well, for me, it is mainly ease of use. I really like emacs and tend to do most things in it or using the emacs "paradigm." I run stumpwm, a tiling window manager written in common lisp which is modeled after GNU/screen and GNU/emacs. I check my mail with gnus and offlineimap. I talk with people using erc and bitlbee. I browse the web with conkeror. I use emacs for latex, lisp(s), and todo-lists with org-mode. Org-mode is something that has really changed my life. I've even started to experiment with typesetting documents using org-mode. Long story short, I want a blog setup which consists of firing up an org file in an emacs buffer.

Use version control (aka write locally, have drafts, and push when you're ready)

I'd like to edit my blog posts on my own machine. This fits in with the earlier point: editing blog posts on the web is potentially less reliable. I know there are blogging systems with drafts, but I'd rather edit in emacs on my own machine and use git to store drafts that aren't ready for the web. With static, I can launch a jetty server and visit my site and check out my post before pushing to the web. Because it is a static site generator, I don't have to worry about differences between my remote machine where I host the site and my local machine where I test the site.

Also, using git I can keep the site anywhere. I keep a copy of my blog on github as well just for the hell of it ;).