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?
tools.cliand then manipulate the parameters as data. github.com/clojure/tools.cli