Skip to content

Commit

Permalink
Add ns-path op
Browse files Browse the repository at this point in the history
This op returns the file path to the file containing some ns on classpath.

The new op is meant to be the basis for cider-find-ns
  • Loading branch information
expez committed May 2, 2015
1 parent 88f01f2 commit c949c85
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Middleware | Op(s) | Description
`wrap-info` | `info/eldoc` | File/line, arglists, docstrings and other metadata for vars.
`wrap-inspect` |`inspect-(start/refresh/pop/push/reset)` | Inspect a Clojure expression.
`wrap-macroexpand`| `macroexpand/macroexpand-1/macroexpand-all` | Macroexpand a Clojure form.
`wrap-ns` | `ns-list/ns-vars` | Namespace browsing.
`wrap-ns` | `ns-list/ns-vars/ns-path` | Namespace browsing.
`wrap-pprint` | | Adds pretty-printing support to code evaluation. It also installs a dummy `pprint-middleware` op. Thus `wrap-pprint` is discoverable through the `describe` op.
`wrap-refresh` | `refresh/refresh-all` | Code reloading.
`wrap-resource` | `resource` | Return resource path.
Expand Down
62 changes: 55 additions & 7 deletions src/cider/nrepl/middleware/ns.clj
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
(ns cider.nrepl.middleware.ns
(:require [clojure.tools.nrepl.transport :as transport]
[clojure.tools.nrepl.middleware :refer [set-descriptor!]]
[clojure.tools.nrepl.misc :refer [response-for]]
[cider.nrepl.middleware.util.cljs :as cljs]
[cljs-tooling.util.analysis :as cljs-analysis]))
(:require [cider.nrepl.middleware.util.cljs :as cljs]
[cljs-tooling.util.analysis :as cljs-analysis]
[clojure.java.classpath :as cp]
[clojure.java.io :as io]
[clojure.tools.namespace
[file :refer [read-file-ns-decl]]
[find :refer [clojure-sources-in-jar find-clojure-sources-in-dir]]]
[clojure.tools.nrepl
[middleware :refer [set-descriptor!]]
[misc :refer [response-for]]
[transport :as transport]])
(:import java.util.jar.JarFile))

(defn ns-list-clj []
(->> (all-ns)
Expand Down Expand Up @@ -51,13 +58,50 @@
(transport/send transport (response-for msg :ns-vars (ns-vars msg)))
(transport/send transport (response-for msg :status :done)))

(defn- jar-file?
"Returns true if file is a normal file with a .jar or .JAR extension."
[f]
(let [file (io/file f)]
(and (.isFile file)
(.endsWith (.. file getName toLowerCase) ".jar"))))

(defn- get-clojure-sources-in-jar
[^JarFile jar]
(let [path-to-jar (.getName jar)]
(map #(str "jar:file:" path-to-jar "!/" %) (clojure-sources-in-jar jar))))

(defn- all-clj-files-on-cp []
(let [dirs-on-cp (filter #(.isDirectory %) (cp/classpath))
jars-on-cp (map #(JarFile. %) (filter jar-file? (cp/classpath)))]
(concat (->> dirs-on-cp
(mapcat find-clojure-sources-in-dir)
(map #(.getAbsolutePath %)))
(mapcat get-clojure-sources-in-jar jars-on-cp))))

(defn- ns-path
[{:keys [ns]}]
(let [ns (symbol ns)]
(loop [paths (all-clj-files-on-cp)]
(when (seq paths)
(let [file-ns (second (read-file-ns-decl (first paths)))]
(if (= file-ns ns)
(first paths)
(recur (rest paths))))))))

(defn- ns-path-reply
[{:keys [transport] :as msg}]
(when-let [path (ns-path msg)]
(transport/send transport (response-for msg :path (ns-path msg))))
(transport/send transport (response-for msg :status :done)))

(defn wrap-ns
"Middleware that provides ns listing/browsing functionality."
[handler]
(fn [{:keys [op] :as msg}]
(case op
"ns-list" (ns-list-reply msg)
"ns-vars" (ns-vars-reply msg)
"ns-path" (ns-path-reply msg)
(handler msg))))

(set-descriptor!
Expand All @@ -69,5 +113,9 @@
:returns {"status" "done"}}
"ns-vars"
{:doc "Returns a sorted list of all vars in a namespace."
:requires {"ns" "The namespace to browse"}
:returns {"status" "done"}}}}))
:requires {"ns" "The namespace to browse."}
:returns {"status" "done"}}
"ns-path"
{:doc "Returns the path to the file containing ns."
:requires {"ns" "The namespace to find."}
:return {"status" "done" "path" "The path to the file containing ns."}}}}))
8 changes: 8 additions & 0 deletions test/clj/cider/nrepl/middleware/ns_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@
:ns "clojure.walk"}))]
(is (sequential? ns-vars))
(is (every? string? ns-vars))))

(deftest ns-path-integration-test
(let [ns-path (:path (session/message {:op "ns-path"
:ns "cider.nrepl.middleware.ns"}))
core-path (:path (session/message {:op "ns-path"
:ns "clojure.core"}))]
(is (.endsWith ns-path "cider/nrepl/middleware/ns.clj"))
(is (.endsWith core-path "clojure/core.clj"))))

0 comments on commit c949c85

Please sign in to comment.