Building a Clojure app with a command-line interface?
I just started w/ Clojure (coming from Ruby) and I would like to build an small app with a command-line interface. How do I handle input/output to a CL?
I noticed that there is a clojure.contrib.command-line, but documentation is slim.
http://github.com/richhickey/clojure-contrib/blob/ffa868411cda6c617105b52b4f6f9e0f37ee8c24/src/clojure/contrib/command_line.clj
Here is an example of using its with-command-line
macro. The following code specifies a trivial class with a main method that does nothing but print out the values of its command line arguments.
(ns cmd-line-demo
(:gen-class)
(:use clojure.contrib.command-line))
(defn -main [& args]
(with-command-line args
"Command line demo"
[[foo "This is the description for foo" 1]
[bar "This is the description for bar" 2]
[boolean? b? "This is a boolean flag."]
remaining]
(println "foo: " foo)
(println "bar: " bar)
(println "boolean?: " boolean?)
(println "remaining: " remaining)))
Compile the class at the REPL:
user> (compile 'cmd-line-demo)
cmd-line-demo
Example usage
1) Executing with no command line arguments will cause the help info to be displayed. The help info can also be displayed with --help
or -h
flags. Note that the help info is automatically generated from your cmdspec.
$ java -classpath . cmd_line_demo
Command line demo
Options
--foo <arg> This is the description for foo [default 1]
--bar <arg> This is the description for bar [default 2]
--boolean, -b This is a boolean flag.
2) Unspecified arguments receive the default value as specified in the cmdspec binding. For example, bar
has a default value of 2
.
$ java -classpath . cmd_line_demo --foo "changed value"
foo: changed value
bar: 2
boolean?: nil
remaining: []
3) Boolean flags are denoted by the suffix "?" in the cmdspec. Note that the flag itself does not include the "?" as part of its name.
$ java -classpath . cmd_line_demo -boolean
foo: 1
bar: 2
boolean?: true
remaining: []
4) Also note that you may specify flag aliases by specifying multiple symbols in the cmdspec. I have done this with the boolean?
and b?
flags.
5) Finally, I've specified that remaining
capture all remaining arguments without associated flags.
$ java -classpath . cmd_line_demo -foo test file1 file2 file3
foo: test
bar: 2
boolean?: nil
remaining: [file1 file2 file3]
The old clojure.contrib.command-line has been replaced with tools.cli.
https://github.com/clojure/tools.cli
tools.cli used to be called clargon. Below are two blog posts that give examples of using tools.cli (simple replace any reference to clargon with tools.cli. Posts are out of date).
This shows a few methods ways, including old clojure.contrib.command-line
Post focusing on Clargon by original author
I'd like to add that you can do
(apply -main *command-line-args*)
below the (defn -main ...)
to make it work in interpreted mode.
Long time after the question was raised I can suggest to use docopt
libraries when it comes to build CLI interface. There is one for Clojure - docopt.clj
docopt is based on conventions that are used for decades in help messages and man pages for program interface description. Interface description in docopt is such a help message, but formalized
So you can declare your interface and document it in the same time - that is amazing and easy to do.
For more details I recommend to check http://docopt.org/
Also there is a online app to check your interface http://try.docopt.org/
And finally here is my example how the Clojure lib can be used.