Planck is a ClojureScript REPL and script execution environment. It’s a standalone native binary for OS X. You launch it by simply typing
planck in a terminal on your Mac.
How does this work?
By default, Planck then starts a REPL. This means that it waits for you to type a Clojure expression. Planck makes entering expressions a little easier by employing a library making it possible to edit the line as well as access previously entered lines by using the up arrow.
Planck enhances this experience by providing tab completion and brace highlighting:
- When you type a closing
$ planck -v cljs.user=> (+ 2 3) Evaluating (+ 2 3) (2 + 3) 5
cljs.user=> (first [4 7]) Evaluating (first [4 7]) cljs.core.first.call(null,new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [4,7], null)) 4
That's cool when evaluating pure expressions. What about interacting with the outside environment?
Let's say you want to read the content of a file you have on disk, and you enter these forms:
(require '[planck.core :refer [slurp]]) (slurp "foo.txt")
self.inputStream = [NSInputStream inputStreamWithFileAtPath:path]
PLANCK_FILE_READER_OPEN. This capability is made available to you in ClojureScript by having functions like
slurp employ ClojureScript code like
To actually read from the file,
slurp calls another
js/PLANCK_FILE_READER_READ primitive, which invokes code like
[self.inputStream read:buf maxLength:1024]
A few Planck ClojureScript namespaces are bundled with Planck in order to provide mappings onto these I/O primitives, exposing the simple APIs—like
slurp—that you are familiar with:
In a nutshell, that’s really a big part of what Plank is: Some glue between ClojureScript and the native host environment.
Planck wraps all this with some niceties making it suitable as a scripting environment.
One aspect is the loading of custom ClojureScript source files. Let's say you have
src/my_cool_code/core.cljs, and at the REPL you invoke
Planck implements the
require “REPL special form,” which causes bootstrapped ClojureScript—specifically
cljs.js, via its
The nice thing is that
*load-fn* is also used for
:require specs that may appear in namespace declarations in your code, as well as
To top it off, Planck is free to implement
*load-fn* in convenient ways:
- It loads its own namespaces (like
- It also loads code from JAR files: Planck can be provided a classpath, specifying directories and JAR files to be searched when satisfying a load request.
To make Planck maximally useful in this regard, Planck implements all of the command line arguments that are supported by the regular Clojure JAR. This is covered in in Planck Scripting and ClojureScript Mainia.
The above covers, at a high level, how Planck works. It is actually quite simple in concept.
The real work behind Planck, to be honest, involves lots of mundane and pragmatic aspects such a making it efficient, supporting different versions of OS X, packaging / deployment, testing, bug fixes, fleshing out corner cases of APIs, etc.
Planck is definitely 90% perspiration, supported by several contributors. If you'd like to chip in to help either smooth out rough corners or to flesh out new functionality, PRs are welcome!