<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>README</filename>
    </added>
    <added>
      <filename>TODO</filename>
    </added>
    <added>
      <filename>formatters.lisp</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,5 +1,5 @@
-bdd.el from Yurii Rashkovskii
+bdd.el is by Yurii Rashkovskii, used with implicit permission (it's on his blog)
 
-template.html layout from rspec
+The css and structure of template.html are from rspec.
 
-inspiration from rspec
+Inspiration from rspec.</diff>
      <filename>CREDITS</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,9 @@
     :version &quot;0.1&quot;
     :author &quot;Oliver Steele &lt;steele@osteele.com&gt;&quot;
     :licence &quot;unknown&quot;
-    :components ((:file &quot;cl-spec&quot; :depends-on (&quot;bdd&quot; &quot;utilities&quot;))
+    :components ((:file &quot;formatters&quot;
+                        :depends-on (&quot;specify&quot; &quot;utilities&quot; &quot;templates&quot;))
+                 (:file &quot;specify&quot; :depends-on (&quot;bdd&quot; &quot;utilities&quot;))
                  (:file &quot;templates&quot; :depends-on (&quot;utilities&quot;))
                  (:file &quot;utilities&quot;)
                  (:file &quot;bdd&quot;))</diff>
      <filename>cl-spec.asdf</filename>
    </modified>
    <modified>
      <diff>@@ -17,16 +17,15 @@ since it runs the specifications once it has collected them all.&quot;)
   &quot;(RUN-SPECIFICATION PATHNAME) binds this to a list of specifications
 for DEFINE-SPECIFICATION to collect into.&quot;)
 
