Command Line Flags in Clojure

Clojure provides a built-in clojure.tools.cli library for parsing command-line options. We’ll use this library to implement our example command-line program.

(ns command-line-flags
  (:require [clojure.tools.cli :refer [parse-opts]]
            [clojure.string :as string])
  (:gen-class))

(def cli-options
  [["-w" "--word WORD" "a string"
    :default "foo"]
   ["-n" "--numb NUM" "an int"
    :default 42
    :parse-fn #(Integer/parseInt %)
    :validate [#(< 0 % 100) "Must be a number between 0 and 100"]]
   ["-f" "--fork" "a bool"]
   ["-s" "--svar SVAR" "a string var"
    :default "bar"]
   ["-h" "--help"]])

(defn -main [& args]
  (let [{:keys [options arguments errors summary]} (parse-opts args cli-options)]
    (if (:help options)
      (println (str "Usage:\n" summary))
      (do
        (println "word:" (:word options))
        (println "numb:" (:numb options))
        (println "fork:" (:fork options))
        (println "svar:" (:svar options))
        (println "tail:" (string/join " " arguments))))))

To experiment with the command-line flags program, it’s best to first compile it and then run the resulting JAR file directly.

$ lein uberjar

Try out the built program by first giving it values for all flags.

$ java -jar target/command-line-flags-0.1.0-SNAPSHOT-standalone.jar -w opt -n 7 -f -s flag
word: opt
numb: 7
fork: true
svar: flag
tail: 

Note that if you omit flags they automatically take their default values.

$ java -jar target/command-line-flags-0.1.0-SNAPSHOT-standalone.jar -w opt
word: opt
numb: 42
fork: false
svar: bar
tail: 

Trailing positional arguments can be provided after any flags.

$ java -jar target/command-line-flags-0.1.0-SNAPSHOT-standalone.jar -w opt a1 a2 a3
word: opt
...
tail: a1 a2 a3

Use the -h or --help flag to get automatically generated help text for the command-line program.

$ java -jar target/command-line-flags-0.1.0-SNAPSHOT-standalone.jar -h
Usage:
  -w, --word WORD    a string
  -n, --numb NUM     an int
  -f, --fork         a bool
  -s, --svar SVAR    a string var
  -h, --help

If you provide a flag that wasn’t specified in the cli-options, the program will print an error message.

$ java -jar target/command-line-flags-0.1.0-SNAPSHOT-standalone.jar -wat
Unknown option: "-wat"

This Clojure implementation uses the clojure.tools.cli library to parse command-line options. It defines the options using a vector of option specifications, which includes the short and long names of each option, along with their descriptions, default values, and any parsing or validation functions.

The -main function uses parse-opts to process the command-line arguments, and then either prints the help message or the values of the options and any additional arguments.