An executable "clojure" script

42 views
Skip to first unread message

Dudley Flanders

unread,
Jun 6, 2008, 12:56:00 PM6/6/08
to clo...@googlegroups.com
Rich mentioned that he might be open to including "clojure" launcher
scripts in the distribution so that every Clojure application wouldn't
have to reinvent that particular wheel. I've called his bluff, and put
one up on github[0]. Feedback is welcome. It's intended to live in a
bin/ directory inside the Clojure distribution, so you should check it
out there if you want to play with it:

cd whatever-your-clojure-directory-is-called
git clone git://github.com/dudleyf/clojure-bin.git bin

If you don't have git, you can download the raw script file from [1].
This one's just for *nix, but we'll need a Windows version, too. I'll
try and write it if nobody else jumps in, but I'm not a Windows user,
so it'll likely suck.

:dudley

[0] http://github.com/dudleyf/clojure-bin/tree/master/clojure
[1] http://github.com/dudleyf/clojure-bin/tree/master%2Fclojure?raw=true

Stephen C. Gilardi

unread,
Jun 6, 2008, 4:40:46 PM6/6/08
to clo...@googlegroups.com
On Jun 6, 2008, at 12:56 PM, Dudley Flanders wrote:

> Rich mentioned that he might be open to including "clojure" launcher
> scripts in the distribution so that every Clojure application wouldn't
> have to reinvent that particular wheel. I've called his bluff, and put
> one up on github[0]. Feedback is welcome.

Hi Dudley,

Thanks for the script, I think it will be helpful in making Clojure
easier to get started with. I look forward to using it.

I have a few comments:

[1] Near the bottom, clojure_classpath is set without including its
prior value. It looks like the intent was to append a value instead
of replacing the old value.

[2] This may be a simpler but still effective way to find clojure_home:

script_dir="$(cd "$(dirname "$0")"; pwd)"
clojure_home="$(dirname "$script_dir")" # the real Clojure home

[3] Consider allowing a defined "CLOJURE_HOME" environment variable to
override the automatic finding process.

[4] A generic clojure launcher might want to set any or all of:

CLOJURE_JAVA
which java executable to use
CLOJURE_JAVA_OPTS
options besides classpath and librarypath
CLOJURE_CLASSPATH
classpath to use for clojure
CLOJURE_LIBRARY_PATH
path for finding DLLs, JNI implementations, generates "-
Djava.library.path=$CLOJURE_LIBRARY_PATH" for the java command line

Consider making these environment variables (or ones with different
names that have similar meanings) affect your script's operation.

[5] Your CLOJURE_LIB variable is currently written to work for a
single directory. Consider making it work for a set of directories
separated by ":" (make it act as a "path").

[6] On the last line, enclosing "$clojure_classpath" in quotes will
allow spaces in path names.

Cheers,

--Steve

Dudley Flanders

unread,
Jun 6, 2008, 9:22:26 PM6/6/08
to clo...@googlegroups.com

On Jun 6, 2008, at 3:40 PM, Stephen C. Gilardi wrote:
> [1] Near the bottom, clojure_classpath is set without including its
> prior value. It looks like the intent was to append a value instead
> of replacing the old value.

Fixed, thanks.

> [2] This may be a simpler but still effective way to find
> clojure_home:
>
> script_dir="$(cd "$(dirname "$0")"; pwd)"
> clojure_home="$(dirname "$script_dir")" # the real Clojure home

I don't think that'll work if $0 is a symlink to the real clojure
script, though. Also, $() is a syntax error in Solaris' sh.

> [3] Consider allowing a defined "CLOJURE_HOME" environment variable to
> override the automatic finding process.

I originally left that out because the JRuby guys had a lot of "bugs"
related to users with bad JRUBY_HOME settings, but now that I think
about it, that's less likely to be a problem for Clojure.

