annotate src/clojure/contrib/gen_html_docs.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 ;;; gen-html-docs.clj: Generate HTML documentation for Clojure libs
rlm@10 2
rlm@10 3 ;; by Craig Andera, http://pluralsight.com/craig, candera@wangdera.com
rlm@10 4 ;; February 13th, 2009
rlm@10 5
rlm@10 6 ;; Copyright (c) Craig Andera, 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 ;; Generates a single HTML page that contains the documentation for
rlm@10 15 ;; one or more Clojure libraries. See the comments section at the end
rlm@10 16 ;; of this file for usage.
rlm@10 17
rlm@10 18 ;; TODO
rlm@10 19 ;;
rlm@10 20 ;; * Make symbols in the source hyperlinks to the appropriate section
rlm@10 21 ;; of the documentation.
rlm@10 22 ;; * Investigate issue with miglayout mentioned here:
rlm@10 23 ;; http://groups.google.com/group/clojure/browse_thread/thread/5a0c4395e44f5a79/3ae483100366bd3d?lnk=gst&q=documentation+browser#3ae483100366bd3d
rlm@10 24 ;;
rlm@10 25 ;; DONE
rlm@10 26 ;;
rlm@10 27 ;; * Move to clojure.contrib
rlm@10 28 ;; * Change namespace
rlm@10 29 ;; * Change license as appropriate
rlm@10 30 ;; * Double-check doc strings
rlm@10 31 ;; * Remove doc strings from source code
rlm@10 32 ;; * Add collapse/expand functionality for all namespaces
rlm@10 33 ;; * Add collapse/expand functionality for each namespace
rlm@10 34 ;; * See if converting to use clojure.contrib.prxml is possible
rlm@10 35 ;; * Figure out why the source doesn't show up for most things
rlm@10 36 ;; * Add collapsible source
rlm@10 37 ;; * Add links at the top to jump to each namespace
rlm@10 38 ;; * Add object type (var, function, whatever)
rlm@10 39 ;; * Add argument lists for functions
rlm@10 40 ;; * Add links at the top of each namespace to jump to members
rlm@10 41 ;; * Add license statement
rlm@10 42 ;; * Remove the whojure dependency
rlm@10 43
rlm@10 44 (ns
rlm@10 45 ^{:author "Craig Andera",
rlm@10 46 :doc "Generates a single HTML page that contains the documentation for
rlm@10 47 one or more Clojure libraries."}
rlm@10 48 clojure.contrib.gen-html-docs
rlm@10 49 (:require [clojure.contrib.io :as io]
rlm@10 50 [clojure.contrib.string :as s])
rlm@10 51 (:use [clojure.contrib repl-utils def prxml])
rlm@10 52 (:import [java.lang Exception]
rlm@10 53 [java.util.regex Pattern]))
rlm@10 54
rlm@10 55 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
rlm@10 56 ;; Doc generation constants
rlm@10 57 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
rlm@10 58
rlm@10 59 (def *script* " // <![CDATA[
rlm@10 60
rlm@10 61 function getElem(id)
rlm@10 62 {
rlm@10 63 if( document.getElementById )
rlm@10 64 {
rlm@10 65 return document.getElementById( id )
rlm@10 66 }
rlm@10 67 else if ( document.all )
rlm@10 68 {
rlm@10 69 return eval( 'document.all.' + id )
rlm@10 70 }
rlm@10 71 else
rlm@10 72 return false;
rlm@10 73 }
rlm@10 74
rlm@10 75 function setDisplayStyle(id,displayStyle)
rlm@10 76 {
rlm@10 77 var elem = getElem (id)
rlm@10 78 if (elem)
rlm@10 79 {
rlm@10 80 elem.style.display = displayStyle
rlm@10 81 }
rlm@10 82
rlm@10 83 }
rlm@10 84
rlm@10 85 function setLinkToggleText (id, text)
rlm@10 86 {
rlm@10 87 var elem = getElem (id)
rlm@10 88 if (elem)
rlm@10 89 {
rlm@10 90 elem.innerHTML = text
rlm@10 91 }
rlm@10 92 }
rlm@10 93
rlm@10 94 function collapse(id)
rlm@10 95 {
rlm@10 96 setDisplayStyle (id, 'none')
rlm@10 97 }
rlm@10 98
rlm@10 99 function expand (id)
rlm@10 100 {
rlm@10 101 setDisplayStyle (id, 'block')
rlm@10 102 }
rlm@10 103
rlm@10 104 function toggleSource( id )
rlm@10 105 {
rlm@10 106 toggle(id, 'linkto-' + id, 'Hide Source', 'Show Source')
rlm@10 107 }
rlm@10 108
rlm@10 109 function toggle(targetid, linkid, textWhenOpen, textWhenClosed)
rlm@10 110 {
rlm@10 111 var elem = getElem (targetid)
rlm@10 112 var link = getElem (linkid)
rlm@10 113
rlm@10 114 if (elem && link)
rlm@10 115 {
rlm@10 116 var isOpen = false
rlm@10 117 if (elem.style.display == '')
rlm@10 118 {
rlm@10 119 isOpen = link.innerHTML == textWhenOpen
rlm@10 120 }
rlm@10 121 else if( elem.style.display == 'block' )
rlm@10 122 {
rlm@10 123 isOpen = true
rlm@10 124 }
rlm@10 125
rlm@10 126 if (isOpen)
rlm@10 127 {
rlm@10 128 elem.style.display = 'none'
rlm@10 129 link.innerHTML = textWhenClosed
rlm@10 130 }
rlm@10 131 else
rlm@10 132 {
rlm@10 133 elem.style.display = 'block'
rlm@10 134 link.innerHTML = textWhenOpen
rlm@10 135 }
rlm@10 136 }
rlm@10 137 }
rlm@10 138
rlm@10 139 //]]>
rlm@10 140 ")
rlm@10 141
rlm@10 142 (def *style* "
rlm@10 143 .library
rlm@10 144 {
rlm@10 145 padding: 0.5em 0 0 0
rlm@10 146 }
rlm@10 147 .all-libs-toggle,.library-contents-toggle
rlm@10 148 {
rlm@10 149 font-size: small;
rlm@10 150 }
rlm@10 151 .all-libs-toggle a,.library-contents-toggle a
rlm@10 152 {
rlm@10 153 color: white
rlm@10 154 }
rlm@10 155 .library-member-doc-whitespace
rlm@10 156 {
rlm@10 157 white-space: pre
rlm@10 158 }
rlm@10 159 .library-member-source-toggle
rlm@10 160 {
rlm@10 161 font-size: small;
rlm@10 162 margin-top: 0.5em
rlm@10 163 }
rlm@10 164 .library-member-source
rlm@10 165 {
rlm@10 166 display: none;
rlm@10 167 border-left: solid lightblue
rlm@10 168 }
rlm@10 169 .library-member-docs
rlm@10 170 {
rlm@10 171 font-family:monospace
rlm@10 172 }
rlm@10 173 .library-member-arglists
rlm@10 174 {
rlm@10 175 font-family: monospace
rlm@10 176 }
rlm@10 177 .library-member-type
rlm@10 178 {
rlm@10 179 font-weight: bold;
rlm@10 180 font-size: small;
rlm@10 181 font-style: italic;
rlm@10 182 color: darkred
rlm@10 183 }
rlm@10 184 .lib-links
rlm@10 185 {
rlm@10 186 margin: 0 0 1em 0
rlm@10 187 }
rlm@10 188
rlm@10 189 .lib-link-header
rlm@10 190 {
rlm@10 191 color: white;
rlm@10 192 background: darkgreen;
rlm@10 193 width: 100%
rlm@10 194 }
rlm@10 195
rlm@10 196 .library-name
rlm@10 197 {
rlm@10 198 color: white;
rlm@10 199 background: darkblue;
rlm@10 200 width: 100%
rlm@10 201 }
rlm@10 202
rlm@10 203 .missing-library
rlm@10 204 {
rlm@10 205 color: darkred;
rlm@10 206 margin: 0 0 1em 0
rlm@10 207 }
rlm@10 208
rlm@10 209 .library-members
rlm@10 210 {
rlm@10 211 list-style: none
rlm@10 212 }
rlm@10 213
rlm@10 214 .library-member-name
rlm@10 215 {
rlm@10 216 font-weight: bold;
rlm@10 217 font-size: 105%
rlm@10 218 }")
rlm@10 219
rlm@10 220 (defn- extract-documentation
rlm@10 221 "Pulls the documentation for a var v out and turns it into HTML"
rlm@10 222 [v]
rlm@10 223 (if-let [docs (:doc (meta v))]
rlm@10 224 (map
rlm@10 225 (fn [l]
rlm@10 226 [:div {:class "library-member-doc-line"}
rlm@10 227 (if (= 0 (count l))
rlm@10 228 [:span {:class "library-member-doc-whitespace"} " "] ; We need something here to make the blank line show up
rlm@10 229 l)])
rlm@10 230 (s/split #"\n" docs))
rlm@10 231 ""))
rlm@10 232
rlm@10 233 (defn- member-type
rlm@10 234 "Figures out for a var x whether it's a macro, function, var or multifunction"
rlm@10 235 [x]
rlm@10 236 (try
rlm@10 237 (let [dx (deref x)]
rlm@10 238 (cond
rlm@10 239 (:macro (meta x)) :macro
rlm@10 240 (fn? dx) :fn
rlm@10 241 (= clojure.lang.MultiFn (:tag (meta x))) :multi
rlm@10 242 true :var))
rlm@10 243 (catch Exception e
rlm@10 244 :unknown)))
rlm@10 245
rlm@10 246 (defn- anchor-for-member
rlm@10 247 "Returns a suitable HTML anchor name given a library id and a member
rlm@10 248 id"
rlm@10 249 [libid memberid]
rlm@10 250 (str "member-" libid "-" memberid))
rlm@10 251
rlm@10 252 (defn- id-for-member-source
rlm@10 253 "Returns a suitable HTML id for a source listing given a library and
rlm@10 254 a member"
rlm@10 255 [libid memberid]
rlm@10 256 (str "membersource-" libid "-" memberid))
rlm@10 257
rlm@10 258 (defn- id-for-member-source-link
rlm@10 259 "Returns a suitable HTML id for a link to a source listing given a
rlm@10 260 library and a member"
rlm@10 261 [libid memberid]
rlm@10 262 (str "linkto-membersource-" libid "-" memberid))
rlm@10 263
rlm@10 264 (defn- symbol-for
rlm@10 265 "Given a namespace object ns and a namespaceless symbol memberid
rlm@10 266 naming a member of that namespace, returns a namespaced symbol that
rlm@10 267 identifies that member."
rlm@10 268 [ns memberid]
rlm@10 269 (symbol (name (ns-name ns)) (name memberid)))
rlm@10 270
rlm@10 271 (defn- elide-to-one-line
rlm@10 272 "Elides a string down to one line."
rlm@10 273 [s]
rlm@10 274 (s/replace-re #"(\n.*)+" "..." s))
rlm@10 275
rlm@10 276 (defn- elide-string
rlm@10 277 "Returns a string that is at most the first limit characters of s"
rlm@10 278 [s limit]
rlm@10 279 (if (< (- limit 3) (count s))
rlm@10 280 (str (subs s 0 (- limit 3)) "...")
rlm@10 281 s))
rlm@10 282
rlm@10 283 (defn- doc-elided-src
rlm@10 284 "Returns the src with the docs elided."
rlm@10 285 [docs src]
rlm@10 286 (s/replace-re (re-pattern (str "\"" (Pattern/quote docs) "\""))
rlm@10 287 (str "\""
rlm@10 288 (elide-to-one-line docs)
rlm@10 289 ;; (elide-string docs 10)
rlm@10 290 ;; "..."
rlm@10 291 "\"")
rlm@10 292 src))
rlm@10 293
rlm@10 294 (defn- format-source [libid memberid v]
rlm@10 295 (try
rlm@10 296 (let [docs (:doc (meta v))
rlm@10 297 src (if-let [ns (find-ns libid)]
rlm@10 298 (get-source (symbol-for ns memberid)))]
rlm@10 299 (if (and src docs)
rlm@10 300 (doc-elided-src docs src)
rlm@10 301 src))
rlm@10 302 (catch Exception ex
rlm@10 303 nil)))
rlm@10 304
rlm@10 305 (defn- generate-lib-member [libid [n v]]
rlm@10 306 [:li {:class "library-member"}
rlm@10 307 [:a {:name (anchor-for-member libid n)}]
rlm@10 308 [:dl {:class "library-member-table"}
rlm@10 309 [:dt {:class "library-member-name"}
rlm@10 310 (str n)]
rlm@10 311 [:dd
rlm@10 312 [:div {:class "library-member-info"}
rlm@10 313 [:span {:class "library-member-type"} (name (member-type v))]
rlm@10 314 " "
rlm@10 315 [:span {:class "library-member-arglists"} (str (:arglists (meta v)))]]
rlm@10 316 (into [:div {:class "library-member-docs"}] (extract-documentation v))
rlm@10 317 (let [member-source-id (id-for-member-source libid n)
rlm@10 318 member-source-link-id (id-for-member-source-link libid n)]
rlm@10 319 (if-let [member-source (format-source libid n v)]
rlm@10 320 [:div {:class "library-member-source-section"}
rlm@10 321 [:div {:class "library-member-source-toggle"}
rlm@10 322 "[ "
rlm@10 323 [:a {:href (format "javascript:toggleSource('%s')" member-source-id)
rlm@10 324 :id member-source-link-id} "Show Source"]
rlm@10 325 " ]"]
rlm@10 326 [:div {:class "library-member-source" :id member-source-id}
rlm@10 327 [:pre member-source]]]))]]])
rlm@10 328
rlm@10 329 (defn- anchor-for-library
rlm@10 330 "Given a symbol id identifying a namespace, returns an identifier
rlm@10 331 suitable for use as the name attribute of an HTML anchor tag."
rlm@10 332 [id]
rlm@10 333 (str "library-" id))
rlm@10 334
rlm@10 335 (defn- generate-lib-member-link
rlm@10 336 "Emits a hyperlink to a member of a namespace given libid (a symbol
rlm@10 337 identifying the namespace) and the vector [n v], where n is the symbol
rlm@10 338 naming the member in question and v is the var pointing to the
rlm@10 339 member."
rlm@10 340 [libid [n v]]
rlm@10 341 [:a {:class "lib-member-link"
rlm@10 342 :href (str "#" (anchor-for-member libid n))} (name n)])
rlm@10 343
rlm@10 344 (defn- anchor-for-library-contents
rlm@10 345 "Returns an HTML ID that identifies the element that holds the
rlm@10 346 documentation contents for the specified library."
rlm@10 347 [lib]
rlm@10 348 (str "library-contents-" lib))
rlm@10 349
rlm@10 350 (defn- anchor-for-library-contents-toggle
rlm@10 351 "Returns an HTML ID that identifies the element that toggles the
rlm@10 352 visibility of the library contents."
rlm@10 353 [lib]
rlm@10 354 (str "library-contents-toggle-" lib))
rlm@10 355
rlm@10 356 (defn- generate-lib-doc
rlm@10 357 "Emits the HTML that documents the namespace identified by the
rlm@10 358 symbol lib."
rlm@10 359 [lib]
rlm@10 360 [:div {:class "library"}
rlm@10 361 [:a {:name (anchor-for-library lib)}]
rlm@10 362 [:div {:class "library-name"}
rlm@10 363 [:span {:class "library-contents-toggle"}
rlm@10 364 "[ "
rlm@10 365 [:a {:id (anchor-for-library-contents-toggle lib)
rlm@10 366 :href (format "javascript:toggle('%s', '%s', '-', '+')"
rlm@10 367 (anchor-for-library-contents lib)
rlm@10 368 (anchor-for-library-contents-toggle lib))}
rlm@10 369 "-"]
rlm@10 370 " ] "]
rlm@10 371 (name lib)]
rlm@10 372 (let [ns (find-ns lib)]
rlm@10 373 (if ns
rlm@10 374 (let [lib-members (sort (ns-publics ns))]
rlm@10 375 [:a {:name (anchor-for-library lib)}]
rlm@10 376 [:div {:class "library-contents" :id (anchor-for-library-contents lib)}
rlm@10 377 (into [:div {:class "library-member-links"}]
rlm@10 378 (interpose " " (map #(generate-lib-member-link lib %) lib-members)))
rlm@10 379 (into [:ol {:class "library-members"}]
rlm@10 380 (map #(generate-lib-member lib %) lib-members))])
rlm@10 381 [:div {:class "missing-library library-contents" :id (anchor-for-library-contents lib)} "Could not load library"]))])
rlm@10 382
rlm@10 383 (defn- load-lib
rlm@10 384 "Calls require on the library identified by lib, eating any
rlm@10 385 exceptions."
rlm@10 386 [lib]
rlm@10 387 (try
rlm@10 388 (require lib)
rlm@10 389 (catch java.lang.Exception x
rlm@10 390 nil)))
rlm@10 391
rlm@10 392 (defn- generate-lib-link
rlm@10 393 "Generates a hyperlink to the documentation for a namespace given
rlm@10 394 lib, a symbol identifying that namespace."
rlm@10 395 [lib]
rlm@10 396 (let [ns (find-ns lib)]
rlm@10 397 (if ns
rlm@10 398 [:a {:class "lib-link" :href (str "#" (anchor-for-library lib))} (str (ns-name ns))])))
rlm@10 399
rlm@10 400 (defn- generate-lib-links
rlm@10 401 "Generates the list of hyperlinks to each namespace, given libs, a
rlm@10 402 vector of symbols naming namespaces."
rlm@10 403 [libs]
rlm@10 404 (into [:div {:class "lib-links"}
rlm@10 405 [:div {:class "lib-link-header"} "Namespaces"
rlm@10 406 [:span {:class "all-libs-toggle"}
rlm@10 407 " [ "
rlm@10 408 [:a {:href "javascript:expandAllNamespaces()"}
rlm@10 409 "Expand All"]
rlm@10 410 " ] [ "
rlm@10 411 [:a {:href "javascript:collapseAllNamespaces()"}
rlm@10 412 "Collapse All"]
rlm@10 413 " ]"]]]
rlm@10 414 (interpose " " (map generate-lib-link libs))))
rlm@10 415
rlm@10 416 (defn generate-toggle-namespace-script
rlm@10 417 [action toggle-text lib]
rlm@10 418 (str (format "%s('%s');\n" action (anchor-for-library-contents lib))
rlm@10 419 (format "setLinkToggleText('%s', '%s');\n" (anchor-for-library-contents-toggle lib) toggle-text)))
rlm@10 420
rlm@10 421 (defn generate-all-namespaces-action-script
rlm@10 422 [action toggle-text libs]
rlm@10 423 (str (format "function %sAllNamespaces()" action)
rlm@10 424 \newline
rlm@10 425 "{"
rlm@10 426 \newline
rlm@10 427 (reduce str (map #(generate-toggle-namespace-script action toggle-text %) libs))
rlm@10 428 \newline
rlm@10 429 "}"))
rlm@10 430
rlm@10 431 (defn generate-documentation
rlm@10 432 "Returns a string which is the HTML documentation for the libraries
rlm@10 433 named by libs. Libs is a vector of symbols identifying Clojure
rlm@10 434 libraries."
rlm@10 435 [libs]
rlm@10 436 (dorun (map load-lib libs))
rlm@10 437 (let [writer (new java.io.StringWriter)]
rlm@10 438 (binding [*out* writer]
rlm@10 439 (prxml
rlm@10 440 [:html {:xmlns "http://www.w3.org/1999/xhtml"}
rlm@10 441 [:head
rlm@10 442 [:title "Clojure documentation browser"]
rlm@10 443 [:style *style*]
rlm@10 444 [:script {:language "JavaScript" :type "text/javascript"} [:raw! *script*]]
rlm@10 445
rlm@10 446 [:script {:language "JavaScript" :type "text/javascript"}
rlm@10 447 [:raw! "// <![CDATA[!" \newline]
rlm@10 448 (generate-all-namespaces-action-script "expand" "-" libs)
rlm@10 449 (generate-all-namespaces-action-script "collapse" "+" libs)
rlm@10 450 [:raw! \newline "// ]]>"]]]
rlm@10 451 (let [lib-vec (sort libs)]
rlm@10 452 (into [:body (generate-lib-links lib-vec)]
rlm@10 453 (map generate-lib-doc lib-vec)))]))
rlm@10 454 (.toString writer)))
rlm@10 455
rlm@10 456
rlm@10 457 (defn generate-documentation-to-file
rlm@10 458 "Calls generate-documentation on the libraries named by libs and
rlm@10 459 emits the generated HTML to the path named by path."
rlm@10 460 [path libs]
rlm@10 461 (io/spit path (generate-documentation libs)))
rlm@10 462
rlm@10 463 (comment
rlm@10 464 (generate-documentation-to-file
rlm@10 465 "C:/TEMP/CLJ-DOCS.HTML"
rlm@10 466 ['clojure.contrib.accumulators])
rlm@10 467
rlm@10 468 (defn gen-all-docs []
rlm@10 469 (generate-documentation-to-file
rlm@10 470 "C:/temp/clj-libs.html"
rlm@10 471 [
rlm@10 472 'clojure.set
rlm@10 473 'clojure.main
rlm@10 474 'clojure.core
rlm@10 475 'clojure.zip
rlm@10 476 'clojure.xml
rlm@10 477 'clojure.contrib.accumulators
rlm@10 478 'clojure.contrib.apply-macro
rlm@10 479 'clojure.contrib.auto-agent
rlm@10 480 'clojure.contrib.combinatorics
rlm@10 481 'clojure.contrib.command-line
rlm@10 482 'clojure.contrib.complex-numbers
rlm@10 483 'clojure.contrib.cond
rlm@10 484 'clojure.contrib.def
rlm@10 485 'clojure.contrib.io
rlm@10 486 'clojure.contrib.enum
rlm@10 487 'clojure.contrib.error-kit
rlm@10 488 'clojure.contrib.except
rlm@10 489 'clojure.contrib.fcase
rlm@10 490 'clojure.contrib.generic
rlm@10 491 'clojure.contrib.generic.arithmetic
rlm@10 492 'clojure.contrib.generic.collection
rlm@10 493 'clojure.contrib.generic.comparison
rlm@10 494 'clojure.contrib.generic.functor
rlm@10 495 'clojure.contrib.generic.math-functions
rlm@10 496 'clojure.contrib.import-static
rlm@10 497 'clojure.contrib.javadoc
rlm@10 498 'clojure.contrib.javalog
rlm@10 499 'clojure.contrib.lazy-seqs
rlm@10 500 'clojure.contrib.lazy-xml
rlm@10 501 'clojure.contrib.macro-utils
rlm@10 502 'clojure.contrib.macros
rlm@10 503 'clojure.contrib.math
rlm@10 504 'clojure.contrib.miglayout
rlm@10 505 'clojure.contrib.mmap
rlm@10 506 'clojure.contrib.monads
rlm@10 507 'clojure.contrib.ns-utils
rlm@10 508 'clojure.contrib.prxml
rlm@10 509 'clojure.contrib.repl-ln
rlm@10 510 'clojure.contrib.repl-utils
rlm@10 511 'clojure.contrib.seq
rlm@10 512 'clojure.contrib.server-socket
rlm@10 513 'clojure.contrib.shell
rlm@10 514 'clojure.contrib.sql
rlm@10 515 'clojure.contrib.stream-utils
rlm@10 516 'clojure.contrib.string
rlm@10 517 'clojure.contrib.test-contrib
rlm@10 518 'clojure.contrib.trace
rlm@10 519 'clojure.contrib.types
rlm@10 520 'clojure.contrib.zip-filter
rlm@10 521 'clojure.contrib.javadoc.browse
rlm@10 522 'clojure.contrib.json.read
rlm@10 523 'clojure.contrib.json.write
rlm@10 524 'clojure.contrib.lazy-xml.with-pull
rlm@10 525 'clojure.contrib.miglayout.internal
rlm@10 526 'clojure.contrib.probabilities.finite-distributions
rlm@10 527 'clojure.contrib.probabilities.monte-carlo
rlm@10 528 'clojure.contrib.probabilities.random-numbers
rlm@10 529 'clojure.contrib.sql.internal
rlm@10 530 'clojure.contrib.test-clojure.evaluation
rlm@10 531 'clojure.contrib.test-clojure.for
rlm@10 532 'clojure.contrib.test-clojure.numbers
rlm@10 533 'clojure.contrib.test-clojure.printer
rlm@10 534 'clojure.contrib.test-clojure.reader
rlm@10 535 'clojure.contrib.test-clojure.sequences
rlm@10 536 'clojure.contrib.test-contrib.shell
rlm@10 537 'clojure.contrib.test-contrib.string
rlm@10 538 'clojure.contrib.zip-filter.xml
rlm@10 539 ]))
rlm@10 540 )