* query a sum store * make extract-hooks public

--- src/cljc/commos/delta/compscribe.cljc
+++ src/cljc/commos/delta/compscribe.cljc
@@ -56,7 +56,7 @@
             (close! target)))))
     m))

-(defn- extract-hooks
+(defn extract-hooks
   "Return [hooks delta]

   Where hooks is a map of required subscriptions and unsubscriptions
@@ -337,6 +337,47 @@
                              (unsubs-fn)))))
                spec id)))

-;; New
-
-
+;; Util
+(defn request-spec
+  "Return the request spec from compscribe-request-spec"
+  [[[partial-request-spec _] id]]
+  [partial-request-spec id])
+
+(defn compscribe-spec
+  "Return the compscribe spec of compscribe-request-spec"
+  [[[_ compscribe-spec] _]]
+  compscribe-spec)
+
+(defn query-crs
+  "Recursively query the full sum of compscribe-request-spec in
+  rs->sum, given that its there."
+  [rs->sum crs]
+  (let [rs (request-spec crs)
+        cs (compscribe-spec crs)
+        sum (rs->sum rs)
+        [{:keys [subs-one subs-many] :as hooks} _]
+        (extract-hooks cs [:is [] sum])]
+
+    (merge (if (set? sum) ; retain non compscribed keys in a map
+             {}
+             sum)
+           (reduce (fn [sum [ks vs]]
+                     (let [child-cs (get-in cs ks)]
+                       (reduce (fn [sum v]
+                                 (assoc-in sum (conj ks v)
+                                           (query-crs
+                                            rs->sum
+                                            [child-cs v])))
+                               {}
+                               vs)))
+                   {}
+                   subs-many)
+           (reduce (fn [sum [ks v]]
+                     (assert (seq ks) "subs-one not possible on root")
+                     (let [child-cs (get-in cs ks)]
+                       (assoc-in sum ks
+                                 (query-crs
+                                  rs->sum
+                                  [child-cs v]))))
+                   {}
+                   subs-one))))


xf require new input, thus mult based caching

--- src/cljc/commos/delta/compscribe.cljc
+++ src/cljc/commos/delta/compscribe.cljc
@@ -7,7 +7,7 @@
                                                alts!
                                                pipe
                                                #?@(:clj [go go-loop])
-                                               mult tap untap] :as a]
+                                               tap untap] :as a]
             [clojure.walk :refer [prewalk postwalk]]
             [commos.shared.core :refer [flatten-keys]])
   #?(:cljs (:require-macros [cljs.core.async.macros :refer [go-loop go]])))
@@ -341,31 +341,48 @@
           #_(println "unsubscribing" (::identifier (meta unsubs-fn)))
           (unsubs-fn))))))