> [4] A generic clojure launcher might want to set any or all of:
>
> CLOJURE_JAVA
> which java executable to use
> CLOJURE_JAVA_OPTS
> options besides classpath and librarypath
> CLOJURE_CLASSPATH
> classpath to use for clojure
> CLOJURE_LIBRARY_PATH
> path for finding DLLs, JNI implementations, generates "-
> Djava.library.path=$CLOJURE_LIBRARY_PATH" for the java command line
>
> Consider making these environment variables (or ones with different
> names that have similar meanings) affect your script's operation.

These are all good knobs to expose, but is it better to set these
things via environment vars or command-line options?

> [5] Your CLOJURE_LIB variable is currently written to work for a
> single directory. Consider making it work for a set of directories
> separated by ":" (make it act as a "path").

I'm not really sure why I had CLOJURE_LIB in there at all. Exposing
CLOJURE_CLASSPATH makes CLOJURE_LIB redundant.

> [6] On the last line, enclosing "$clojure_classpath" in quotes will
> allow spaces in path names.

Fixed, thanks.

Thanks for your feedback, that's exactly what I was looking for :-)

:dudley

Stephen C. Gilardi

unread,
Jun 7, 2008, 3:06:14 AM6/7/08
to clo...@googlegroups.com
>> [2] This may be a simpler but still effective way to find
>> clojure_home:
>>
>> script_dir="$(cd "$(dirname "$0")"; pwd)"
>> clojure_home="$(dirname "$script_dir")" # the real Clojure home
>
> I don't think that'll work if $0 is a symlink to the real clojure
> script, though. Also, $() is a syntax error in Solaris' sh.

Here's the equivalent with backticks:

script_dir=`dirname "$0"`
script_dir_real=`cd "$script_dir"; pwd`
clojure_home=`dirname "$script_dir_real"` # the real Clojure home

Unfortunately I can't easily test this on Mac OS X because bash is
always giving me a path without symlinks in $0 even if I put symlinks
in the path (I tried using them for the script and for its parent
directory).

>> [4] A generic clojure launcher might want to set any or all of:
>>
>> CLOJURE_JAVA
>> which java executable to use
>> CLOJURE_JAVA_OPTS
>> options besides classpath and librarypath
>> CLOJURE_CLASSPATH
>> classpath to use for clojure
>> CLOJURE_LIBRARY_PATH
>> path for finding DLLs, JNI implementations, generates "-
>> Djava.library.path=$CLOJURE_LIBRARY_PATH" for the java command line
>>
>> Consider making these environment variables (or ones with different
>> names that have similar meanings) affect your script's operation.
>
> These are all good knobs to expose, but is it better to set these
> things via environment vars or command-line options?

I would want to set those things up for my environment rarely, but
launch Clojure with a short command line often. I think environment
variables with command line arguments which append to them (for paths)
or override them (for the java executable) is a good way to go.

>> [5] Your CLOJURE_LIB variable is currently written to work for a
>> single directory. Consider making it work for a set of directories
>> separated by ":" (make it act as a "path").
>
> I'm not really sure why I had CLOJURE_LIB in there at all. Exposing
> CLOJURE_CLASSPATH makes CLOJURE_LIB redundant.

The addition of all the jar files within $CLOJURE_LIB to CLASSPATH was
a nice feature.

>> [6] On the last line, enclosing "$clojure_classpath" in quotes will
>> allow spaces in path names.

In bash, quoting "$file" on the execution line puts '' (two single
quotes) at the end of it and causes clojure to complain that it can't
open a file with an empty name. (file not found). One way to fix
this for bash is to require that files always go at the end of the
clojure command line and not process them in your "process the
options" loop--break out as soon as you see an unrecognized arg.
Then, putting "$@" (with the quotes) at the end of the command line
will append all the filenames properly quoted. ("$@" is a special
syntax intended to do just that. It's handled differently than
"$files" is in your current script.)

It looks like supporting both bash and solaris sh may be a bit of a
challenge. Fortunately bash is the default shell on both Mac OS X and
most Linux distributions.

