Wednesday, February 1, 2012

cljsh & repls - so many repls, so little time...

"repls" is a persistent clojure repl-server, while "cljsh" is the associated client that sends the clojure code that is passed as command line arguments and/or as a clj-files to that repl-server for evaluation. The code and detailed installation instructions can be found on github: https://github.com/franks42/lein-repls.

With a number of annotated command line sessions, I wanted to illustrate some of the features of cljsh and repls. The first thing you have to do is start a new project with lein, and for this example, that's all we need to do:


We created a new "cljsh-test" project, and started the repl-server inside of the project directory tree with "lein repls". Besides the repl-server, it also started an interactive java-based repl-client. We will not use this repl-client at all, but you should consider it like a "console" as it will show the error messages and stack traces if anything goes wrong with the submitted code by cljsh. Note that the repl-prompt shows the "user" namespace as the default, which will be the starting point for all cljsh invocation.

Hello World in many flavors and name spaces.
The next session shows a different terminal session from the one where the repl-server was started. Note that you have to start the cljsh-repls interaction from within the same project directory where you started the server. The reason is that the repl-server recorded the port-number on which it listens in the project's home directory (.lein_repls), and cljsh will use that info to connect to the right server.


As you see, clj-code can be submitted as option values on the command line, and -c and -e are equivalent (cljsh -h will give you a list of all the option). Furthermore, the default namespace seems to be "user" as expected.


Notice that the namespace set in a cljsh invocation is not persistent across invocations - each invocation starts at the default ns. Newly created vars and functions are persistent, however, and can be used across invocations.

Eval results and errors.
The evaluation results are discarded by default. The -p option turns the printing of eval results on. Notice also that any errors that are reported in stack traces and such, are shown on the console:


Error is shown on console:


The many ways to skin the script.
Clojure code can be passed as statements or as files in a number of different ways:


cljsh processes the code specified by the options in sequence. Note that the input from stdin is last by default and can optionally be indicated with "-".

Note that all the code submitted with one cljsh invocation is evaluated within the same context: changing the ns in the first statement has effect for all subsequent statements within that one invocation.

One other option is to create executable "#!" clojure-shell script files, like:



which also show that cljsh passed the additional arguments in the var "cljsh.core/*cljsh-command-line-args*".

The following last example show that the -t flag allows you to pass arbitrary data thru stdin, which you can then process with you clojure scripts. Unix-style filters can be written that way:


Well, enough for this first cljsh blog... the plan is to show how to use cljsh with labrepl, growl and macosx-automation next time.

No comments:

Post a Comment

Followers