diff options
author | scgilardi <scgilardi@gmail.com> | 2008-10-06 05:06:22 +0000 |
---|---|---|
committer | scgilardi <scgilardi@gmail.com> | 2008-10-06 05:06:22 +0000 |
commit | 7136e152bdfa55fbe95860373ddf01eef5225495 (patch) | |
tree | a13977b87dd88f01f01d9fd219e769b2eeb7e329 /src/clojure/contrib/lib/lib.clj | |
parent | 6d370202f40f5e25648ebd71f20ee5ce3a1ac593 (diff) |
remove 'lib' contrib which is now integrated into boot.clj
Diffstat (limited to 'src/clojure/contrib/lib/lib.clj')
-rw-r--r-- | src/clojure/contrib/lib/lib.clj | 473 |
1 files changed, 0 insertions, 473 deletions
diff --git a/src/clojure/contrib/lib/lib.clj b/src/clojure/contrib/lib/lib.clj deleted file mode 100644 index fdf3410c..00000000 --- a/src/clojure/contrib/lib/lib.clj +++ /dev/null @@ -1,473 +0,0 @@ -;; Copyright (c) Stephen C. Gilardi. All rights reserved. The use and -;; distribution terms for this software are covered by the Common Public -;; License 1.0 (http://opensource.org/licenses/cpl.php) which can be found -;; in the file CPL.TXT at the root of this distribution. By using this -;; software in any fashion, you are agreeing to be bound by the terms of -;; this license. You must not remove this notice, or any other, from this -;; software. -;; -;; clojure.contrib.lib (Lib) -;; -;; Lib provides functions for loading and managing Clojure source code -;; contained in Java resources. -;; -;; A 'lib' is a unit of Clojure source code contained in a Java resource -;; and named by a symbol. The lib's name is used to identify the lib and -;; to locate the resource that contains it. -;; -;; Lib provides functions to: -;; -;; - find a resource given a classpath-relative path -;; - load code from a resource given an absolute path -;; - load libs from resources given lib names -;; - load namespace definitions given namespace specs -;; - ensure namespace definitions have been loaded while avoiding -;; duplicate loads, and -;; - create a namespace and refer 'clojure into it succinctly -;; -;; Symbols, Namespaces, Packages -;; -;; Symbols in Clojure are two-part identifiers - with an optional -;; namespace and a name, both strings. Namespaces are used to distinguish -;; two symbols that have the same name. Vars are named by symbols that -;; must have a namespace part, and thus can be considered to be in -;; namespaces. [From Clojure documentation] -;; -;; Packages in Java play a role similar to Clojure namespaces - they -;; partition the global namespace to allow large programs to avoid name -;; conflicts. Java defines a mapping from package names to directories -;; within classpath: components of a package name separated by periods -;; correspond to components of a classpath-relative path separated by -;; slashes. Lib uses this same mapping to locate libs and namespaces in -;; classpath. -;; -;; Loading Libs -;; -;; A lib's name provides the location of the resource that contains it in -;; classpath. The resource name is the last component of the lib's path -;; followed by ".clj". For example, a lib named 'a.b.c is contained in the -;; resource "<classpath>/a/b/c.clj". -;; -;; Loading Namespaces -;; -;; To load a namespace definition, Lib loads the 'root lib' for the -;; namespace. The root lib's name is derived from the namespace name by -;; repeating its last component. For example, the root lib for the -;; namespace 'x.y.z is the lib 'x.y.z.z contained in the resource -;; "<classpath>/x/y/z/z.clj". The namespace definition may be entirely -;; within the root lib or it may span multiple libs in the hierarchy of -;; directories at and under the namespace's directory. In the latter case -;; the root lib must include commands to (directly or indirectly) load the -;; remaining libs. -;; -;; Nsspecs -;; -;; An nsspec specifies a namespace to load. It is either a namespace name -;; or a list containing the namespace name and zero or more options -;; expressed as squential keywords and values. Nsspec examples: -;; - 'clojure.contrib.sql -;; - '(clojure.contrib.sql) -;; - '(clojure.contrib.sql :exclude (get-connection)). -;; - '(clojure.contrib.sql :as sql) -;; -;; Prefix Lists -;; -;; It is common for Clojure code to depend on several libs or namespaces -;; whose names have one or more initial components in common. When -;; specifying lib or namespace names for Lib to use, prefix lists can be -;; used to reduce repetition in the call. A prefix list is a list -;; containing the shared prefix followed by lib or namespace names and/or -;; prefix lists with the shared prefix elided. For example, the following -;; are all equivalent: -;; (load-libs 'a.b.c 'a.b.d 'a.c.e 'a.c.f) ; all names fully qualified -;; (load-libs '(a.b c d) '(a.c e f)) ; 'a.b and 'a.c extracted -;; (load-libs '(a (b c d) (c e f))) ; all common prefixes extracted -;; Symbols containing explicit periods and the equivalent prefix lists may -;; be mixed freely. -;; -;; Lib Functions -;; -;; Resources -;; -;; Function: find-resource -;; Searches available class loaders for a resource, returns URL or nil -;; -;; Function: load-resource -;; Loads Clojure source from an absolute path: URI, URL or String -;; -;; Libs -;; -;; Function: load-libs -;; Loads libs by name from arbitrary locations within classpath -;; -;; Namespaces -;; -;; Function: load-namespaces -;; Loads namespace definitions by loading namespace root libs -;; -;; Function: namespaces -;; Returns a sorted set symbols naming namespaces that have been loaded -;; with the :require option - used to track and avoid duplicate loads. -;; -;; Function: require -;; Loads namespace definitions that have not yet been loaded -;; -;; Function: use -;; Requires namespaces and refers to them using clojure/refer -;; -;; Function: init-ns -;; Creates and enters a namespace and refers to 'clojure and -;; 'clojure.contrib.lib (use in namespace root libs) -;; -;; Examples -;; -;; (load-namespaces :require '(clojure.contrib sql sql.tests)) -;; (require '(clojure.contrib sql sql.tests)) -;; -;; (load-namespaces :require :use '(clojure.contrib sql ns-utils) :verbose) -;; (use '(clojure.contrib sql ns-utils) :verbose) -;; -;; (use :reload-all :verbose -;; '(clojure.contrib -;; (sql :exclude (get-connection) -;; :rename {execute-commands do-commands}) -;; ns-utils)) -;; -;; scgilardi (gmail) -;; Created 7 April 2008 -;; -;; Thanks to Stuart Sierra for providing many useful ideas, discussions -;; and code contributions for lib.clj. - -(clojure/in-ns 'clojure.contrib.lib) -(clojure/refer 'clojure) - -(alias 'set 'clojure.set) - -(import '(clojure.lang RT)) -(import '(java.io BufferedReader InputStreamReader)) -(import '(java.net URI URL)) - -;; Private - -(defmacro init-once - "Initializes a var exactly once. The var must already exist." - {:private true} - [var init] - `(let [v# (resolve '~var)] - (when-not (.isBound v#) - (.bindRoot v# ~init)))) - -(def - #^{:private true :doc - "A ref to a sorted set of symbols representing loaded namespaces"} - *namespaces*) -(init-once *namespaces* (ref (sorted-set))) - -(def - #^{:private true :doc - "True while a verbose load is pending"} - *verbose*) -(init-once *verbose* false) - -(def - #^{:private true :doc - "A list of keywords that clojure/refer recognizes as filters"} - *filter-keys*) -(init-once *filter-keys* '(:exclude :only :rename)) - -(def - #^{:private true :doc - "A vector of the available class loaders ordered by the degree to which - they are controlled by Clojure. The root loader's classpath can be - extended with clojure/add-classpath"} - *class-loaders* - (let [root (.ROOT_CLASSLOADER RT) - runtime (.getClassLoader (identity RT)) - system (.getSystemClassLoader ClassLoader)] - (if (= system runtime) - [root system] - [root runtime system]))) - -(defn- throw-if - "Throws an exception with a message if pred is true. See - java.util.Formatter for format string syntax." - [pred fmt & args] - (when pred - (let [message (apply format fmt args) - exception (Exception. message) - raw-trace (.getStackTrace exception) - boring? #(not= (.getMethodName %) "doInvoke") - trace (into-array (drop 2 (drop-while boring? raw-trace)))] - (.setStackTrace exception trace) - (throw exception)))) - -(defn- nsspec? - "Returns true if x is an nsspec" - [x] - (or (symbol? x) - (nil? (second x)) - (keyword? (second x)))) - -(defn- prepend - "Prepends a symbol or collection to coll" - [x coll] - (if (symbol? x) - (cons x coll) - (concat x coll))) - -(def find-resource) ; forward declaration -(def load-resource) ; forward declaration - -(defn- load-one - "Loads one lib from a resource at url. If need-ns is 'true' ensures that - the namespace named by sym exists after loading. If require is 'true' - also records the namespace named by sym as loaded so any duplicate loads - can be skipped." - [url need-ns sym require] - (load-resource url) - (throw-if (and need-ns (not (find-ns sym))) - "namespace '%s' not found after loading '%s'" sym url) - (when require - (dosync - (commute *namespaces* conj sym)))) - -(defn- load-all - "Loads a lib from a resource at url and forces a load of any namespaces - it directly or indirectly loads via require/use/load-namespaces" - [url need-ns sym require] - (dosync - (commute *namespaces* set/union - (binding [*namespaces* (ref (sorted-set))] - (load-one url need-ns sym require) - @*namespaces*)))) - -(defn- name-path - "Returns a classpath-relative path given a symbol name" - [name] - (.. name - (replace \- \_) - (replace \. \/))) - -(defn- lib-path - "Returns the resource path for a lib" - [lib-sym] - (str (name-path (name lib-sym)) ".clj")) - -(defn- root-lib-path - "Returns the resource path for a namespace root lib" - [ns-sym] - (let [n (name-path (name ns-sym)) - i (inc (.lastIndexOf n (int \/))) - leaf (.substring n i)] - (str n \/ leaf ".clj"))) - -(defn- load-lib - "Loads a lib with options: sequential keywords and arguments." - [prefix sym & options] - (let [sym (symbol (str prefix (when prefix \.) sym)) - opts (apply hash-map options) - as (:as opts) - reload (:reload opts) - reload-all (:reload-all opts) - require (:require opts) - root (:root opts) - use (:use opts) - verbose (:verbose opts) - loaded (contains? @*namespaces* sym) - load (cond reload-all - load-all - (or reload (not require) (not loaded)) - load-one) - need-ns (or as use) - path ((if root root-lib-path lib-path) sym) - url (find-resource path) - filter-opts (select-keys opts *filter-keys*)] - (binding [*verbose* (or *verbose* verbose)] - (when load - (throw-if (not url) "'%s' not found in classpath" path) - (when *verbose* - (printf "(clojure.contrib.lib/load-resource \"%s\")\n" url) - (flush)) - (load url need-ns sym require)) - (throw-if (and need-ns (not (find-ns sym))) - "namespace '%s' not found" sym) - (when (and need-ns *verbose*) - (printf "(clojure/in-ns '%s)\n" (ns-name *ns*))) - (when as - (when *verbose* - (printf "(clojure/alias '%s '%s)\n" as sym)) - (alias as sym)) - (when use - (when *verbose* - (printf "(clojure/refer '%s" sym) - (doseq opt filter-opts - (printf " %s '%s" (key opt) (print-str (val opt)))) - (printf ")\n")) - (apply refer sym (mapcat seq filter-opts)))))) - -(defn- load-prefix-list - "Loads libs and handles (nested) prefix lists" - [load? prefix opts & args] - (doseq arg args - (if (load? arg) - (apply load-lib prefix (prepend arg opts)) - (let [[nested-prefix & nested-args] arg] - (throw-if (nil? nested-prefix) "prefix cannot be nil") - (apply load-prefix-list - load? - (symbol (str prefix (when prefix \.) nested-prefix)) - opts - nested-args))))) - -;; Resources - -(defn find-resource - "Searches for a resource given a classpath-relative path using available - ClassLoaders. If the resource is found, returns its URL, otherwise nil." - [rel-path] - (some #(.findResource % rel-path) *class-loaders*)) - -(defn load-resource - "Loads Clojure source from a resource specified by an absolute path. The - path may be a URI, URL, or String. Accepts any URI scheme supported by - URLConnection (http and jar), plus file paths." - [abs-path] - (let [url (cond (instance? URL abs-path) - abs-path - (instance? URI abs-path) - (.toURL abs-path) - (string? abs-path) - (URL. abs-path))] - (throw-if (not url) "Cannot coerce %s to %s" (class abs-path) URL) - (with-open reader - (BufferedReader. - (InputStreamReader. - (.openStream url))) - (.load Compiler reader (.getPath url) (.getFile url))))) - -;; Libs - -(defn load-libs - "Loads libs - Clojure source contained in resources in classpath. Each - argument is a either a symbol that identifies a lib, a prefix list that - identifies multiple libs with names that share common prefixes, or a flag - that modifies how all the identified libs are loaded. Symbol names map to - paths within classpath: components of the symbol name separated by - periods correspond to components in classpath-relative paths separated by - slashes. The full resource path is the mapped path with '.clj' - appended. For example, the resource containing the lib 'a.b.c is - '<classpath>/a/b/c.clj'. - - - Multiple libs whose names share the same period-delimited prefix can be - identified succinctly using a prefix list: a list containing the shared - prefix followed by symbols and/or prefix lists with the shared prefix - elided. For example, the following are all equivalent: - (load-libs 'a.b.c 'a.b.d 'a.c.e 'a.c.f) ; all names fully qualified - (load-libs '(a.b c d) '(a.c e f)) ; 'a.b and 'a.c extracted - (load-libs '(a (b c d) (c e f))) ; all common prefixes extracted - Symbols containing explicit periods and the equivalent prefix lists may - be mixed freely. - - Recognized flags: :reload-all, :verbose - - :reload-all forces loading of all namespaces that the identified libs - directly or indirectly load via load-namespaces/require/use - :verbose triggers printing information about each load and refer" - [& args] - (let [flags (filter keyword? args) - opts (interleave flags (repeat true)) - args (filter (complement keyword?) args)] - (apply load-prefix-list symbol? nil opts args))) - -;; Namespaces - -(defn load-namespaces - "Loads namespace definitions contained in resources in classpath. - Each argument is a either an nsspec that identifies a namespace, a prefix - list that identifies multiple namespaces with names that share common - prefixes, or a flag that modifies how all the identified namespaces are - loaded. Namespace names map to paths within classpath: components of the - namespace name separated by periods correspond to components in - classpath-relative paths separated by slashes. To load the namespace - definition, load-namespaces loads the namespace's 'root lib'. The root - lib's name is derived from the namespace name by repeating its last - component. The root lib for namespace 'a.b.c is the lib 'a.b.c.c - contained in the resource '<classpath>/a/b/c/c.clj'. The namespace - definition need not be completely contained in its root lib. If it's not - the root lib must contain code to (directly or indirectly) load the - additional libs using load-libs. - - An nsspec is a symbol or a list containing a symbol and options. Some - options may have meaning only when specific flags are set. - - An option is a keyword followed by an argument. - Recognized options: :as :exclude, :only, :rename - - The argument for :as is a symbol to use as an alias for the specified - namespace. - The arguments and semantics for :exclude, :only, and :rename are those - documented for clojure/refer. They are only effective when the :use flag - is present. - - Multiple namespaces whose names share the same period-delimited prefix - can be identified succinctly using a prefix list: a list containing the - shared prefix followed by nsspecs and/or prefix lists with the shared - prefix elided. For example, the following are all equivalent: - (load-namespaces 'a.b.c 'a.b.d 'a.c.e 'a.c.f) ; fully qualified names - (load-namespaces '(a.b c d) '(a.c e f)) ; 'a.b and 'a.c extracted - (load-namespaces '(a (b c d) (c e f))) ; all common prefixes extracted - Symbols containing explicit periods and the equivalent prefix lists may be - mixed freely. - - A flag is a keyword. - Recognized flags: :require, :use, :reload, :reload-all, :verbose - - :require indicates that any identified namespace definitions that are - already loaded need not be reloaded - :use triggers referring to each namespace with optional filters specified - in its options - :reload forces loading of all the identified namespace definitions even - if they are already loaded. :reload supersedes :require - :reload-all implies :reload and also forces loading of all namespace - definitions that the identified namespace definitions directly or - indirectly load via load-namespaces/require/use - :verbose triggers printing information about each load, alias and refer" - [& args] - (let [flags (cons :root (filter keyword? args)) - opts (interleave flags (repeat true)) - args (filter (complement keyword?) args)] - (apply load-prefix-list nsspec? nil opts args))) - -(defn namespaces - "Returns a sorted set of symbols naming loaded namespaces" - [] - @*namespaces*) - -(defn require - "Ensures that namespaces are loaded while avoiding duplicate - loads. Arguments are described in the docs for 'load-namespaces. The - :require flag is automatically set." - [& args] - (apply load-namespaces :require args)) - -(defn use - "Ensures that namespaces are loaded while avoiding duplicate loads and - refers to them in the current namespace. Arguments are described in the - docs for 'load-namespaces. The :require and :use flags are automatically - set." - [& args] - (apply load-namespaces :require :use args)) - -(defn init-ns - "Creates ns (if necessary), makes it current, and uses clojure/refer to - make the 'clojure namespace available to it. Optional clojure-filters can - be passed along to clojure/refer to modify how much of and how 'clojure - is pulled in. init-ns also refers to (all of) 'clojure.contrib.lib. - Namespace root libs will typically begin with a call to init-ns; any - subordinate libs can begin with a call to in-ns." - [ns & clojure-filters] - (in-ns ns) - (apply refer 'clojure clojure-filters) - (refer 'clojure.contrib.lib)) |