Skip to content

Instantly share code, notes, and snippets.

@emidln
Created June 15, 2016 23:36
Show Gist options
  • Save emidln/f2ee7ec7753bb83de1b974c919e1eb0b to your computer and use it in GitHub Desktop.
Save emidln/f2ee7ec7753bb83de1b974c919e1eb0b to your computer and use it in GitHub Desktop.
(ns fnk-sourcery
(:require clojure.string
taoensso.encore
plumbing.core)
(:import clojure.lang.RT
clojure.lang.Reflector
java.io.LineNumberReader
java.io.InputStreamReader
java.io.PushbackReader))
(defn filepath-from-fnk
[fnk]
(some-> (->> fnk meta :plumbing.fnk.impl/positional-info first pr-str
(re-matches #"#.*\[([A-z.\-]*).*\]")
second)
(clojure.string/replace #"\." "/")
(str ".clj")))
(defn fnk-source
"Gets the source of a plumbing.core/fnk (or plumbing.core/defnk) object.
Does so in a way that is almost certainly guaranteed to break if you look at it wrong.
Can we please annotate fnk's with the :file they came from? Please?"
[afnk]
(with-local-vars [*text* (StringBuilder.)]
(taoensso.encore/when-lets
[afnk-meta (meta afnk)
filepath (filepath-from-fnk afnk)
strm (.getResourceAsStream (RT/baseLoader) filepath)]
(with-open [rdr (LineNumberReader. (InputStreamReader. strm))]
;; move the reader up to our line
(dotimes [_ (dec (:line afnk-meta))] (.readLine rdr))
(let [pbr (proxy [PushbackReader] [rdr]
(read [] (let [i (proxy-super read)]
(.append (var-get *text*) (char i))
i)))
read-opts {}]
(loop [tries 2]
(var-set *text* (StringBuilder.))
(read read-opts (PushbackReader. pbr))
(let [text (str (var-get *text*))
code (read-string text)]
(if (and (list? code) (#{'defnk 'fnk} (first code)))
(clojure.string/trim text)
(when (> tries 0)
(recur (dec tries)))))))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment