Mercurial > lasercutter
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/clojure/contrib/find_namespaces.clj Sat Aug 21 06:25:44 2010 -0400 1.3 @@ -0,0 +1,136 @@ 1.4 +;;; find_namespaces.clj: search for ns declarations in dirs, JARs, or CLASSPATH 1.5 + 1.6 +;; by Stuart Sierra, http://stuartsierra.com/ 1.7 +;; April 19, 2009 1.8 + 1.9 +;; Copyright (c) Stuart Sierra, 2009. All rights reserved. The use 1.10 +;; and distribution terms for this software are covered by the Eclipse 1.11 +;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 1.12 +;; which can be found in the file epl-v10.html at the root of this 1.13 +;; distribution. By using this software in any fashion, you are 1.14 +;; agreeing to be bound by the terms of this license. You must not 1.15 +;; remove this notice, or any other, from this software. 1.16 + 1.17 + 1.18 +(ns 1.19 + ^{:author "Stuart Sierra", 1.20 + :doc "Search for ns declarations in dirs, JARs, or CLASSPATH"} 1.21 + clojure.contrib.find-namespaces 1.22 + (:require [clojure.contrib.classpath :as cp] 1.23 + [clojure.contrib.jar :as jar]) 1.24 + (import (java.io File FileReader BufferedReader PushbackReader 1.25 + InputStreamReader) 1.26 + (java.util.jar JarFile))) 1.27 + 1.28 + 1.29 +;;; Finding namespaces in a directory tree 1.30 + 1.31 +(defn clojure-source-file? 1.32 + "Returns true if file is a normal file with a .clj extension." 1.33 + [^File file] 1.34 + (and (.isFile file) 1.35 + (.endsWith (.getName file) ".clj"))) 1.36 + 1.37 +(defn find-clojure-sources-in-dir 1.38 + "Searches recursively under dir for Clojure source files (.clj). 1.39 + Returns a sequence of File objects, in breadth-first sort order." 1.40 + [^File dir] 1.41 + ;; Use sort by absolute path to get breadth-first search. 1.42 + (sort-by #(.getAbsolutePath %) 1.43 + (filter clojure-source-file? (file-seq dir)))) 1.44 + 1.45 +(defn comment? 1.46 + "Returns true if form is a (comment ...)" 1.47 + [form] 1.48 + (and (list? form) (= 'comment (first form)))) 1.49 + 1.50 +(defn ns-decl? 1.51 + "Returns true if form is a (ns ...) declaration." 1.52 + [form] 1.53 + (and (list? form) (= 'ns (first form)))) 1.54 + 1.55 +(defn read-ns-decl 1.56 + "Attempts to read a (ns ...) declaration from rdr, and returns the 1.57 + unevaluated form. Returns nil if read fails or if a ns declaration 1.58 + cannot be found. The ns declaration must be the first Clojure form 1.59 + in the file, except for (comment ...) forms." 1.60 + [^PushbackReader rdr] 1.61 + (try (let [form (read rdr)] 1.62 + (cond 1.63 + (ns-decl? form) form 1.64 + (comment? form) (recur rdr) 1.65 + :else nil)) 1.66 + (catch Exception e nil))) 1.67 + 1.68 +(defn read-file-ns-decl 1.69 + "Attempts to read a (ns ...) declaration from file, and returns the 1.70 + unevaluated form. Returns nil if read fails, or if the first form 1.71 + is not a ns declaration." 1.72 + [^File file] 1.73 + (with-open [rdr (PushbackReader. (BufferedReader. (FileReader. file)))] 1.74 + (read-ns-decl rdr))) 1.75 + 1.76 +(defn find-ns-decls-in-dir 1.77 + "Searches dir recursively for (ns ...) declarations in Clojure 1.78 + source files; returns the unevaluated ns declarations." 1.79 + [^File dir] 1.80 + (filter identity (map read-file-ns-decl (find-clojure-sources-in-dir dir)))) 1.81 + 1.82 +(defn find-namespaces-in-dir 1.83 + "Searches dir recursively for (ns ...) declarations in Clojure 1.84 + source files; returns the symbol names of the declared namespaces." 1.85 + [^File dir] 1.86 + (map second (find-ns-decls-in-dir dir))) 1.87 + 1.88 + 1.89 +;;; Finding namespaces in JAR files 1.90 + 1.91 +(defn clojure-sources-in-jar 1.92 + "Returns a sequence of filenames ending in .clj found in the JAR file." 1.93 + [^JarFile jar-file] 1.94 + (filter #(.endsWith % ".clj") (jar/filenames-in-jar jar-file))) 1.95 + 1.96 +(defn read-ns-decl-from-jarfile-entry 1.97 + "Attempts to read a (ns ...) declaration from the named entry in the 1.98 + JAR file, and returns the unevaluated form. Returns nil if the read 1.99 + fails, or if the first form is not a ns declaration." 1.100 + [^JarFile jarfile ^String entry-name] 1.101 + (with-open [rdr (PushbackReader. 1.102 + (BufferedReader. 1.103 + (InputStreamReader. 1.104 + (.getInputStream jarfile (.getEntry jarfile entry-name)))))] 1.105 + (read-ns-decl rdr))) 1.106 + 1.107 +(defn find-ns-decls-in-jarfile 1.108 + "Searches the JAR file for Clojure source files containing (ns ...) 1.109 + declarations; returns the unevaluated ns declarations." 1.110 + [^JarFile jarfile] 1.111 + (filter identity 1.112 + (map #(read-ns-decl-from-jarfile-entry jarfile %) 1.113 + (clojure-sources-in-jar jarfile)))) 1.114 + 1.115 +(defn find-namespaces-in-jarfile 1.116 + "Searches the JAR file for Clojure source files containing (ns ...) 1.117 + declarations. Returns a sequence of the symbol names of the 1.118 + declared namespaces." 1.119 + [^JarFile jarfile] 1.120 + (map second (find-ns-decls-in-jarfile jarfile))) 1.121 + 1.122 + 1.123 +;;; Finding namespaces anywhere on CLASSPATH 1.124 + 1.125 +(defn find-ns-decls-on-classpath 1.126 + "Searches CLASSPATH (both directories and JAR files) for Clojure 1.127 + source files containing (ns ...) declarations. Returns a sequence 1.128 + of the unevaluated ns declaration forms." 1.129 + [] 1.130 + (concat 1.131 + (mapcat find-ns-decls-in-dir (cp/classpath-directories)) 1.132 + (mapcat find-ns-decls-in-jarfile (cp/classpath-jarfiles)))) 1.133 + 1.134 +(defn find-namespaces-on-classpath 1.135 + "Searches CLASSPATH (both directories and JAR files) for Clojure 1.136 + source files containing (ns ...) declarations. Returns a sequence 1.137 + of the symbol names of the declared namespaces." 1.138 + [] 1.139 + (map second (find-ns-decls-on-classpath)))