Thanks for the updates!

--Steve

Dudley Flanders

unread,
Jun 7, 2008, 10:36:07 AM6/7/08
to clo...@googlegroups.com

On Jun 7, 2008, at 2:06 AM, Stephen C. Gilardi wrote:
> Here's the equivalent with backticks:
>
> script_dir=`dirname "$0"`
> script_dir_real=`cd "$script_dir"; pwd`
> clojure_home=`dirname "$script_dir_real"` # the real Clojure home
>
> Unfortunately I can't easily test this on Mac OS X because bash is
> always giving me a path without symlinks in $0 even if I put symlinks
> in the path (I tried using them for the script and for its parent
> directory).

bash gives you $0 as a path with the symlinks already resolved? sh,
zsh, ksh, and bash all give me the symlinked path on Mac OS 10.5. Is
the nasty symlink dance in the script not working for you, or is it
just aesthetically displeasing?

> I would want to set those things up for my environment rarely, but
> launch Clojure with a short command line often. I think environment
> variables with command line arguments which append to them (for paths)
> or override them (for the java executable) is a good way to go.

I tend to set up aliases for the commands I use often.

>> I'm not really sure why I had CLOJURE_LIB in there at all. Exposing
>> CLOJURE_CLASSPATH makes CLOJURE_LIB redundant.
>
> The addition of all the jar files within $CLOJURE_LIB to CLASSPATH was
> a nice feature.

Okay, I'll put it back in, then.

> In bash, quoting "$file" on the execution line puts '' (two single
> quotes) at the end of it and causes clojure to complain that it can't
> open a file with an empty name. (file not found). One way to fix
> this for bash is to require that files always go at the end of the
> clojure command line and not process them in your "process the
> options" loop--break out as soon as you see an unrecognized arg.
> Then, putting "$@" (with the quotes) at the end of the command line
> will append all the filenames properly quoted. ("$@" is a special
> syntax intended to do just that. It's handled differently than
> "$files" is in your current script.)

Yeah, zsh sticks the quotes in there, too. I wanted to avoid requiring
files to always be at the end of the line, but that's probably more
trouble than it's worth.

> It looks like supporting both bash and solaris sh may be a bit of a
> challenge. Fortunately bash is the default shell on both Mac OS X and
> most Linux distributions.

Solaris sh is a bit of a challenge in and of itself, but I don't think
the script needs to do anything fancy enough to justify making it
require bash.

:dudley

Stephen C. Gilardi

unread,
Jun 7, 2008, 8:26:55 PM6/7/08
to clo...@googlegroups.com
On Jun 7, 2008, at 10:36 AM, Dudley Flanders wrote:
bash gives you $0 as a path with the symlinks already resolved? sh,  
zsh, ksh, and bash all give me the symlinked path on Mac OS 10.5. Is  
the nasty symlink dance in the script not working for you, or is it  
just aesthetically displeasing?

That's interesting that we're seeing different behavior.   Im using Leopard as well.  I'll look at that again.

The symlink dance is just aesthetically displeasing, relying on the textual representation of filesystem objects to determine their type.

It looks like supporting both bash and solaris sh may be a bit of a
challenge.  Fortunately bash is the default shell on both Mac OS X and
most Linux distributions.

Solaris sh is a bit of a challenge in and of itself, but I don't think  
the script needs to do anything fancy enough to justify making it  
require bash.

Sounds right.

--Steve

Dudley Flanders

unread,
Jun 8, 2008, 3:16:46 PM6/8/08
to clo...@googlegroups.com

On Jun 7, 2008, at 7:26 PM, Stephen C. Gilardi wrote:

> The symlink dance is just aesthetically displeasing, relying on the
> textual representation of filesystem objects to determine their type.

Yep. It's super gross, but it seems to be the standard way to do it.
I've incorporated most of your suggestions, thanks!

:dudley

Reply all
Reply to author
Forward
0 new messages