|
57 | 57 | "Given a sequence of column widths, return a string suitable for use in |
58 | 58 | format to print a sequences of strings in those columns." |
59 | 59 | [lens] |
60 | | - (s/join (map #(str " %" (if-not (zero? %) (str "-" %)) "s") lens))) |
| 60 | + (s/join (map #(str " %" (when-not (zero? %) (str "-" %)) "s") lens))) |
61 | 61 | ;; |
62 | 62 | ;; Legacy API |
63 | 63 | ;; |
|
148 | 148 | extra-args |
149 | 149 | (drop 2 args)) |
150 | 150 |
|
151 | | - :default |
| 151 | + :else |
152 | 152 | (recur options (conj extra-args (first args)) (rest args))))))) |
153 | 153 |
|
154 | 154 | (defn- switches-for |
|
160 | 160 | (and flag (s/starts-with? s "--")) |
161 | 161 | [(s/replace s #"--" "--no-") s] |
162 | 162 |
|
163 | | - :default |
| 163 | + :else |
164 | 164 | [s])) |
165 | 165 | flatten)) |
166 | 166 |
|
|
218 | 218 | [(first specs) (rest specs)] |
219 | 219 | [nil specs]) |
220 | 220 | specs (map generate-spec specs) |
221 | | - args (normalize-args specs args)] |
222 | | - (let [[options extra-args] (apply-specs specs args) |
223 | | - banner (with-out-str (banner-for desc specs))] |
224 | | - [options extra-args banner]))) |
| 221 | + args (normalize-args specs args) |
| 222 | + [options extra-args] (apply-specs specs args) |
| 223 | + banner (with-out-str (banner-for desc specs))] |
| 224 | + [options extra-args banner])) |
225 | 225 |
|
226 | 226 | ;; |
227 | 227 | ;; New API |
228 | 228 | ;; |
229 | 229 |
|
230 | 230 | (def ^{:private true} spec-keys |
231 | 231 | [:id :short-opt :long-opt :required :desc :default :default-desc :default-fn |
232 | | - :parse-fn :assoc-fn :update-fn :validate-fn :validate-msg :missing]) |
| 232 | + :parse-fn :assoc-fn :update-fn :multi :validate-fn :validate-msg :missing]) |
233 | 233 |
|
234 | 234 | (defn- select-spec-keys |
235 | 235 | "Select only known spec entries from map and warn the user about unknown |
|
381 | 381 | (let [{:keys [validate-fn validate-msg]} spec] |
382 | 382 | (or (loop [[vfn & vfns] validate-fn [msg & msgs] validate-msg] |
383 | 383 | (when vfn |
384 | | - (if (try (vfn value) (catch #?(:clj Throwable :cljs :default) e)) |
| 384 | + (if (try (vfn value) (catch #?(:clj Throwable :cljs :default) _)) |
385 | 385 | (recur vfns msgs) |
386 | 386 | [::error (validation-error opt optarg msg)]))) |
387 | 387 | [value nil]))) |
|
444 | 444 | (find-spec specs :long-opt optarg))) |
445 | 445 | [m ids (conj errors (missing-required-error opt (:required spec)))] |
446 | 446 | [(if-let [update-fn (:update-fn spec)] |
447 | | - (update-in m [id] update-fn) |
| 447 | + (if (:multi spec) |
| 448 | + (update m id update-fn value) |
| 449 | + (update m id update-fn)) |
448 | 450 | ((:assoc-fn spec assoc) m id value)) |
449 | 451 | (conj ids id) |
450 | 452 | errors]) |
|
641 | 643 | You cannot specify both :assoc-fn and :update-fn for an |
642 | 644 | option. |
643 | 645 |
|
644 | | - :update-fn A function that receives the the current parsed option value, |
| 646 | + :update-fn Without :multi true: |
| 647 | +
|
| 648 | + A function that receives just the existing parsed option value, |
645 | 649 | and returns a new option value, for each option :id present. |
646 | 650 | The default is 'identity'. |
647 | 651 |
|
|
659 | 663 | [\"-v\" \"--verbose\" |
660 | 664 | :update-fn (fnil inc 0)] |
661 | 665 |
|
662 | | - You cannot specify both :assoc-fn and :update-fn for an |
663 | | - option. |
| 666 | + With :multi true: |
| 667 | +
|
| 668 | + A function that receives both the existing parsed option value, |
| 669 | + and the parsed option value from each instance of the option, |
| 670 | + and returns a new option value, for each option :id present. |
| 671 | + The :multi option is ignored if you do not specify :update-fn. |
| 672 | +
|
| 673 | + For non-idempotent options, where you need to compute a option |
| 674 | + value based on the current value and a new value from the |
| 675 | + command line. This can sometimes be easier than use :assoc-fn. |
| 676 | +
|
| 677 | + [\"-f\" \"--file NAME\" |
| 678 | + :default [] |
| 679 | + :update-fn conj |
| 680 | + :multi true] |
| 681 | +
|
| 682 | + :default is applied first. If you wish to omit the :default |
| 683 | + option value, use fnil in your :update-fn as follows: |
| 684 | +
|
| 685 | + [\"-f\" \"--file NAME\" |
| 686 | + :update-fn (fnil conj []) |
| 687 | + :multi true] |
| 688 | +
|
| 689 | + Regardless of :multi, you cannot specify both :assoc-fn |
| 690 | + and :update-fn for an option. |
664 | 691 |
|
665 | 692 | :validate A vector of [validate-fn validate-msg ...]. Multiple pairs |
666 | 693 | of validation functions and error messages may be provided. |
|
0 commit comments