I use Cygwin at work, so my starting point was the clj Bash script at http://en.wikibooks.org/wiki/Clojure_Programming/Getting_Started#Create_clj_Script. I used this one:
CLASSPATH="/path/to/clojure.jar"
if [ $# -eq 0 ] ; then
JLINE="/path/to/jline.jar"
CLASSPATH=$JLINE:$CLASSPATH
java -cp $CLASSPATH jline.ConsoleRunner clojure.main --repl
else
TMPFILE=""
while [ $# -gt 0 ] ; do
case "$1" in
-cp|-classpath)
CLASSPATH=$CLASSPATH:$2
shift
;;
-e)
TMPFILE="/tmp/$(basename $0).$$.tmp"
/bin/echo $2 > $TMPFILE
ARGS=$TMPFILE
break
;;
*)
ARGS="$ARGS $1"
;;
esac
shift
done
java -cp $CLASSPATH clojure.main $ARGS
if [ "$TMPFILE" != "" ] ; then
rm $TMPFILE
fi
fi
I had to edit it a bit to make it Windows friendly, but the script basically worked. However, I wasn't satisfied. I didn't want to have to manually edit the script, or an environment variable, simply to add jar files to the classpath. I wanted a simpler, more obvious way. And so I created a directory in my home directory called .clojure-classpath. The contents of the directory are:$ ls -l total 24 -rw-r--r-- 1 alexanc mkgroup-l-d 82 Jan 22 11:16 README lrwxrwxrwx 1 alexanc mkgroup-l-d 92 Jan 22 12:06 clojure-contrib.jar -> /cygdrive/c/m2repository/org/clojure/clojure-contrib/1.1.0-RC3/clojure-contrib-1.1.0-RC3.jar lrwxrwxrwx 1 alexanc mkgroup-l-d 68 Jan 22 12:06 clojure.jar -> /cygdrive/c/m2repository/org/clojure/clojure/1.1.0/clojure-1.1.0.jar lrwxrwxrwx 1 alexanc mkgroup-l-d 79 Jan 22 12:42 commons-exec-1.0.1.jar -> /cygdrive/c/m2repository/commons-exec/commons-exec/1.0.1/commons-exec-1.0.1.jar lrwxrwxrwx 1 alexanc mkgroup-l-d 60 Jan 22 12:06 jline.jar -> /cygdrive/c/m2repository/jline/jline/0.9.94/jline-0.9.94.jar lrwxrwxrwx 1 alexanc mkgroup-l-d 82 Jan 22 12:08 swank-clojure.jar -> /cygdrive/c/m2repository/swank-clojure/swank-clojure/1.1.0/swank-clojure-1.1.0.jarI already have a mountain of jar files in my local maven repository so, in order to make them available to Clojure, I simply created symbollic links to them. Then, I modified the clj
Bash script to automajically add all the jar files in this directory to the classpath prior to starting up Clojure. My new, modified version of clj is as follows:
#!/bin/bash
# set up the classpath dynamically. Note this includes the jline jar
CLASSPATH=""
for jarfile in `ls -l ~/.clojure-classpath/ | pcol 11`; do
JAR=`cygpath --windows $jarfile`
CLASSPATH="$CLASSPATH;$JAR"
done
if [ $# -eq 0 ] ; then
stty -icanon min 1 -echo
java -Djline.terminal=jline.UnixTerminal -cp $CLASSPATH jline.ConsoleRunner clojure.main
else
TMPFILE=""
while [ $# -gt 0 ] ; do
case "$1" in
-cp|-classpath)
CLASSPATH="$CLASSPATH;$2"
shift
;;
-e)
TMPFILE="/tmp/$(basename $0).$$.tmp"
/bin/echo $2 > $TMPFILE
ARGS=$TMPFILE
break
;;
*)
ARGS="$ARGS $1"
;;
esac
shift
done
java -cp $CLASSPATH clojure.main $ARGS
if [ "$TMPFILE" != "" ] ; then
rm $TMPFILE
fi
fi
The only non-standard thing in the script is the call to pcol which is a little Perl script I wrote to split a line on whitespace and print the column specified by the number. This modified version of clj:- Lists all the files in the .clojure-classpath directory, and gets the full path from the output of ls.
- Converts the path to a Windows friendly path.
- Dynamically adds every file to the classpath.
- Starts Clojure.
The next problem I had to solve was how to edit my scripts in Emacs using the same classpath. Fortunately I knew that I could do this by starting an instance of a Swank-clojure server from within the repl on the command line. Note that the swank-clojure.jar is in the .clojure-classpath directory. The script to start the server is simply:
(require 'swank.swank) (swank.swank/start-server "nul" :encoding "utf-8" :port 4005)I can start the server by:
- Running: clj start-swank.clj
- From a running repl loading start-swank.clj.
- Entering the commands directly into the running repl:
user=> (require 'swank.swank) nil user=> (swank.swank/start-server "nul" :encoding "utf-8" :port 4005) Connection opened on local port 4005 #Bingo. I can now edit my scripts in Emacs using Slime, with exactly the same classpath that will be used to run them. And since the .clojure-classpath directory contains a symbollic link to the directory I keep the scripts in (not shown in the listing above - I copied that before I added the link to the directory), all the scripts I write will automatically be on the classpath, and hence I can start building up a library of utility functions.
I am delighted with this set up, and can't wait to start writing some utility scripts in Clojure using Emacs.
0 comments:
Post a Comment