Live coding is a methodology and a mindset that lends itself to all kinds of scenarios. When composing music, designing an algorithm or sketching with CSS, instant feedback informs the creator of his ideas while he's nurturing them. The workflow influences the thought process as it's happening. It’s a bottom-up approach, well-known among Lispers, but also by artists of all kinds. Live coding is to programmers what jazz is to musicians, a culture of improvisation, a set of techniques that fluidify the pursuit of a higher goal.
tl;dr Scroll down for a video demonstrating live coding applied to sketching with CSS.
This post is meant to demonstrate the symbiosis between powerful interactive programming environments such as Clojure and Emacs. Emacs is well known to be a glorified interactive environment. Clojure, as a Lisp language, provided a REPL from day one. The tooling around it, on the other hand, took some time to coalesce. In the early days, every IDE came with its own REPL foundation (enclojure-repl, swank-clojure, counterclockwise). Then the nREPL came along—a community effort to standardize protocols and APIs around the REPL. Cider is an Emacs Lisp client that leverages the nREPL to great effect, establishing interoperability between the Clojure and Emacs ecosystems, and offering many tooling opportunities in the process.
Let’s consider sketching with CSS, a new and welcome trend in web design that eschews photoshop comps, mockups or prototypes. Instead, the design process takes place in the target medium—the browser—from the get-go. This strategy is sound and cost-effective because it eliminates the need for an intermediary, redundant stage of converting media to and fro authoring tools.
A live coding setup for web applications is not always trivial: code typically runs on the server-side and on the client-side, two environments with which you might want to interact. Known techniques include a plugin called lein-ring, providing hot reloading when Ring handlers change. Or Stuart Sierra's reloaded workflow, which allows you to refresh your application code at the tip of a keyboard binding. Also, specialized REPLs such as Austin are available for Clojurescript, enabling real-time in-browser interaction.
But sketching with CSS is a simple use case that calls for a simple workflow. All we need is sending a HTML string to a running browser. Emacs Lisper Brian Taylor wrote an extension mode called impatient-mode, initially used on buffers with HTML source. Since we’re dealing with Clojure source code and not HTML, I've submitted a patch that allows to define a user filter on the current buffer, so that transformation to HTML can occur prior to the browser dispatch. The patch has been merged and the functionality is now available in master.
Here is a demo adapted from the flexbox tutorial by Sean Firoritto:
A quick glance at the github repo will reveal a bare minimum setup: only one source file and two dependencies in project.clj. So how is this possible? Hiccup emits HTML strings. Garden emits CSS directives. It's all strings, after all. You still need a Clojure REPL in the background to evaluate your hiccup and garden functions, but that's about it.
If you're going to try this at home, and you should, here are the steps to repeat:
- Clone the repo.
$ git clone email@example.com:danielsz/sketching-with-css-in-clojure.git $ cd sketching-with-css-in-clojure $ emacs src/fioritto/sketch.clj
- In Emacs, start a Clojure REPL, for example
M-x cider-jack-inand load the file with
- Start Emacs's embedded web server.
- With the buffer visiting sketch.clj, start impatient-mode,
M-x impatient mode.
- Try now:
M-x imp-visit-buffer. You will see the buffer in your browser. That's because the default filter for non-html source files is set to
htmlize. We'll want to set our own filter for Clojure buffers.
- The user filter, a regular Emacs lisp function, can be found in the root folder of the project (sketching.el). Open it and evaluate it (
C-x C-e) so that Emacs knows about it. Now
M-x imp-set-user-filterand type imp-clj-html.
(require 's) (defun imp-clj-html (buffer) (with-current-buffer (get-buffer buffer) (cider-eval-defun-at-point)) (let* ((content (with-temp-buffer (cider-interactive-eval-print "(fioritto.sketch/page)") (sleep-for 0.1) (buffer-string))) (sanitized-content (s-replace-all '(("\\n" . "") ("\\\"" . "'")) content))) (princ sanitized-content (current-buffer)) ) (delete-region (point-min) (+ (point-min) 1)) (delete-region (- (point-max) 1) (point-max)))
The secret sauce is cider-interactive-eval-print, which evaluates a Clojure expression and prints its output in an Emacs buffer. In our case, it calls fioritto.sketch/page on the REPL, a HTML emitting function, wich impatient-mode will subsequently send to the browser.
- Try again:
M-x imp-visit-buffer. Now make changes in your Clojure buffer and witness instant rendering in the browser.
Happy live coding!