Upgrade catacumba to 2.0.0-SNAPSHOT

Upgrade catacumba to 2.0.0-SNAPSHOT

--- project.clj
+++ project.clj
@@ -19,7 +19,7 @@
                  [funcool/struct "1.0.0"]
                  [funcool/suricatta "1.2.0"]
                  [funcool/promesa "1.6.0"]
-                 [funcool/catacumba "1.2.0"]
+                 [funcool/catacumba "2.0.0-SNAPSHOT"]

                  [org.clojure/data.xml "0.1.0-beta2"]
                  [org.jsoup/jsoup "1.10.1"]


Version 0.1.2

Version 0.1.2

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject api "0.1.2-SNAPSHOT"
+(defproject api "0.1.2"
   :min-lein-version "2.6.1"
   :description "Optly API"
   :url "https://github.com/optly/api"


We no longer target Cassandra 1.2.x

We no longer target Cassandra 1.2.x

--- project.clj
+++ project.clj
@@ -21,8 +21,7 @@
                          :plugins [[codox "0.8.10"]]
                          :dependencies [[com.codahale.metrics/metrics-core "3.0.2"]
                                         [org.xerial.snappy/snappy-java     "1.1.0.1"]
-                                        [org.clojure/tools.trace           "0.7.6"]]}
-                   :cassandra1211 {:dependencies [[org.apache.cassandra/cassandra-all "1.2.11"]]}}
+                                        [org.clojure/tools.trace           "0.7.6"]]}}
   :aliases        {"all" ["with-profile" "dev:dev,1.4:dev,1.5:dev,master"]}
   :test-selectors {:focus   :focus
                    :cql     :cql


Bump version

Bump version

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject keechma/keechma "0.2.0-SNAPSHOT-10"
+(defproject keechma/keechma "0.2.0-SNAPSHOT-11"
   :description "Frontend micro framework for ClojureScript and Reagent"
   :url "http://github.com/keechma/keechma"
   :license {:name "MIT"}
@@ -29,10 +29,10 @@
           :namespaces [keechma.app-state keechma.controller keechma.controller-manager keechma.ui-component]}

   :clean-targets ^{:protect false} ["resources/public/js/compiled" "target"]
-
+
   :cljsbuild {:builds
               [{:id "dev"
-                :source-paths ["src"]
+                :source-paths ["src"]

                 :compiler {:main keechma.core
                            :asset-path "js/compiled/out"


Update dependencies

Update dependencies

--- project.clj
+++ project.clj
@@ -9,7 +9,7 @@
                  [ring/ring-defaults "0.3.3"]
                  [selmer "1.12.40"]
                  [cheshire "5.10.0"]
-                 [org.postgresql/postgresql "42.2.21"]
+                 [org.postgresql/postgresql "42.2.22"]
                  [org.clojure/java.jdbc "0.7.12"]
                  [honeysql "1.0.461"]
                  [buddy/buddy-auth "3.0.1"]
@@ -19,7 +19,7 @@
                  ;; included by commons-text
                  [commons-codec/commons-codec "1.15"]
                  [org.clojure/tools.logging "1.1.0"]
-                 [org.slf4j/slf4j-log4j12 "1.7.30"]
+                 [org.slf4j/slf4j-log4j12 "1.7.31"]
                  [org.jsoup/jsoup "1.13.1"]
                  [clojure.java-time "0.3.2"]]
   :main ^:skip-aot ktra-indexer.handler


Version 0.4.1-SNAPSHOT

Version 0.4.1-SNAPSHOT

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject lein-droid/lein-droid "0.4.0"
+(defproject lein-droid/lein-droid "0.4.1-SNAPSHOT"
   :description "Plugin for easy Clojure/Android development and deployment"
   :url "https://github.com/clojure-android/lein-droid"
   :license {:name "Eclipse Public License"


Update dependencies, fixes #1

Update dependencies, fixes #1

--- project.clj
+++ project.clj
@@ -4,9 +4,9 @@
   :url               "http://clojurecassandra.info"
   :license           {:name "Eclipse Public License"
                       :url  "http://www.eclipse.org/legal/epl-v10.html"}
-  :dependencies      [[org.clojure/clojure                          "1.7.0"]
-                      [com.datastax.cassandra/cassandra-driver-core "3.0.0"]
-                      [com.datastax.cassandra/cassandra-driver-dse  "3.0.0"]
+  :dependencies      [[org.clojure/clojure                          "1.8.0"]
+                      [com.datastax.cassandra/cassandra-driver-core "3.0.2"]
+                      [com.datastax.cassandra/cassandra-driver-dse  "3.0.0-rc1"]
                       [org.clojure/core.match                       "0.3.0-alpha4"]]
   :aot [clojurewerkz.cassaforte.query]
   :source-paths      ["src/clojure"]
@@ -14,7 +14,7 @@
   :java-source-paths ["test/java" "src/java"]
   :profiles          {:1.6    {:dependencies [[org.clojure/clojure "1.6.0"]]}
                       :1.7    {:dependencies [[org.clojure/clojure "1.7.0"]]}
-                      :master {:dependencies [[org.clojure/clojure "1.8.0-master-SNAPSHOT"]]}
+                      :master {:dependencies [[org.clojure/clojure "1.9.0-master-SNAPSHOT"]]}
                       :dev    {:jvm-opts       ["-Dlog4j.configuration=log4j.properties.unit"
                                                 "-Xmx2048m"
                                                 "-javaagent:lib/jamm-0.2.5.jar"]


Start 2.8.3-SNAPSHOT

Start 2.8.3-SNAPSHOT

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject nightcode "2.8.2"
+(defproject nightcode "2.8.3-SNAPSHOT"
   :description "An IDE for Clojure"
   :url "https://github.com/oakes/Nightcode"
   :license {:name "Public Domain"


Try jdbc4, match heroku docs version

Try jdbc4, match heroku docs version

--- project.clj
+++ project.clj
@@ -10,7 +10,7 @@
                  [compojure "1.3.2"]
                  [enlive "1.1.5"]
                  [yesql "0.4.0"]
-                 [org.postgresql/postgresql "9.4-1201-jdbc41"]
+                 [org.postgresql/postgresql "9.4-1201-jdbc4"]
                  [ragtime "0.3.8"]
                  [com.cemerick/friend "0.2.1"]
                  [clj-time "0.9.0"]


(PCP-535) Add test-schema-validation profile and test-all task

--- project.clj
+++ project.clj
@@ -55,6 +55,15 @@
              :cljfmt {:plugins [[lein-cljfmt "0.3.0"]
                                 [lein-parent "0.2.1"]]
                       :parent-project {:path "../pl-clojure-style/project.clj"
-                                       :inherit [:cljfmt]}}}
+                                       :inherit [:cljfmt]}}
+             :test-base [
+                         :dev
+                         {:source-paths ["test-resources"]
+                          :test-paths ^:replace ["test"]}]
+             :test-schema-validation [:test-base
+                                      {:injections [(do
+                                                      (require 'schema.core)
+                                                      (schema.core/set-fn-validation! true))]}]}

-  :aliases {"cljfmt" ["with-profile" "+cljfmt" "cljfmt"]})
+  :aliases {"cljfmt" ["with-profile" "+cljfmt" "cljfmt"]
+            "test-all" ["with-profile" "test-base:test-schema-validation" "test"]})


Bumped QiMessaging version

Bumped QiMessaging version

--- project.clj
+++ project.clj
@@ -10,4 +10,4 @@
   :test-paths ["test" "src/test/clojure"]
   :dependencies [[org.clojure/clojure "1.5.1"]
                  [org.clojure/core.async "0.1.242.0-44b1e3-alpha"]
-                 [com.aldebaran/qimessaging "1.22.1"]])
+                 [com.aldebaran/qimessaging "1.22.2"]])


Turn maybe monad into record

Turn maybe monad into record

--- src/cats/monad/maybe.cljc
+++ src/cats/monad/maybe.cljc
@@ -40,51 +40,23 @@

 (declare context)

-(deftype Just [v]
+(defrecord Just [just]
   p/Contextual
   (-get-context [_] context)

   p/Extract
-  (-extract [_] v)
+  (-extract [_] just)

   p/Printable
   (-repr [_]
-    (str "#<Just " (pr-str v) ">"))
-
-  #?@(:cljs [cljs.core/ILookup
-             (-lookup
-               [this k]
-                 (if (= k :just) @this nil))
-             (-lookup
-               [this k not-found]
-                 (if (= k :just) @this not-found))]
-      :clj  [clojure.lang.ILookup
-             (valAt
-               [this k]
-                 (if (= k :just) @this nil))
-             (valAt
-               [this k not-found]
-                 (if (= k :just) @this not-found))])
+    (str "#<Just " (pr-str just) ">"))

   #?@(:cljs [cljs.core/IDeref
-             (-deref [_] v)]
+             (-deref [_] just)]
       :clj  [clojure.lang.IDeref
-             (deref [_] v)])
-
-  #?@(:clj
-      [Object
-       (equals [self other]
-         (if (instance? Just other)
-           (= v (.-v ^Just other))
-           false))]
-      :cljs
-      [cljs.core/IEquiv
-       (-equiv [_ other]
-         (if (instance? Just other)
-           (= v (.-v ^Just other))
-           false))]))
-
-(deftype Nothing []
+             (deref [_] just)]))
+
+(defrecord Nothing []
   p/Contextual
   (-get-context [_] context)

@@ -95,34 +67,10 @@
   (-repr [_]
     "#<Nothing>")

-  #?@(:cljs [cljs.core/ILookup
-             (-lookup
-               [this k]
-                 (if (= k :nothing) this nil))
-             (-lookup
-               [this k not-found]
-                 (if (= k :nothing) this not-found))]
-      :clj  [clojure.lang.ILookup
-             (valAt
-               [this k]
-                 (if (= k :nothing) this nil))
-             (valAt
-               [this k not-found]
-                 (if (= k :nothing) this not-found))])
-
   #?@(:cljs [cljs.core/IDeref
              (-deref [_] nil)]
       :clj  [clojure.lang.IDeref
-             (deref [_] nil)])
-
-  #?@(:clj
-      [Object
-       (equals [self other]
-         (instance? Nothing other))]
-      :cljs
-      [cljs.core/IEquiv
-       (-equiv [_ other]
-         (instance? Nothing other))]))
+             (deref [_] nil)]))

 (alter-meta! #'->Nothing assoc :private true)
 (alter-meta! #'->Just assoc :private true)
@@ -152,7 +100,7 @@
 (defn nothing
   "A Nothing type constructor."
   []
-  (Nothing.))
+  (assoc (Nothing.) :nothing nil))

 (defn just?
   "Returns true if `v` is an instance


Remove TODO (see #4)

Remove TODO (see #4)

--- src/caesium/binding.clj
+++ src/caesium/binding.clj
@@ -169,8 +169,6 @@
       ^bytes ^{Pinned {}} salt
       ^bytes ^{Pinned {}} personal]]

-    ;; TODO: how do I reference a crypto_generichash_blake2b_state *?
-
     [^int crypto_hash_sha256_bytes []]
     [^int crypto_hash_sha256
      [^bytes ^{Pinned {}} buf


Support for multiple templates

Support for multiple templates

Non-default templates can be indicated with a keyword in wrap-template.

--- modules/template/src/modular/template.clj
+++ modules/template/src/modular/template.clj
@@ -13,30 +13,40 @@
 (defprotocol Templater
   (render-template [_ template model]))

-(defrecord SingleTemplate [template]
+(defrecord Template [template]
   RingBinding
   (ring-binding [this req]
-    {::template
-     (fn [req content]
-       (let [model (apply merge
-                          (for [[k v] this
-                                :when (satisfies? TemplateModel v)]
-                            {k (template-model v {:request req})}))]
-         (debugf "Template model, prior to merge with content, is %s" (pr-str model))
-         (debugf "After will be: %s" (merge model content))
-         (render-template
-          (:templater this)
-          template
-          (merge-with merge model content))))}))
+    {::template {(:key this)
+                 (fn [req content]
+                   (let [model (apply merge
+                                      (for [[k v] this
+                                            :when (satisfies? TemplateModel v)]
+                                        {k (template-model v {:request req})}))]
+                     (debugf "Template model, prior to merge with content, is %s" (pr-str model))
+                     (debugf "After will be: %s" (merge model content))
+                     (render-template
+                      (:templater this)
+                      template
+                      (merge-with merge model content))))}}))

-(defn new-single-template
+(defn new-template
   "The template argument can be a path, resource, file or whatever is
   supported by the dependant templater."
   [& {:as opts}]
   (component/using
    (->> opts
         (s/validate {:template s/Any})
-        map->SingleTemplate)
+        map->Template)
+   [:templater]))
+
+(defn new-keyed-template
+  "The template argument can be a path, resource, file or whatever is
+  supported by the dependant templater."
+  [& {:as opts}]
+  (component/using
+   (->> opts
+        (s/validate {:key s/Keyword :template s/Any})
+        map->Template)
    [:templater]))

 ;; TODO: The issue with SingleTemplate is that it is static, it is given
@@ -50,13 +60,17 @@
   use it to process the response of the delegate handler. The initial
   response is considered to be a template model, and merged with other
   template models from other components."
-  [h]
-  (fn [req]
-    (if-let [merge-with-template (::template req)]
-      (let [resp (h req)]
-        (merge resp {:body (merge-with-template req resp)}))
-      (throw (ex-info "wrap-template expects that a template is bound in the request with key :modular.template/template" {})))))
-
+  ([h & [k]]
+     (fn [req]
+       (if-let [merge-with-template (get-in req [::template k])]
+         (let [resp (h req)]
+           (merge resp {:body (merge-with-template req resp)}))
+         (throw
+          (if (::template req)
+            (if k
+              (ex-info (format "No template with key %s" k) {:key k})
+              (ex-info (format "No default template") {}))
+            (ex-info "wrap-template expects that a template is included in the system" {:key k})))))))

 (defrecord TemplateModelMap []
   TemplateModel


bring in Om Next protocols

bring in Om Next protocols

--- src/cellophane/next.clj
+++ src/cellophane/next.clj
@@ -1,6 +1,27 @@
 (ns cellophane.next
   (:require [cellophane.protocols :as p]))

+;; ===================================================================
+;; Protocols
+
+(defprotocol Ident
+  (ident [this props] "Return the ident for this component"))
+
+(defprotocol IQueryParams
+  (params [this] "Return the query parameters"))
+
+(extend-type Object
+  IQueryParams
+  (params [_]))
+
+(defprotocol IQuery
+  (query [this] "Return the component's unbound query"))
+
+(defprotocol ILocalState
+  (-set-state! [this new-state] "Set the component's local state")
+  (-get-state [this] "Get the component's local state")
+  (-get-rendered-state [this] "Get the component's rendered local state")
+  (-merge-pending-state! [this] "Get the component's pending local state"))

 ;; ===================================================================
 ;; defui


Use appropriate Content-Type for RSS

Use appropriate Content-Type for RSS

--- src/clj/chili_dog_night/core.clj
+++ src/clj/chili_dog_night/core.clj
@@ -22,7 +22,10 @@
       (views/gathering gathering)))
   (GET "/colophon" [] (views/colophon))
   (GET "/about" [] (views/about))