-;; this doesn't really test that every element has type TYPE, but
-;; I don't think there's a way to do that in CL
-(deftype list-type (&amp;optional (type t))
-  `(and list (or null (cons ,type))))
-
-;; DEFINE-SPECIFICATION instantiates this.  It holds a list of named
-;; examples.
-(define-class specification name
-  (setup nil (or function null)) ; a function to run before each example
-  (examples nil (list-type (cons string function))))
+(defclass specification ()
+  ((name :initarg :name :reader specification-name :type string)
+   (setup :initarg :setup :reader specification-setup :initform nil
+          :type (or function null)
+          :documentation &quot;Run this before each example&quot;)
+   (examples :initarg :examples :reader specification-examples
+             :type (list-type (cons string function))))
+  (:documentation &quot;DEFINE-SPECIFICATION instantiates this.  It holds a list
+of named examples.&quot;))
 
 (define-print-method (specification name) &quot;#&lt;specification ~S&gt;&quot; name)
 
@@ -73,30 +72,32 @@ subdirectory for examples in Lisp syntax.&quot;
 ;; but they work fine for now.
 
 (define-accumulating-method (specification-results-examples
-                             (self abstract-specification-results)
-                             :child-reader specification-results-children)
-    append)
+                             (self specification-results-group))
+    append
+  :child-reader specification-results-children)
 
 (define-accumulating-method (specification-results-failures
-                             (self abstract-specification-results)
-                             :child-reader specification-results-children)
-    append)
+                             (self specification-results-group))
+    append
+  :child-reader specification-results-children)
 
 (define-accumulating-method (specification-results-elapsed-time
-                             (self abstract-specification-results)
-                             :child-reader specification-results-children)
-    sum)
+                             (self specification-results-group))
+    sum
+  :child-reader specification-results-children)
 
-(define-method (specification-results-examples-count
-                (self abstract-specification-results))
-  (length (specification-results-examples self)))
+(define-accumulating-method (specification-results-examples-count
+                             (self specification-results-group))
+    sum
+  :child-reader specification-results-children)
 
-(define-method (specification-results-failures-count
-                (self abstract-specification-results))
-  (length (specification-results-failures self)))
+(define-accumulating-method (specification-results-failures-count
+                             (self specification-results-group))
+    sum
+  :child-reader specification-results-children)
 
 
-;; TODO: reify example's type?
+;; TODO: reify example result's type?
 (defclass specification-results (abstract-specification-results)
   ((specification :initarg :specification
                   :reader specification-results-specification
@@ -121,11 +122,11 @@ subdirectory for examples in Lisp syntax.&quot;
 ;;;
 
 (define-method (run-specification (self specification) &amp;key onsuccess onerror)
-  &quot;Test all the examples, and returns a list of dictionaries {:name, :success, :condition, :time}.
+  &quot;Run all the examples.  Returns a SPECIFICATION-RESULTS.
 
-Applies ONSUCCESS or ONERROR to each one, depending on whether it
-passes.  Callbacks are used so that the caller can show incremental
-progress during execution.&quot;
+Applies ONSUCCESS or ONERROR to each example name, depending on
+whether the example passes.  Callbacks are used so that the caller can
+show incremental progress during execution.&quot;
   (flet ((run-example (name fn)
            &quot;Returns values success and condition&quot;
            (if (specification-setup self)
@@ -201,78 +202,3 @@ progress during execution.&quot;
 
 (define-method (specification-runner (string string) &amp;rest args &amp;key &amp;allow-other-keys)
   (apply #'run-specification (pathname string) args))
-
-
-;;;
-;;; Formatters
-;;;
-
-(define-class specification-formatter)
-(define-class text-specification-formatter (specification-formatter))
-
-(define-method (format-specification-results
-                (formatter text-specification-formatter)
-                results
-                &amp;key (output-stream t) pathname
-                &amp;allow-other-keys)
-  (format t &quot;~%~%&quot;)
-  (loop for result in (specification-results-failures results)
-     for i upfrom 1
-     do (format output-stream &quot;~D)~%~A~%~A~%~%&quot; i (ref1 result :condition) pathname))
-  (format output-stream &quot;Finished in ~F seconds~%~%&quot;
-          (specification-results-elapsed-time results))
-  (format output-stream &quot;~D example~:P, ~D failure~:P&quot;
-          (specification-results-examples-count results)
-          (specification-results-failures-count results)))
-
-(define-class html-specification-formatter (specification-formatter))
-
-(defvar *html-spec-parameter-pathname*
-  (merge-pathnames &quot;template.html&quot; *load-pathname*)
-  &quot;The :FORMAT 'HTML option to RUN-SPECIFICATION starts with this.&quot;)
-
-(define-method (format-specification-results
-                (formatter html-specification-formatter)
-                results
-                &amp;key
-                &amp;allow-other-keys)
-  ;; for now, the group hierarchy must be exactly one deep
-  (labels ((translate-results (results depth)
-             (etypecase results
-               (specification-results-group
-                (assert (= depth 0) () &quot;for now, groups can't be nested&quot;)
-                ;; TODO: would be nicer with a general serialization
-                ;; mechanism instead of adding keys afterwards; or
-                ;; else maybe the templater should use accessors
-                ;; instead of dictionary conversion
-                (let ((dict
-                       (object-&gt;dictionary results
-                                          '(examples-count
-                                            failures-count
-                                            elapsed-time)
-                                          :basename 'specification-results)))
-                  (setref dict 'name
-                          (specification-name (specification-results-specification (first (specification-results-children results)))))
-                  (setref dict 'children
-                          (loop for child in (specification-results-children results)
-                             collect (translate-results child (1+ depth))))
-                  dict))
-               (specification-results
-                (assert (= depth 1) ()
-                        &quot;for now, specification result leaves must be exactly one deep&quot;)
-                (let ((dict
-                       (object-&gt;dictionary results '(examples-count
-                                                     failures-count
-                                                     elapsed-time)
-                                           :basename 'specification-results)))
-                  (setref dict 'name
-                          (specification-name (specification-results-specification results)))
-                  (setref dict 'examples
-                          (mapcar #'translate-example (specification-results-examples results)))
-                  dict))))
-          (translate-example (example)
-            ;; it's already in dictionary form
-            example))
-    (copy-template *html-spec-parameter-pathname*
-                   (merge-pathnames &quot;spec.html&quot; *html-spec-parameter-pathname*)
-                   (translate-results results 0))))</diff>
      <filename>specify.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,10 @@
 ;;; Copyright 2008 by Oliver Steele.  Released under the MIT License.
 
+;; this doesn't really test that every element has type TYPE, but
+;; I don't think there's a way to do that in CL
+(deftype list-type (&amp;optional (type t))
+  `(and list (or null (cons ,type))))
+
 (define-method (trim (s string))
   (flet ((whitespace-char-p (char)
            (or(char= #\space char) (not (graphic-char-p char)))))
@@ -12,6 +17,8 @@
             (t
              (subseq s start (1+ end)))))))
 
+(defsetf rref setref)
+
 ;; TODO: default slot-names by introspection
 (define-method (object-&gt;dictionary (object t) reader-names &amp;key basename)
   (plist-&gt;dictionary
@@ -36,10 +43,17 @@
                 'float)))
        (values value elapsed-time))))
 
-(defmacro define-accumulating-method ((function-name (self type) &amp;rest args)
-                                      accumulation-construct)
+(defmacro define-accumulating-method ((function-name (self type))
+                                      accumulation-construct
+                                      &amp;key child-reader)
+  &quot;Defines a method on FUNCTION-NAME, specialized on a first argument of TYPE,
+that uses ACCUMALATION-CONSTRUCT (a LOOP-friendly accumulation keyword) to
+accumulate the values of the projections of its children.
+
+Children are accessed via CHILD-READER, which defaults to {TYPE}-CHILDREN,
+and projected via FUNCTION-NAME.&quot;
   (let ((value-reader function-name)
-        (child-reader (or (getf args :child-reader)
+        (child-reader (or child-reader
                           (concatenate-symbol type &quot;-CHILDREN&quot;)))
         (child (gensym &quot;child&quot;)))
     `(define-method (,function-name (,self ,type))</diff>
      <filename>utilities.lisp</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>README.txt</filename>
    </removed>
    <removed>
      <filename>agenda.txt</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>f497b7165c15396b673cbd3a1d71323c2f1fffc3</id>
    </parent>
  </parents>
  <author>
    <name>Oliver Steele</name>
    <email>steele@osteele.com</email>
  </author>
  <url>http://github.com/osteele/cl-spec/commit/25a9d6585673e18268f395d16c7328483180a0b2</url>
  <id>25a9d6585673e18268f395d16c7328483180a0b2</id>
  <committed-date>2008-01-07T19:32:25-08:00</committed-date>
  <authored-date>2008-01-07T19:32:25-08:00</authored-date>
  <message>factor out formatters; lots more file-level rearrangement</message>
  <tree>55f98626372becfae6a58bfc941e48075ef499a7</tree>
  <committer>
    <name>Oliver Steele</name>
    <email>steele@osteele.com</email>
  </committer>
</commit>
