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