-  (GET "/rss" [] (views/rss-feed (take *rss-feed-item-limit* data/gatherings)))
+  (GET "/rss" []
+    {:status 200
+     :headers {"Content-Type" "text/xml"}
+     :body (views/rss-feed (take *rss-feed-item-limit* data/gatherings))})
   (route/files "/" {:root "target/resources"})
   (route/not-found (views/not-found)))


GM logging

GM logging

--- src/clj_gamification/handler.clj
+++ src/clj_gamification/handler.clj
@@ -167,8 +167,10 @@
   (let [first-visitor? (compare-and-set! state :not-started :brainstorming)
         gm? (:gamemaster? session)]
    (cond
-    (or gm? first-visitor?) {:session {:gamemaster? true},
-                             :body (page-gamemaster)}
+    (or gm? first-visitor?) (do
+                              (info (str "GM access; first? " first-visitor? ", session " (-> req :cookies (get "ring-session") :value) ", ip " (:remote-addr req)))
+                              {:session {:gamemaster? true},
+                              :body (page-gamemaster)})
     (= @state :brainstorming) (page-team-registration)
     (= @state :voting) (if (has-voted? req)
                            "Thank you for your vote!"


update about page

update about page

--- src/cljs/tictag/views/about.cljs
+++ src/cljs/tictag/views/about.cljs
@@ -46,7 +46,8 @@
                      "of methods like manual time tracking. You can zone out and forget all about time tracking (because it will call you!) but you also "
                      "can correctly classify time that RescueTime would get wrong: things like 'talking to a coworker while Reddit is open in my browser'"
                      "or 'drooling on my keyboard with vim open'."]
-                    [re-com/p "Because TicTag works on multiple clients, you can also track time that RescueTime and the like would miss entirely. I "
+                    [re-com/p "Because TicTag works on multiple clients and is tracking what " [:span.italic "you" ] " are doing (not your device), you can also "
+                     "track time that RescueTime and the like would miss entirely. I "
                      "probably spend too much of my time at the computer, but I don't spend " [:span.italic "all"] " of it here. I want to track time "
                      "spent with kids, biking, cooking, cleaning--everything! Just tracking the time I spend on the computer isn't nearly as useful to me."]
                     [re-com/p ""]


fix whitespace

fix whitespace

--- src/com/billpiel/sayid/trace.clj
+++ src/com/billpiel/sayid/trace.clj
@@ -166,8 +166,9 @@
         (doseq [f ns-fns]
           (trace-var* f
                       (util/assoc-var-meta-to-fn shallow-tracer
-                                        ::trace-type)
-                      workspace))))))
+                                                 ::trace-type)
+                      workspace
+                      :no-overwrite true))))))

 (defn untrace-ns*
   [ns*]


fix first drag on mobile issue

fix first drag on mobile issue

--- src/chessground/drag.cljs
+++ src/chessground/drag.cljs
@@ -1,6 +1,6 @@
 (ns chessground.drag
   "Make pieces draggable, and squares droppable"
-  (:require [chessground.common :as common :refer [pp]]
+  (:require [chessground.common :as common :refer [pp touch-device?]]
             [chessground.chess :as chess]
             [cljs.core.async :as a]))

@@ -21,7 +21,8 @@
 (defn start [this]
   (fn [e]
     (event-stop e)
-    (when (and (== (.-button e) 0) ; only left button
+    (when (and (or touch-device?
+                   (== (.-button e) 0)) ; only left button
                (-> this .-state (aget "draggable")))
       (let [board (.. this getDOMNode -parentNode -parentNode)
             x (.-offsetLeft board)


Clean up forms-seq implementation, pass file information to reader, simplify analyze-file even more.

--- src/clj/cljs/analyzer.clj
+++ src/clj/cljs/analyzer.clj
@@ -13,7 +13,8 @@
   (:require [clojure.java.io :as io]
             [clojure.string :as string]
             [cljs.tagged-literals :as tags]
-            [clojure.tools.reader :as reader])
+            [clojure.tools.reader :as reader]
+            [clojure.tools.reader.reader-types :as readers])
   (:import java.lang.StringBuilder))

 (def ^:dynamic *cljs-ns* 'cljs.user)
@@ -1057,12 +1058,14 @@

 (defn forms-seq
   "Seq of forms in a Clojure or ClojureScript file."
-  ([f]
-     (forms-seq f (clojure.tools.reader.reader-types/indexing-push-back-reader (slurp f))))
-  ([f rdr]
-     (lazy-seq
-      (if-let [form (binding [*ns* (create-ns *cljs-ns*)] (reader/read rdr nil nil))]
-        (cons form (forms-seq f rdr))))))
+  [f]
+  (let [rdr (readers/indexing-push-back-reader (slurp f) 1 f)
+        forms-seq*
+        (fn forms-seq* []
+          (lazy-seq
+            (if-let [form (binding [*ns* (create-ns *cljs-ns*)] (reader/read rdr nil nil))]
+              (cons form (forms-seq*)))))]
+    (forms-seq*)))

 (defn analyze-file [f]
   (let [res (cond
@@ -1075,7 +1078,6 @@
                             (.getPath ^java.io.File res)
                             (.getPath ^java.net.URL res))]
       (let [env (empty-env)]
-        (with-open [rdr (io/reader res)]
-          (doseq [form (seq (forms-seq rdr))]
-            (let [env (assoc env :ns (get-namespace *cljs-ns*))]
-              (analyze env form))))))))
+        (doseq [form (seq (forms-seq res))]
+          (let [env (assoc env :ns (get-namespace *cljs-ns*))]
+            (analyze env form)))))))


All errors encountered during ns parsing now throw.

Only validate uses and use-macros if `cljs.analyzer/*analyze-deps*
is true to support `cljs.analyzer/parse-ns` usage.

--- src/clj/cljs/analyzer.clj
+++ src/clj/cljs/analyzer.clj
@@ -1060,30 +1060,36 @@
           f))))

 (defn analyze-deps
-  ([lib deps env] (analyze-deps lib deps nil))
+  ([lib deps env] (analyze-deps lib deps env))
   ([lib deps env opts]
      (binding [*cljs-dep-set* (vary-meta (conj *cljs-dep-set* lib) update-in [:dep-path] conj lib)]
        (assert (every? #(not (contains? *cljs-dep-set* %)) deps)
          (str "Circular dependency detected " (-> *cljs-dep-set* meta :dep-path)))
        (doseq [dep deps]
          (when-not (or (contains? (::namespaces @env/*compiler*) dep)
-                     (contains? (:js-dependency-index @env/*compiler*) (name dep))
-                     (deps/find-classpath-lib dep))
+                       (contains? (:js-dependency-index @env/*compiler*) (name dep))
+                       (deps/find-classpath-lib dep))
            (let [relpath (util/ns->relpath dep)
                  src (locate-src relpath)]
              (if src
                (analyze-file src opts)
-               (warning :undeclared-ns env {:ns-sym dep}))))))))
+               (throw
+                 (error env
+                   (error-message :undeclared-ns {:ns-sym dep}))))))))))

 (defn check-uses [uses env]
   (doseq [[sym lib] uses]
     (when (= (get-in @env/*compiler* [::namespaces lib :defs sym] ::not-found) ::not-found)
-      (warning :undeclared-ns-form env {:type "var" :lib lib :sym sym}))))
+      (throw
+        (error env
+          (error-message :undeclared-ns-form {:type "var" :lib lib :sym sym}))))))

 (defn check-use-macros [use-macros env]
   (doseq [[sym lib] use-macros]
     (when (nil? (.findInternedVar ^clojure.lang.Namespace (find-ns lib) sym))
-      (warning :undeclared-ns-form env {:type "macro" :lib lib :sym sym}))))
+      (throw
+        (error env
+          (error-message :undeclared-ns-form {:type "macro" :lib lib :sym sym}))))))

 (defn parse-ns-error-msg [spec msg]
   (str msg "; offending spec: " (pr-str spec)))
@@ -1245,10 +1251,10 @@
                 {} (remove (fn [[r]] (= r :refer-clojure)) args))]
     (when (and *analyze-deps* (seq @deps))
       (analyze-deps name @deps env opts))
-    (when (seq uses)
+    (when (and *analyze-deps* (seq uses))
       (check-uses uses env))
     (set! *cljs-ns* name)
-    (when *load-macros*
+    (when (and *analyze-deps* *load-macros*)
       (load-core)
       (doseq [nsym (concat (vals require-macros) (vals use-macros))]
         (clojure.core/require nsym))


* src/clj/cljs/compiler.clj: remove pointless emission of "void 0;"

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -189,8 +189,7 @@
      ~@body
      (when-not (= :expr (:context env#)) (emitln ";"))))

-(defmethod emit :no-op
-  [m] (emits "void 0;"))
+(defmethod emit :no-op [m])

 (defmethod emit :var
   [{:keys [info env] :as arg}]
@@ -322,15 +321,14 @@

 (defmethod emit :def
   [{:keys [name init env doc export]}]
-  (if init
+  (when init
     (let [mname (munge name)]
       (emit-comment doc (:jsdoc init))
       (emits mname)
       (emits " = " init)
       (when-not (= :expr (:context env)) (emitln ";"))
       (when export
-        (emitln "goog.exportSymbol('" (munge export) "', " mname ");")))
-    (emitln "void 0;")))
+        (emitln "goog.exportSymbol('" (munge export) "', " mname ");")))))

 (defn emit-apply-to
   [{:keys [name params env]}]


Update comments on game loop

Update comments on game loop

--- src/cljs/engine/core.cljs
+++ src/cljs/engine/core.cljs
@@ -57,19 +57,26 @@
         delta (- now last-timestamp)
         ;; Minimum duration processed is 1 second
         duration (+ duration (Math.min 1 (/ delta 1000)))]
+
     ;; Throw an error if we get into a bad state
     (when (< duration 0)
       (throw (js/Error. "Bad state, duration is < 0")))
-    ;; FIX this exit flag does not get thrown
+
+    ;; Check if the stop flag has been thrown otherwise iterate
+    ;; through all systems then request the next animation
     (if (-> s/state :game deref :stop)
       (do (debug ":stop flag thrown, stopping game loop")
-        (swap! (:game s/state) assoc :stopped true))
+          (swap! (:game s/state) assoc :stopped true))
+      ;; Calculate all changes for each step in the duration since the
+      ;; last run through the game loop
       (loop [dt duration]
         (if (< (- dt step) step)
           ;; Break the loop, render, and request the next frame
           (do
             (render-system s/state)
             (request-animation #(game-loop now dt step)))
+          ;; If the game is paused, keep the loop going but don't
+          ;; calculate any changes
           (if (:paused @s/game)
             (recur (- dt step))
             (do (iter-systems s/state step)


Show week number.

Show week number.

--- src/cljs/tunnit/core.cljs
+++ src/cljs/tunnit/core.cljs
@@ -5,13 +5,22 @@
             [cljs-time.format :as format]
             [om-tools.dom :as ot :include-macros true]
             [om-tools.core :refer-macros [defcomponent]]
+            [clojure.string :as str]
             ))

 (enable-console-print!)

-(def app-state (atom {:text "Viikko" :date ""}))
+(defn week []
+  (subs
+    (get
+      (str/split
+        (format/unparse (format/formatters :week-date) (t/now))
+        #"-")
+      1) 1))

-(def week-map
+(def app-state (atom {:text (str "Viikko " (week)) :date ""}))
+
+(def day-map
   {1 {:name "Ma" :date ""}
    2 {:name "Ti" :date ""}
    3 {:name "Ke" :date ""}
@@ -21,7 +30,12 @@
    7 {:name "Su" :date ""}})

 (def date-format
-  (format/formatter "dd.MM.yyyy"))
+  (format/formatter "dd.MM."))
+
+(defn update-vals [m f & args]
+  (reduce
+    (fn [r [k v]] (assoc r k (apply f v args)))
+    {} m))

 (defn today []
   (format/unparse date-format (t/now)))
@@ -30,7 +44,7 @@
   (t/day-of-week date))

 (defn week-dates []
-  (assoc-in week-map [(week-day (t/now))
+  (assoc-in day-map [(week-day (t/now))
                       :date] (today)))

 (defcomponent week-view [app owner]


Add more examples

Add more examples

--- src/clojure/cfbt/ch08.clj
+++ src/clojure/cfbt/ch08.clj
@@ -215,3 +215,53 @@
 ;; (= 1 2) was not successfull: false

 ;; Validation Function (p180)
+(def order-details
+  {:name "Michard Blimmons"
+   :email "michard.blimmons@gmail.com"})
+
+(def order-details-validations
+  {:name ["Please enter a name" not-empty]
+   :email ["Please enter an email address" not-empty
+    "Your email address doesn't look like an email address"
+    #(or (empty? %) (re-seq #"@" %))]})
+
+(defn error-messages-for
+  "Return a seq of error messages"
+  [to-validate message-validator-pairs]
+  (map first (filter #(not ((second %) to-validate))
+                     (partition 2 message-validator-pairs))))
+
+(error-messages-for "" ["Please enter a name" not-empty]) ;; ("Please enter a name")
+
+(defn validate
+  "Returns a map with a vector of errors for each key"
+  [to-validate validations]
+  (reduce (fn [errors validation]
+            (let [[fieldname validation-check-groups] validation value (get to-validate fieldname)
+                  error-messages (error-messages-for value validation-check-groups)]
+              (if (empty? error-messages)
+                errors
+                (assoc errors fieldname error-messages))))
+          {}
+          validations))
+
+(validate order-details order-details-validations)
+
+;; if-valid
+(defn if-valid
+  [record validations success-code failure-code]
+  (let [errors (validate order-details order-details-validations)]
+    (if (empty? errors)
+      (println :success)
+      (println :failure errors))))
+
+(defmacro if-valid
+  "Handle validation more concisely"
+  [to-validate validations errors-name & then-else]
+  `(let [~errors-name (validate ~to-validate ~validations)]
+     (if (empty? ~errors-name)
+       ~@then-else)))
+
+(;; if-valid order-details order-details-validation errors
+ ;;   (render :success)
+ ;;   (render :failure errors))


finished section on functions in brave clojure

--- src/clojure_noon/core.clj
+++ src/clojure_noon/core.clj
@@ -200,3 +200,57 @@
   (str "OH MY. God. " name " YOU are most definitely like the best"))

 (too-enthusiastic "Link")