-(def ^:private sum-and-delta
-  "Transducer that sums deltas and passes on [sum delta] for each
-  delta."
-  (fn [rf]
-    (let [sum (volatile! nil)]
-      (fn
-        ([] (rf))
-        ([result] (rf result))
-        ([result input]
-         (rf result [[:is (vswap! sum delta/add input)] input]))))))
-
-(def ^:private first-then-second
-  (fn [rf]
-    (let [done (volatile! false)]
-      (fn
-        ([] (rf))
-        ([result] (rf result))
-        ([result input]
-         (if @done
-           (rf result (second input))
-           (do (vreset! done true)
-               (rf result (first input)))))))))
+(defn- caching-mult
+  [ch accumulate]
+  (let [tap-ch (chan)
+        chs (atom #{})
+        dctr (atom nil)
+        dchan (chan 1)
+        done (fn [_] (when (zero? (swap! dctr dec))
+                       (put! dchan true)))
+        m (reify
+            a/Mux
+            (muxch* [_] ch)
+            a/Mult
+            (tap* [_ ch close?]
+              (if close?
+                (put! tap-ch ch)
+                (throw (throw (UnsupportedOperationException.
+                               "close?=false not supported")))))
+            (untap* [_ ch]
+              (swap! chs disj ch))
+            (untap-all* [_] (throw (throw (UnsupportedOperationException.)))))]
+    (go-loop [cache nil]
+      (let [[v port] (alts! [tap-ch ch] :priority true)]
+        (condp identical? port
+          tap-ch
+          (do (when (or (nil? cache)
+                        (put! v cache))
+                (swap! chs conj v))
+              (recur cache))
+          ch
+          (if (nil? v)
+            (run! close! @chs)
+            (do (when-let [chs (seq @chs)]
+                  (reset! dctr (count chs))
+                  (doseq [ch chs]
+                    (when-not (put! ch v done)
+                      (a/untap* m ch)))
+                  (<! dchan))
+                (recur (accumulate cache v)))))))
+    m))

 (defn- cached-service
-  [service source-xf target-xf]
+  [service accumulate]
   (let [subscribe-ch (chan)
         cancel-ch (chan)]
     (go-loop [subs {}
@@ -378,25 +395,27 @@
           (let [[this identifier target] msg
                 [m :as cache]
                 (or (get subs identifier)
-                    (let [ch-in (chan 1 source-xf)
-                          m (mult ch-in)]
+                    (let [ch-in (chan)
+                          m (caching-mult ch-in accumulate)]
                       (subscribe (caching service this)
                                  identifier
                                  ch-in)
                       [m #{} ch-in]))
-                target-step (chan 1 target-xf)]
-            (pipe target-step target)
-            (tap m target-step)
+                target (wrap-on-close target
+                                      #(cancel this target))]
+            (println ["cache subscribing" identifier])
+            (tap m target)
             (recur (assoc subs identifier (update cache 1 conj target))
-                   (assoc chs target [identifier target-step])))
+                   (assoc chs target identifier)))
           cancel-ch
           (let [[this target] msg]
-            (if-let [[identifier target-step] (get chs target)]
+            (if-let [identifier (get chs target)]
               (let [[m m-chs ch-in :as cache] (get subs identifier)
                     m-chs (disj m-chs target)
                     chs (dissoc chs target)]
-                (untap m target-step)
-                (close! target-step)
+                (println ["cache canceling" identifier])
+                (untap m target)
+                (close! target)
                 (if (empty? m-chs)
                   (do
                     (cancel service ch-in)
@@ -417,7 +436,10 @@
   "Caches on endpoints.  Sends the current sum to a new subscriber,
   continues with deltas."
   [service]
-  (cached-service service sum-and-delta first-then-second))
+  (cached-service service {:accumulate
+                           (fn [cache v]
+                             (update (or cache [:is]) 1
+                                     delta/add v))}))

 (defn compscriber
   [service]


state recognition is not working in the moment.

--- src/org/domaindrivenarchitecture/pallet/crate/backup.clj
+++ src/org/domaindrivenarchitecture/pallet/crate/backup.clj
@@ -129,16 +129,9 @@

 (defn install-backup-environment
   [& {:keys [app-name]}]
-  (let [installed-marker
-        (str "/home/pallet/state/" (name facility))]
-    (actions/plan-when-not
-      (stevedore/script (file-exists? installed-marker))
-      (create-backup-source-user)
-      (create-source-environment app-name)
-      (actions/file
-        installed-marker
-        :action :create)
-      )))
+  (create-backup-source-user)
+  (create-source-environment app-name)
+  )

 (defn install-backup-app-instance
   [& {:keys [app-name
@@ -146,14 +139,7 @@
              backup-lines
              source-transport-lines
              restore-lines]}]
-  (let [installed-marker
-        (str "/home/pallet/state/" (name facility) "-" instance-name)]
-    (actions/plan-when-not
-      (stevedore/script (file-exists? installed-marker))
-      (create-source-backup app-name instance-name backup-lines)
-      (create-source-transport app-name instance-name source-transport-lines)
-      (create-source-restore app-name instance-name restore-lines)
-      (actions/file
-        (str "/home/pallet/state/" (name facility) "-" instance-name)
-        :action :create)
-      )))+  (create-source-backup app-name instance-name backup-lines)
+  (create-source-transport app-name instance-name source-transport-lines)
+  (create-source-restore app-name instance-name restore-lines)
+  )


Added filter-with

Added filter-with

--- src/hangman/core.clj
+++ src/hangman/core.clj
@@ -82,15 +82,30 @@
             (< 0 (num-rows word-array) )
             (< 0 (num-cols word-array) ) ]
     :post [ (vector? %) ] }
-  (println "word-array:" word-array)
   (vec
     (for [idx (range 0 (num-cols word-array)) ]
       (let [curr-col (get-array-col word-array idx)]
-        (println "idx=" idx "  curr-col:" curr-col)
         (frequencies curr-col)) )))

+(defn filter-with
+  "Returns values from data-seq where corresponding pred-seq elements are truthy."
+  [pred-seq data-seq]
+  (let [ both-seq     (map vector pred-seq data-seq )
+         filt-seq     (filter #(% 0) both-seq)
+         result       (vec (map second filt-seq)) ]
+    (println "both-seq"   both-seq)
+    (println "filt-seq"   filt-seq)
+    (println "result"     result)
+    result
+  ) )
+(def data-vec (range 5))
+(def pred-vec [ true false true false true nil false true ])
+(filter-with pred-vec data-vec )

 (defn run-tests []
+  (println "----------------------------------------")
+  (println "Tests:")
+
   ; Manipulation of strings/vectors/character seq's
   (assert (= (vec "abcd")                [\a \b \c \d] ))
   (assert (= (str/join  (vec "abcd"))    "abcd" ))
@@ -106,25 +121,6 @@
     (assert (= (get-array-col tstArr 2) [:c  3 \c] ))
   )

-  ; Test frequency function
-  (println "----------------------------------------")
-  (println "Tests:")
-  (let [tst-words [ "abcd" "xbcd" "xxcd" "xxxd" ]
-        words-map (words-by-length tst-words)
-        _ (println words-map) ]
-        (doseq [ curr-len (sort (keys words-map)) ]
-          (println)
-          (let [curr-words  (words-map curr-len)
-                word-array  (to-word-array  curr-words)
-                _ (show-info curr-words (str "len=" curr-len) )
-                col-char-freqs (freqs-by-col word-array)
-                _ (println "freqs-by-col:" col-char-freqs)
-                all-char-freqs (apply merge-with + col-char-freqs)
-                _ (println "all-char-freqs" all-char-freqs)
-               ] )
-        ))
-  (println)
-
   ; Use of (frequencies...) and (merge-with...)
   (assert (= (frequencies "abbccc")
              {\a 1, \b 2, \c 3} ))
@@ -134,6 +130,24 @@
              [ {\a 1, \b 1, \c 1} {\b 1, \c 1} {\c 1} ] ))
   (assert (= (apply merge-with + (map frequencies ["abc" "bc" "c"]) )
              {\a 1 \b 2 \c 3} ))
+
+  ; Test frequency function
+  (let [tst-words [ "abcd" "xbcd" "xxcd" "xxxd" ]
+        words-map (words-by-length tst-words)
+        curr-len  4
+        curr-words  (words-map curr-len)
+        word-array  (to-word-array  curr-words)
+        col-char-freqs (freqs-by-col word-array)
+        all-char-freqs (apply merge-with + col-char-freqs)
+       ]
+    (println curr-words)
+    (assert (= words-map   {4 ["abcd" "xbcd" "xxcd" "xxxd"]} ))
+    (assert (= curr-words     ["abcd" "xbcd" "xxcd" "xxxd"]  ))
+    (assert (= col-char-freqs [{\a 1, \x 3} {\b 2, \x 2} {\c 3, \x 1} {\d 4}] ))
+    (assert (= all-char-freqs {\d 4, \c 3, \b 2, \a 1, \x 6} ))
+  )
+
+  (println)
 )


Entity saving implemented

Entity saving implemented

--- src/helda/schema.clj
+++ src/helda/schema.clj
@@ -6,9 +6,11 @@

 (s/defschema Model {
     :full-name s/Keyword
+
     :package s/Keyword
     :name s/Keyword
     (s/optional-key :description) s/Str
+
     :extends [s/Keyword]
     :attrs {s/Keyword s/Str} ;{attr schema}
     :actions {s/Keyword s/Keyword} ;{action model} ;todo add description
@@ -16,7 +18,7 @@

 (s/defschema World {
     :world s/Keyword
-    :description s/Str
+    (s/optional-key :description) s/Str
     :tags [s/Keyword]
   })

@@ -24,7 +26,10 @@
     :world s/Keyword
     :model s/Keyword
     :tags [s/Keyword]
+    (s/optional-key :description) s/Str
+
     :attrs {s/Keyword s/Any}
+
     (s/optional-key :id) s/Str
     (s/optional-key :parent-id) s/Str
   })


enforce distinct bytecode fn arities

enforce distinct bytecode fn arities

--- src/insn/clojure.clj
+++ src/insn/clojure.clj
@@ -15,8 +15,10 @@
         [vsig more] (filter #(some #{'&} %) (map first decls))
         nvargs (dec (count vsig))
         vparam (second (split-with #(not= % '&) vsig))
-        vprims (->> vsig (map (comp :tag meta)) (filter '#{long double}) seq)]
+        vprims (->> vsig (map (comp :tag meta)) (filter '#{long double}) seq)
+        arities (map (comp count first) decls)]
     (check (nil? more) "can't have multiple variadic overloads")
+    (check (apply distinct? arities) "can't have two overloads with same arity")
     (when vsig
       (check (not= (count vparam) 1) "missing variadic parameter after '&'")
       (check (= (count vparam) 2) "invalid extra variadic parameter")


log stopping container

log stopping container

--- clj-test-utils/src/clj_test_utils/elasticsearch_docker_utils.clj
+++ clj-test-utils/src/clj_test_utils/elasticsearch_docker_utils.clj
@@ -7,6 +7,7 @@
 (def elastic (delay (new ElasticsearchContainer "docker.elastic.co/elasticsearch/elasticsearch:7.10.2")))

 (defn stop-elasticsearch []
+  (println "Stopping elasticsearch container")
   (.stop @elastic))

 (defn- elastic-has-started? [elastic-ip]


fix flaky reporters_integration_test (#592)

--- waiter/integration/waiter/reporters_integration_test.clj
+++ waiter/integration/waiter/reporters_integration_test.clj
@@ -55,8 +55,8 @@
                                                                                .getMillis)]
                                                  (if (not= next-last-event-time-ms last-event-time-ms)
                                                    next-last-event-time-ms nil)))
-                    ;; expected precision for system "sleep" calls. a sleep call will sleep the right duration within 100 ms.
-                    sleep_precision 100]
+                    ;; expected precision for system "sleep" calls. a sleep call will sleep the right duration within 500 ms.
+                    sleep_precision 500]
                 (is next-last-event-time-ms)
                 (when next-last-event-time-ms
                   (is (< (Math/abs (- next-last-event-time-ms last-event-time-ms period-ms))


day 15

day 15

--- src/adventofcode/day15.clj
+++ src/adventofcode/day15.clj
@@ -18,15 +18,45 @@
                       str/split-lines
                       (map parse-ingredient)))

-(defn update-vals [m vals f]
-  (reduce #(update-in %1 [%2] f) m vals))
+(def proportions
+  (for [p1 (range 0 101)
+        p2 (range 0 101)
+        p3 (range 0 101)
+        p4 (range 0 101)
+        :when (= 100 (+ p1 p2 p3 p4))]
+    [p1 p2 p3 p4]))

-(comment (update-vals {:foo 1 :bar 2} [:foo :bar] (partial * 10)))
+(defn score [ingredient]
+  (->> (select-keys ingredient [:capacity :durability :flavor :texture])
+       vals
+       (map (fn [n] (if (> n 0) n 0)))
+       (apply *)))

-(defn get-proportions []
-  (for [sprinkles (range 0 101)
-        butterscotch (range 0 101)
-        chocolate (range 0 101)
-        candy (range 0 101)
-        :when (= 100 (+ sprinkles butterscotch chocolate candy))]
-    [sprinkles butterscotch chocolate candy]))
+(defn apply-proportions [ingredients proportions]
+  (->> ingredients
+       (interleave proportions)
+       (partition 2)
+       (map (fn [[proportion ingredient]]
+              (reduce #(update %1 %2 (partial * proportion))
+                      ingredient
+                      [:capacity :durability :flavor :texture :calories])))
+       (map #(-> % (dissoc :name)))
+       (reduce #(-> %1
+                    (update :capacity (partial + (:capacity %2)))
+                    (update :durability (partial + (:durability %2)))
+                    (update :flavor (partial + (:flavor %2)))
+                    (update :texture (partial + (:texture %2)))
+                    (update :calories (partial + (:calories %2)))))))
+
+(def part-one
+  (->> proportions
+       (map #(apply-proportions ingredients %))
+       (map score)
+       (apply max)))
+
+(def part-two
+  (->> proportions
+       (map #(apply-proportions ingredients %))
+       (filter #(= (:calories %) 500))
+       (map score)
+       (apply max)))


Electron's ipc module has been replaced with ipcRenderer

--- src/lt/util/ipc.cljs
+++ src/lt/util/ipc.cljs
@@ -1,7 +1,8 @@
 (ns lt.util.ipc
   "Util functions for the ipc renderer - https://github.com/atom/electron/blob/master/docs/api/ipc-renderer.md")

-(def ipc "Provides access to the ipc renderer." (js/require "ipc"))
+(def electron (js/require "electron"))
+(def ipc "Provides access to the ipc renderer." (.-ipcRenderer electron))

 ;; `send` and `on` are declared here with their bodies defined later as otherwise Codox will use the
 ;; redefined `send` and `on` in the below when block instead.


Updating todo list.

Updating todo list.

--- Spraff/src/spraff/core.clj
+++ Spraff/src/spraff/core.clj
@@ -4,9 +4,7 @@
 ;; IRC bot which spraffs randomly generated sentences.

 ;; # Todo list #
-;; * Log all messages.
-;; * Update markov tables based on channel chat.
-;; * Rehydrate tables from old log files on startup.
+;; * Think of next feature..

 (ns spraff.core
     (:gen-class)


CMR-1699 Fixes handling of channel messages.

I don't even know anymore. Why do we use core.async here?

--- bootstrap-app/src/cmr/bootstrap/services/bootstrap_service.clj
+++ bootstrap-app/src/cmr/bootstrap/services/bootstrap_service.clj
@@ -83,4 +83,4 @@
     (vp/bootstrap-virtual-products (:system context))
     (go
       (info "Adding message to virtual products channel.")
-      (-> context :system (get vp/channel-name) (>! params)))))
+      (-> context :system (get vp/channel-name) (>! :bootstrap-virtual-products)))))


Update ring-core dependency to Clojure 1.2.0-beta1, updated version to 0.3.0-beta1

--- ring-core/project.clj
+++ ring-core/project.clj
@@ -1,8 +1,8 @@
-(defproject ring/ring-core "0.2.5"
+(defproject ring/ring-core "0.3.0-beta1"
   :description "Ring core libraries."
   :url "http://github.com/mmcgrana/ring"
-  :dependencies [[org.clojure/clojure "1.1.0"]
-                 [org.clojure/clojure-contrib "1.1.0"]
+  :dependencies [[org.clojure/clojure "1.2.0-beta1"]
+                 [org.clojure/clojure-contrib "1.2.0-beta1"]
                  [commons-codec "1.4"]
                  [commons-io "1.4"]
                  [commons-fileupload "1.2.1"]


add a todo

add a todo

--- frontend/models/action.cljs
+++ frontend/models/action.cljs
@@ -4,6 +4,7 @@
             [goog.string :as gstring]
             goog.string.format))

+;; XXX: write an id function
 (defn id [action]
   )


Improve documentation for `paths-of`

Improve documentation for `paths-of`

--- src/structural_typing/guts/type_descriptions/flatten.clj
+++ src/structural_typing/guts/type_descriptions/flatten.clj
@@ -62,10 +62,13 @@

         (type! :StrictX (includes :X)
                         (requires (paths-of :X)))
-

    The above example constructs a stricter version of `:X` by insisting
    all of its paths are required.
+
+   When the argument is a map, it is flattened before the paths are extracted, so that
+   `{:a {:b even?}}` and `{[:a :b] even?}` have the same effect.
+   (Included types are already flat.)
 "
   [type-signifier-or-map]
   (let [handle-kvs #(->Fork (keys %))]


Added fix to prevent nil equator-crossing-date-times from breaking indexing.

--- src/cmr/indexer/services/concepts/orbit_calculated_spatial_domain.clj
+++ src/cmr/indexer/services/concepts/orbit_calculated_spatial_domain.clj
@@ -13,7 +13,7 @@
                 stop-orbit-number
                 equator-crossing-longitude
                 equator-crossing-date-time]} ocsd
-        ecdt (attr/value->elastic-value :datetime equator-crossing-date-time)]
+        ecdt (when equator-crossing-date-time (attr/value->elastic-value :datetime equator-crossing-date-time))]
     {:orbit-number orbit-number
      :start-orbit-number start-orbit-number
      :stop-orbit-number stop-orbit-number


CMR-3678 PR fix

CMR-3678 PR fix

--- umm-spec-lib/src/cmr/umm_spec/test/iso19115_expected_conversion.clj
+++ umm-spec-lib/src/cmr/umm_spec/test/iso19115_expected_conversion.clj
@@ -126,8 +126,7 @@
  [related-urls]
  (let [related-urls (expected-iso-19115-2-related-urls related-urls)]
    (seq (for [related-url
-              (remove #(or (= "DataCenterURL" (:URLContentType %))
-                           (= "DataContactURL" (:URLContentType %)))
+              (remove #(#{"DataCenterURL" "DataContactURL"} (:URLContentType %))
                       related-urls)]
           (-> related-url
               (update :Description #(when % (str/trim %))))))))


import not used and breaks cljs build

import not used and breaks cljs build

--- src/bardo/interpolate.cljc
+++ src/bardo/interpolate.cljc
@@ -3,8 +3,7 @@
     #?(:cljs [cljs.core.match :refer-macros [match]]
        :clj  [clojure.core.match :refer [match]])
     [clojure.set :refer [union]]
-    [bardo.ease :as ease])
-  (:import (clojure.lang PersistentArrayMap)))
+    [bardo.ease :as ease]))

 ;; a protocol for birthing new values from nil


Add `node` to the Elastic system protocol, so it can be forwarded.

--- systems/elasticsearch/src/containium/systems/elasticsearch.clj
+++ systems/elasticsearch/src/containium/systems/elasticsearch.clj
@@ -12,14 +12,15 @@
 ;;; The public API for Elastic systems.

 (defprotocol Elastic
-  (whut? [this])) ;;--- FIXME: What would be a good API for Elastic?
+  (node [this]
+    "Returns the Node object used connecting.")) ;;---TODO: Is this a good API?

 ;;; The embedded implementation.

 (defrecord EmbeddedElastic [^ Node node]
   Elastic
-  (whut? [_])
+  (node [_] node)

   Stoppable
   (stop [_]


Remove unused subscription

Remove unused subscription

--- src/braid/client/subs.cljs
+++ src/braid/client/subs.cljs
@@ -204,18 +204,6 @@
   (fn [state _]
     (get-in state [:page :search-query])))

-(defn tee [x]
-  (println x) x)
-
-(reg-sub-raw
-  :tags-for-thread
-  (fn [state [_ thread-id]]
-    (let [tag-ids (reaction (get-in @state [:threads thread-id :tag-ids]))
-          tags (reaction (doall
-                           (map (fn [thread-id]
-                                  (get-in @state [:tags thread-id])) @tag-ids)))]
-      tags)))
-
 (reg-sub
   :messages-for-thread
   (fn [state [_ thread-id]]


Fix typo in comment.

Fix typo in comment.

--- src/open_company/resources/common.clj
+++ src/open_company/resources/common.clj
@@ -29,7 +29,7 @@
             category (some #(if (= category-name (keyword (:name %))) %) categories)]
     (vec (map #(keyword (:name %)) (:sections category))))))

-;; Categories in default order as keys in a map with the value a vector of sections in each category in order
+;; Categories as keys in a map with the value a vector of sections in each category in order
 (def ordered-sections (zipmap categories (map sections-for categories)))

 (defun category-for


[#1067] Change users list to sort by username by default

--- Dashboard/app/cljs/src/org/akvo/flow/dashboard/users/users_list.cljs
+++ Dashboard/app/cljs/src/org/akvo/flow/dashboard/users/users_list.cljs
@@ -114,7 +114,7 @@
     (init-state [this]
       {:pagination {:offset 0
                     :limit 20}
-       :sort {:sort-by "emailAddress"
+       :sort {:sort-by "userName"
               :sort-order "ascending"}
        :current-user-id nil})


Remove code duplication in validation

Remove code duplication in validation

--- src/catalog/validation.clj
+++ src/catalog/validation.clj
@@ -31,7 +31,7 @@
    (s/one (s/maybe s/Str) "accompanying-material")])

 (def SignatureKey
-  [(s/one (s/maybe (apply s/enum (vals vubis/braille-grade-raw-to-braille-grade))) "grade")
+  [(s/one (s/maybe BrailleGrade) "grade")
    (s/one s/Bool "double-spaced?")])

 (def LibrarySignature


Add confusing stuff about protocols and inheritance.

--- test/com/nomistech/clojure_the_language/protocols_and_records_test.clj
+++ test/com/nomistech/clojure_the_language/protocols_and_records_test.clj
@@ -29,3 +29,36 @@
   => (MyRecord. 1 2))

 ;;;; ___________________________________________________________________________
+;;;; ---- Confusing stuff about protocols and inheritance ----
+
+(defprotocol PI-1
+  (pi-1-a [x])
+  (pi-1-b [x]))
+
+(extend-protocol PI-1
+  java.util.Collection
+  (pi-1-a [x] :pi-1-a-collection)
+  (pi-1-b [x] :pi-1-b-collection))
+
+(fact "Inheritance works as you expect"
+  (pi-1-a #{}) => :pi-1-a-collection
+  (pi-1-b #{}) => :pi-1-b-collection
+  (pi-1-a [])  => :pi-1-a-collection
+  (pi-1-b [])  => :pi-1-b-collection)
+
+(defprotocol PI-2
+  (pi-2-a [x])
+  (pi-2-b [x]))
+
+(extend-protocol PI-2
+  java.util.Collection
+  (pi-2-a [x] :pi-2-a-collection)
+  (pi-2-b [x] :pi-2-b-collection)
+  java.util.List
+  (pi-2-a [x] :pi-2-a-list))
+
+(fact "Inheritance does not work as you expect"
+  (pi-2-a #{}) => :pi-2-a-collection
+  (pi-2-b #{}) => :pi-2-b-collection
+  (pi-2-a [])  => :pi-2-a-list
+  (pi-2-b [])  => (throws))


Don't produce output when running tests.


Updated world.clj to support new meshes package.

--- yaw/yaw/world.clj
+++ yaw/yaw/world.clj
@@ -91,12 +91,14 @@

 ;; Save Tools for Items
 (defn meshToVector [mesh]
-	"Converts Meshes into a savable vector. Predefined Meshes not yet supported."
-	(if (= (.getClass mesh) gameEngine.Mesh)
+	"Converts Meshes into a savable vector. Special Meshes not yet supported."
+	(if (= (.getClass mesh) gameEngine.meshs.Mesh)
 		(let [material (.getMaterial mesh)
 					color (.getColor material)]
 					(vector (.getClass mesh) (vec (.getVertices mesh)) (.x color) (.y color) (.z color) (.getReflectance material) (vec (.getNormales mesh)) (vec (.getIndices mesh)) (.getWeight mesh)))
-		(vector (.getClass mesh))
+		(let [material (.getMaterial mesh)
+					color (.getColor material)]
+					(vector (.getClass mesh) (vec (.getVertices mesh)) (.x color) (.y color) (.z color) (.getReflectance material) (vec (.getNormales mesh)) (vec (.getIndices mesh)) (.getWeight mesh)))
 	))

 (defn myItemToVector [myItem]
@@ -225,7 +227,7 @@
 ;; Load Tools for Items
 (defn loadMesh [mesh]
 	"Loads a Mesh. Does not support subclasses of Mesh yet."
-	(let [loadedMesh (gameEngine.Mesh. (float-array (get mesh 1)) (get mesh 2) (get mesh 3) (get mesh 4) (get mesh 5) (float-array (get mesh 6)) (int-array (get mesh 7)) (get mesh 8))]
+	(let [loadedMesh (gameEngine.meshs.Mesh. (float-array (get mesh 1)) (get mesh 2) (get mesh 3) (get mesh 4) (get mesh 5) (float-array (get mesh 6)) (int-array (get mesh 7)) (get mesh 8))]
 		loadedMesh
 ))


(PCP-385) Provide message-type in CapsuleLog

--- src/puppetlabs/pcp/broker/capsule.clj
+++ src/puppetlabs/pcp/broker/capsule.clj
@@ -41,11 +41,13 @@
   "Schema for a loggable summary of a capsule"
   {:messageid p/MessageId
    :source s/Str
+   :messagetype s/Str
    :destination (s/either p/Uri [p/Uri])})

 (s/defn -summarize :- CapsuleLog
   [capsule :- Capsule]
   {:messageid (get-in capsule [:message :id])
+   :messagetype (get-in capsule [:message :message_type])
    :source (get-in capsule [:message :sender])
    :destination (or (:target capsule)
                     (get-in capsule [:message :targets]))})


(maint) Log queries at INFO level

(maint) Log queries at INFO level

Query Logging is enabled by a config variable, and disabled by default,
so we can log them at info level without causing unecessary log growth.

--- src/puppetlabs/puppetdb/query_eng.clj
+++ src/puppetlabs/puppetdb/query_eng.clj
@@ -104,7 +104,7 @@
 (defn maybe-log-sql [logging-options gen-sql]
   (if-let [log-id (:log-id logging-options)]
     (let [sql-output (gen-sql)]
-      (log/debugf "%s:%s:%s" "PDBQuery" log-id (:results-query sql-output))
+      (log/infof "%s:%s:%s" "PDBQuery" log-id (:results-query sql-output))
       sql-output)
     (gen-sql)))

@@ -215,7 +215,7 @@

      (when log-queries
        ;; log the AST of the incoming query
-       (log/debugf "%s:%s:%s" "PDBQuery" log-id query))
+       (log/infof "%s:%s:%s" "PDBQuery" log-id query))

      (let [f #(let [{:keys [results-query]}
                     (query->sql remaining-query entity version
@@ -369,7 +369,7 @@

     (when log-queries
       ;; log the AST of the incoming query
-      (log/debugf "%s:%s:%s" "PDBQuery" log-id (:query query-map)))
+      (log/infof "%s:%s:%s" "PDBQuery" log-id (:query query-map)))

     (try
       (let [munge-fn (get-munge-fn entity version query-options url-prefix)
@@ -408,7 +408,7 @@

     (when log-queries
       ;; log the AST of the incoming query
-      (log/debugf "%s:%s:%s" "PDBQuery" log-id (:query query-map)))
+      (log/infof "%s:%s:%s" "PDBQuery" log-id (:query query-map)))

     (try
       (jdbc/with-transacted-connection scf-read-db


accept string for the system of houses wanted, coerce to character, anythng else defaults to O for Porphyry, invalid character calculates to Placidus, Swiss Ephemeris always calculates houses together with the angles, a future false / nil will simply have to hide them from the result

--- src/clj/ephemeris/core.clj
+++ src/clj/ephemeris/core.clj
@@ -8,7 +8,7 @@
                :geo {:lat nil :lon nil}
                :bodies []
                :angles []
-               :houses \O})
+               :houses "O"})

 (defn- valid-geo? [geo]
   (if (and
@@ -19,6 +19,15 @@
         (number? (:lon geo)))
     true
     false))
+
+(defn- coerce-houses [hs]
+  (if (= (type hs) java.lang.Character)
+    hs
+    (if (and
+          (= (type hs) java.lang.String)
+          (> (count hs) 0))
+      (get hs 0)
+      \O)))

 (defn calc [stuff]
   (let [want (merge defaults stuff)
@@ -49,7 +58,7 @@
                               0 ;; what flag?
                               (:lat (:geo want))
                               (:lon (:geo want))
-                              (int (:houses want))
+                              (int (coerce-houses (:houses want)))
                               cusps
                               ascmc)]
           {:houses (zipmap (range 1 13) (rest cusps))})))))


Fixed typo in munch.

Fixed typo in munch.

--- src/clj/minijava/munch.clj
+++ src/clj/minijava/munch.clj
@@ -14,7 +14,7 @@
 ;;I'm not sure what the best way to implement this is yet. But emit just appends x to the end of a list, so theres not too much to it.
 ;;emit should return nil.
 	(do
-			(reset! *instr* (cons x (deref *instr*)))
+			(reset! *instr* (cons x @*instr*))
 	nil)
 )

@@ -42,7 +42,7 @@
 	(do
 		(reset! *instr* '()) ;;reset instr to empty list
 		(munch irtree)
-		(reverse (@ *instr*))))
+		(reverse  @*instr*)))


Generating modes.

Generating modes.

--- src/cljs/guitar1/neck.cljs
+++ src/cljs/guitar1/neck.cljs
@@ -7,22 +7,6 @@
 ;; Add all the modes.
 ;; Add arpeggios.
 ;; See below TODOs too.
-
-(def pairs (partial partition 2))
-(def chromatic [:A :A# :B :C :C# :D :D# :E :F :F# :G :G#])
-(def strings [:E :A :D :G :B :E])
-(def ionian
-  '(true false true false true true false true false true false true))
-(def aeolian
-  '(true false true true false true false true true false true false))
-(def dorian
-  '(true false true true false true false true false true true false))
-(def pentatonic-minor
-  '(true false false true false true false true false false true false))
-
-;; Set Initial State
-(def neck-scale (atom pentatonic-minor))
-(def neck-key (atom :A))

 ;; TODO - Move to core
 (defn index-of
@@ -34,6 +18,27 @@

 ;; TODO - Move to core
 (defn contains [item coll] (some #{item} coll))
+
+(def pairs (partial partition 2))
+(def chromatic [:A :A# :B :C :C# :D :D# :E :F :F# :G :G#])
+(def strings [:E :A :D :G :B :E])
+(def lydian
+  '(true false true false true false true true false true false true))
+(def pentatonic-minor
+  '(true false false true false true false true false false true false))
+(def mode-names [:Lydian :Mixolydian :Aeolian :Locrian :Ionian :Dorian :Phrygian])
+(defn mode
+  [mode-name]
+  (take 12
+        (subvec (into [] (take 24 (cycle lydian)))
+                ;; This is wrong. Needs to just ignore false ones.
+                (index-of mode-names mode-name))))
+
+(def modes (zipmap mode-names (map mode mode-names)))
+
+;; Set Initial State
+(def neck-scale (atom pentatonic-minor))
+(def neck-key (atom :A))

 (defn set-key [key] (reset! neck-key key))

@@ -71,9 +76,14 @@
   [key scale]
   [:div.neck
    [:button {:on-click #(set-scale pentatonic-minor)} "Pentatonic Minor"]
+   [:button {:on-click #(set-scale lydian)} "Lydian"]
+   [:button {:on-click #(set-scale mixolydian)} "Mixolydian"]
+   [:button {:on-click #(set-scale aeolian)} "Aeolian"]
+   [:button {:on-click #(set-scale locrian)} "Locrian"]
    [:button {:on-click #(set-scale ionian)} "Ionian"]
-   [:button {:on-click #(set-scale aeolian)} "Aeolian"]
    [:button {:on-click #(set-scale dorian)} "Dorian"]
+   [:button {:on-click #(set-scale phrygian)} "Phrygian"]
+   ;;(map (fn [mode] [:button {:on-click #(set-scale (mode modes))} (name mode)]) (keys modes))
    (conj (map build-string (reverse strings))
          [:ul.string.frets (map #(vector :li %) (into [] (range 24)))])])


Dont write put nil onto channel

Dont write put nil onto channel

--- src/cljs/ji/websocket.cljs
+++ src/cljs/ji/websocket.cljs
@@ -31,7 +31,8 @@
                                  (.close ws))))))))
            (aset "onmessage"
                  (fn [m]
-                   (put! out (read-string (.-data m)))))
+                   (when-let [data (read-string (.-data m))]
+                     (put! out data))))
            (aset "onclose"
                  (fn []
                    (close! in)


Fix dom errors in #10 & fix rows in #9

Fix dom errors in #10 & fix rows in #9

--- src/cljs/russyll/core.cljs
+++ src/cljs/russyll/core.cljs
@@ -170,7 +170,12 @@
       [:div
        [:h2.ribbon (str "Put in some data!")]
        [:select.form-control
-        {:on-change (fn [evt] (do (re-frame/dispatch [:change-model (-> evt .-target .-value)]) (re-frame/dispatch [:syllaby @text-in]))) :value @current-model}
+        {
+         :on-change (fn [evt]
+                      (do
+                        (re-frame/dispatch [:change-model (-> evt .-target .-value)])
+                        (re-frame/dispatch [:syllaby @text-in])))
+         :value (or @current-model "")}
         (for [{:keys [name i]} models]
           [:option {:value i :key i} name])
         ]
@@ -179,13 +184,14 @@
          :on-change (fn [evt] (do (re-frame/dispatch [:change-text (-> evt .-target .-value)]) (re-frame/dispatch [:syllaby]))) :value @text-in}]
        [:pre @text-syllabied]
        [:table.table.table-striped.table-bordered.table-hover.table-condensed.syllabied
-        [:tr [:th] (for [{:keys [short name]} models] [:th {:key name :title name} short])]
-        (for
-            [[word syll-models] @splitted-mapped]
-          [:tr {:key (rand)} [:td word]
-           (map-indexed (fn [ix word] [:td {:key ix} word]) syll-models)
-           ]
-          )
+        [:tbody
+         [:tr [:th] (for [{:keys [short name]} models] [:th {:key name :title name} short])]
+         (for
+             [[word syll-models] (filter #(not= (first %) " ") @splitted-mapped)]
+           [:tr {:key (rand) :value (not= word " ")} [:td word]
+            (map-indexed (fn [ix word] [:td {:key ix} word]) syll-models)
+            ]
+           )]
         ]
        ]
       ))
@@ -206,7 +212,7 @@
       [:div
        [:h2.ribbon "Your turn!"]
        [:h4 "Here you can check yourself: Which model follows your intution?"]
-       [:p.well.bg-warning
+       [:div.well.bg-warning
         [:strong "Important: "]
         "Set the division with a dash '-': 'игорь' -> 'и-горь'. There will be 10 words to divide."
         [:div.input-group.col-sm-4
@@ -219,8 +225,9 @@
          (for [[i [k v]] (zipmap (-> @user-history (count) (range)) @user-history)]
            [:li.list-group-item {:key k} (str (inc i) ". " k " -> " v)])]]
        [:table.table
-        [:tr
-         (for [{:keys [short]} models] [:th {:key short}  short])] [:tr (for [v @result] [:td {:key (rand)} v])]]
+        [:tbody
+         [:tr
+          (for [{:keys [short]} models] [:th {:key short}  short])] [:tr (for [v @result] [:td {:key (rand)} v])]]]
        ((progress-tab))
        ])))


Add heavy artillery data

Add heavy artillery data

--- src/cljs/zetawar/data.cljs
+++ src/cljs/zetawar/data.cljs
@@ -399,7 +399,30 @@
                   :base   {:movement-cost 2 :armor-bonus  0 :attack-bonus  0}}
                  :attack-strengths
                  {:personnel 12
-                  :armored   13}}}}})
+                  :armored   13}}
+     :heavyartillery {:description "Heavy Artillery"
+                      :cost 1250
+                      :movement 2
+                      :can-capture false
+                      :can-repair #{}
+                      :min-range 4
+                      :max-range 6
+                      :armor-type :armored
+                      :armor 8
+                      :repair 1
+                      :state-map :exclusive
+                      :image "tilesets/elite-command/units/heavyartillery-COLOR.png"
+                      :terrain-effects
+                      {:plains {:movement-cost 2 :armor-bonus  0 :attack-bonus  0}
+                       :woods  {:movement-cost 2 :armor-bonus -3 :attack-bonus -5}
+                       :desert {:movement-cost 2 :armor-bonus  0 :attack-bonus  0}
+                       :tundra {:movement-cost 2 :armor-bonus  0 :attack-bonus  0}
+                       :swamp  {:movement-cost 2 :armor-bonus -3 :attack-bonus -5}
+                       :ford   {:movement-cost 2 :armor-bonus -2 :attack-bonus  0}
+                       :base   {:movement-cost 1 :armor-bonus  0 :attack-bonus  0}}
+                      :attack-strengths
+                      {:personnel 14
+                       :armored   15}}}}})

 ;; TODO: remove redundant id keys (?)
 (def maps


code reformatting

code reformatting

--- src/paredit/core.clj
+++ src/paredit/core.clj
@@ -292,10 +292,14 @@
           ; we reached the start of the parent form, indent depending on the form's type
           (if (#{"(" "#("} (loc-text loc))
             (cond
-              (nil? seen-loc) (+ (loc-col loc) (loc-count loc) 1)
-              (lisp-form? (loc-text (first seen-loc))) (+ (loc-col loc) (loc-count loc) 1)
-              (second seen-loc) (loc-col (second seen-loc))
-              :else (+ (loc-col loc) (loc-count loc) 1))
+              (nil? seen-loc)
+                (+ (loc-col loc) (loc-count loc) 1)
+              (lisp-form? (loc-text (first seen-loc)))
+                (+ (loc-col loc) (loc-count loc) 1)
+              (second seen-loc)
+                (loc-col (second seen-loc))
+              :else
+                (+ (loc-col loc) (loc-count loc) 1))
             (+ (loc-col loc) (loc-count loc)))
         (= :whitespace (loc-tag loc))
           ; we see a space
@@ -314,8 +318,6 @@
         offset (start-offset l)
         length (if (nil? r) 0 (- (end-offset r) offset))]
     [offset length]))
-
-

 (defn sel-match-normalized?
   "Does the selection denoted by offset and length match l (left) and r (right) locs ?"


comment

comment

--- src/prais2/main.cljs
+++ src/prais2/main.cljs
@@ -70,7 +70,7 @@

 ;;;
-;;
+;; Read events off the event bus and handle them
 ;;;
 (defn dispatcher []
   "Listen for events and dispatch to store, log etc."


lol parens

lol parens

--- src/pronouns/web.clj
+++ src/pronouns/web.clj
@@ -36,8 +36,8 @@

 (defn -main []
   (let [port (or (Integer. (env :port))
-                 (:default-server-port config))])
-  (jetty/run-jetty app {:port port}))
+                 (:default-server-port config))]
+    (jetty/run-jetty app {:port port})))

 ;; For interactive development:
 ;; (.stop server)


Pretty-print boot.user file when --verbose (fixes #315)

--- boot/core/src/boot/main.clj
+++ boot/core/src/boot/main.clj
@@ -4,6 +4,7 @@
   (:require
     [clojure.java.io             :as io]
     [clojure.string              :as string]
+    [clojure.pprint              :as pp]
     [boot.pod                    :as pod]
     [boot.core                   :as core]
     [boot.file                   :as file]
@@ -89,6 +90,14 @@
           base-pat  (re-pattern (format "^#!\\s*/usr/bin/env\\s+\\Q%s\\E(?:\\s+.*)?$" base-path))]
       (or (re-find full-pat bang-line) (re-find base-pat bang-line)))))

+(defn pr-boot-form [form]
+  (if (<= @util/*verbosity* 1)
+    (pr-str form)
+    (let [[op & [msg & more]] form]
+      (if (and (= op 'clojure.core/comment) (not more) (string? msg))
+        (format ";; %s" msg)
+        (with-out-str (pp/write form :dispatch pp/code-dispatch))))))
+
 (defn -main [pod-id worker-pod shutdown-hooks [arg0 & args :as args*]]
   (when (not= (boot.App/getVersion) (boot.App/getBootVersion))
     (let [url "https://github.com/boot-clj/boot#install"]
@@ -162,7 +171,7 @@
               import-ns   (export-task-namespaces initial-env)
               scriptforms (emit boot? args userforms localforms bootforms import-ns)
               scriptstr   (binding [*print-meta* true]
-                            (str (string/join "\n\n" (map pr-str scriptforms)) "\n"))]
+                            (str (string/join "\n\n" (map pr-boot-form scriptforms)) "\n"))]

           (when (:boot-script opts) (util/exit-ok (print scriptstr)))


Logic fail fix for default paths when no bootscript

--- boot/core/src/boot/main.clj
+++ boot/core/src/boot/main.clj
@@ -103,13 +103,11 @@
               profile?    (not (:no-profile opts))
               bootforms   (some->> arg0 slurp util/read-string-all)
               userforms   (when profile? (some->> userscript slurp util/read-string-all))
-              update-env  #(let [keep? (or have-bootscript? (contains? %3 %1))]
-                             (if keep? %3 (assoc %3 %1 %2)))
               initial-env (->> [:src-paths :tgt-path :dependencies]
                             (reduce #(if-let [v (opts %2)] (assoc %1 %2 v) %1) {})
                             (merge {} (:set-env opts))
-                            (update-env :tgt-path ".")
-                            (update-env :src-paths #{"."}))
+                            (#(let [done? (or have-bootscript? (% :tgt-path) (% :src-paths))]
+                                 (if done? % (assoc % :tgt-path "." :src-paths #{"."})))))
               import-ns   (export-task-namespaces initial-env)
               scriptforms (emit boot? args userforms bootforms import-ns)
               scriptstr   (str (string/join "\n\n" (map pr-str scriptforms)) "\n")]


Further :size explanations.

Further :size explanations.

--- src/re_demo/gap.cljs
+++ src/re_demo/gap.cljs
@@ -36,18 +36,19 @@
                                       [:pre
                                        {:style {:width "40em"}}
 "[h-box
- :gap      \"10px\"                ; <-- in between children
+ :gap      \"10px\"                ; <-- in between each children
  :children [[component-1]
             [component-2]
-            [gap :size \"5px\"]    ; <-- one off
+            [gap :size \"5px\"]    ; <-- ad hoc
             [component-3]]]"]

                                        [p "Notes:"
                                         [:ul
-                                         [:li "h-box and v-box allow a " [:code ":gap"] " parameter which inserts a
-                                         given amount of white space between " [:span.bold "all"] " children."]
-                                         [:li "For more adhoc gaps, use the " [:span.bold "[gap ...]"] " component."]
-                                         [:li "In the example above, the gap between the second and third components will be 25px because the gap component (5px) is surrounded above and below by a 10px " [:code ":gap"] "."]]]
+                                         [:li "h-box and v-box have a " [:code ":gap"] " parameter which inserts a
+                                         given amount of white space between each child."]
+                                         [:li "For more ad hoc gaps, use the " [:span.bold "[gap ...]"] " component itself."]
+                                         [:li "In this example, the gap between components 2and 3 will be 25px
+                                         because the [gap ] is a child of the h-box and will have \"10px\" above and below."]]]

                                       [gap :size "10px"]
                                       [line]
@@ -85,6 +86,6 @@
                                        [:ul
                                         [:li "This example has a gap with a " [:span.bold "proporational size"] ", not an absolute size. "]
                                         [:li "Because it \"grows\" to fill all available space, it \"pushes\" box2 and box3 as far apart as possible."]
-                                        [:li "Imagine these boxes as buttons, to see the utility."]]]
+                                        [:li "Imagine the boxes as buttons, to see the utility."]]]
                                       ]]]]
               [gap :size "30px"]]])


Correct default chunk-size

Correct default chunk-size

--- src/riffle/write.clj
+++ src/riffle/write.clj
@@ -29,7 +29,7 @@
           hash :murmur32
           checksum :crc32
           block-size 4096
-          chunk-size 1e7}
+          chunk-size 1e8}
      :as options}]
      (l/write-riffle kvs x
        {:sorted? sorted?


rf devtools wrapping

rf devtools wrapping

--- src/frontend/devtools.cljs
+++ src/frontend/devtools.cljs
@@ -286,11 +286,13 @@
   "Adds devtools to a component.
   For replay to work correctly component is required to handle ::on-did-replay signal."
   [spec storage storage-key]
-  (-> {:init       (-wrap-init (:init spec))
-       :view-model (-wrap-view-model (:view-model spec))
-       :view       (-wrap-view (:view spec))
-       :control    (-wrap-control (:control spec))
-       :reconcile  (-wrap-reconcile (:reconcile spec))}
+  (-> spec
+      (update :init -wrap-init)
+      (update :view-model -wrap-view-model)
+      (update :view -wrap-view)
+      (update :control -wrap-control)
+      (update :reconcile -wrap-reconcile)
+
       ; blacklisted keys are provided on init and should not be overwritten by middleware
       ; (otherwise, on hot reload, we will not see changes after modifying component init code)
       ; thus they also don't need to be saved


Add global symbols

Add global symbols

--- src/hatti/views/table.cljs
+++ src/hatti/views/table.cljs
@@ -114,19 +114,27 @@
   (str "
" label "
"
        (when hxl (str "
" hxl "
"))))

+(def select-unselect-all-records-id "select-unselect-all-records")
+(def select-unselect-all-records-element
+  (str "
+            Select all on this page
+            <input type=\"checkbox\" id=\"" select-unselect-all-records-id "\">
+           "))
+(def delete-record-class "delete-record")
+
 (defn actions-column
   [owner has-hxl?]
   {:id "actions"
    :field _id
    :type "text"
-   :name ""
+   :name select-unselect-all-records-element
    :toolTip ""
    :sortable false
    :formatter (action-buttons owner)
    :headerCssClass (str (when has-hxl? "hxl-min-height ")
                         "record-actions header")
    :cssClass "record-actions"
-   :maxWidth 70})
+   :maxWidth 100})

 (defn- flat-form->sg-columns
   "Get a set of slick grid column objects when given a flat form."


OO: Add alignment class to tip-info

OO: Add alignment class to tip-info

--- src/hatti/views/table.cljs
+++ src/hatti/views/table.cljs
@@ -96,11 +96,11 @@
        (when value
          [:ul
           [:li.tooltip
-           [:span.tip-info "View"]
+           [:span.tip-info.right "View"]
            [:a.view-record
             [:i.fa.fa-clone {:data-id value}]]]
           [:li.tooltip
-           [:span.tip-info "Edit"]
+           [:span.tip-info.right "Edit"]
            [:a.edit-record {:data-id value :target "_blank"
                             :href edit-link}
             [:i.fa.fa-pencil-square-o]]]])))))


Refactor camel-case.

Refactor camel-case.

Thanks to @jhn for the suggestion!

--- src/soy_clj/core.clj
+++ src/soy_clj/core.clj
@@ -42,14 +42,11 @@
         (swap! template-cache assoc files templates)
         templates))))

-(defn- dash-split
-  [s]
-  (string/split (name s) #"-"))
-
 (defn- camel-case
   [s]
-  (let [uc (->> s (dash-split) (map string/capitalize) (string/join) (vec))]
-    (string/join (cons (string/lower-case (first uc)) (next uc)))))
+  (let [ss (string/split (name s) #"-")]
+    (string/join (cons (string/lower-case (first ss))
+                       (map string/capitalize (next ss))))))

 (defn- camelize-keys
   ^java.util.Map [m]


Better comment/documentation on the data format

--- src/themis/query.clj
+++ src/themis/query.clj
@@ -1,4 +1,26 @@
 (ns themis.query)
+
+;; Themis Validation queries
+;; --------------------------
+;;
+;; ### Structure
+;; The query is specifically just data that gets ingested into
+;; some validation engine.  This has a few key benefits like
+;; composability and packaging/serializing.
+;;
+;; A query is a vector of vector pairs.
+;; In its short form:
+;; `[[:coordinate validation-fn]]`
+;;
+;; In its long form:
+;; `[[[:coordinate] [vaildation-fn]]`
+;;
+;; The query vectory pair is some coordinate into the data structure you're
+;; validation, and the validation function that should be applied at that
+;; location.
+;; Care has been taken to make it work well with hash maps, but it should
+;; work equally well with other data structures - the engine is open for
+;; modification.

 (defn balanced?
   "Ensure that every key/map selection


New test: test-new-file-3

New test: test-new-file-3

--- test/clj_fileutils/fileutils_test.clj
+++ test/clj_fileutils/fileutils_test.clj
@@ -91,3 +91,13 @@
             "abc/def"     (.toString (new-file "abc/def" ""))
             "abc/def/xyz" (.toString (new-file "abc/def/xyz" "")))))

+(deftest test-new-file-3
+    "Check the function clj-fileutils.fileutils/new-file."
+    (testing "Check the function clj-fileutils.fileutils/new-file."
+        (are [x y] (= x y)
+            "/"            (.toString (new-file "" ""))
+            "/abc"         (.toString (new-file "" "abc"))
+            "/abc.def"     (.toString (new-file "" "abc.def"))
+            "/abc/def"     (.toString (new-file "" "abc/def"))
+            "/abc/def/xyz" (.toString (new-file "" "abc/def/xyz")))))
+


subset? is not needed anymore

subset? is not needed anymore

--- test/github_changelog/github_test.clj
+++ test/github_changelog/github_test.clj
@@ -5,7 +5,6 @@
     [github-changelog.schema-generators :refer [generate sample]]
     [github-changelog.schema-complete :refer [complete]]
     [clojure.test :refer :all]
-    [clojure.set :refer [subset?]]
     [clj-http.fake :refer [with-fake-routes-in-isolation]]
     [cheshire.core :refer [generate-string]]
     [schema.core :refer [validate]]))


refactor to use stateful robots map.

refactor to use stateful robots map.

--- clojure/robot-name/robot.clj
+++ clojure/robot-name/robot.clj
@@ -1,28 +1,32 @@
 (ns robot)

-(def name-seq (ref (list "A" "A" 1)))
+(def id-seq (ref 0))
+(def name-seq (ref (list "A" "A" 0)))
+(def robots (ref {}))

-(defn- format-name
-  [name-seq]
-  (apply format "%s%s%03d" @name-seq))
-
-(defn- inc-name-seq
-  [curr-seq]
+(defn- inc-name-seq [curr-seq]
   (list "A" "A" (inc (last curr-seq))))

-(defn- generate-name
-  []
-  (dosync
-   (alter name-seq inc-name-seq))
-  (format-name name-seq))
+(defn- format-name [name]
+  (apply format "%s%s%03d" name))

-(defn robot
-  []
-  {:name (generate-name)})
+(defn- build []
+  {:name (format-name @name-seq)
+   :id @id-seq})

-(defn robot-name
-  [robot]
-  (:name robot))
+(defn- manufacture []
+  (let [new-robot (build)]
+    (dosync
+     (alter robots assoc @id-seq new-robot)
+     (alter name-seq inc-name-seq)
+     (alter id-seq inc))
+    new-robot))
+
+(defn robot []
+  (manufacture))
+
+(defn robot-name [robot]
+  (:name (@robots (robot :id))))

 ;; (defn reset-name
 ;;   [robot])


Replace FilterNull with filter macro

Replace FilterNull with filter macro

--- test/marceline/topology/wordcount.clj
+++ test/marceline/topology/wordcount.clj
@@ -40,6 +40,13 @@
       (doseq [word words]
         (t/emit-fn coll word)))))

+(t/deffilterfn
+  filter-null
+  [tuple]
+  (if (nil? (t/first tuple))
+    false
+    true))
+
 (defn build-topology [spout drpc]
   (let [word-state-factory (MemoryMapState$Factory.)
         trident-topology (TridentTopology.)
@@ -65,7 +72,7 @@
                                        ["word"]
                                        (MapGet.)
                                        ["count"])
-                        (t/each ["count"] (FilterNull.))
+                        (t/each ["count"] filter-null)
                         (t/aggregate ["count"]
                                      sum
                                      ["sum"])


Remove unused variable.

Remove unused variable.

--- src/klangmeister/core.cljs
+++ src/klangmeister/core.cljs
@@ -8,9 +8,6 @@
     [reagent.core :as reagent])
   (:require-macros
     [klangmeister.macros :as macro]))
-
-(def initial-code
-  (macro/text "src/klangmeister/live.cljs.txt"))

 (defn empty-state []
   (reagent/atom


Fixed defvar and defparam bugs.

Fixed defvar and defparam bugs.

--- core.clj
+++ core.clj
@@ -58,25 +58,30 @@
                            (sys-action [~type] [~'value] (~f-set ~'value))))

 (defmacro defvar
+    "Define a minibuffer variable. This variable is mutable therefore the value
+is wrapped in `(atom value)'."
     ([name value]
-           `(defvar name nil value))
+           `(defvar ~name nil ~value))
     ([name doc value]
-           `(do (def ~name ~doc (atom ~value))
+           `(do (def ~name ~@(if doc [doc] []) (atom ~value))
                 (register-variable ~(type value) {:name ~(clojure.core/name name) :description ~doc
                                                   :defined-in ~(format "namespace %s" (ns-name *ns*)) }
                                    (fn [] (deref ~name))
                                    (fn [~'v] (reset! ~name ~'v))))))

 (defmacro defparam
-    ([name value]
-           `(defparam name nil value))
+    "Define a minibuffer parameter. The parameter is not mutable and will
+provide an error message if `M-x edit-variable param-name' is attempted."
+  ([name value]
+         `(defparam ~name nil ~value))
   ([name doc value]
-         `(do (def ~name ~doc ~value)
-              (register-variable ~(type value) {:name ~(clojure.core/name name) :description ~doc
-                                                :defined-in ~(format "namespace %s" (ns-name *ns*)) }
-                                 (fn [] ~name)
-                                 (fn [~'v]
-                                     (message "Cannot change parameter value. Consider using defvar."))))))
+         `(do (def ~name ~@(if doc [doc] []) ~value)
+              (register-variable
+               ~(type value) {:name ~(clojure.core/name name) :description ~doc
+                              :defined-in ~(format "namespace %s" (ns-name *ns*)) }
+               (fn [] ~name)
+               (fn [~'v]
+                   (message "Cannot change parameter value. Consider using defvar."))))))

 ;; BUG messed up defcmd by changing register-command into a macro
 (defmacro defcmd


Update version to match current cucumber-jvm snapshot

--- examples/clojure_cukes/project.clj
+++ examples/clojure_cukes/project.clj
@@ -1,4 +1,4 @@
-(defproject clojure_cukes "1.0.4"
+(defproject clojure_cukes "1.0.5-SNAPSHOT"
   :description "A demo of Cucumber with Clojure and Leiningen"
   :dependencies [[org.clojure/clojure "1.4.0-alpha3"]]
   :plugins [[lein-cucumber "1.0.0"]]


refine word list

refine word list

--- src-cljs/frontend/components/landing.cljs
+++ src-cljs/frontend/components/landing.cljs
@@ -126,6 +126,9 @@
     (init-state [_]
       {:word-list ["demos"
                    "stuff"
+                   "lines"
+                   "squares"
+                   "circles"
                    "doodles"
                    "mockups"
                    "designs"
@@ -140,7 +143,6 @@
                    "products"
                    "new ideas"
                    "documents"
-                   "notebooks"
                    "precursors"
                    "prototypes"
                    "wireframes"
@@ -149,10 +151,11 @@
                    "interfaces"
                    "inventions"
                    "some stuff"
+                   "life easier"
                    "experiences"
                    "brainstorms"
-                   "big squares"
                    "masterpieces"
+                   "collaboration"
                    "presentations"
                    "illustrations"
                    "walk-throughs"


Sensor flattening.

Sensor flattening.

--- src-cljs/kixi/hecuba/tabs/programmes.cljs
+++ src-cljs/kixi/hecuba/tabs/programmes.cljs
@@ -148,6 +148,15 @@
         :headers {"Accept" "application/edn"}
         :response-format :text}))

+(defn flatten-device [device]
+  (let [device-keys (->> device keys (remove #(= % :readings)))
+            parent-device (select-keys device device-keys)
+            readings (:readings device)]
+        (map #(assoc % :parent-device parent-device) readings)))
+
+(defn extract-sensors [devices]
+  (mapcat flatten-device devices))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; History loop - this drives the fetches and clear downs
 (defn history-loop [history-channel data]
@@ -162,7 +171,6 @@
       (println "New Programmes: " programmes " New Projects: " projects " New Properties: " properties)
       (println "New Active Components: " (-> nav-event :args :ids))

-      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
       ;; Clear down
       (when (and old-programmes
                  (nil? programmes))
@@ -185,7 +193,6 @@
         (om/update! data [:sensors :data] [])
         (om/update! data [:measurements :data] []))

-      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
       ;; Fetchers
       (when-not programmes
         (om/update! data [:programmes :selected] nil)
@@ -203,15 +210,18 @@
         (om/update! data [:projects :selected] projects)
         (fetch-properties projects data))

+      ;; property handling is special as it gets a tree of data
       (when (and properties
                  (not= properties old-properties))
         (om/update! data [:properties :selected] properties)
         (om/update! data [:property-details :property_id] properties)
-        (om/update! data [:property-details :data] (->> @data
-                                                        :properties
-                                                        :data
-                                                        (filter #(= (:id %) properties))
-                                                        first)))
+        (let [property-details (->> @data
+                                    :properties
+                                    :data
+                                    (filter #(= (:id %) properties))
+                                    first)]
+          (om/update! data [:property-details :data] property-details)
+          (om/update! data [:sensors :data] (extract-sensors (get property-details :devices [])))))

       ;; Update the new active components
       (om/update! data :active-components (-> nav-event :args :ids)))


*load-fn* can only return a map or nil

*load-fn* can only return a map or nil

--- src/main/cljs/cljs/js.cljs
+++ src/main/cljs/cljs/js.cljs
@@ -87,6 +87,8 @@
      (let [env (:*env* bound-vars)]
        (*load-fn* (ns->relpath name)
          (fn [resolved]
+           (assert (or (map? resolved) (nil? resolved))
+             "*load-fn* may only return a map or nil")
            (if resolved
              (let [{:keys [lang source]} resolved]
                (condp = lang
@@ -160,6 +162,8 @@
          (let [dep (first deps)]
            (*load-fn* (ns->relpath dep)
              (fn [resolved]
+               (assert (or (map? resolved) (nil? resolved))
+                 "*load-fn* may only return a map or nil")
                (if resolved
                  (let [{:keys [lang source]} resolved]
                    (condp = lang


More on atoms.

More on atoms.

--- test/com/nomistech/clojure_the_language/intro_to_state.clj
+++ test/com/nomistech/clojure_the_language/intro_to_state.clj
@@ -48,14 +48,16 @@

 (def my-map-atom (atom {}))

-(swap! my-map-atom assoc :first-name "Alice") ; (assoc {} :first-name "Alice"}
+(swap! my-map-atom assoc :first-name "Alice")
+;; (assoc {} :first-name "Alice"}
 (fact @my-map-atom => {:first-name "Alice"})

-(swap! my-map-atom assoc :first-name "Bob")   ; (assoc {:first-name "Alice"}
-                                              ;        :first-name "Bob")
+(swap! my-map-atom assoc :first-name "Bob")
+;; (assoc {:first-name "Alice"} :first-name "Bob")
 (fact @my-map-atom => {:first-name "Bob"})

 (swap! my-map-atom assoc-in [:address :line-1] "78 Green Lane")
+;; (assoc-in {:first-name "Bob"} [:address :line-1] "78 Green Lane")
 (fact @my-map-atom => {:first-name "Bob"
                        :address {:line-1 "78 Green Lane"}})


Add comment about race condition.

Add comment about race condition.

--- src/clj/collect_earth_online/db/plots.clj
+++ src/clj/collect_earth_online/db/plots.clj
@@ -101,6 +101,10 @@
     (if plot-info
       (do
         (unlock-plots user-id)
+        ;; TODO, CEO-90 Technically there is a race condition here.  We need a lock function
+        ;;       that returns truthy/falsy if it correctly created a unique lock.
+        ;;       The quickest way to finish this is to return a "race condition error."
+        ;;       If we get users complaining we can try a recursive find.
         (call-sql "lock_plot"
                   (:plot_id plot-info)
                   user-id


Use static HTML page provided by the challenge

--- src/cljs/flux_challenge_reagent/core.cljs
+++ src/cljs/flux_challenge_reagent/core.cljs
@@ -10,7 +10,30 @@
 ;; Views

 (defn home-page []
-  [:div [:h2 "Welcome to flux-challenge-reagent"]])
+  [:div {:class "css-root"}
+   [:h1 {:class "css-planet-monitor"} "Obi-Wan currently on Tatooine"]
+
+   [:section {:class "css-scrollable-list"}
+    [:ul {:class "css-slots"}
+     [:li {:class "css-slot"}
+      [:h3 "Jorak Uln"]
+      [:h6 "Homeworld: Korriban"]]
+     [:li {:class "css-slot"}
+      [:h3 "Skere Kaan"]
+      [:h6 "Homeworld: Coruscant"]]
+     [:li {:class "css-slot"}
+      [:h3 "Na'daz"]
+      [:h6 "Homeworld: Ryloth"]]
+     [:li {:class "css-slot"}
+      [:h3 "Kas'im"]
+      [:h6 "Homeworld: Nal Hutta"]]
+     [:li {:class "css-slot"}
+      [:h3 "Darth Bane"]
+      [:h6 "Homeworld: Apatros"]]]]
+
+   [:div {:class "css-scroll-buttons"}
+    [:button {:class "css-button-up"}]
+    [:button {:class "css-button-down"}]]])

 (defn current-page []
   [:div [(session/get :current-page)]])


Revert "Revert "Merge branch 'master' of https://git.earthdata.nasa.gov/scm/cmr/cmr-indexer-app into CMR-183""

This reverts commit 7323ba2154f7ef7dae06cda9a319e525ced1a649.


Use `incidence instead' of `incidence-relation' in `to-binary-context'

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

--- src/conexp/contrib/algorithms/bitwise.clj
+++ src/conexp/contrib/algorithms/bitwise.clj
@@ -9,7 +9,7 @@
 (ns conexp.contrib.algorithms.bitwise
   (:import [java.util BitSet])
   (:import [java.util.concurrent SynchronousQueue])
-  (:use [conexp.fca.contexts :only (objects attributes incidence-relation)]))
+  (:use [conexp.fca.contexts :only (objects attributes incidence)]))

 ;;; Helpers to convert to and from BitSets
@@ -83,14 +83,14 @@
 (defn to-binary-matrix
   "Converts the incidence-relation to a binary matrix (in the sense of
   Java) filled with 1 and 0."
-  [object-vector attribute-vector incidence-relation]
+  [object-vector attribute-vector incidence]
   (let [incidence-matrix (make-array Integer/TYPE (count object-vector) (count attribute-vector))]
     (dotimes [obj-idx (count object-vector)]
       (let [^ints row (aget ^objects incidence-matrix obj-idx)]
         (dotimes [att-idx (count attribute-vector)]
           (aset row att-idx
-                (if (contains? incidence-relation [(nth object-vector obj-idx)
-                                                   (nth attribute-vector att-idx)])
+                (if (incidence [(nth object-vector obj-idx)
+                                (nth attribute-vector att-idx)])
                   (int 1)
                   (int 0))))))
     incidence-matrix))
@@ -104,7 +104,7 @@
         attribute-vector (vec (attributes context)),
         object-count     (count object-vector),
         attribute-count  (count attribute-vector),
-        incidence-matrix (to-binary-matrix object-vector attribute-vector (incidence-relation context))]
+        incidence-matrix (to-binary-matrix object-vector attribute-vector (incidence context))]
     [object-vector attribute-vector object-count attribute-count incidence-matrix]))

 (defmacro with-binary-context


Updated getting-started doc

Updated getting-started doc

--- src/css-guide/styles/getting_started.cljs
+++ src/css-guide/styles/getting_started.cljs
@@ -13,19 +13,23 @@
 rendered with ClojureScript.

-
 #### History of this project

+In a 3 month span the main codebase for this project was formed using PostCSS, Gulp and a vision for future spec compliance.
+With over 25 components, this library has matured into a simplified collection that lines up with Google's Material Design.

 ## What is this for?

-This project is meant to suppliment your next project with a wide array of components that are styled for your HTML or
-Clojurescript project. If you are using Untangled UI, you will automatically get these styles by default.
+This project is meant to suppliment your next application or website with a wide array of components that are styled for
+your HTML or Clojurescript project. If you are using Untangled UI, you will automatically get these styles by default.
+

 ## What problem does this solve?

-
+This project sets you up with common and designed components and utilities to make crafting a new front-end UI as simple
+an painless as possible. Each component has been researched and added with the intention that we are not duplicating
+patterns and that they all serve a specific purpose.

 ## What design principles underlie this UI?

@@ -33,6 +37,10 @@
 utilities and produces a stylesheet that has a healthy inclining specificity graph.

 ## How does this UI accomplish it's goals?
+
+Through well established coding practices and following the Material Design spec, we have a great blend of technology
+and design that compliments any web project. This project is also coded with future spec compliant code for CSS that we
+can expect to ship in browsers a decade from now. In short, you can write new styles in future code!

 # Getting Started

@@ -156,6 +164,5 @@
   (vec [;; NOTE: :examples is a list of example names, rendered in order given
         {:id :settings-config :title "What is this?" :examples [intro]}
         {:id :settings-config :title "Config" :examples [settings-config]}
-        {:id :settings-global :title "Global" :examples [settings-global]}
-        ]))
+        {:id :settings-global :title "Global" :examples [settings-global]}]))


cleaning up routes

cleaning up routes

--- src/bad_movie_back_end/core/routes/bad_movie_back_end_routes.clj
+++ src/bad_movie_back_end/core/routes/bad_movie_back_end_routes.clj
@@ -1,12 +1,6 @@
 (ns bad-movie-back-end.core.routes.bad-movie-back-end-routes

-  (:import [
-            javax.script
-            ScriptEngineManager])
-
   (:require
-    [clojure.data.json :as json]
-    [ring.util.response :as response]
     [compojure.core :refer :all]
     [bad-movie-back-end.core.renderer :refer [render]]))


Ok, I've managed to make something, it is not even close Scala solution in terms of idiomaticity but it is as close enough as I could manage it in clojure. I've made perhaps some mistakes upwards but really have no time go again over it.

--- src/fpinscala/purely_functional_state.clj
+++ src/fpinscala/purely_functional_state.clj
@@ -305,12 +305,12 @@
   "flatMap for exercise 6.8 from FPINS but generalized to state for exercise 6.10"
   [f g]
   #(from-state (f %) :let [v s]
-               ((g v) s)))
+              ((g v) s)))

 (defn unit-state
   "Generalized Unit function from section 6.5 of fpins"
   [a]
-  (fn [rng] (make-state a rng)))
+  (fn [s] (make-state a s)))

 (defn map-via-flat-map-s
   "Generalized version of map-via-flat-map from exercise 6.9, for exercise 6.10"
@@ -328,7 +328,7 @@
     (unit-state '())                                        ;Check out that "unit-produced" function is used as z value (now - it wouldn't be really
     #(map2-via-flat-map-s % %2 (fn [a b] (cons a b)))       ;correct to say it is "initial" but rather neutral (or terminating?) element
     fs))                                                    ;UPDATE (25.11.2015) Check out wikipedia about monad, it is actually "return" also
-;called "unit" operation of a monad
+                                                            ;called "unit" operation of a monad

 (declare simple-rng-s)

@@ -394,12 +394,14 @@
   "inputs is sequence of either coins or turns, s is 'machine' in focus"
   [i]
   (fn [s]
-    (println s)
     (match [i s]
-         [_ {:locked _ :candies 0 :coins _}] s
-         [:coin {:locked false :candies _ :coins _}] s
-         [:turn {:locked true :candies _ :coins _}] s
-         [:coin {:locked true :candies candies :coins coins}]
-         (machine false candies (inc coins))
-         [:turn {:locked false :candies candies :coins coins}]
-         (machine true (dec candies) coins))))
+         [_ {:locked _ :candies 0 :coins _}] (make-state s nil)
+         [:coin {:locked false :candies _ :coins _}] (make-state s nil)
+         [:turn {:locked true :candies _ :coins _}] (make-state s nil)
+         [:coin {:locked true :candies candies :coins coins}] (make-state (machine false candies (inc coins)) nil)
+         [:turn {:locked false :candies candies :coins coins}] (make-state (machine true (dec candies) coins) nil))))
+
+(defn simulate-machine [inputs]
+  (fn [m]
+    (let [{{{:keys [coins candies]} :val} :next-state} ((state-sequence-fpins (map #(modify-state (step-machine %)) inputs)) (make-state m nil))]
+      [coins candies])))


cast repness to double

cast repness to double

--- src/polismath/clusters.clj
+++ src/polismath/clusters.clj
@@ -99,7 +99,7 @@
               (/ up not-up)))]
     (let [in-cols  (columns (:matrix in-part))
           out-cols (columns (:matrix out-part))]
-      (map #(/ (frac-up %1) (frac-up %2)) in-cols out-cols))))
+      (map #(double (/ (frac-up %1) (frac-up %2))) in-cols out-cols))))

 (defn conv-repness [data clusters]


Tweak the logic for handling responses & timeouts

--- src/io/aviso/rook/jetty_async_adapter.clj
+++ src/io/aviso/rook/jetty_async_adapter.clj
@@ -6,7 +6,7 @@
            (org.eclipse.jetty.continuation ContinuationSupport Continuation))
   (:require
     [clojure.tools.logging :as l]
-    [clojure.core.async :refer [go <! timeout alts! take!]]
+    [clojure.core.async :refer [go <! timeout alts! take! close!]]
     [io.aviso.rook.utils :as utils]
     [ring.util
      [servlet :as servlet]
@@ -60,6 +60,7 @@
       (let [response-ch (-> request
                             (dissoc ::http-servlet-request ::http-servlet-response)
                             handler)
+            timeout-ch (timeout timeout-ms)
             responded (atom false)]

         (take! response-ch
@@ -67,20 +68,19 @@
                  (if-not response
                    (l/warnf "Handler for %s closed the channel without providing a response."
                             (utils/summarize-request request))
-                   (if (compare-and-set! responded false true)
-                     (do
-                       (l/debugf "Asynchronous response:%n%s" (utils/pretty-print response))
-                       (send-async-response continuation response))
-                     (l/warnf "Ignoring response for %s, received after %,d ms timeout."
-                              (utils/summarize-request request)
-                              timeout-ms)))))
+                   (when (compare-and-set! responded false true)
+                     (l/debugf "Asynchronous response:%n%s" (utils/pretty-print response))
+                     (send-async-response continuation response)
+                     (close! timeout-ch)))))

-        (take! (timeout timeout-ms)
+        (take! timeout-ch
                (fn [_]
                  (when (compare-and-set! responded false true)
                    (l/warnf "Request %s timed out after %,d ms."
                             (utils/summarize-request request)
                             timeout-ms)
+                   ;; At this point, no longer interested in the response should it ever arrive.
+                   (close! response-ch)
                    (send-async-response continuation
                                         (->
                                           (utils/response HttpServletResponse/SC_GATEWAY_TIMEOUT


improve typeahead demo

improve typeahead demo

--- src/re_demo/typeahead.cljs
+++ src/re_demo/typeahead.cljs
@@ -6,28 +6,38 @@
             [reagent.core  :as    reagent]
             [cljs.core.async  :refer    [timeout]]))

-(declare states-data)
+(declare md-icon-names)
+
+(defn md-classes-for-icon [name] (str "zmdi zmdi-" name " zmdi-hc-2x"))

 (defn typeahead-demo
   []
-  (let [text-val        (reagent/atom "")
-        regex           (reagent/atom nil)
-        regex999        #"^(\d{0,2})$|^(\d{0,2}\.\d{0,1})$"
-        status          (reagent/atom nil)
-        status-icon?    (reagent/atom false)
-        status-tooltip  (reagent/atom "")
-        disabled?       (reagent/atom false)
-        change-on-blur? (reagent/atom true)
-        slider-val      (reagent/atom 4)
-        data-source     (fn [s callback]
-                          (go
-                            (<! (timeout 500))
-                            (callback
-                             s
-                             (for [r states-data
-                                   :when (re-find (re-pattern (str "(?i)" s)) r)]
-                               r))))
-        ]
+  (let [typeahead-on-change-value (reagent/atom nil)
+        status                    (reagent/atom nil)
+        status-icon?              (reagent/atom false)
+        status-tooltip            (reagent/atom "")
+        disabled?                 (reagent/atom false)
+        change-on-blur?           (reagent/atom true)
+        data-source-choice        (reagent/atom :immediate)
+        md-icon-result #(-> {:name % :more :stuff})
+        data-source-async
+        (fn [s callback]
+          (go
+            ;; simulate an asynchronous data-source
+            (<! (timeout 500))
+            (callback
+             s
+             (take 16 (for [n md-icon-names
+                            :when (re-find (re-pattern (str "(?i)" s)) n)]
+                        [n (md-icon-result n)]))))
+          ;; must return falsey for an async data-source
+          nil)
+        data-source-immediate
+        (fn [s]
+          [s
+           (take 16 (for [n md-icon-names
+                          :when (re-find (re-pattern (str "(?i)" s)) n)]
+                      [n (md-icon-result n)]))])]
     (fn
       []
       [v-box
@@ -43,7 +53,7 @@
                                :gap      "10px"
                                :width    "450px"
                                :children [[title2 "Notes"]
-                                          [status-text "Stable"]
+                                          [status-text "Experimental"]
                                           [p "Text entry components."]
                                           [p "The " [:code ":on-change"] " function will be called either after each character is entered or on blur."]
                                           [p "Input warnings and errors can be indicated visually by border colors and icons."]
@@ -57,14 +67,17 @@
                                                        :children [[label :label "[typeahead ... ]"]
                                                                   [gap :size "5px"]
                                                                   [typeahead
-                                                                   :model            text-val
-                                                                   :data-source      data-source
+                                                                   :data-source      (case @data-source-choice :async data-source-async :immediate data-source-immediate)
+                                                                   :render-suggestion (fn [[_ {:keys [name]}]]
+                                                                                [:span
+                                                                                [:i {:style {:width "40px"} :class (md-classes-for-icon name)}]
+                                                                                name])
                                                                    :status           @status
                                                                    :status-icon?     @status-icon?
                                                                    :status-tooltip   @status-tooltip
                                                                    :width            "300px"
-                                                                   :placeholder      "Choose state"
-                                                                   :on-change        #(reset! text-val %)
+                                                                   :placeholder      "Material Design Icons"
+                                                                   :on-change        #(reset! typeahead-on-change-value %)
                                                                    :change-on-blur?  change-on-blur?
                                                                    :disabled?        disabled?]]]
                                                       [v-box
@@ -73,10 +86,24 @@
                                                                   [h-box
                                                                    :align    :center
                                                                    :gap      "5px"
-                                                                   :children [[:code ":on-change"]
-                                                                              " last called with this value: "
-                                                                              [:span.bold (if @text-val @text-val "nil")]]]
+                                                                   :children [[v-box
+                                                                               :children [[:p [:code ":on-change"] " last called with this value: " ]
+                                                                                [:p [:pre (str @typeahead-on-change-value)]]]]]]
                                                                   [title :level :level3 :label "Parameters"]
+                                                                  [v-box
+                                                                   :children [[box :align :start :child [:code ":data-source"]]
+                                                                              [radio-button
+                                                                               :label     [:p "Synchronous " [:code "string -> results"]]
+                                                                               :value     :immediate
+                                                                               :model     @data-source-choice
+                                                                               :on-change #(reset! data-source-choice :immediate)
+                                                                               :style     {:margin-left "20px"}]
+                                                                              [radio-button
+                                                                               :label     [:p "Asynchronous " [:code "string, callback -> nil"]]
+                                                                               :value     :async
+                                                                               :model     @data-source-choice
+                                                                               :on-change #(reset! data-source-choice :async)
+                                                                               :style     {:margin-left "20px"}]]]
                                                                   [v-box
                                                                    :children [[box :align :start :child [:code ":change-on-blur?"]]
                                                                               [radio-button
@@ -140,54 +167,776 @@
   []
   [typeahead-demo])

-(def ^:private states-data
-  ["Alabama"
-   "Alaska"
-   "Arizona"
-   "Arkansas"
-   "California"
-   "Colorado"
-   "Connecticut"
-   "Delaware"
-   "Florida"
-   "Georgia"
-   "Hawaii"
-   "Idaho"
-   "Illinois"
-   "Indiana"
-   "Iowa"
-   "Kansas"
-   "Kentucky"
-   "Louisiana"
-   "Maine"
-   "Maryland"
-   "Massachusetts"
-   "Michigan"
-   "Minnesota"
-   "Mississippi"
-   "Missouri"
-   "Montana"
-   "Nebraska"
-   "Nevada"
-   "New Hampshire"
-   "New Jersey"
-   "New Mexico"
-   "New York"
-   "North Carolina"
-   "North Dakota"
-   "Ohio"
-   "Oklahoma"
-   "Oregon"
-   "Pennsylvania"
-   "Rhode Island"
-   "South Carolina"
-   "South Dakota"
-   "Tennessee"
-   "Texas"
-   "Utah"
-   "Vermont"
-   "Virginia"
-   "Washington"
-   "West Virginia"
-   "Wisconsin"
-   "Wyoming"])
+(def ^:private md-icon-names
+  ["google"
+   "google-plus-box"
+   "google-plus"
+   "paypal"
+   "3d-rotation"
+   "airplane-off"
+   "airplane"
+   "album"
+   "archive"
+   "assignment-account"
+   "assignment-alert"
+   "assignment-check"
+   "assignment-o"
+   "assignment-return"
+   "assignment-returned"
+   "assignment"
+   "attachment-alt"
+   "attachment"
+   "audio"
+   "badge-check"
+   "balance-wallet"
+   "balance"
+   "battery-alert"
+   "battery-flash"
+   "battery-unknown"
+   "battery"
+   "bike"
+   "block-alt"
+   "block"
+   "boat"
+   "book-image"
+   "book"
+   "bookmark-outline"
+   "bookmark"
+   "brush"
+   "bug"
+   "bus"
+   "cake"
+   "car-taxi"
+   "car-wash"
+   "car"
+   "card-giftcard"
+   "card-membership"
+   "card-travel"
+   "card"
+   "case-check"
+   "case-download"
+   "case-play"
+   "case"
+   "cast-connected"
+   "cast"
+   "chart-donut"
+   "chart"
+   "city-alt"
+   "city"
+   "close-circle-o"
+   "close-circle"
+   "close"
+   "cocktail"
+   "code-setting"
+   "code-smartphone"
+   "code"
+   "coffee"
+   "collection-bookmark"
+   "collection-case-play"
+   "collection-folder-image"
+   "collection-image-o"
+   "collection-image"
+   "collection-item-1"
+   "collection-item-2"
+   "collection-item-3"
+   "collection-item-4"
+   "collection-item-5"
+   "collection-item-6"
+   "collection-item-7"
+   "collection-item-8"
+   "collection-item-9-plus"
+   "collection-item-9"
+   "collection-item"
+   "collection-music"
+   "collection-pdf"
+   "collection-plus"
+   "collection-speaker"
+   "collection-text"
+   "collection-video"
+   "compass"
+   "cutlery"
+   "delete"
+   "dialpad"
+   "dns"
+   "drink"
+   "edit"
+   "email-open"
+   "email"
+   "eye-off"
+   "eye"
+   "eyedropper"
+   "favorite-outline"
+   "favorite"
+   "filter-list"
+   "fire"
+   "flag"
+   "flare"
+   "flash-auto"
+   "flash-off"
+   "flash"
+   "flip"
+   "flower-alt"
+   "flower"
+   "font"
+   "fullscreen-alt"
+   "fullscreen-exit"
+   "fullscreen"
+   "functions"
+   "gas-station"
+   "gesture"
+   "globe-alt"
+   "globe-lock"
+   "globe"
+   "graduation-cap"
+   "home"
+   "hospital-alt"
+   "hospital"
+   "hotel"
+   "hourglass-alt"
+   "hourglass-outline"
+   "hourglass"
+   "http"
+   "image-alt"
+   "image-o"
+   "image"
+   "inbox"
+   "invert-colors-off"
+   "invert-colors"
+   "key"
+   "label-alt-outline"
+   "label-alt"
+   "label-heart"
+   "label"
+   "labels"
+   "lamp"
+   "landscape"
+   "layers-off"
+   "layers"
+   "library"
+   "link"
+   "lock-open"
+   "lock-outline"
+   "lock"
+   "mail-reply-all"
+   "mail-reply"
+   "mail-send"
+   "mall"
+   "map"
+   "menu"
+   "money-box"
+   "money-off"
+   "money"
+   "more-vert"
+   "more"
+   "movie-alt"
+   "movie"
+   "nature-people"
+   "nature"
+   "navigation"
+   "open-in-browser"
+   "open-in-new"
+   "palette"
+   "parking"
+   "pin-account"
+   "pin-assistant"
+   "pin-drop"
+   "pin-help"
+   "pin-off"
+   "pin"
+   "pizza"
+   "plaster"
+   "power-setting"
+   "power"
+   "print"
+   "puzzle-piece"
+   "quote"
+   "railway"
+   "receipt"
+   "refresh-alt"
+   "refresh-sync-alert"
+   "refresh-sync-off"
+   "refresh-sync"
+   "refresh"
+   "roller"
+   "ruler"
+   "scissors"
+   "screen-rotation-lock"
+   "screen-rotation"
+   "search-for"
+   "search-in-file"
+   "search-in-page"
+   "search-replace"
+   "search"
+   "seat"
+   "settings-square"
+   "settings"
+   "shape"
+   "shield-check"
+   "shield-security"
+   "shopping-basket"
+   "shopping-cart-plus"
+   "shopping-cart"
+   "sign-in"
+   "sort-amount-asc"
+   "sort-amount-desc"
+   "sort-asc"
+   "sort-desc"
+   "spellcheck"
+   "spinner"
+   "storage"
+   "store-24"
+   "store"
+   "subway"
+   "sun"
+   "tab-unselected"
+   "tab"
+   "tag-close"
+   "tag-more"
+   "tag"
+   "thumb-down"
+   "thumb-up-down"
+   "thumb-up"
+   "ticket-star"
+   "toll"
+   "toys"
+   "traffic"
+   "translate"
+   "triangle-down"
+   "triangle-up"
+   "truck"
+   "turning-sign"
+   "wallpaper"
+   "washing-machine"
+   "window-maximize"
+   "window-minimize"
+   "window-restore"
+   "wrench"
+   "zoom-in"
+   "zoom-out"
+   "alert-circle-o"
+   "alert-circle"
+   "alert-octagon"
+   "alert-polygon"
+   "alert-triangle"
+   "help-outline"
+   "help"
+   "info-outline"
+   "info"
+   "notifications-active"
+   "notifications-add"
+   "notifications-none"
+   "notifications-off"
+   "notifications-paused"
+   "notifications"
+   "account-add"
+   "account-box-mail"
+   "account-box-o"
+   "account-box-phone"
+   "account-box"
+   "account-calendar"
+   "account-circle"
+   "account-o"
+   "account"
+   "accounts-add"
+   "accounts-alt"
+   "accounts-list-alt"
+   "accounts-list"
+   "accounts-outline"
+   "accounts"
+   "face"
+   "female"
+   "male-alt"
+   "male-female"
+   "male"
+   "mood-bad"
+   "mood"
+   "run"
+   "walk"
+   "cloud-box"
+   "cloud-circle"
+   "cloud-done"
+   "cloud-download"
+   "cloud-off"
+   "cloud-outline-alt"
+   "cloud-outline"
+   "cloud-upload"
+   "cloud"
+   "download"
+   "file-plus"
+   "file-text"
+   "file"
+   "folder-outline"
+   "folder-person"
+   "folder-star-alt"
+   "folder-star"
+   "folder"
+   "gif"
+   "upload"
+   "border-all"
+   "border-bottom"
+   "border-clear"
+   "border-color"
+   "border-horizontal"
+   "border-inner"
+   "border-left"
+   "border-outer"
+   "border-right"
+   "border-style"
+   "border-top"
+   "border-vertical"
+   "copy"
+   "crop"
+   "format-align-center"
+   "format-align-justify"
+   "format-align-left"
+   "format-align-right"
+   "format-bold"
+   "format-clear-all"
+   "format-clear"
+   "format-color-fill"
+   "format-color-reset"
+   "format-color-text"
+   "format-indent-decrease"
+   "format-indent-increase"
+   "format-italic"
+   "format-line-spacing"
+   "format-list-bulleted"
+   "format-list-numbered"
+   "format-ltr"
+   "format-rtl"
+   "format-size"
+   "format-strikethrough-s"
+   "format-strikethrough"
+   "format-subject"
+   "format-underlined"
+   "format-valign-bottom"
+   "format-valign-center"
+   "format-valign-top"
+   "redo"
+   "select-all"
+   "space-bar"
+   "text-format"
+   "transform"
+   "undo"
+   "wrap-text"
+   "comment-alert"
+   "comment-alt-text"
+   "comment-alt"
+   "comment-edit"
+   "comment-image"
+   "comment-list"
+   "comment-more"
+   "comment-outline"
+   "comment-text-alt"
+   "comment-text"
+   "comment-video"
+   "comment"
+   "comments"
+   "check-all"
+   "check-circle-u"
+   "check-circle"
+   "check-square"
+   "check"
+   "circle-o"
+   "circle"
+   "dot-circle-alt"
+   "dot-circle"
+   "minus-circle-outline"
+   "minus-circle"
+   "minus-square"
+   "minus"
+   "plus-circle-o-duplicate"
+   "plus-circle-o"
+   "plus-circle"
+   "plus-square"
+   "plus"
+   "square-o"
+   "star-circle"
+   "star-half"
+   "star-outline"
+   "star"
+   "bluetooth-connected"
+   "bluetooth-off"
+   "bluetooth-search"
+   "bluetooth-setting"
+   "bluetooth"
+   "camera-add"
+   "camera-alt"
+   "camera-bw"
+   "camera-front"
+   "camera-mic"
+   "camera-party-mode"
+   "camera-rear"
+   "camera-roll"
+   "camera-switch"
+   "camera"
+   "card-alert"
+   "card-off"
+   "card-sd"
+   "card-sim"
+   "desktop-mac"
+   "desktop-windows"
+   "device-hub"
+   "devices-off"
+   "devices"
+   "dock"
+   "floppy"
+   "gamepad"
+   "gps-dot"
+   "gps-off"
+   "gps"
+   "headset-mic"
+   "headset"
+   "input-antenna"
+   "input-composite"
+   "input-hdmi"
+   "input-power"
+   "input-svideo"
+   "keyboard-hide"
+   "keyboard"
+   "laptop-chromebook"
+   "laptop-mac"
+   "laptop"
+   "mic-off"
+   "mic-outline"
+   "mic-setting"
+   "mic"
+   "mouse"
+   "network-alert"
+   "network-locked"
+   "network-off"
+   "network-outline"
+   "network-setting"
+   "network"
+   "phone-bluetooth"
+   "phone-end"
+   "phone-forwarded"
+   "phone-in-talk"
+   "phone-locked"
+   "phone-missed"
+   "phone-msg"
+   "phone-paused"
+   "phone-ring"
+   "phone-setting"
+   "phone-sip"
+   "phone"
+   "portable-wifi-changes"
+   "portable-wifi-off"
+   "portable-wifi"
+   "radio"
+   "reader"
+   "remote-control-alt"
+   "remote-control"
+   "router"
+   "scanner"
+   "smartphone-android"
+   "smartphone-download"
+   "smartphone-erase"
+   "smartphone-info"
+   "smartphone-iphone"
+   "smartphone-landscape-lock"
+   "smartphone-landscape"
+   "smartphone-lock"
+   "smartphone-portrait-lock"
+   "smartphone-ring"
+   "smartphone-setting"
+   "smartphone-setup"
+   "smartphone"
+   "speaker"
+   "tablet-android"
+   "tablet-mac"
+   "tablet"
+   "tv-alt-play"
+   "tv-list"
+   "tv-play"
+   "tv"
+   "usb"
+   "videocam-off"
+   "videocam-switch"
+   "videocam"
+   "watch"
+   "wifi-alt-2"
+   "wifi-alt"
+   "wifi-info"
+   "wifi-lock"
+   "wifi-off"
+   "wifi-outline"
+   "wifi"
+   "arrow-left-bottom"
+   "arrow-left"
+   "arrow-merge"
+   "arrow-missed"
+   "arrow-right-top"
+   "arrow-right"
+   "arrow-split"
+   "arrows"
+   "caret-down-circle"
+   "caret-down"
+   "caret-left-circle"
+   "caret-left"
+   "caret-right-circle"
+   "caret-right"
+   "caret-up-circle"
+   "caret-up"
+   "chevron-down"
+   "chevron-left"
+   "chevron-right"
+   "chevron-up"
+   "forward"
+   "long-arrow-down"
+   "long-arrow-left"
+   "long-arrow-return"
+   "long-arrow-right"
+   "long-arrow-tab"
+   "long-arrow-up"
+   "rotate-ccw"
+   "rotate-cw"
+   "rotate-left"
+   "rotate-right"
+   "square-down"
+   "square-right"
+   "swap-alt"
+   "swap-vertical-circle"
+   "swap-vertical"
+   "swap"
+   "trending-down"
+   "trending-flat"
+   "trending-up"
+   "unfold-less"
+   "unfold-more"
+   "directions-bike"
+   "directions-boat"
+   "directions-bus"
+   "directions-car"
+   "directions-railway"
+   "directions-run"
+   "directions-subway"
+   "directions-walk"
+   "directions"
+   "layers-off"
+   "layers"
+   "local-activity"
+   "local-airport"
+   "local-atm"
+   "local-bar"
+   "local-cafe"
+   "local-car-wash"
+   "local-convenience-store"
+   "local-dining"
+   "local-drink"
+   "local-florist"
+   "local-gas-station"
+   "local-grocery-store"
+   "local-hospital"
+   "local-hotel"
+   "local-laundry-service"
+   "local-library"
+   "local-mall"
+   "local-movies"
+   "local-offer"
+   "local-parking"
+   "local-pharmacy"
+   "local-phone"
+   "local-pizza"
+   "local-activity"
+   "local-post-office"
+   "local-printshop"
+   "local-see"
+   "local-shipping"
+   "local-store"
+   "local-taxi"
+   "local-wc"
+   "map"
+   "my-location"
+   "nature-people"
+   "nature"
+   "navigation"
+   "pin-account"
+   "pin-assistant"
+   "pin-drop"
+   "pin-help"
+   "pin-off"
+   "pin"
+   "traffic"
+   "apps"
+   "grid-off"
+   "grid"
+   "view-agenda"
+   "view-array"
+   "view-carousel"
+   "view-column"
+   "view-comfy"
+   "view-compact"
+   "view-dashboard"
+   "view-day"
+   "view-headline"
+   "view-list-alt"
+   "view-list"
+   "view-module"
+   "view-quilt"
+   "view-stream"
+   "view-subtitles"
+   "view-toc"
+   "view-web"
+   "view-week"
+   "widgets"
+   "alarm-check"
+   "alarm-off"
+   "alarm-plus"
+   "alarm-snooze"
+   "alarm"
+   "calendar-alt"
+   "calendar-check"
+   "calendar-close"
+   "calendar-note"
+   "calendar"
+   "time-countdown"
+   "time-interval"
+   "time-restore-setting"
+   "time-restore"
+   "time"
+   "timer-off"
+   "timer"
+   "android-alt"
+   "android"
+   "apple"
+   "behance"
+   "codepen"
+   "dribbble"
+   "dropbox"
+   "evernote"
+   "facebook-box"
+   "facebook"
+   "github-box"
+   "github"
+   "google-drive"
+   "google-earth"
+   "google-glass"
+   "google-maps"
+   "google-pages"
+   "google-play"
+   "google-plus-box"
+   "google-plus"
+   "google"
+   "instagram"
+   "language-css3"
+   "language-html5"
+   "language-javascript"
+   "language-python-alt"
+   "language-python"
+   "lastfm"
+   "pocket"
+   "polymer"
+   "rss"
+   "share"
+   "steam-square"
+   "steam"
+   "twitter-box"
+   "twitter"
+   "vk"
+   "wikipedia"
+   "windows"
+   "500px"
+   "8tracks"
+   "aspect-ratio-alt"
+   "aspect-ratio"
+   "blur-circular"
+   "blur-linear"
+   "blur-off"
+   "blur"
+   "brightness-2"
+   "brightness-3"
+   "brightness-4"
+   "brightness-5"
+   "brightness-6"
+   "brightness-7"
+   "brightness-auto"
+   "brightness-setting"
+   "broken-image"
+   "center-focus-strong"
+   "center-focus-weak"
+   "compare"
+   "crop-16-9"
+   "crop-3-2"
+   "crop-5-4"
+   "crop-7-5"
+   "crop-din"
+   "crop-free"
+   "crop-landscape"
+   "crop-portrait"
+   "crop-square"
+   "exposure-alt"
+   "exposure"
+   "filter-b-and-w"
+   "filter-center-focus"
+   "filter-frames"
+   "filter-tilt-shift"
+   "gradient"
+   "grain"
+   "graphic-eq"
+   "hdr-off"
+   "hdr-strong"
+   "hdr-weak"
+   "hdr"
+   "iridescent"
+   "leak-off"
+   "leak"
+   "looks"
+   "loupe"
+   "panorama-horizontal"
+   "panorama-vertical"
+   "panorama-wide-angle"
+   "photo-size-select-large"
+   "photo-size-select-small"
+   "picture-in-picture"
+   "slideshow"
+   "texture"
+   "tonality"
+   "vignette"
+   "wb-auto"
+   "eject-alt"
+   "eject"
+   "equalizer"
+   "fast-forward"
+   "fast-rewind"
+   "forward-10"
+   "forward-30"
+   "forward-5"
+   "hearing"
+   "pause-circle-outline"
+   "pause-circle"
+   "pause"
+   "play-circle-outline"
+   "play-circle"
+   "play"
+   "playlist-audio"
+   "playlist-plus"
+   "repeat-one"
+   "repeat"
+   "replay-10"
+   "replay-30"
+   "replay-5"
+   "replay"
+   "shuffle"
+   "skip-next"
+   "skip-previous"
+   "stop"
+   "surround-sound"
+   "tune"
+   "volume-down"
+   "volume-mute"
+   "volume-off"
+   "volume-up"
+   "n-1-square"
+   "n-2-square"
+   "n-3-square"
+   "n-4-square"
+   "n-5-square"
+   "n-6-square"
+   "neg-1"
+   "neg-2"
+   "plus-1"
+   "plus-2"
+   "sec-10"
+   "sec-3"
+   "zero"])