0

I'm an absolute Clojure beginner and I'm trying to build a CLI app using the clojure.tools.cli library.

My problem is that I can't show any error when an option is not provided with required parameter.

What I want:

$ java -jar test.jar -m SAMPLE
Given file: SAMPLE

$ java -jar test.jar -m
ERROR: Please provide a file

What happens:

$ java -jar test.jar -m SAMPLE
Given file: SAMPLE

$ java -jar test.jar -m

$

It doesn't show anything.

Here is my code:

(ns obmed-clj.core
  (:require [clojure.tools.cli :refer [parse-opts]])
  (:gen-class))

(def cli-options
  [["-m" "--menu FILE" "Provide menu file path"
    :parse-fn #(if (nil? %) 
                   (println "ERROR: Please provide a file") 
                   %)
    :validate-fn #(println "Given file:" %)]])

(defn -main [& args]
  (parse-opts args cli-options))
Raj
  • 23
  • 1
  • 4

1 Answers1

0

You are abusing the -fn arguments here a little. Their use is to convert the "string" (in your case, since you have "--menu FILE") and then do additional validation on that (but rather use :validate [fn msg] instead). So e.g.:

user=> (def cli-opts [["-m" "--menu FILE" "menu file" 
            :parse-fn #(java.io.File. %) 
            :validate [#(.exists %) "file must exist"]]])
#'user/cli-opts

Missing argument:

user=> (parse-opts ["-m"] cli-opts)
{:arguments [],
 :errors ["Missing required argument for \"-m FILE\""],
 :options {},
 :summary "  -m, --menu FILE  menu file"}

File not existing:

user=> (parse-opts ["-m" "XXX"] cli-opts)
{:arguments [],
 :errors ["Failed to validate \"-m XXX\": file must exist"],
 :options {},
 :summary "  -m, --menu FILE  menu file"}

All is well:

user=> (parse-opts ["-m" "/etc/hosts"] cli-opts)
{:arguments [],
 :errors nil,
 :options {:menu #<java.io.File@34d63c80 /etc/hosts>},
 :summary "  -m, --menu FILE  menu file"}
cfrick
  • 35,203
  • 6
  • 56
  • 68
  • Thank you, it worked. I've added `(println (get parsed :errors))` to show errors if found. I realized that tools.cli is more complete than I thought. – Raj Dec 26 '17 at 02:42