+
+;; functions with multiple arities
+(defn no-params
+  []
+  "I take no parameters!")
+(defn one-param
+  [x]
+  (str "I take one parameter: " x))
+(defn two-params
+  [x y]
+  (str "Two parameters! I will smoosh them " x y)) ;two-arity function
+
+;; functions also support arity overloading - different function body will run depending on the number of parameters passed in
+(defn multi-arity
+  ;; 3 arity arguments and body
+  ([first-arg second-arg third-arg]
+   (do-things first-arg second-arg third-arg))
+  ;; 2-arity arguments and body
+  ([first-arg second-arg]
+   (do-things first-arg second-arg))
+  ;; 1-arity argument and body
+  ([first-arg]
+   (do-things first-arg)))
+
+(defn x-chop
+  "Describe the kind of chop you're inflicting on someone"
+  ([name chop-type]
+   (str "I " chop-type " chop " name "! Take That!"))
+  ([name]
+   (x-chop name "karate")))
+
+(x-chop "myself" "chop")
+
+(x-chop "yourself") ;function supplies a default of karate in case that the function is called with just one argument
+
+(defn senior-comm
+  [youngn]
+  (str "Get off my lawn, " youngn "!!"))
+
+(defn senior
+  [& youngns]
+  (map senior-comm youngns))
+
+(senior "Billy" "Joel" "Jay") ; one function calls another
+
+(defn favourite-things
+  [name & things]
+  (str "Hi, " name ", here are some of my favourite things: "
+       (clojure.string/join ", " things)))
+
+(favourite-things "shoes" "learning" "travel" "hackathons")
+
+;;now onto restructuring
+


:morph: use 'morph' created in last commit

--- src/babel/english/grammar.cljc
+++ src/babel/english/grammar.cljc
@@ -696,7 +696,7 @@
          :lexicon lexicon
          :lookup (fn [arg]
                    (analyze arg lexicon))
-         :morph fo
+         :morph morph
          :morph-ps fo-ps
          ;; TODO: remove: not used
          :morph-walk-tree (fn [tree]


add participle for "go upstairs"

add participle for "go upstairs"

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -669,6 +669,7 @@
                     :pred :go-upstairs
                     :subj {:animate true}}}
     :english {:past "went upstairs"
+              :participle "going upstrairs"
               :present {:3sing "goes upstairs"}}}

    "grab"  {:synsem {:cat :verb


added chanter

added chanter

--- src/babel/francais/lexicon.clj
+++ src/babel/francais/lexicon.clj
@@ -60,6 +60,10 @@

    "changer" {:synsem {:cat :verb
                          :sem {:pred :change}}}
+
+    "chanter" {:synsem {:cat :verb
+                         :sem {:pred :sing}}}
+

    "commencer" {:synsem {:cat :verb
                          :sem {:pred :begin}}}


add more reflexive pronouns

add more reflexive pronouns

--- src/babel/francais/lexicon.clj
+++ src/babel/francais/lexicon.clj
@@ -380,11 +380,29 @@
             common
             {:synsem {:agr {:gender :masc}}})])

