Skip to content

Instantly share code, notes, and snippets.

@MrGung
Created September 29, 2022 12:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MrGung/671b3476f9274ef6955bb5d4ba9fde29 to your computer and use it in GitHub Desktop.
Save MrGung/671b3476f9274ef6955bb5d4ba9fde29 to your computer and use it in GitHub Desktop.
;; https://stackoverflow.com/questions/24897818/how-to-add-docstring-support-to-defn-like-clojure-macro
(defn resolve-params
"Takes parameters to a def* macro, allowing an optional docstring and opts by sorting
out which parameter is which.
Returns the params, body, docstring, and opts it found."
[args]
(let [[docstring args] (if (string? (first args))
[(first args) (rest args)]
[nil args])
[params args] [(first args) (rest args)]
[opts args] (if (associative? (first args))
[(first args) (rest args)]
[nil args])
body args]
[params body docstring opts]))
(defmacro with-cli-pipe-for
[piped-field-kw [_ fn-name & defn-form]]
(let [[params body docstring opts] (resolve-params defn-form)
piped-field (symbol (name piped-field-kw))]
;; so that potentially nil opts is removed - hacky
(remove nil?
`(defn ~fn-name {:doc ~docstring} ~params
;; may result in `nil`
~(if opts opts)
;; fallback to piping if `piped-field` has no value
(let [~piped-field (or
~piped-field
(do
(println "piping!")
(line-seq (java.io.BufferedReader. *in*))))]
~@body)))))
(do
(with-cli-pipe-for :workitem-ids
(defn test1 [{:keys [workitem-ids] :as m}]
(prn m)
(run! println workitem-ids)))
(with-open [is (java.io.StringReader. "1\n2\n3\n5")]
(binding [*in* is]
(test1 {:opt1 true})))
(macroexpand '(with-cli-pipe-for :workitem-ids
(defn test1 [{:keys [workitem-ids] :as m}]
(prn m)
(run! println workitem-ids)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment