clojureclojure-contrib

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


Solution

  • 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]