view src/clojure/contrib/find_namespaces.clj @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
line wrap: on
line source
1 ;;; find_namespaces.clj: search for ns declarations in dirs, JARs, or CLASSPATH
3 ;; by Stuart Sierra, http://stuartsierra.com/
4 ;; April 19, 2009
6 ;; Copyright (c) Stuart Sierra, 2009. All rights reserved. The use
7 ;; and distribution terms for this software are covered by the Eclipse
8 ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
9 ;; which can be found in the file epl-v10.html at the root of this
10 ;; distribution. By using this software in any fashion, you are
11 ;; agreeing to be bound by the terms of this license. You must not
12 ;; remove this notice, or any other, from this software.
15 (ns
16 ^{:author "Stuart Sierra",
17 :doc "Search for ns declarations in dirs, JARs, or CLASSPATH"}
18 clojure.contrib.find-namespaces
19 (:require [clojure.contrib.classpath :as cp]
20 [clojure.contrib.jar :as jar])
21 (import (java.io File FileReader BufferedReader PushbackReader
22 InputStreamReader)
23 (java.util.jar JarFile)))
26 ;;; Finding namespaces in a directory tree
28 (defn clojure-source-file?
29 "Returns true if file is a normal file with a .clj extension."
30 [^File file]
31 (and (.isFile file)
32 (.endsWith (.getName file) ".clj")))
34 (defn find-clojure-sources-in-dir
35 "Searches recursively under dir for Clojure source files (.clj).
36 Returns a sequence of File objects, in breadth-first sort order."
37 [^File dir]
38 ;; Use sort by absolute path to get breadth-first search.
39 (sort-by #(.getAbsolutePath %)
40 (filter clojure-source-file? (file-seq dir))))
42 (defn comment?
43 "Returns true if form is a (comment ...)"
44 [form]
45 (and (list? form) (= 'comment (first form))))
47 (defn ns-decl?
48 "Returns true if form is a (ns ...) declaration."
49 [form]
50 (and (list? form) (= 'ns (first form))))
52 (defn read-ns-decl
53 "Attempts to read a (ns ...) declaration from rdr, and returns the
54 unevaluated form. Returns nil if read fails or if a ns declaration
55 cannot be found. The ns declaration must be the first Clojure form
56 in the file, except for (comment ...) forms."
57 [^PushbackReader rdr]
58 (try (let [form (read rdr)]
59 (cond
60 (ns-decl? form) form
61 (comment? form) (recur rdr)
62 :else nil))
63 (catch Exception e nil)))
65 (defn read-file-ns-decl
66 "Attempts to read a (ns ...) declaration from file, and returns the
67 unevaluated form. Returns nil if read fails, or if the first form
68 is not a ns declaration."
69 [^File file]
70 (with-open [rdr (PushbackReader. (BufferedReader. (FileReader. file)))]
71 (read-ns-decl rdr)))
73 (defn find-ns-decls-in-dir
74 "Searches dir recursively for (ns ...) declarations in Clojure
75 source files; returns the unevaluated ns declarations."
76 [^File dir]
77 (filter identity (map read-file-ns-decl (find-clojure-sources-in-dir dir))))
79 (defn find-namespaces-in-dir
80 "Searches dir recursively for (ns ...) declarations in Clojure
81 source files; returns the symbol names of the declared namespaces."
82 [^File dir]
83 (map second (find-ns-decls-in-dir dir)))
86 ;;; Finding namespaces in JAR files
88 (defn clojure-sources-in-jar
89 "Returns a sequence of filenames ending in .clj found in the JAR file."
90 [^JarFile jar-file]
91 (filter #(.endsWith % ".clj") (jar/filenames-in-jar jar-file)))
93 (defn read-ns-decl-from-jarfile-entry
94 "Attempts to read a (ns ...) declaration from the named entry in the
95 JAR file, and returns the unevaluated form. Returns nil if the read
96 fails, or if the first form is not a ns declaration."
97 [^JarFile jarfile ^String entry-name]
98 (with-open [rdr (PushbackReader.
99 (BufferedReader.
100 (InputStreamReader.
101 (.getInputStream jarfile (.getEntry jarfile entry-name)))))]
102 (read-ns-decl rdr)))
104 (defn find-ns-decls-in-jarfile
105 "Searches the JAR file for Clojure source files containing (ns ...)
106 declarations; returns the unevaluated ns declarations."
107 [^JarFile jarfile]
108 (filter identity
109 (map #(read-ns-decl-from-jarfile-entry jarfile %)
110 (clojure-sources-in-jar jarfile))))
112 (defn find-namespaces-in-jarfile
113 "Searches the JAR file for Clojure source files containing (ns ...)
114 declarations. Returns a sequence of the symbol names of the
115 declared namespaces."
116 [^JarFile jarfile]
117 (map second (find-ns-decls-in-jarfile jarfile)))
120 ;;; Finding namespaces anywhere on CLASSPATH
122 (defn find-ns-decls-on-classpath
123 "Searches CLASSPATH (both directories and JAR files) for Clojure
124 source files containing (ns ...) declarations. Returns a sequence
125 of the unevaluated ns declaration forms."
126 []
127 (concat
128 (mapcat find-ns-decls-in-dir (cp/classpath-directories))
129 (mapcat find-ns-decls-in-jarfile (cp/classpath-jarfiles))))
131 (defn find-namespaces-on-classpath
132 "Searches CLASSPATH (both directories and JAR files) for Clojure
133 source files containing (ns ...) declarations. Returns a sequence
134 of the symbol names of the declared namespaces."
135 []
136 (map second (find-ns-decls-on-classpath)))