-  "laisser" {:synsem {:cat :verb
+   "la" {:synsem {:cat :noun
+                  :pronoun true
+                  :reflexive true
+                  :case pronoun-acc
+                  :agr {:person :3rd
+                        :gender :fem
+                        :number :sing}
+                  :subcat '()}}
+
+   "laisser" {:synsem {:cat :verb
                       :sem {:pred :leave-behind}}}

-  "male" {:synsem {:cat :adverb
-                     :sem {:pred :bad}}}
+   "le" {:synsem {:cat :noun
+                  :pronoun true
+                  :reflexive true
+                  :case pronoun-acc
+                  :agr {:person :3rd
+                        :gender :masc
+                        :number :sing}
+                  :subcat '()}}
+
+   "mal" {:synsem {:cat :adverb
+                   :sem {:pred :bad}}}

   "manger"
   {:synsem {:cat :verb
@@ -418,7 +436,7 @@

                      :sem {:pred :put}}}
   "nous"
-  (let [common {:synsem {:case :nom
+  (let [common {:synsem {:case :top
                          :agr {:person :1st
                                :number :plur}
                          :sem {:human true
@@ -496,7 +514,15 @@
   "répondre" {:synsem {:cat :verb
                        :sem {:pred :answer}}}

-  "se amuser" (let [subject-semantics (ref {:human true})
+   "se" {:synsem {:cat :noun
+                  :pronoun true
+                  :reflexive true
+                  :case pronoun-acc
+                  :agr {:person :3rd
+                        :number :plur}
+                  :subcat '()}}
+
+   "se amuser" (let [subject-semantics (ref {:human true})
                     subject-agr (ref :top)]
                 {:synsem {:cat :verb
                           :essere true
@@ -640,7 +666,7 @@
             common
             {:synsem {:agr {:gender :masc}}})])
   "vous"
-  (let [common {:synsem {:case :nom
+  (let [common {:synsem {:case :top
                          :agr {:person :2nd
                                :number :plur}
                          :sem {:human true


Add tests for s/coll-of and s/every using s/spec to avoid CLJ-2168

--- test/spectrace/trace_test.clj
+++ test/spectrace/trace_test.clj
@@ -63,15 +63,18 @@
        :in []}
       {:spec `(= (count ~'%) 2) :path [] :val [1 "foo" 3] :in []}]]

-    ;; Can't test them until CLJ-2168 will be fixed
-    #_(s/coll-of integer?)
-    #_[1 :a]
-    #_[[{:spec `(s/coll-of integer?) :path [] :val [1 :a] :in [1]}
-      {:spec `integer? :path [] :val :a :in []}]]
-
-    #_(s/every integer?)
-    #_[1 :a]
-    #_[[{:spec `(s/every integer?) :path [] :val [1 :a] :in [1]}
+    ;; we can omit `s/spec` once CLJ-2168 is fixed
+    (s/coll-of (s/spec integer?))
+    [1 :a]
+    [[{:spec `(s/coll-of (s/spec integer?)) :path [] :val [1 :a] :in [1]}
+      {:spec `(s/spec integer?) :path [] :val :a :in []}
+      {:spec `integer? :path [] :val :a :in []}]]
+
+    ;; ditto
+    (s/every (s/spec integer?))
+    [1 :a]
+    [[{:spec `(s/every (s/spec integer?)) :path [] :val [1 :a] :in [1]}
+      {:spec `(s/spec integer?) :path [] :val :a :in []}
       {:spec `integer? :path [] :val :a :in []}]]

     (s/map-of integer? string?)


add the wrapping middleware, debug-log the version

--- src/clj/runbld/main.clj
+++ src/clj/runbld/main.clj
@@ -19,11 +19,12 @@
             [runbld.pipeline :refer [after around before make-pipeline]]
             [runbld.scm :as scm]
             [runbld.util.date :as date]
+            [runbld.util.debug :as debug]
             [runbld.vcs.git :refer [checkout-commit]]
             [runbld.vcs.middleware :as vcs]
             [runbld.version :as version]
             [schema.core :as s]
-            [slingshot.slingshot :refer [try+ throw+]]))
+            [slingshot.slingshot :refer [try+]]))

 (defn really-die
   ([code]
@@ -65,7 +66,8 @@

   Order matters as there are stages that may rely on information from
   previous stages.  Pay particular attention to before/after."
-  [(before java/add-java)
+  [(around debug/with-debug-logging)
+   (before java/add-java)
    (before scheduler/add-scheduler)
    (before build/add-build-meta)
    (before store/store-result) ;; store that we started
@@ -86,6 +88,7 @@
   (try+
    (io/log "runbld started")
    (io/log (version/string))
+   (debug/log (version/string))
    (let [raw-opts (assoc (opts/parse-args args) :logger io/log)
          runbld-proc (make-pipeline proc/run default-middleware)
          {:as opts


* src/cljs/cljs/core.cljs: attempting to optimize seq on vectors

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -2481,6 +2481,25 @@

 (declare tv-editable-root tv-editable-tail TransientVector deref)

+(defn vector-seq [v offset]
+  (let [c (-count v)]
+    (when (pos? c)
+      (reify
+        IPrintable
+        (-pr-seq [vseq opts] (pr-sequential pr-seq "(" " " ")" opts vseq))
+        ISequential
+        IEquiv
+        (-equiv [vseq other] (equiv-sequential vseq other))
+        ISeq
+        (-first [_] (-nth v offset))
+        (-rest [_]
+          (let [offset (inc offset)]
+            (if (< offset c)
+              (vector-seq v offset)
+              ())))
+        ISeqable
+        (-seq [vseq] vseq)))))
+
 (deftype PersistentVector [meta cnt shift root tail ^:mutable __hash]
   Object
   (toString [this]
@@ -2538,13 +2557,7 @@

   ISeqable
   (-seq [coll]
-    (when (pos? cnt)
-      (let [vector-seq
-             (fn vector-seq [i]
-               (lazy-seq
-                 (when (< i cnt)
-                   (cons (-nth coll i) (vector-seq (inc i))))))]
-        (vector-seq 0))))
+    (vector-seq coll 0))

   ICounted
   (-count [coll] cnt)


don't call `sorted-map` at runtime, this dead code eliminates all the sorted map related code if never used.

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -5868,7 +5868,8 @@
   (-invoke [coll k not-found]
     (-lookup coll k not-found)))

-(set! cljs.core.PersistentTreeSet/EMPTY (PersistentTreeSet. nil (sorted-map) 0))
+(set! cljs.core.PersistentTreeSet/EMPTY
+  (PersistentTreeSet. nil cljs.core.PersistentTreeMap/EMPTY 0))

 (defn hash-set
   ([] cljs.core.PersistentHashSet/EMPTY)


Finished cleaning up globals.

Finished cleaning up globals.

--- src/clojush/globals.clj
+++ src/clojush/globals.clj
@@ -3,10 +3,13 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;   globals
 ;; The values def'ed here tend to remain constant over all runs. The atoms
-;; may change depending on the problem. The only values and atoms in this
-;; file should be those that are used by Push instructions; all others, with
-;; few exceptions, should be defined in push-argmap in pushgp.clj and should
-;; be passed to whatever functions use them as arguments.
+;; not starting with "global-" are used in a variety of places and therefore
+;; it is easiest to keep them global. The atoms starting with "global-"
+;; may change depending on arguments to pushgp.
+;;
+;; Most of the values and atoms in this file are those that are used by Push
+;; instructions; all others, with few exceptions, should be defined in push-argmap
+;; in pushgp.clj and should be passed to whatever functions use them as arguments.

 ;; push-types is the list of stacks used by the Push interpreter
 (def push-types '(:exec :integer :float :code :boolean :string :zip
@@ -25,6 +28,12 @@
 (def max-random-string-length 10) ;; The maximum length of string created by the string_rand instruction
 (def max-points-in-random-expressions 50) ;; The maximum length of code created by the string_rand instruction

+;; These atoms are used in different places and are therefore difficult to make fully functional
+(def timer-atom (atom 0)) ;; Used for timing of different parts of pushgp
+(def timing-map (atom {:initialization 0 :reproduction 0 :report 0 :fitness 0 :other 0}))  ;; Used for timing of different parts of pushgp
+(def solution-rates (atom (repeat 0))) ;; Is used in historically-assessed hardness
+(def elitegroups (atom ())) ;; Is used for elitegroup lexicase selection (will only work if lexicase-selection is off)
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; The globals below may be reset by arguments to pushgp
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -42,20 +51,4 @@
 (def global-pop-when-tagging (atom true)) ;; When true, tagging instructions will pop the exec stack when tagging; otherwise, the exec stack is not popped

 ;; Special defs not used by Push instructions, but still need to be globally def'ed, go here.
-(def timer-atom (atom 0)) ;; Used for timing of different parts of pushgp
-(def timing-map (atom {:initialization 0 :reproduction 0 :report 0 :fitness 0 :other 0}))  ;; Used for timing of different parts of pushgp
-
-
-
-;;-------DONE THROUGH HERE
-
-;; The following globals may be reset by arguments to pushgp or other systems that use Push.
-(def global-use-bushy-code (atom false))
-
-;; solution-rates is used in HAH:
-;; Historically-assessed hardness (http://hampshire.edu/lspector/pubs/kleinspector-gptp08-preprint.pdf)
-;; using the "Previous Generation / Difference" method.
-(def solution-rates (atom (repeat 0)))
-
-;; elitegroups is used for elitegroup lexicase selection (will only work if lexicase-selection is off)
-(def elitegroups (atom ()))
+(def global-use-bushy-code (atom false)) ;; When true, random code and code changed by ULTRA mutation, will be "bushy", as in close to a binary tree


Don't serve resources in production mode

--- src/clj/dictionator/server.clj
+++ src/clj/dictionator/server.clj
@@ -31,8 +31,7 @@
   (-> router
       (wrap-state app-state)
       wrap-transit-response
-      wrap-transit-body
-      (wrap-resource "public")))
+      wrap-transit-body))

 (defn dev-handler [app-state]
   (fn [req]


print the protoc command thats run, makes it easier to figure out what happened; fix another proto-path issue

--- src/clj/leiningen/protobuf.clj
+++ src/clj/leiningen/protobuf.clj
@@ -128,18 +128,13 @@
          (.mkdirs dest)
          (.mkdir (io/file target "proto"))
          (doseq [proto protos]
-           (print "Compiling" proto "to" dest-path "... ")
+           (println "Compiling" proto "to" dest-path "... ")
            (extract-dependencies (io/file proto-path proto) target)
-           (let [protoc-result (sh "protoc"
-                                   proto
-                                   (str "--java_out=" dest-path)
-                                   "-I."
-                                   (str "-I" target "/proto")
-                                   :dir proto-path)]
-             (if (= (:exit protoc-result) 0)
-               (println "Success")
-               (do (println "Error")
-                   (println (:err protoc-result))))))
+           (let [args ["protoc" proto (str "--java_out=" dest-path) "-I." (str "-I" target proto-path)]]
+             (println (apply str " > " (interpose " " args)))
+             (let [protoc-result (apply sh (concat args [:dir proto-path]))]
+               (if (not (= (:exit protoc-result) 0))
+                 (println " > ERROR: " (:err protoc-result))))))
          (javac (assoc project :java-source-path dest-path))))))

 (defn compile-google-protobuf


move edit button out of attributes/name area

--- src/cljs/greffe/doc_comps.cljs
+++ src/cljs/greffe/doc_comps.cljs
@@ -112,45 +112,45 @@
          (dom/div #js {:className "block-data col-md-1"}
            (dom/div #js {:className "name"}
              (name (:tag elem)))
-           (om/build element-attributes-component (:attrs elem))
-           (when (:showButton state)
-             (dom/div #js {:className "controls"}
-               (dom/a #js {:onClick
-                           (fn [ev]
-                              (om/set-state! owner
-                                  :editContent (gm/to-gmark @elem tei))
-                             (if (om/get-state owner :editText)
-
-                               ;; we are going to close the edit box,
-                               ;; so we quit listening to edit events
-                               (unsub
-                                 (:notif-chan (om/get-shared owner))
-                                 :open-edit
-                                 (om/get-state owner :local-edit-chan))
-
-                               ;; we are going to open the edit box,
-                               ;; so we start listening for other edit
-                               ;; events and we tell the other edit
-                               ;; boxes that we are opening. The uuid
-                               ;; ensures that we don't listen to ourselves.
-                               (let [uuid  (om/get-state owner :uuid)
-                                     listening (sub
-                                                 (:notif-chan (om/get-shared owner))
-                                                 :open-edit (om/get-state owner :local-edit-chan))]
-                                (put! (:pub-chan (om/get-shared owner))
-                                  {:topic :open-edit
-                                   :message :open
-                                   :uuid uuid})
-                                (go-loop []
-                                  (let [msg (<! listening)]
-                                    (when-not (= uuid (:uuid msg))
-                                      (om/set-state! owner :editText false))
-                                    (recur)))))
-                             (om/set-state!
-                               owner
-                               :editText
-                               (not (om/get-state owner :editText))))}
-                 "Editer"))))
+           (om/build element-attributes-component (:attrs elem)))
+         (when (:showButton state)
+           (dom/div #js {:className "controls"}
+             (dom/a #js {:onClick
+                         (fn [ev]
+                           (om/set-state! owner
+                             :editContent (gm/to-gmark @elem tei))
+                           (if (om/get-state owner :editText)
+
+                             ;; we are going to close the edit box,
+                             ;; so we quit listening to edit events
+                             (unsub
+                               (:notif-chan (om/get-shared owner))
+                               :open-edit
+                               (om/get-state owner :local-edit-chan))
+
+                             ;; we are going to open the edit box,
+                             ;; so we start listening for other edit
+                             ;; events and we tell the other edit
+                             ;; boxes that we are opening. The uuid
+                             ;; ensures that we don't listen to ourselves.
+                             (let [uuid  (om/get-state owner :uuid)
+                                   listening (sub
+                                               (:notif-chan (om/get-shared owner))
+                                               :open-edit (om/get-state owner :local-edit-chan))]
+                               (put! (:pub-chan (om/get-shared owner))
+                                 {:topic :open-edit
+                                  :message :open
+                                  :uuid uuid})
+                               (go-loop []
+                                 (let [msg (<! listening)]
+                                   (when-not (= uuid (:uuid msg))
+                                     (om/set-state! owner :editText false))
+                                   (recur)))))
+                           (om/set-state!
+                             owner
+                             :editText
+                             (not (om/get-state owner :editText))))}
+               "Editer")))

            (when (:editText state)
              (dom/textarea #js {:value (:editContent state)


make add and remove players work

make add and remove players work

--- src/cljs/schafkopfen/core.cljs
+++ src/cljs/schafkopfen/core.cljs
@@ -1,31 +1,61 @@
 (ns schafkopfen.core
+  (:require-macros [cljs.core.async.macros :refer [go-loop]])
   (:require [om.core :as om :include-macros true]
-            [om.dom :as dom :include-macros true]))
+            [om.dom :as dom :include-macros true]
+            [cljs.core.async :refer [put! chan <!]]))

 (enable-console-print!)

-(def app-state (atom {:header "Schafkopfen at BarCamp"
-                          :players [
-                                    {:name "Player 1"}
+(defonce app-state (atom {:header "Schafkopfen at BarCamp"
+                          :players [{:name "Player 1"}
                                     {:name "Player 2"}
                                     {:name "Player 3"}
                                     {:name "Player 4"}]}))

 (defn player-view [player owner]
   (reify
-    om/IRender
-    (render [this]
-            (dom/li nil (:name player)))))
+    om/IRenderState
+    (render-state [this {:keys [delete]}]
+      (dom/li nil
+              (:name player)
+              (dom/button #js {:type "button"
+                               :onClick (fn [e] (put! delete player))
+                               :style #js {:marginLeft "10px"}
+                               :className "btn btn-danger btn-xs"}
+                          "delete")))))
+

 (defn players-view [data owner]
   (reify
-    om/IRender
-    (render [this]
-            (dom/div nil
-                     (dom/h2 nil "Players")
-                     (apply dom/ul nil
-                            (om/build-all player-view (:players data)))
-                     (dom/button nil "add player")))))
+    om/IInitState
+    (init-state [_]
+      {:delete (chan)})
+    om/IWillMount
+    (will-mount [_]
+      (let [delete (om/get-state owner :delete)]
+        (go-loop []
+          (let [player (<! delete)]
+            (om/transact! data :players
+                          (fn [xs] (vec (remove #(= player %) xs))))
+            (recur)))))
+    om/IRenderState
+    (render-state [this {:keys [delete]}]
+      (let [on-name-submit (fn [e]
+                             (let [input (om/get-node owner "new-player-name")
+                                   name (-> input .-value)]
+                               (when name
+                                 (om/transact! data :players #(conj % {:name name}))
+                                 (set! (.-value input) "")))
+                             false)]
+        (dom/div nil
+                 (dom/h2 nil "Players")
+                 (apply dom/ul nil
+                        (om/build-all player-view (:players data) {:init-state {:delete delete}}))
+                 (dom/form #js {:onSubmit on-name-submit}
+                           (dom/input #js {:type :text :placeholder "Name" :ref "new-player-name"})
+                           (dom/button
+                            #js {:onClick on-name-submit}
+                            "add player")))))))

 (defn main []
   (om/root


Fix cljx|s exception, merge!.

Fix cljx|s exception, merge!.

--- src/cljx/geschichte/stage.cljx
+++ src/cljx/geschichte/stage.cljx
@@ -72,7 +72,9 @@
 source/symbols to fn.). The metadata has the form {:meta {:causal-order ...}, :transactions [[p fn]...] ...}. Returns go block to synchronize."
   [store eval-fn repo branch]
   (when (repo/multiple-branch-heads? (:meta repo) branch)
-    (throw (IllegalArgumentException. "Branch has multiple heads!")))
+    (let [msg "Branch has multiple heads!"]
+      #+cljs (throw msg)
+      #+clj (throw (IllegalArgumentException. msg))))
   (go (reduce (partial trans-apply eval-fn)
               (<! (commit-value store eval-fn (-> repo :meta :causal-order)
                                 (first (get-in repo [:meta :branches branch]))))
@@ -342,7 +344,7 @@
   ([stage [user repo branch] heads-order]
      (go
        (<! (timeout (rand-int 10000)))
-       (if (repo/multiple-branch-heads? (get-in @stage [user repo :meta]))
+       (if (repo/multiple-branch-heads? (get-in @stage [user repo :meta]) branch)
          (do
            (swap! stage (fn [{{u :user} :config :as old}]
                           (update-in old [user repo]


Support Hiccup syntax sugar for multiple classes. Fixes #2.

--- src/clojure/freactive/dom.cljs
+++ src/clojure/freactive/dom.cljs
@@ -291,7 +291,7 @@
                nil (.createElement js/document tag)
                (assert false (str "Don't know how to handle tag ns " tag-ns)))]
     (when id (set! (.-id node) id))
-    (when class (set! (.-className node) class))
+    (when class (set! (.-className node) (.replace class "." " ")))
     node))

 ;; ## Core DOM Manipulation Methods


Reformat register-event

Reformat register-event

--- src/bukkure/events.clj
+++ src/bukkure/events.clj
@@ -23,13 +23,13 @@
   [plugin eventname f & [priority-key]]
   (let [eventclass (resolve (symbol (util/package-classname "org.bukkit.event" (str eventname "-event"))))]
     (.registerEvent
-     (bk/plugin-manager)
-     eventclass
-     (proxy [org.bukkit.event.Listener] [])
-     (get priorities (or priority-key :normal))
-     (proxy [org.bukkit.plugin.EventExecutor] []
-       (execute [l e] (handle-event f e)))
-     plugin)))
+      (bk/plugin-manager)
+      eventclass
+      (proxy [org.bukkit.event.Listener] [])
+      (get priorities (or priority-key :normal))
+      (proxy [org.bukkit.plugin.EventExecutor] []
+        (execute [l e] (handle-event f e)))
+      plugin)))

 (defonce registered-events
   (atom #{}))


improved new help doc

improved new help doc

--- src/cake/tasks/new.clj
+++ src/cake/tasks/new.clj
@@ -17,6 +17,7 @@

 (deftask new
   "Create scaffolding for a new project."
+  "You can put a default project template in ~/.cake/project.template.clj with %s in place of the project name."
   (let [project (symbol (first (:new *opts*)))
         name    (name project)
         root    (file *pwd* name)]


CMR-5199 remove request-id assoc.

CMR-5199 remove request-id assoc.

--- src/cmr/sizing/core.clj
+++ src/cmr/sizing/core.clj
@@ -103,8 +103,7 @@
               {:errors (errors/check
                         [not granule-links metadata-errors/empty-gnl-data-files])})

-        params (assoc params :total-granule-input-bytes (:total-granule-input-bytes raw-params)
-                             :request-id (:request-id raw-params))
+        params (assoc params :total-granule-input-bytes (:total-granule-input-bytes raw-params))
         fmt (:format params)]
     (log/trace "raw-params:" raw-params)
     (log/debug "Got format:" fmt)


whitespace

whitespace

--- src/cheshire/parse.clj
+++ src/cheshire/parse.clj
@@ -32,13 +32,13 @@
        (if-not (= (.getCurrentToken ~jp)
                   JsonToken/END_ARRAY)
          (let [coll# (conj!
-                     coll#
-                     (parse
-                      ~jp
-                      false
-                      ~keywords?
-                      ~eof
-                      ~array-coerce-fn))]
+                      coll#
+                      (parse
+                       ~jp
+                       false
+                       ~keywords?
+                       ~eof
+                       ~array-coerce-fn))]
            (.nextToken ~jp)
            (recur coll#))
          (persistent! coll#)))))


add d3 static path

add d3 static path

--- src/clj/ceres/core.clj
+++ src/clj/ceres/core.clj
@@ -26,6 +26,7 @@
   [:#react-js] (set-attr "src" "static/react/react-0.9.0.min.js")
   [:#jquery-js] (set-attr "src" "static/jquery/jquery-1.11.0.min.js")
   [:#bootstrap-js] (set-attr "src" "static/bootstrap/bootstrap-3.1.1-dist/js/bootstrap.min.js")
+  [:d3-js] (set-attr "src" "static/d3/d3.min.js")
   [:#js-files] (substitute (html [:script {:src "js/main.js" :type "text/javascript"}])))


Use compojure context

Use compojure context

--- src/clj_crud/admin.clj
+++ src/clj_crud/admin.clj
@@ -6,7 +6,7 @@
             [clj-crud.data.users :as users]
             [liberator.core :refer [resource defresource]]
             [liberator.representation :refer [as-response] :as lib-rep]
-            [compojure.core :refer [defroutes ANY GET]]
+            [compojure.core :refer [defroutes ANY GET context]]
             [net.cgrand.enlive-html :as html]
             [cemerick.friend :as friend]))

@@ -83,6 +83,7 @@
   )

 (defroutes admin-routes
-  (ANY "/admin" [] (fn [req]
-                     (admin-index req)))
-  (ANY "/admin/users" [] admin-users-list))
+  (context "/admin" _
+           (ANY "/" _ (fn [req]
+                         (admin-index req)))
+           (ANY "/users" _ admin-users-list)))


nom nom nom

nom nom nom

--- src/cljs/uix/core.cljs
+++ src/cljs/uix/core.cljs
@@ -11,69 +11,65 @@
 ;; Views

-(def ui-state (atom
-               {:current [:editors 0 0 2]
-                :desktops
-                {:editors
-                 {[0 0] {:formalism :event-b}
-                  [0 0 0] {:file "m2" :type :machine}
-                  [0 0 1] {:file "m1" :type :machine}
-                  [0 0 2] {:file "c1" :type :context}
-                  [0 0 3] {:file "m0" :type :machine}
-                  [1 0] {:formalism :classical-b}
-                  [1 0 0] {:file "Scheduler"}}
-                 :animations
-                 {[0] {:model-id "animator0"}
-                  [0 0] {:trace-id "123"}
-                  [0 0 0] {:type :state-view}
-                  [0 0 1] {:type :events-view}
-                  [0 1] {:trace-id "999"}
-                  [0 1 0] {:type :state-view}
-                  [1 0] {:model-id "animator4" :trace-id "645"}
-                  [1 0 0] {:type :state-view}}}}))
+(def ui-state
+  (atom
+   {:current-page 0
+    :current-view [0 0 0]
+    :views [
+     [
+      [[{:type :editor :formalism :event-b :file "m1"}
+        {:type :editor :formalism :event-b :file "m0"}]]
+      [[{:type :editor :formalism :classical-b :file "s1.mch"}]]
+      ]
+     [[[{:model "animation0" :trace "1" :editor 0 :type :state-view}
+        {:model "animation0" :trace "1" :editor 0 :type :events-view}]
+       [{:model "animation0" :trace "2" :editor 0 :type :state-view}
+        {:model "animation0" :trace "2" :editor 0 :type :history-view}]]
+      [[{:model "animation3" :trace "9" :editor 1 :type :events-view}]]]]
+    }))

-(defn merge-elem [state page]
-  (fn [a e]
-    (merge a (get-in state (conj [:desktops page] e) {}))))
+(defmulti render-view :type)
+(defmethod render-view :editor [{:keys [formalism file]}]
+  [:div.editor (str "Editor: " file)])

-(defn get-elem [state page row sub-row column]
-  (reduce
-   (merge-elem state page)
-   {}
-   [[row]
-    [row sub-row]
-    [row sub-row column]]))
+(defmethod render-view :state-view [{:keys [model trace]}]
+  [:div.state-view (str "State: " model "/" trace)])

-(defn get-row [state page row subrow]
-  )
+(defmethod render-view :events-view [{:keys [model trace]}]
+  [:div.events-view (str "Events: " model "/" trace)])
+
+(defmethod render-view :history-view [{:keys [model trace]}]
+  [:div.history-view (str "History: " model "/" trace)])

+(defn render-subrow [elements]
+  [:div.subrow (map render-view elements)])
+
+(defn render-row [subrows]
+  [:div.row (map render-subrow subrows)])
+
+(defn render-page [current index rows]
+  (.log js/console current index (count rows))
+  [:div.page
+   (when-not (= current index) {:class "hidden"})
+   (map render-row rows)])
+
+(defn ^:extern animation->editor []
+  (swap! ui-state
+         (fn [{:keys [current-page current-view views] :as s}
+             {:keys [editor]} views]
+           (assoc s :current-view [editor 0 0] :current-page 0))))
+
+(defn ^:extern editor->animation []
+  (swap! ui-state
+         (fn [{:keys [current-page current-view views] :as s}
+             {:keys [editor]} views]
+           (assoc s :current-view [editor 0 0] :current-page 0))))
+
 (defn home-page []
-  [:div
-   [:h1 "Trololo"]
-   [:p "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
-
-Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
-
-Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
-
-Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
-
-Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.
-
-At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.
-
-Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus.
-
-Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
-
-Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
-
-Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
-
-Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
-
-Duis"]])
+  (let [{:keys [current-page views current-view]} @ui-state]
+    [:div.ui
+     (map-indexed (partial render-page current-page current-view) views)]))

 ;; -------------------------


Remove spec code.

Remove spec code.

--- spec/buddy/auth/accessrules_spec.clj
+++ spec/buddy/auth/accessrules_spec.clj
@@ -1,169 +0,0 @@
-(ns buddy.auth.accessrules-spec
-  (:require [speclj.core :refer :all]
-            [ring.util.response :as ring]
-            [cats.core :as m]
-            [cats.monad.either :as either]
-            [buddy.auth.accessrules :refer [compile-rule-handler restrict wrap-access-rules
-                                            success error]]))
-
-(defn ok [v] (success v))
-(defn fail [v] (error v))
-
-(defn ok2 [v] true)
-(defn fail2 [v] false)
-
-(describe "Compile one rule (handler or composition of them)"
-  (it "compile access rules 1"
-    (let [rule (compile-rule-handler ok)
-          result (rule 1)]
-      (should= (success 1) result)))
-
-  (it "compile access rules 2"
-    (let [rule (compile-rule-handler {:or [ok fail]})
-          result (rule 1)]
-      (should= (success 1) result)))
-
-  (it "compile access rules 3"
-    (let [rule (compile-rule-handler {:and [ok fail]})
-          result (rule 1)]
-      (should= (error 1) result)))
-
-  (it "compile access rules 4"
-    (let [rule (compile-rule-handler {:or [fail fail {:and [ok ok]}]})
-          result (rule 1)]
-      (should= (success 1) result)))
-
-  (it "compile access rules 5"
-    (let [rule (compile-rule-handler {:and [ok ok]})
-          result (rule 1)]
-      (should= (success 1) result)))
-
-  (it "compile access rules 6"
-    (let [rule (compile-rule-handler {:and [ok2 ok2]})
-          result (rule 1)]
-      (should= true result)))
-
-  (it "compile access rules 7"
-    (let [rule (compile-rule-handler {:or [fail2 ok2]})
-          result (rule 1)]
-      (should= true result)))
-)
-
-(defn test-handler
-  [req]
-  (ring/response req))
-
-(describe "Restrict one handler with ok"
-  (it "restrict handler 1"
-    (let [handler (restrict test-handler {:handler {:or [ok fail]}})
-          rsp     (handler "test")]
-      (should= "test" (:body rsp))))
-
-  (it "restrict handler with failure 1"
-    (let [handler (restrict test-handler {:handler {:or [fail fail]}})]
-      (should-throw (handler 1))))
-
-  (it "restrict handler with failure 2"
-    (let [handler (restrict test-handler {:handler {:or [fail fail]}})
-          rsp (handler "Failure message")]
-      (should= "Failure message" (:body rsp))
-      (should= 400 (:status rsp))))
-
-  (it "restrict handlerw with failure and explicit on-error handler"
-    (let [handler (restrict test-handler
-                            {:handler {:or [fail fail]}
-                             :on-error (fn [req val] (ring/response (str "onfail-" val)))})
-          rsp     (handler "test")]
-      (should= "onfail-test" (:body rsp))))
-
-  (it "restrict handlerw with failure and redirect"
-    (let [handler (restrict test-handler
-                            {:handler {:or [fail fail]}
-                             :redirect "/foobar"})
-          rsp     (handler "test")]
-      (should= 302 (:status rsp))
-      (should= "/foobar" (get-in rsp [:headers "Location"]))))
-)
-
-
-
-(def params1
-  {:rules [{:pattern #"^/path1$"
-            :handler {:or [ok fail]}}
-           {:pattern #"^/path2$"
-            :handler ok}
-           {:pattern #"^/path3$"
-            :handler {:and [fail ok]}}]})
-
-(def params2
-  {:rules [{:uri "/path1"
-            :handler {:or [ok fail]}}
-           {:uri "/path2"
-            :handler ok}
-           {:uris ["/path3" "/path0"]
-            :handler {:and [fail ok]}}]})
-
-(defn on-error
-  [req val]
-  (-> (ring/response val)
-      (ring/status 400)))
-
-
-(def handler1
-  (wrap-access-rules test-handler
-                     (assoc params1 :policy :reject)))
-
-(def handler2
-  (wrap-access-rules test-handler
-                     (assoc params1
-                       :policy :reject
-                       :on-error on-error)))
-
-(def handler3
-  (wrap-access-rules test-handler
-                     (assoc params2 :policy :reject)))
-
-(describe "Wrap access rules using pattern"
-  (it "check access rules 1"
-    (let [rsp (handler1 {:uri "/path1"})]
-      (should= {:uri "/path1"} (:body rsp))))
-
-  (it "check access rules 2"
-    (let [rsp (handler1 {:uri "/path2"})]
-      (should= {:uri "/path2"} (:body rsp))))
-
-  (it "check access rules 3"
-    (should-throw (handler1 {:uri "/path3"})))
-
-  (it "check access rules 4"
-    (should-throw (handler1 {:uri "/path4"})))
-
-  (it "check access rules 5"
-    (let [rsp (handler2 {:uri "/path3"})]
-      (should= 400 (:status rsp))
-      (should= {:uri "/path3"} (:body rsp))))
-
-  (it "check access rules 6"
-    (let [rsp (handler2 {:uri "/path4"})]
-      (should= 400 (:status rsp))
-      (should= nil (:body rsp))))
-)
-
-(describe "Wrap access rules using clout"
-  (it "check access rules 1"
-    (let [rsp (handler3 {:uri "/path1"})]
-      (should= {:uri "/path1"} (:body rsp))))
-
-  (it "check access rules 2"
-    (let [rsp (handler3 {:uri "/path2"})]
-      (should= {:uri "/path2"} (:body rsp))))
-
-  (it "check access rules 3"
-    (should-throw (handler3 {:uri "/path3"})))
-
-  (it "check access rules 4"
-    (should-throw (handler3 {:uri "/path4"})))
-)
-
-(run-specs)
-


remove stray use of AwsHostnameUtils

remove stray use of AwsHostnameUtils

--- src/eulalie/sign_util.clj
+++ src/eulalie/sign_util.clj
@@ -5,7 +5,7 @@
   (:import [org.joda.time.format
             DateTimeFormatter
             DateTimeFormat]
-           [com.amazonaws.util AwsHostNameUtils]))
+           [java.util.regex Pattern]))

 (def trim (fn-some-> string/trim))

@@ -36,11 +36,37 @@
     host
     (str host ":" port)))

+(def default-region "us-east-1")
+
+(defn parse-standard-region-name [fragment]
+  ;; AWS has a bunch of S3 & cloudfront special-casing here
+  (let [region (from-last-match fragment ".")]
+    ;; no dot
+    (cond (= region fragment) default-region
+          (= region "us-gov") "us-gov-west-1"
+          :else               region)))
+
+(defn host->region [service-hint host]
+  (when service-hint
+    ;; AWS does some CloundFront specific junk with service hints
+    (let [pattern (re-matcher
+                   (re-pattern
+                    (str "^(?:.+\\.)?"
+                         (Pattern/quote service-hint)
+                         "[.-]([a-z0-9-]+)\\."))
+                   host)]
+      (-> pattern re-find last))))
+
+(defn parse-region-name [service-hint host]
+  (let [prefix (to-last-match host ".amazonaws.com")]
+    (if (not= prefix host)
+      (parse-standard-region-name prefix)
+      (or (host->region service-hint host) default-region))))
+
 (defn get-or-calc-region [service-name host]
   ;; TODO maybe allow region to be overridden?  it's not clear under
   ;; what circumstances we won't be able to figure it out.
-  (AwsHostNameUtils/parseRegionName
-   ^String host ^String service-name))
+  (parse-region-name service-name host))

 (def collapse-whitespace
   (fn-some-> (string/replace #"\s+" " ")))


print table for string query

print table for string query

--- src/athena_cmd/core.clj
+++ src/athena_cmd/core.clj
@@ -64,6 +64,10 @@
   [file]
   (print-table (query file)))

+(defn exec-table
+  [query]
+  (print-table (exec query)))
+
 (defn -main
   [& args]
   (let [file (nth args 0)]


Use `if-cljs`.

Use `if-cljs`.

--- src/active/clojure/record_spec.cljc
+++ src/active/clojure/record_spec.cljc
@@ -8,21 +8,21 @@
     [(:require
       [active.clojure.condition :as c]
       [clojure.spec.alpha :as s]
-      [clojure.spec.gen.alpha :as gen])]
+      [clojure.spec.gen.alpha :as gen]
+      [active.clojure.macro :refer (if-cljs)])]
     :cljs
     [(:require
       [active.clojure.condition :as c]
-      [cljs.spec.alpha :as s]
-      [cljs.spec.gen.alpha :as gen])]))
+      [cljs.spec.alpha :as s :include-macros true]
+      [cljs.spec.gen.alpha :as gen :include-macros true])
+     (:require-macros
+      [active.clojure.macro :refer (if-cljs)])]))

 (def pass (constantly true))

 (defn throw-illegal-argument-exception
   [msg]
-  (c/assertion-violation `throw-illegal-argument-exception "Illegal argument" msg)
-  #_(throw
-   #?(:clj  (IllegalArgumentException. msg)
-      :cljs (js/Error. msg))))
+  (c/assertion-violation `throw-illegal-argument-exception "Illegal argument" msg))

 ;; Only needed in ClojureScript, does nothing in Clojure
 (defn check-type
@@ -124,7 +124,7 @@
                :gen (fn []
                       (->> (s/gen (s/keys :req-un ~ks))
                            (gen/fmap (fn [ks#] (apply ~constructor
-                                                   (vals ks#))))))))))
+                                                      (vals ks#))))))))))

 (defn define-constructor-spec-form
@@ -163,59 +163,45 @@
            :args (s/cat ~(keyword the-type-name) ~(ns-keyword the-type-name))
            :res ~boolean?))

-(defn compiling-cljs?
-  []
-  (if-let [cljs-ns-var (resolve 'cljs.analyzer/*cljs-ns*)]
-    (some? @cljs-ns-var)
-    false))
-
-(defn s-def
-  []
-  (if (compiling-cljs?)
-    'cljs.spec.alpha/def
-    'clojure.spec.alpha/def))
-
-(defn s-fdef
-  []
-  (if (compiling-cljs?)
-    'cljs.spec.alpha/fdef
-    'clojure.spec.alpha/fdef))
-
-(defn s-and
-  []
-  (if (compiling-cljs?)
-    'cljs.spec.alpha/and
-    'clojure.spec.alpha/and))
-
-(defn s-cat
-  []
-  (if (compiling-cljs?)
-    'cljs.spec.alpha/cat
-    'clojure.spec.alpha/cat))
-
-(defn s-spec
-  []
-  (if (compiling-cljs?)
-    'cljs.spec.alpha/spec
-    'clojure.spec.alpha/spec))
-
-(defn s-keys
-  []
-  (if (compiling-cljs?)
-    'cljs.spec.alpha/keys
-    'clojure.spec.alpha/keys))
-
-(defn s-gen
-  []
-  (if (compiling-cljs?)
-    'cljs.spec.alpha/gen
-    'clojure.spec.alpha/gen))
-
-(defn s-fmap
-  []
-  (if (compiling-cljs?)
-    'cljs.spec.gen.alpha/fmap
-    'clojure.spec.gen.alpha/fmap))
+(defmacro s-def
+  [& args]
+  `(if-cljs (cljs.spec.alpha/def ~@args)
+            (clojure.spec.alpha/def ~@args)))
+
+(defmacro s-fdef
+  [& args]
+  `(if-cljs (cljs.spec.alpha/fdef ~@args)
+            (clojure.spec.alpha/fdef ~@args)))
+
+(defmacro s-and
+  [& args]
+  `(if-cljs (cljs.spec.alpha/and ~@args)
+            (clojure.spec.alpha/and ~@args)))
+
+(defmacro s-cat
+  [& args]
+  `(if-cljs (cljs.spec.alpha/cat ~@args)
+            (clojure.spec.alpha/cat ~@args)))
+
+(defmacro s-spec
+  [& args]
+  `(if-cljs (cljs.spec.alpha/spec ~@args)
+            (clojure.spec.alpha/spec ~@args)))
+
+(defmacro s-keys
+  [& args]
+  `(if-cljs (cljs.spec.alpha/keys ~@args)
+            (clojure.spec.alpha/keys ~@args)))
+
+(defmacro s-gen
+  [& args]
+  `(if-cljs (cljs.spec.alpha/gen ~@args)
+            (clojure.spec.alpha/gen ~@args)))
+
+(defmacro s-fmap
+  [& args]
+  `(if-cljs (cljs.spec.gen.alpha/fmap ~@args)
+            (clojure.spec.gen.alpha/fmap ~@args)))

 #?(:clj
 (defmacro define-record-type
@@ -235,29 +221,29 @@
             [the-name constructor predicate the-keys]
             (let [ns-key (ns-keyword the-name)
                   ks (mapv ns-keyword the-keys)]
-              `(~(s-def) ~ns-key
-                (~(s-spec) (~(s-and) ~predicate (~(s-keys) :req-un ~ks))
+              `(s-def ~ns-key
+                (s-spec (s-and ~predicate (s-keys :req-un ~ks))
                  :gen (fn []
-                        (->> (~(s-gen) (~(s-keys) :req-un ~ks))
-                             (~(s-fmap) (fn [ks#] (apply ~constructor
-                                                        (vals ks#))))))))))
+                        (->> (s-gen (s-keys :req-un ~ks))
+                             (s-fmap (fn [ks#] (apply ~constructor
+                                                      (vals ks#))))))))))
           (define-constructor-spec-form
             [the-name the-ret-type the-args-list the-specs-list]
             (let [key-args-list (map keyword the-args-list)
                   ns-spec-list (map ns-keyword the-specs-list)
                   the-args-entry (apply concat (map (fn [l r] [l r]) key-args-list ns-spec-list))]
-              `(~(s-fdef) ~the-name
-                :args (~(s-cat) ~@the-args-entry)
+              `(s-fdef ~the-name
+                :args (s-cat ~@the-args-entry)
                 :ret ~(ns-keyword the-ret-type))))
           (define-accessor-spec-form
             [the-accessor-name the-type-name]
-            `(~(s-fdef) ~the-accessor-name
-              :args (~(s-cat) ~(keyword the-type-name) ~(ns-keyword the-type-name))
+            `(s-fdef ~the-accessor-name
+              :args (s-cat ~(keyword the-type-name) ~(ns-keyword the-type-name))
               :res boolean?))
           (define-spec-form
             [the-name the-predicate]
             (let [ns-key (ns-keyword the-name)]
-              `(~(s-def) ~ns-key ~the-predicate)))]
+              `(s-def ~ns-key ~the-predicate)))]
     (let [?field-triples (field-triples ?field-specs &form)
           ?constructor (first ?constructor-call)
           ?constructor-args (rest ?constructor-call)


Add safe singleton

Add safe singleton


merging (defn generate2) and (defn add-bolt-at)

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -162,25 +162,25 @@
   "Return all expressions matching spec _spec_ given the model _model_."
   [spec model]
   (log/debug (str "generate2: spec: " spec))
-  (flatten
-   (mapfn (fn [bolt]
-            (let [comp-paths (find-comp-paths bolt)
-                  comp-bolts
-                  (map #(comp-path-to-bolts bolt % model 0 max-total-depth)
-                       comp-paths)]
-              ;; filter by the following constraint:
-              ;; that for every path that points to a complement of a bolt,
-              ;; there is a non-empty set of bolts that satisfies
-              ;; that complement's path.
-              (when (not (some empty? comp-bolts))
-                (mapfn #(do-defaults % model)
+  (mapfn #(do-defaults % model)
+         (flatten
+          (mapfn (fn [bolt]
+                   (let [comp-paths (find-comp-paths bolt)
+                         comp-bolts
+                         (map #(comp-path-to-bolts bolt % model 0 max-total-depth)
+                              comp-paths)]
+                     ;; filter by the following constraint:
+                     ;; that for every path that points to a complement of a bolt,
+                     ;; there is a non-empty set of bolts that satisfies
+                     ;; that complement's path.
+                     (when (not (some empty? comp-bolts))
                        (add-comps bolt
                                   model
                                   comp-paths
                                   comp-bolts
                                   0 max-total-depth
-                                  bolt)))))
-          (lightning-bolts model spec 0 max-total-depth))))
+                                  bolt))))
+                 (lightning-bolts model spec 0 max-total-depth)))))

 (defn generate-n
   "Returns all possible expressions generated by the given language model, constrained by the given spec.


Make reconcile-solved-count less inscrutable. @dbyrne, can you look at this and confirm it's still doing what it's supposed to be?

--- src/foreclojure/mongo.clj
+++ src/foreclojure/mongo.clj
@@ -44,21 +44,16 @@
 (defn reconcile-solved-count
   "Overwrites the times-solved field in the problems collection based on data from the users collection. Should only be called on server startup since it isn't a safe operation. Also updates the total-solved agent."
   []
-  (send
-   total-solved +
-   (let [problems (get-problem-list)]
-     (reduce
-      #(do
-         (update! :problems
-                  {:_id (first %2)}
-                  {:$set {:times-solved (last %2)}})
-         (+ %1 (last %2)))
-      0
-      (reduce #(update-in %1 [%2] inc)
-              (reduce #(conj %1 [%2 0])
-                      {}
-                      (map :_id problems))
-              (mapcat :solved (get-users)))))))
+  (let [total (->> (get-users)
+                   (mapcat :solved)
+                   (frequencies)
+                   (reduce (fn [sum [id solved]]
+                             (update! :problems
+                                      {:_id id}
+                                      {:$set {:times-solved solved}})
+                             (+ sum solved))
+                           0))]
+    (send total-solved (constantly total))))

 (defn prepare-mongo []
   (connect-to-db)


(zero? (mod x 2)) == (even? x)

(zero? (mod x 2)) == (even? x)

--- src/foreclojure/utils.clj
+++ src/foreclojure/utils.clj
@@ -20,7 +20,7 @@
       ~@code)))

 (defn row-class [x]
-  {:class (if (zero? (mod x 2))
+  {:class (if (even? x)
             "evenrow"
             "oddrow")})


Change how block-forever! refs core.async

--- src/desdemona/launcher/utils.clj
+++ src/desdemona/launcher/utils.clj
@@ -1,7 +1,7 @@
 (ns desdemona.launcher.utils
   (:require
-   [clojure.core.async :refer [chan <!!]]))
+   [clojure.core.async :as a]))

 (defn block-forever!
   []
-  (<!! (chan)))
+  (a/<!! (a/chan)))


Added doc strings to sequences functions.

--- src/grafter/sequences.clj
+++ src/grafter/sequences.clj
@@ -2,15 +2,27 @@
   "A library of useful lazy sequences.")

 (defn integers-from
-  ([n]
-     (iterate inc n)))
+  "Returns an infinite sequence of integers counting from the supplied
+  starting number.

-(defn column-names-seq [alphabet]
-  "Given an alphabet string generate a lazy sequences of column
+  Supports the use of an optional increment amount to allow increments
+  of arbitrary or negative amounts.
+
+  If no arguments are supplied an infinite sequence of all positive
+  integers from 1 is returned."
+  ([]
+     (iterate inc 1))
+  ([from]
+     (iterate inc from))
+  ([from inc-by]
+     (iterate #(+ % inc-by) from)))
+
+(defn column-names-seq "Given an alphabet string generate a lazy sequences of column
   names e.g.

   (column-names-seq \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\") ;; => (\"A\" \"B\" \"C\" ... \"AA\" \"AB\")
 "
+  [alphabet]
   (->> (map str alphabet)
        (iterate (fn [chars]
                   (for [x chars


add watchers to refs

add watchers to refs

--- src/ca_recipe/store.clj
+++ src/ca_recipe/store.clj
@@ -50,3 +50,22 @@
   "Returns a list of items purchased"
   [shopping-list]
   (reduce shop-for-item [] shopping-list))
+
+(declare sold-items)
+
+(defn restock-order
+  "a watch to restock an item"
+  [k r ov nv]
+  (doseq [item (for [kw (keys ov)
+                     :when (not= (kw ov) (kw nv))] kw)]
+    (swap! sold-items unpdate-in [item] (fnil inc 0))
+    (ptint "need to restock" item)))
+
+(defn init-with-restock
+  "set up store with inventory"
+  [m]
+  (def inventory (atom m))
+  (def sold-items (atom {}))
+  (set-validator! inventory no-negative-values?)
+  (add-wath inventory :restock restock-other))
+


Bump Cassaforte to 2.0.0-beta4

Bump Cassaforte to 2.0.0-beta4

--- joplin.cassandra/project.clj
+++ joplin.cassandra/project.clj
@@ -6,5 +6,5 @@
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
   :dependencies [[org.clojure/clojure "1.6.0"]
-                 [clojurewerkz/cassaforte "2.0.0-beta1"]
+                 [clojurewerkz/cassaforte "2.0.0-beta4"]
                  [joplin.core "0.1.12-SNAPSHOT"]])


sunrise/sunset messages

sunrise/sunset messages

--- src/clj_mrazik/core.clj
+++ src/clj_mrazik/core.clj
@@ -23,7 +23,7 @@
 (require '[clj-mrazik.irc-bot  :as irc-bot])

 (def sleep-amount
-    10000)
+    50000)

 (defn between?
     [schedule-item minutes]
@@ -35,6 +35,8 @@
     (if (some #(between? % minutes) schedule)
         :should-be-open
         :should-be-closed))
+
+; TODO refactor following four functions!

 (defn open-window
     [config]
@@ -52,13 +54,44 @@
           (println message)
           (irc-bot/send-message recipients channel message)))

+(defn sunrise
+    [config]
+    (let [message    "sunrise!"
+          recipients (-> config :server :recipients)
+          channel    (-> config :server :channel)]
+          (irc-bot/send-message recipients channel message)))
+
+(defn sunset
+    [config]
+    (let [message    "sunset"
+          recipients (-> config :server :recipients)
+          channel    (-> config :server :channel)]
+          (irc-bot/send-message recipients channel message)))
+
+(defn is-sunrise?
+    [geolocation cal minutes]
+    (let [sunrise     (schedule/get-sunrise geolocation cal)
+          sunrise-min (config/parse-hh-mm-time-as-minutes sunrise)]
+          (= sunrise-min minutes)))
+
+(defn is-sunset?
+    [geolocation cal minutes]
+    (let [sunset     (schedule/get-sunset geolocation cal)
+          sunset-min (config/parse-hh-mm-time-as-minutes sunset)]
+          (= sunset-min minutes)))
+
 (defn run-bot
     [config schedule]
     (loop [status :window-closed]
         (Thread/sleep sleep-amount)
-        (let [minutes (calendar/minute-of-day)
-              actual  (in-schedule? schedule minutes)]
-            (println "minutes: " minutes status actual)
+        (let [cal            (calendar/get-calendar)
+              minutes        (calendar/minute-of-day)
+              actual         (in-schedule? schedule minutes)
+              sunrise?       (is-sunrise? (:geolocation config) cal minutes)
+              sunset?        (is-sunset?  (:geolocation config) cal minutes)]
+            (println "minutes: " minutes status actual sunrise? sunset?)
+            (if sunrise? (sunrise config))
+            (if sunset?  (sunset config))
             (condp = [status actual]
                 [:window-closed :should-be-closed] (recur :window-closed)
                 [:window-closed :should-be-open]   (do (open-window config)  (recur :window-open))
@@ -77,10 +110,8 @@
           schedule (schedule/compute-schedule (:bot config))]
          (config/print-configuration config)
          (pprint/pprint schedule)
-         (println (schedule/get-sunrise (:geolocation config)))
-         (println (schedule/get-sunset (:geolocation config)))
-         ;(irc-bot/start-irc-bot (:server config))
-         ;(irc-bot/send-message (-> config :server :recipients) (-> config :server :channel) "Hi!")
-         ;(run-bot config schedule)
+         (irc-bot/start-irc-bot (:server config))
+         (irc-bot/send-message (-> config :server :recipients) (-> config :server :channel) "Hi!")
+         (run-bot config schedule)
     ))


Add more translation strings

Add more translation strings

--- src/cljc/mdr2/i18n.cljc
+++ src/cljc/mdr2/i18n.cljc
@@ -14,7 +14,6 @@
                     :repair "Repair"
                     :input-not-valid "Input not valid"
                     :unknown "Unknown"
-                    :type "Type"
                     :action "action"
                     :search "Search"
                     :loading "Loading..."
@@ -41,33 +40,45 @@
                     :in-production "In Production"
                     :finished "Finished"
                     ;;
+                    :audio_format "Audio Format"
+                    :creator "Author"
                     :dam "DAM"
+                    :date "Date"
+                    :depth "Number of levels"
+                    :description "Description"
+                    :format "Format"
                     :id "DAM Number"
                     :identifier "Identifier"
-                    :title "Title"
-                    :creator "Author"
-                    :source_publisher "Source Publisher"
-                    :description "Description"
-                    :state "State"
+                    :language "Language"
+                    :library_number "Library Number"
+                    :library_record_id "Record Id"
+                    :library_signature "Library Signature"
+                    :modified-at "Last modified at"
+                    :multimedia_content "Multimedia Content"
+                    :multimedia_type "Multimedia Type"
+                    :narrator "Narrator"
+                    :periodical_number "Periodical Number"
+                    :produced_date "Production Date"
+                    :producer "Producer"
                     :product_number "Product Number"
-                    :library_number "Library Number"
-                    :library_signature "Library Signature"
-                    :library_record_id "Record Id"
-                    :total_time "Total Time"
-                    :narrator "Narrator"
-                    :source_date "Source Date"
-                    :produced_date "Production Date"
-                    :language "Language"
-                    :spelling "Spelling"
-                    :date "Date"
-                    :modified-at "Last modified at"
-                    :format "Format"
+                    :production_type "Type of production"
                     :publisher "Publisher"
                     :revision "Revision"
+                    :revision_date "Revision Date"
+                    :revision_description "Revision Description"
+                    :rights "Rights"
                     :source "Source"
+                    :source_date "Source Date"
+                    :source_edition "Source Edition"
+                    :source_publisher "Source Publisher"
+                    :source_rights "Source Rights"
+                    :spelling "Spelling"
+                    :state "State"
+                    :subject "Subject"
+                    :title "Title"
+                    :total_time "Total Time"
+                    :type "Type"
                     :volumes "Number of Volumes"
-                    :depth "Number of levels"
-                    :production_type "Type of production"
                     ;;
                     :transitions-state "Transition state to '%1'"
                     :upload-structure-for "Upload structure for '%1' (DAM %2)"
@@ -110,7 +121,6 @@
                     :repair "Reparieren"
                     :input-not-valid "Eingabe ungültig"
                     :unknown "Unbekannt"
-                    :type "Typ"
                     :action "Aktion"
                     :search "Suche"
                     :loading "Laden..."
@@ -136,33 +146,45 @@
                     :in-production "In Produktion"
                     :finished "Fertig"
                     ;;
+                    :audio_format "Audio Format"
+                    :creator "Autor"
                     :dam "DAM"
+                    :date "Datum"
+                    :depth "Anzahl Levels"
+                    :description "Beschreibung"
+                    :format "Format"
                     :id "DAM Nummer"
                     :identifier "Identifier"
-                    :title "Titel"
-                    :creator "Autor"
-                    :source_publisher "Verlag"
-                    :description "Beschreibung"
-                    :state "Status"
+                    :language "Sprache"
+                    :library_number "DS Nummer"
+                    :library_record_id "Record Id"
+                    :library_signature "Signatur"
+                    :modified-at "Letzte Änderung"
+                    :multimedia_content "Multimedia Content"
+                    :multimedia_type "Multimedia Typ"
+                    :narrator "Sprecher"
+                    :periodical_number "Periodical Nummer"
+                    :produced_date "Datum der Produktion"
+                    :producer "Producer"
                     :product_number "Produkt Nummer"
-                    :library_number "DS Nummer"
-                    :library_signature "Signatur"
-                    :library_record_id "Record Id"
-                    :total_time "Total Time"
-                    :narrator "Sprecher"
-                    :source_date "Source Date"
-                    :produced_date "Datum der Produktion"
-                    :language "Sprache"
-                    :spelling "Rechtschreibung"
-                    :date "Datum"
-                    :modified-at "Letzte Änderung"
-                    :format "Format"
+                    :production_type "Art der Produktion"
                     :publisher "Verlag"
                     :revision "Revision"
-                    :source "Source"
+                    :revision_date "Datum der Revision"
+                    :revision_description "Beschreibung der Revision"
+                    :rights "Rechte"
+                    :source "Original"
+                    :source_date "Datum der Originalausgabe"
+                    :source_edition "Originalausgabe"
+                    :source_publisher "Verlag des Originals"
+                    :source_rights "Rechte des Originals"
+                    :spelling "Rechtschreibung"
+                    :state "Status"
+                    :subject "Subject"
+                    :title "Titel"
+                    :total_time "Spieldauer"
+                    :type "Typ"
                     :volumes "Anzahl Bände"
-                    :depth "Anzahl Levels"
-                    :production_type "Art der Produktion"
                     ;;
                     :transitions-state "Status auf '%1' setzen"
                     :upload-structure-for "Struktur Datei für '%1' (DAM %2) hochladen"


Added first cut at apply.  Not yet lazy

Added first cut at apply.  Not yet lazy

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -571,6 +571,56 @@
   ([a b c args] (cons a (cons b (cons c args))))
   ([a b c d & more]
      (cons a (cons b (cons c (cons d (spread more)))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; apply ;;;;;;;;;;;;;;;;
+
+(defn apply
+  "Applies fn f to the argument list formed by prepending intervening arguments to args.
+  First cut.  Not lazy.  Needs to use emitted toApply."
+  ([f args]
+     (let [fixed-arity (. f maxFixedArity)]
+       (if (. f applyTo)
+         (if (<= (bounded-count args fixed-arity)
+                 fixed-arity)
+           (. f apply f (to-array args))
+           (. f apply f (to-array args))) ;; applyTo
+         (. f apply f (to-array args)))))
+  ([f x args]
+     (let [args (list* x args)
+           fixed-arity (. f maxFixedArity)]
+       (if (. f applyTo)
+         (if (<= (bounded-count args fixed-arity)
+                 fixed-arity)
+           (. f apply f (to-array args))
+           (. f apply f (to-array args))) ;; applyTo
+         (. f apply f (to-array args)))))
+  ([f x y args]
+     (let [args (list* x y args)
+           fixed-arity (. f maxFixedArity)]
+       (if (. f applyTo)
+         (if (<= (bounded-count args fixed-arity)
+                 fixed-arity)
+           (. f apply f (to-array args))
+           (. f apply f (to-array args))) ;; applyTo
+         (. f apply f (to-array args)))))
+  ([f x y z args]
+     (let [args (list* x y z args)
+           fixed-arity (. f maxFixedArity)]
+       (if (. f applyTo)
+         (if (<= (bounded-count args fixed-arity)
+                 fixed-arity)
+           (. f apply f (to-array args))
+           (. f apply f (to-array args))) ;; applyTo
+         (. f apply f (to-array args)))))
+  ([f a b c d & args]
+     (let [args (cons a (cons b (cons c (cons d (spread args)))))
+           fixed-arity (. f maxFixedArity)]
+       (if (. f applyTo)
+         (if (<= (bounded-count args fixed-arity)
+                 fixed-arity)
+           (. f apply f (to-array args))
+           (. f apply f (to-array args))) ;; applyTo
+         (. f apply f (to-array args))))))

 ; should use: count, nth
 (defn- vector-seq [vector i]


Fixing wallclock

Fixing wallclock

--- src/cljs/moon/core.cljs
+++ src/cljs/moon/core.cljs
@@ -110,7 +110,7 @@
 (defn wall-clock []
   (let [output (chan)]
     (go-loop []
-      (<! (timeout 10))
+      (<! (timeout 1000))
       (when (>! output :tick)
         (recur)))
     output))


Added «abort» command to the counterexample REPL

and fixed a small bug in default-handler.

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/fca/exploration.clj
+++ src/conexp/fca/exploration.clj
@@ -125,7 +125,7 @@
   (defn default-handler
     "Default handler for attribute exploration. Does it's interaction on the console."
     [ctx impl]
-    dh))
+    (dh ctx impl)))

 ;;; Counterexample REPL
@@ -152,25 +152,27 @@
   "Runs the given REPL command query with state, context ctx and
   implication impl."
   [query state]
-  (let [suitable-methods (suitable-repl-commands query)]
-    (cond
-     (second suitable-methods)
-     (do
-       (println "Ambigious command, suitable methods are")
-       (doseq [name suitable-methods]
-         (println "  " name))
-       state),
-     (empty? suitable-methods)
-     (do
-       (println "Unknown command")
-       state)
-     :else
-     (try
-       (run-repl-command (first suitable-methods) state)
-       (catch Throwable t
-         (print "Encountered Error: ")
-         (println t)
-         state)))))
+  (if (= query 'abort)
+    (throw (Exception. "Abnormal abortion from attribute exploration"))
+    (let [suitable-methods (suitable-repl-commands query)]
+      (cond
+       (second suitable-methods)
+       (do
+         (println "Ambigious command, suitable methods are")
+         (doseq [name suitable-methods]
+           (println "  " name))
+         state),
+       (empty? suitable-methods)
+       (do
+         (println "Unknown command")
+         state)
+       :else
+       (try
+         (run-repl-command (first suitable-methods) state)
+         (catch Throwable t
+           (print "Encountered Error: ")
+           (println t)
+           state))))))

 (defn counterexample-via-repl
   "Starts a repl for counterexamples."