|
39 | 39 | (doseq [row rows] |
40 | 40 | (println (apply format (str (format (str "%" pad "s") "") fstr) row))))))) |
41 | 41 |
|
42 | | -(defn coerce-to-pairs [o] |
43 | | - (if (vector? o) |
44 | | - (partition 2 o) |
45 | | - o)) |
46 | | - |
47 | 42 | (defn short? [f] |
48 | 43 | (re-find #"^-[^-]$" f)) |
49 | 44 |
|
|
221 | 216 | (map #(str "-" %) (next flag)) |
222 | 217 | [flag]))) |
223 | 218 |
|
224 | | -(def flag-re #"^(--?)(\[no-\])?(.+)$") |
225 | | - |
226 | | -(defn cmd->flags [cmdspec args] |
227 | | - (if (seq args) |
228 | | - (when-let [cmds (:commands cmdspec)] |
229 | | - (cmd->flags (get (into {} (cmdspec/prepare-cmdpairs (:commands cmdspec))) |
230 | | - (first args)) |
231 | | - (rest args))) |
232 | | - (:flags cmdspec))) |
233 | | - |
234 | | -(defn parse-flagstr [flagstr flagopts] |
235 | | - (let [;; support "--foo=<hello>" and "--foo HELLO" |
236 | | - [flags argdoc argnames] (cmdspec/parse-arg-names flagstr) |
237 | | - argcnt (count argnames) |
238 | | - ;; e.g. "-i,--input, --[no-]foo ARG" |
239 | | - flagstrs (map #(re-find flag-re %) flags) |
240 | | - flag-key (keyword (or (some (fn [[_ dash no flag]] |
241 | | - (when (= "--" dash) flag)) |
242 | | - flagstrs) |
243 | | - (last (first flagstrs))))] |
244 | | - (merge {:flagstr flagstr |
245 | | - :argdoc argdoc |
246 | | - :flags flags |
247 | | - :args argnames |
248 | | - :key flag-key |
249 | | - :argcnt argcnt} |
250 | | - flagopts))) |
251 | | - |
252 | | -(defn prepare-flagpairs [flagstrs] |
253 | | - (when (seq flagstrs) |
254 | | - (map (fn [[flagstr flagopts]] |
255 | | - (let [flagopts (if (var? flagopts) |
256 | | - {:doc (:doc (meta flagopts)) |
257 | | - :handler flagopts} |
258 | | - flagopts)] |
259 | | - [flagstr (parse-flagstr flagstr (if (string? flagopts) {:doc flagopts} flagopts))])) |
260 | | - (coerce-to-pairs flagstrs)))) |
261 | | - |
262 | | -(defn build-flagmap-entries [[flagstr flagopts]] |
263 | | - (let [{:keys [args key argcnt flags] :as parsed-flagstr} flagopts |
264 | | - flags (map #(re-find flag-re %) flags)] |
265 | | - (for [[_ dash no flag] flags |
266 | | - negative? (if no [true false] [false])] |
267 | | - (cond-> {:flag (str dash (if negative? "no-") flag) |
268 | | - :key key |
269 | | - :argcnt argcnt} |
270 | | - (= dash "-") |
271 | | - (assoc :short? true) |
272 | | - (seq args) |
273 | | - (assoc :args args) |
274 | | - no |
275 | | - (assoc :value (not negative?) |
276 | | - :boolean? true) |
277 | | - :-> |
278 | | - (merge flagopts))))) |
279 | | - |
280 | | -(defn parse-flagstrs [flagpairs] |
281 | | - (into {"-h" {:key :help :value true} |
282 | | - "--help" {:key :help :value true}} |
283 | | - (comp |
284 | | - (mapcat build-flagmap-entries) |
285 | | - (map (juxt :flag identity))) |
286 | | - flagpairs)) |
287 | | - |
288 | 219 | (defn add-defaults [init-opts flagpairs] |
289 | 220 | (reduce (fn [opts flagspec] |
290 | 221 | (if (some? (get opts (:key flagspec))) |
|
302 | 233 | init-opts |
303 | 234 | (map second flagpairs))) |
304 | 235 |
|
305 | | -(defn add-processed-flags |
306 | | - "We process flag information for easier use, this results in |
307 | | - `:flagpairs` (ordered sequence of pairs, mainly used in printing help |
308 | | - information), and `:flagmap` (for easy lookup), added to the `cmdspec`. As we |
309 | | - process arguments we may need to add additional flags, based on the current |
310 | | - subcommand. This function is used both for the top-level as for subcommand |
311 | | - handling of flags." |
312 | | - [cmdspec extra-flags] |
313 | | - (let [flagpairs (prepare-flagpairs extra-flags) |
314 | | - flagmap (parse-flagstrs flagpairs)] |
315 | | - (-> cmdspec |
316 | | - (update :flagpairs (fn [fp] |
317 | | - (into (vec fp) |
318 | | - ;; This prevents duplicates. Yes, this is not pretty. I'm very sorry. |
319 | | - (remove #((into #{} (map first) fp) (first %))) |
320 | | - flagpairs))) |
321 | | - (update :flagmap merge flagmap)))) |
322 | | - |
323 | 236 | (defn split-flags |
324 | 237 | "Main processing loop, go over raw arguments, split into positional and flags, |
325 | 238 | building up an argument vector, and flag/options map." |
|
331 | 244 | opts opts] |
332 | 245 | ;; Handle additional flags by nested commands |
333 | 246 | (let [extra-flags (when-not (seen-prefixes args) |
334 | | - (cmd->flags cmdspec args)) |
335 | | - opts (add-defaults opts (prepare-flagpairs extra-flags)) |
336 | | - cmdspec (add-processed-flags cmdspec extra-flags)] |
| 247 | + (cmdspec/cmd->flags cmdspec args)) |
| 248 | + opts (add-defaults opts (cmdspec/prepare-flagpairs extra-flags)) |
| 249 | + cmdspec (cmdspec/add-processed-flags cmdspec extra-flags)] |
337 | 250 | (cond |
338 | 251 | (nil? arg) |
339 | 252 | [cmdspec args opts] |
|
0 commit comments