Building a Clojure app with a command-line interface?

ClojureClojure Contrib

Clojure Problem Overview


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

Clojure Solutions


Solution 1 - Clojure

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 This is the description for foo [default 1] --bar 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]

Solution 2 - Clojure

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

Solution 3 - Clojure

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.

Solution 4 - Clojure

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.

Solution 5 - Clojure

Maybe try jark. Jark is a tool to run clojure programs on a persistent JVM. It has some useful command-line utilities.

https://clojars.org/jark

jark ns load file.clj
jark <namespace>.<function> <args>
jark if cli-json <namespace><function> args 

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkushView Question on Stackoverflow
Solution 1 - ClojurealanlcodeView Answer on Stackoverflow
Solution 2 - ClojureJake McCraryView Answer on Stackoverflow
Solution 3 - ClojurePepijnView Answer on Stackoverflow
Solution 4 - ClojuresignalpillarView Answer on Stackoverflow
Solution 5 - ClojureicylisperView Answer on Stackoverflow