On Nov 3, 7:03 pm, Chouser <[EMAIL PROTECTED]> wrote:
> [...] It's not pretty, and it only works on functions defined in the clojure
> namespace.  [...]

The variation below works in a more general setting: it will look for
the source file anywhere in the classpath (including jar files) or in
user.dir

I just combined your get-source function with functionality from swank-
clojure (in swank/commands/basic/basic.clj). I didn't test it much,
there might be a bug or two.

Carlos

(import '(java.io File FileInputStream LineNumberReader
InputStreamReader PushbackReader)
        '(java.util.zip ZipFile)
        '(clojure.lang RT))

(defn- namespace-to-path [ns]
  (-> (name (ns-name ns))
      (.replace \- \_)
      (.replace \. \/)))

(defn- get-path-prop
  "Returns a coll of the paths represented in a system property"
  ([prop]
     (seq (-> (System/getProperty prop)
              (.split File/pathSeparator))))
  ([prop & props]
     (lazy-cat (get-path-prop prop) (mapcat get-path-prop props))))

(defn- search-paths []
  (concat (get-path-prop "user.dir" "java.class.path"
"sun.boot.class.path")
          (map #(.getPath %) (.getURLs clojure.lang.RT/
ROOT_CLASSLOADER))))

(defn- find-file-in-dir [#^File file #^String dir]
  (let [file-name (. file (getPath))
        child (File. (File. dir) file-name)]
    (or (when (.exists child)
          (FileInputStream. child))
        (try
         (let [zipfile (ZipFile. dir)]
           (when (.getEntry zipfile file-name)
             (.getInputStream zipfile (.getEntry zipfile file-name))))
         (catch Throwable e false)))))

(defn- find-file-in-paths [#^String file paths]
  (let [f (File. file)]
    (if (.isAbsolute f)
        (FileInputStream. f)
        (first (filter identity (map #(find-file-in-dir f %) paths))))))

(defn get-source [vn]
  (let [m ^(resolve vn)
        strm (when (:file m)
               (or (find-file-in-paths (str (namespace-to-path (:ns m))
                                            (.separator File)
                                            (:file m)) (search-paths))
                   (find-file-in-paths (:file m) (search-paths))))]
    (if strm
        (with-open rdr (LineNumberReader. (InputStreamReader. strm))
          (dotimes _ (dec (:line m)) (.readLine rdr))
          (.mark rdr 2000)
          (read (PushbackReader. rdr))
          (let [cnt (- (.getLineNumber rdr) (:line m))]
            (.reset rdr)
            (dotimes _ cnt (println (.readLine rdr)))
            true))
        (println "Source not found for" vn))))

(defmacro source [n]
  `(get-source '~n))

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to