2

I'd like to parse a command line string, and group any command switches with their subsequent arguments. So, for example:

(parse "git branch -d f1 f2 -a -m message") => 
[["-d" "f1" "f2"]["-a"]["-m" "message"]]

I ignore args not immediately following a switch.

The code I wrote to do this is as follows:

(defn switch? [s] (re-find #"\-+" s))
(defn tokenify [s] (clojure.string/split s #" "))
(defn parse [cmd-str]
  (loop [lst (tokenify cmd-str), acc [], _acc []]
    (let [fs (first lst), rs (rest lst), new? (empty? _acc)]
      (cond (empty? lst) (if new? acc (conj acc _acc))
            (switch? fs) (if new?
                           (recur rs acc (conj _acc fs))
                           (recur rs (conj acc _acc) (conj [] fs)))
            :else (if new?
                    (recur rs acc _acc)
                    (recur rs acc (conj _acc fs)))))))

That works, but it's pretty low level and horrible. Is there a simple way using reduce or partition or group-by that would make the same functionality a lot cleaner and more idiomatic?

1

1 Answer 1

2

here's a basic outline of using clojure.tools.cli

(def command-line-spec
  [["-m" "--mode 0|1" "description of option that takes 1 or 0"
    :parse-fn #(case (s/lower-case %)
                 ("1" "true" "create") :one
                 ("0" "false" "destroy") :zero
                 :invalid)
    :default :one
    :validate [#{:one :zero} "Unsupported mode"]]
   ["-c" "--config type1|type2|..."
    :desc "config specifies what to do"
    :default :dostuff
    :parse-fn #(if (keyword? %)
                 %
                 (-> % s/lower-case keyword))
    :validate-fn #(contains? configurations %)]
    ["-n" "--name service Name"
     :default (getenv "NAME")]
   [nil "--min number"
    :default 7 :parse-fn #(Integer/parseInt %)]
   [nil "--max number"
    :default 7 :parse-fn #(Integer/parseInt %)]
   [nil "--public true|false" "true or false"
    :default false
    :parse-fn #(Boolean/parseBoolean %)]
   ["-h" "--help"]])

(defn -main [& args]
  (let [{:keys [options arguments errors summary]}
         (parse-opts args
                     command-line-spec)
 ... ) 
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.