Skip to content

Instantly share code, notes, and snippets.

@tatut
Created March 6, 2016 10:54
Show Gist options
  • Save tatut/a447e916c79ac0cc7bee to your computer and use it in GitHub Desktop.
Save tatut/a447e916c79ac0cc7bee to your computer and use it in GitHub Desktop.
Uncle Bob's arg parsing in Clojure
(ns args)
(defn- parse-schema
"Parse comma separated schema. Returns map of character to type keyword."
[schema-spec]
(into {}
(map (fn [flag]
(let [chr (.charAt flag 0)
spec (subs flag 1)]
[chr (case spec
"" :boolean
"#" :integer
"*" :string)])))
(.split schema-spec ",")))
(defn- parse-arg
"Parse a single argument string in the schema."
[schema arg]
(let [chr (.charAt arg 1)]
(if-let [type (schema chr)]
{chr (case (schema chr)
:boolean true
:integer (Integer/parseInt (subs arg 2))
:string (subs arg 2))}
(throw (Exception. (str "Unrecognized flag: " arg))))))
(defn args [schema-spec args-array]
(let [schema (parse-schema schema-spec)]
(reduce merge
(into {}
(map (juxt first (constantly false)))
(filter (comp #(= :boolean %) second) schema))
(map (partial parse-arg schema) args-array))))
;; Works like:
;; (args "l,p#,d*" (into-array String ["-p8080" "-dFoo" "-l"]))
;; => {\l true, \p 8080, \d "Foo"}
;;
;; (args "l,p#,d*" (into-array String ["-p8080" "-dFoo"]))
;; => {\l false, \p 8080, \d "Foo"}
;;
;; (args "l,p#,d*" (into-array String ["-p8080" "-dFoo" "-X"]))
;; Exception Unrecognized flag: -X
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment