2

I'm a Clojure newbie.

I need multiple arguments for option -a of my cli app, like:

java -jar app.jar -a 12 abc xyz

First one is a number, and other two have to be strings.

My code is:

["-a" "--add LINE TYPE ENTRY" "Add entry to specified line number of the menu"
:parse-fn #(split % #" ")
:validate [#(number? (Integer/parseInt (first %))) "ERROR: Invalid position"]

But I observed the % passed to :parse-fn function to be a vector containing only the first argument, i.e., [12]

the other arguments are listed as value of the key :arguments of the map returned by parse-opts

Now,
(1) Is there a way to validate those unprocessed arguments?
(2) How will I retrieve and use those arguments?

Raj
  • 23
  • 1
  • 4
  • 1
    I have not seen this done. You could go the route of passing this in one argument (e.g. `java ... -a "12 abc xyz"` (maybe even use a better separator than ` ` like e.g. `:` or `/`)) -- or pass that with three arguments (e.g. `-[lte]`) -- or just dont use tools.cli at all, pick the first argument as a "command" from allowed ones and apply the rest of the args to it. From a plain user persective i find this even odd. No unix CLI comes into my mind, that has multiple arguments to a single-letter option. – cfrick Dec 26 '17 at 13:17

1 Answers1

1

I think you cannot parse white-space separated values for one option at a time. Normally you would do it like this: -a opt1 -a opt2 -a opt3, but since you have a different type for opt1 this will not work.

What about separating them by comma?

(require '[clojure.tools.cli :refer [parse-opts]])

(def cli-opts
  [["-a" "--add LINE TYPE ENTRY" "Add entry to specified line number of the menu"
    :parse-fn (fn [a-args]
                (-> a-args
                    (str/split #",")
                    (update 0 #(Integer/parseInt %))))
    :validate [(fn [[num s1 s2]]
                 (and (number? num)
                      (string? s1)
                      (string? s2)))]]])

(parse-opts ["-a" "12,abc,xyz"] cli-opts)

;;=> {:options {:add [12 "abc" "xyz"]}, :arguments [], :summary "  -a, --add LINE TYPE ENTRY  Add entry to specified line number of the menu", :errors nil}

Another option would be to introduce two or three different options for a: --line, --type and --entry.

Michiel Borkent
  • 34,228
  • 15
  • 86
  • 149
  • Well a single string with comma delimiter seems a good choice... it wont interfere with names and numbers in anyways. Thank you, I'll try it. – Raj Dec 26 '17 at 16:06