Test multi-get with empty keys.

Test multi-get with empty keys.

--- src/cbfg/test/kvs.cljs
+++ src/cbfg/test/kvs.cljs
@@ -90,7 +90,33 @@
                                (e n res5
                                   (merge m5 {:status :not-found
                                              :status-info [:no-kvs (:kvs-ident res)]})
-                                  (atake tkvs res-ch5))))))))
+                                  (atake tkvs res-ch5)))))))
+                  (let [res-ch (achan tkvs)
+                        m {:opaque @n
+                           :res-ch res-ch
+                           :op :kvs-open
+                           :name :kvs0}]
+                    (aput tkvs cmd-ch m)
+                    (let [res (atake tkvs res-ch)]
+                      (and (e n res
+                              (merge m {:status :ok
+                                        :status-info :created
+                                        :kvs-ident (:kvs-ident res)})
+                              (atake tkvs res-ch))
+                           (let [res-ch2 (achan tkvs)
+                                 m2 {:opaque @n
+                                     :res-ch res-ch2
+                                     :op :multi-get
+                                     :kvs-ident (:kvs-ident res)
+                                     :keys []}]
+                             (aput tkvs cmd-ch m2)
+                             (let [res2 (atake tkvs res-ch2)]
+                               (e n res2
+                                  (dissoc (merge m2 {:status :ok})
+                                          :keys)
+                                  (atake tkvs res-ch2)))))))
+
+                    )
            "pass"
            (str "FAIL: on test-lane #" @n)))))


Hooked up cmd-dispatch-loop to t1.

Hooked up cmd-dispatch-loop to t1.

--- src/cbfg/world/t1.cljs
+++ src/cbfg/world/t1.cljs
@@ -1,6 +1,6 @@
 (ns cbfg.world.t1
   (:require-macros [cljs.core.async.macros :refer [go-loop]]
-                   [cbfg.act :refer [act actx-top achan achan-buf aput atake]])
+                   [cbfg.act :refer [act act-loop actx-top achan achan-buf aput atake]])
   (:require [cljs.core.async :refer [<! >! close! chan map< merge timeout dropping-buffer]]
             [goog.dom :as gdom]
             [om.core :as om :include-macros true]
@@ -161,9 +161,8 @@
         (make-net world
                   (:net-listen-ch @prog-world)
                   (:net-connect-ch @prog-world))
-        (let [req-ch (achan world)
-              res-ch (achan world)
-              vis-chs {}
+        (let [vis-chs {}
+              req-ch (achan world)
               cmd-ch (map< (fn [ev] {:op (.-id (.-target ev))
                                      :x (js/parseInt (get-el-value "x"))
                                      :y (js/parseInt (get-el-value "y"))
@@ -179,10 +178,18 @@
               prog-js (str "with (cbfg.world.t1) {" prog "}")
               prog-res (try (js/eval prog-js) (catch js/Object ex ex))]
           (world-cmd-loop world cbfg.world.lane/cmd-handlers cmd-ch
-                          req-ch res-ch vis-chs world-vis-init el-prefix)
+                          req-ch (:res-ch @prog-world)
+                          vis-chs world-vis-init el-prefix)
+          (act-loop cmd-dispatch-loop world [num-dispatches 0]
+                    (when-let [msg (atake cmd-dispatch-loop req-ch)]
+                      (when-let [client-req-ch
+                                 (get-in @prog-world [:clients (:client msg) :req-ch])]
+                        (aput cmd-dispatch-loop client-req-ch msg))
+                      (recur (inc num-dispatches))))
           (println :prog-res prog-res)
           (<! prog-ch)
           (close! cmd-ch)
+          (close! req-ch)
           (close! event-ch)
           (close! delayed-event-ch)
           (recur (inc num-worlds)))))))


Added default collset and coll.

Added default collset and coll.

--- src/cbfg/world/t2.cljs
+++ src/cbfg/world/t2.cljs
@@ -44,7 +44,7 @@
   {:realms {"_system" {:users {"admin" {:pswd "password"}}
                        :collsets {}}
             "_lobby" {:users {"_anon" {:pswd ""}}
-                      :collsets {}}}})
+                      :collsets {"default" {:colls {"default" {}}}}}}})

 (def initial-lane-state
   {:cur-realm "_lobby"


refactor tests

refactor tests

--- test/clj/salava/user/db_test.clj
+++ test/clj/salava/user/db_test.clj
@@ -31,13 +31,12 @@
         (is (=  "error" (:status connect)))
         (is (=  "user/Enteredaddressisalready" (:message connect)))
         )))
-  (testing "delete user (softdelete) "
+  (testing "delete user"
     (let [registered-user (db/get-user-by-email ctx (:email registration-data))]
       (testing " delete created user"
         (let [connect (db/delete-user ctx (:id registered-user) (:password registration-data))]
           (is (= "success" (:status connect)))
           ))
-
       (testing " check can login with user"
         (let [login (db/login-user ctx (:email registration-data) (:password registration-data))]
           (is (= "error" (:status login)))
@@ -45,8 +44,7 @@

       (testing " check can login with user"
         (let [emails (db/email-addresses ctx (:id registered-user))]
-           (is (= "deleted-test.registration@example.com.so.deleted" (:email (first emails))))))
-
+           (is (= nil (:email (first emails))))))
       ))

   (testing "register user and  verify email"


lol just use unique/value instead of /identity

--- src/chat/server/db.clj
+++ src/chat/server/db.clj
@@ -29,13 +29,13 @@
       {:db/ident :user/email
        :db/valueType :db.type/string
        :db/cardinality :db.cardinality/one
-       :db/unique :db.unique/identity
+       :db/unique :db.unique/value
        :db/id #db/id [:db.part/db]
        :db.install/_attribute :db.part/db}
       {:db/ident :user/nickname
        :db/valueType :db.type/string
        :db/cardinality :db.cardinality/one
-       :db/unique :db.unique/identity
+       :db/unique :db.unique/value
        :db/id #db/id [:db.part/db]
        :db.install/_attribute :db.part/db}
       {:db/ident :user/password-token
@@ -65,14 +65,6 @@
        :db/cardinality :db.cardinality/many
        :db/id #db/id [:db.part/db]
        :db.install/_attribute :db.part/db}
-      ; user - create
-      {:db/ident :add-user
-       :db/id #db/id [:db.part/user]
-       :db/fn (d/function {:lang "clojure"
-                           :params '[db params]
-                           :code '(if-let [e (datomic.api/entity db [:user/email (:user/email params)])]
-                                    (throw (Exception. "User already exists with email"))
-                                    [params])})}

       ; message
       {:db/ident :message/id
@@ -319,17 +311,12 @@
 (defn create-user!
   "creates a user, returns id"
   [{:keys [id email avatar nickname password]}]
-  (let [new-id (d/tempid :entities)
-        {:keys  [db-after tempids]} @(d/transact *conn*
-                                       [[:add-user
-                                         {:db/id new-id
-                                          :user/id id
-                                          :user/email email
-                                          :user/avatar avatar
-                                          :user/password-token (password/encrypt password)}]])]
-    (->> (d/resolve-tempid db-after tempids new-id)
-         (d/entity db-after)
-         db->user)))
+  (-> {:user/id id
+       :user/email email
+       :user/avatar avatar
+       :user/password-token (password/encrypt password)}
+      create-entity!
+      db->user))

 (defn nickname-taken?
   [nickname]


Self-destruct can only be used during a run on its server.

--- src/clj/game/cards.clj
+++ src/clj/game/cards.clj
@@ -1687,7 +1687,8 @@
                                                        :effect (effect (gain :credit 2))} st nil))})))}}}

    "Self-destruct"
-   {:abilities [{:label "Trace X - Do 3 net damage"
+   {:abilities [{:req (req this-server)
+                 :label "Trace X - Do 3 net damage"
                  :effect (req (let [serv (card->server state card)
                                     cards (concat (:ices serv) (:content serv))]
                                    (trash state side card)


Implement Trick of Light.

Implement Trick of Light.

--- src/clj/game/cards.clj
+++ src/clj/game/cards.clj
@@ -491,7 +491,7 @@
    "Dorm Computer"
    {:data {:counter 4}
     :abilities [{:counter-cost 1 :cost [:click 1]
-                 :prompt "Choose a server" :choices (req servers)
+                 :prompt "Choose a server" :choices (req servers)
                  :msg "make a run and avoid all tags for the remainder of the run"
                  :effect (effect (run target))}]}

@@ -1908,6 +1908,27 @@
    {:abilities [{:cost [:click 1] :msg "gain 2 [Credits]" :once :per-turn
                  :effect (effect (gain :credit 2))}]
     :leave-play (effect (damage :meat 3))}
+
+   "Trick of Light"
+   {:choices {:req #(and (contains? % :advance-counter) (> (:advance-counter %) 0))}
+    :effect  (req (let [fr target tol card]
+                       (resolve-ability state side
+                         {:prompt  "Move how many advancement tokens?"
+                          :choices (take (+ (:advance-counter fr) 1) ["0" "1" "2"])
+                          :effect  (req (let [c (Integer/parseInt target)]
+                                             (resolve-ability state side
+                                               {:prompt  "Move to where?"
+                                                ; valid targets: not the "from" card; advanceable always, or advanceable and rezzed, or agenda
+                                                :choices {:req #(and (not= (:cid fr) (:cid %))
+                                                                     (or (and (:advanceable %) (or (= (:advanceable %) "always") (:rezzed %)))
+                                                                         (= (:type %) "Agenda")))}
+                                                :effect  (effect (add-prop :corp target :advance-counter c)
+                                                                 (set-prop :corp fr :advance-counter (- (:advance-counter fr) c))
+                                                                 (system-msg (str "moves " c " advancement tokens from "
+                                                                                (if (:rezzed fr) (:title fr) "a card") " to "
+                                                                                (if (:rezzed target) (:title target) "a card"))))
+                                                } tol nil)))
+                          } card nil)))}

    "Turtlebacks"
    {:events {:server-created {:msg "gain 1 [Credits]" :effect (effect (gain :credit 1))}}}


Removed version metadata carried over from clojure.

--- src/cljs/cljs/set.cljs
+++ src/cljs/cljs/set.cljs
@@ -18,7 +18,6 @@

 (defn union
   "Return a set that is the union of the input sets"
-  {:added "1.0"}
   ([] #{})
   ([s1] s1)
   ([s1 s2]
@@ -31,7 +30,6 @@

 (defn intersection
   "Return a set that is the intersection of the input sets"
-  {:added "1.0"}
   ([s1] s1)
   ([s1 s2]
      (if (< (count s2) (count s1))
@@ -47,7 +45,6 @@

 (defn difference
   "Return a set that is the first set without elements of the remaining sets"
-  {:added "1.0"}
   ([s1] s1)
   ([s1 s2]
      (if (< (count s1) (count s2))
@@ -63,20 +60,17 @@

 (defn select
   "Returns a set of the elements for which pred is true"
-  {:added "1.0"}
   [pred xset]
     (reduce (fn [s k] (if (pred k) s (disj s k)))
             xset xset))

 (defn project
   "Returns a rel of the elements of xrel with only the keys in ks"
-  {:added "1.0"}
   [xrel ks]
     (set (map #(select-keys % ks) xrel)))

 (defn rename-keys
   "Returns the map with the keys in kmap renamed to the vals in kmap"
-  {:added "1.0"}
   [map kmap]
     (reduce
      (fn [m [old new]]
@@ -88,14 +82,12 @@

 (defn rename
   "Returns a rel of the maps in xrel with the keys in kmap renamed to the vals in kmap"
-  {:added "1.0"}
   [xrel kmap]
     (set (map #(rename-keys % kmap) xrel)))

 (defn index
   "Returns a map of the distinct values of ks in the xrel mapped to a
   set of the maps in xrel with the corresponding values of ks."
-  {:added "1.0"}
   [xrel ks]
     (reduce
      (fn [m x]
@@ -105,14 +97,12 @@

 (defn map-invert
   "Returns the map with the vals mapped to the keys."
-  {:added "1.0"}
   [m] (reduce (fn [m [k v]] (assoc m v k)) {} m))

 (defn join
   "When passed 2 rels, returns the rel corresponding to the natural
   join. When passed an additional keymap, joins on the corresponding
   keys."
-  {:added "1.0"}
   ([xrel yrel] ;natural join
    (if (and (seq xrel) (seq yrel))
      (let [ks (intersection (set (keys (first xrel))) (set (keys (first yrel))))
@@ -141,16 +131,12 @@

 (defn subset?
   "Is set1 a subset of set2?"
-  {:added "1.2",
-   :tag Boolean}
   [set1 set2]
   (and (<= (count set1) (count set2))
        (every? #(contains? set2 %) set1)))

 (defn superset?
   "Is set1 a superset of set2?"
-  {:added "1.2",
-   :tag Boolean}
   [set1 set2]
   (and (>= (count set1) (count set2))
        (every? #(contains? set1 %) set2)))
@@ -172,6 +158,5 @@
 (difference #{:a :b :c} #{:c :d :e})
 (intersection #{:a :b :c} #{:c :d :e})

-(index ys [:b])
-)
+(index ys [:b]))


fix indentation in conexp.util.graph

fix indentation in conexp.util.graph

--- src/main/clojure/conexp/util/graph.clj
+++ src/main/clojure/conexp/util/graph.clj
@@ -17,8 +17,8 @@
 ;; and more modifications for use with loom/ubergraph

 (ns
-    #^{:author "Jeffrey Straszheim",
-       :doc "Basic graph theory algorithms"}
+  #^{:author "Jeffrey Straszheim",
+     :doc    "Basic graph theory algorithms"}
   conexp.util.graph
   (:require [ubergraph.core :as uber]
             [loom.graph :as lg])
@@ -66,17 +66,17 @@
   "For each node n, add the edge n->n if not already present."
   [g]
   (make-directed-graph
-          (nodes g)
-          (into {} (map (fn [n]
-                          [n (conj (set (get-neighbors g n)) n)]) (nodes g)))))
+    (nodes g)
+    (into {} (map (fn [n]
+                    [n (conj (set (get-neighbors g n)) n)]) (nodes g)))))

 (defn remove-loops
   "For each node n, remove any edges n->n."
   [g]
   (make-directed-graph
-          (nodes g)
-          (into {} (map (fn [n]
-                          [n (disj (set (get-neighbors g n)) n)]) (nodes g)))))
+    (nodes g)
+    (into {} (map (fn [n]
+                    [n (disj (set (get-neighbors g n)) n)]) (nodes g)))))

 ;; Graph Walk
@@ -86,13 +86,13 @@
 provide a set of visited notes (v) and a collection of nodes to
 visit (ns)."
   ([g n]
-     (lazy-walk g [n] #{}))
+   (lazy-walk g [n] #{}))
   ([g ns v]
-     (lazy-seq (let [s (seq (drop-while v ns))
-                     n (first s)
-                     ns (rest s)]
-                 (when s
-                   (cons n (lazy-walk g (concat (get-neighbors g n) ns) (conj v n))))))))
+   (lazy-seq (let [s (seq (drop-while v ns))
+                   n (first s)
+                   ns (rest s)]
+               (when s
+                 (cons n (lazy-walk g (concat (get-neighbors g n) ns) (conj v n))))))))

 (defn transitive-closure
   "Returns the transitive closure of a graph. The neighbors are lazily computed.
@@ -107,8 +107,8 @@
               [n (delay (lazy-walk g (get-neighbors g n) #{}))])
         nbs (into {} (map nns (nodes g)))]
     (make-directed-graph
-            (nodes g)
-            (fn [n] (force (nbs n))))))
+      (nodes g)
+      (fn [n] (force (nbs n))))))
 ;; Strongly Connected Components

 (defn- post-ordered-visit
@@ -139,7 +139,7 @@
                  (let [[nv comp] (post-ordered-visit rev
                                                      (first stack)
                                                      [visited #{}])
-                       ns (doall (remove nv stack))] ;doall prevents StackOverflow
+                       ns (doall (remove nv stack))]        ;doall prevents StackOverflow
                    (recur ns nv (conj acc comp)))))]
     (step po #{} [])))

@@ -149,17 +149,17 @@
 These sets are the strongly connected components. Each edge will
 be the union of the corresponding edges of the prior graph."
   ([g]
-     (component-graph g (scc g)))
+   (component-graph g (scc g)))
   ([g sccs]
-     (let [find-node-set (fn [n]
-                           (some #(if (% n) % nil) sccs))
-           find-neighbors (fn [ns]
-                            (let [nbs1 (map (partial get-neighbors g) ns)
-                                  nbs2 (map set nbs1)
-                                  nbs3 (apply union nbs2)]
-                              (set (map find-node-set nbs3))))
-           nm (into {} (map (fn [ns] [ns (find-neighbors ns)]) sccs))]
-       (make-directed-graph (set sccs) nm))))
+   (let [find-node-set (fn [n]
+                         (some #(if (% n) % nil) sccs))
+         find-neighbors (fn [ns]
+                          (let [nbs1 (map (partial get-neighbors g) ns)
+                                nbs2 (map set nbs1)
+                                nbs3 (apply union nbs2)]
+                            (set (map find-node-set nbs3))))
+         nm (into {} (map (fn [ns] [ns (find-neighbors ns)]) sccs))]
+     (make-directed-graph (set sccs) nm))))

 (defn recursive-component?
   "Is the component (recieved from scc) self recursive?"


fix the http-kit component for reload workflow

--- src/server/components/http_kit.clj
+++ src/server/components/http_kit.clj
@@ -4,7 +4,8 @@
             [schema.core :as s]
             [schema.coerce :as coerce]
             [schema.utils :as s-utils]
-            [server.schema :refer :all]))
+            [server.schema :refer :all]
+            [clojure.tools.logging :as log]))

 (def WebOptions
   {:host HostName
@@ -25,19 +26,16 @@

 (defrecord HttpKitServer [options]
   component/Lifecycle
+
   (start [component]
-    (if (:server component)
-      component
-      (let [handler (atom (delay (get-in component [:handler :handler-fn])))
-            server (atom (run-server (fn [req] (@@handler req)) options))]
-        (assoc component :server server))))
+    (let [handler (get-in component [:handler :handler-fn])
+          server (run-server handler options)]
+      (assoc component :server server)))

   (stop [component]
-    (when-let [server (:server component)]
-      (@server :timeout 100)
-      (reset! server nil)
-      (dissoc component :server)
-      component)))
+    (if-let [server (:server component)]
+      (server))
+    (assoc component :server nil)))

 (defn new-web-server
   [options]


Test for function render-search-href

Test for function render-search-href

--- test/zg/html_renderer_test.clj
+++ test/zg/html_renderer_test.clj
@@ -132,6 +132,18 @@
 (deftest test-render-html-footer
     "Checking the function zg.html-renderer/render-html-footer."
     (testing "the function zg.html-renderer/render-html-footer."
-        (spit "test/expected/html_footer1.html" (page/xhtml (render-html-footer)))
         (is (= (slurp "test/expected/html_footer1.html") (page/xhtml (render-html-footer))))))

+(deftest test-render-search-href
+    "Checking the function zg.html-renderer/render-search-href."
+    (testing "the function zg.html-renderer/render-search-href."
+        (are [x y] (= (slurp x) y)
+            "test/expected/search-href1.html" (search-href "" :whitelist)
+            "test/expected/search-href2.html" (search-href "" :blacklist)
+            "test/expected/search-href3.html" (search-href "/" :whitelist)
+            "test/expected/search-href4.html" (search-href "/" :blacklist)
+            "test/expected/search-href5.html" (search-href "http://10.20.30.40/" :whitelist)
+            "test/expected/search-href6.html" (search-href "http://10.20.30.40/" :blacklist)
+            "test/expected/search-href7.html" (search-href "http://10.20.30.40/zg/" :whitelist)
+            "test/expected/search-href8.html" (search-href "http://10.20.30.40/zg/" :blacklist))))
+


Broken by new job data format in alpha5

Broken by new job data format in alpha5

--- test/onyx/plugin/output_test.clj
+++ test/onyx/plugin/output_test.clj
@@ -89,8 +89,6 @@
                   peer-config
                   {:catalog catalog :workflow workflow :lifecycles lifecycles
                    :task-scheduler :onyx.task-scheduler/balanced})
-            task-ids (:task-ids job)
-            tasks (zipmap (map :name task-ids) task-ids)

             _ (doseq [v input-values]
                 (>!! @in-chan v))
@@ -98,7 +96,7 @@

             _ (onyx.api/await-job-completion peer-config (:job-id job))
             job-id (:job-id job)
-            task-id (get-in tasks [:write-messages :id])
+            task-id (get-in (:task-ids job) [:write-messages :id])
             ledger-ids (read-ledgers-data (:log (:env env)) id job-id task-id)]
         (is (= input-values
                (sort-by :a


minor UI tweak

minor UI tweak

--- src/main/shadow/cljs/ui/components/build_status.cljs
+++ src/main/shadow/cljs/ui/components/build_status.cljs
@@ -28,8 +28,8 @@

 (defn render-source-line
   [start-idx lines]
-  (sg/simple-seq (map-indexed vector lines)
-    (fn [[idx body]]
+  (sg/simple-seq lines
+    (fn [body idx]
       (<< [:pre (format "%4d | " (+ 1 idx start-idx)) body]))))

 (defn render-build-warning [{:keys [source-excerpt file line column msg resource-name] :as warning}]


Pass in title and action correctly

Pass in title and action correctly

--- src-cljs/frontend/components/pages/team.cljs
+++ src-cljs/frontend/components/pages/team.cljs
@@ -131,88 +131,89 @@
            [:.main
             (if-let [[_ [vcs-type name]] selected-org-ident]
               (card/titled
-                (html
-                  (let [users (remove :circle_member (:github-users (:invite-data app)))
-                        count-users (count users)
-                        count-with-email (count (filter #(utils/valid-email? (:email %)) users))
-                        count-selected (count (filter #(:checked %) users))]
-                    [:div
-                     name
-                     (case vcs-type
-                       "github" [:i.octicon.octicon-mark-github]
-                       "bitbucket" [:i.fa.fa-bitbucket]
-                       nil)
-                     (when (:invite-teammates? (om/get-render-state owner))
-                       (component
-                         (modal/modal-dialog {:title "Invite Teammates"
-                                              :body
-                                              [:div
-                                               [:div
-                                                "These are the people who are not using CircleCI yet:"
-                                                [:br]
-                                                [:span [:b count-with-email] " of " [:b count-users] " users have emails, " [:b count-selected] " are selected"]]
-                                               [:div.constraining-modal
-                                                (om/build table/table {:rows users
-                                                                       :columns [{:header "Username"
-                                                                                :cell-fn (fn [user-map]
-                                                                                [:span
-                                                                                [:img.invite-gravatar {:src (gh-utils/make-avatar-url user-map :size 50)}]
-                                                                                (str "  " (:login user-map))])}
-                                                                                {:header "Email"
-                                                                                :cell-fn (fn [user-map]
-                                                                                (let [{:keys [avatar_url email login index checked]} user-map
-                                                                                id-name (str login "-email")
-                                                                                error? (and (or checked (not (empty? email)))
-                                                                                (not (utils/valid-email? email)))]
-                                                                                [:span
-                                                                                (component
-                                                                                (om/build text-input/text-input {:input-type "email"
-                                                                                :on-change (fn [event]
-                                                                                (utils/edit-input owner (conj (state/invite-github-user-path index) :email) event)
-                                                                                (when (and (not= checked true)
-                                                                                (not (empty? email)))
-                                                                                (utils/toggle-input owner (conj (state/invite-github-user-path index) :checked) nil)))
-                                                                                :required? true
-                                                                                :id id-name
-                                                                                :value email
-                                                                                :size "small"
-                                                                                :long? true
-                                                                                :error? error?
-                                                                                :defaultValue email}))]))}
-                                                                                {:type :shrink
-                                                                                :cell-fn (fn [user-map]
-                                                                                (let [{:keys [email login index checked]} user-map
-                                                                                id-name (str login "-checkbox")
-                                                                                email-valid? (utils/valid-email? email)]
-                                                                                (component
-                                                                                (om/build checkbox/checkbox {:id id-name
-                                                                                :disabled? (and (not (utils/valid-email? email))
-                                                                                (not (empty? email)))
-                                                                                :checked? checked
-                                                                                :on-click #(utils/toggle-input owner (conj (state/invite-github-user-path index) :checked) %)}))))}]
-                                                                       :striped? true
-                                                                       :fixed-header? true})]]
-                                              :actions [(button/button {:on-click #(om/set-state! owner :invite-teammates? false)} "Cancel")
-                                                        (forms/managed-button
-                                                          [:button.btn.btn-success {:data-success-text "Sent"
-                                                                                ;; :on-click #(raise! owner [:invited-github-users {:invitees (invitees users)}])
-                                                                                :on-click #(.log js/console "Send the emails in this on-click!" (seq (invitees users)))
-                                                                                :disabled (or (empty? (invitees users))
-                                                                                (not (every? #(utils/valid-email? (:email %)) (invitees users))))}
-                                                           "Send Invites "
-                                                           [:i.fa.fa-envelope-o]])]
-                                              :close-fn #(om/set-state! owner :invite-teammates? false)})))
-                     (button/button
-                       {:disabled? (nil? (:users selected-org))
-                        :primary? true
-                        :on-click (fn []
-                                    ;; TODO -ac Add tracking back in before merging
-                                    #_((om/get-shared owner :track-event)
-                                       {:event-type :invite-teammates-clicked
-                                        :properties {:view :team}})
-                                    (om/set-state! owner :invite-teammates? (not (:invite-teammates? (om/get-render-state owner)))))}
-                       "Invite Teammates")])
-                  )
+                  {:title (html
+                              [:div name
+                               (case vcs-type
+                                   "github" [:i.octicon.octicon-mark-github]
+                                   "bitbucket" [:i.fa.fa-bitbucket]
+                                   nil)])
+                   :action  (html
+                                (let [users (remove :circle_member (:github-users (:invite-data app)))
+                                      count-users (count users)
+                                      count-with-email (count (filter #(utils/valid-email? (:email %)) users))
+                                      count-selected (count (filter #(:checked %) users))]
+                                    ;; TODO -ac You can turn all of this vvvvv into an :action for the title of the card!
+                                    [:div (when (:invite-teammates? (om/get-render-state owner))
+                                              (component
+                                                  (modal/modal-dialog {:title "Invite Teammates"
+                                                                       :body
+                                                                       [:div
+                                                                        [:div
+                                                                         "These are the people who are not using CircleCI yet:"
+                                                                         [:br]
+                                                                         [:span [:b count-with-email] " of " [:b count-users] " users have emails, " [:b count-selected] " are selected"]]
+                                                                        [:div.constraining-modal
+                                                                         (om/build table/table {:rows users
+                                                                                :key-fn :login
+                                                                                :columns [{:header "Username"
+                                                                                :cell-fn (fn [user-map]
+                                                                                [:span
+                                                                                [:img.invite-gravatar {:src (gh-utils/make-avatar-url user-map :size 50)}]
+                                                                                (str "  " (:login user-map))])}
+                                                                                {:header "Email"
+                                                                                :cell-fn (fn [user-map]
+                                                                                (let [{:keys [avatar_url email login index checked]} user-map
+                                                                                id-name (str login "-email")
+                                                                                error? (and (or checked (not (empty? email)))
+                                                                                (not (utils/valid-email? email)))]
+                                                                                [:span
+                                                                                (component
+                                                                                (om/build text-input/text-input {:input-type "email"
+                                                                                :on-change (fn [event]
+                                                                                (utils/edit-input owner (conj (state/invite-github-user-path index) :email) event)
+                                                                                (when (and (not= checked true)
+                                                                                (not (empty? email)))
+                                                                                (utils/toggle-input owner (conj (state/invite-github-user-path index) :checked) nil)))
+                                                                                :required? true
+                                                                                :id id-name
+                                                                                :value email
+                                                                                :size "small"
+                                                                                :long? true
+                                                                                :error? error?
+                                                                                :defaultValue email}))]))}
+                                                                                {:type :shrink
+                                                                                :cell-fn (fn [user-map]
+                                                                                (let [{:keys [email login index checked]} user-map
+                                                                                id-name (str login "-checkbox")
+                                                                                email-valid? (utils/valid-email? email)]
+                                                                                (component
+                                                                                (om/build checkbox/checkbox {:id id-name
+                                                                                :disabled? (and (not (utils/valid-email? email))
+                                                                                (not (empty? email)))
+                                                                                :checked? checked
+                                                                                :on-click #(utils/toggle-input owner (conj (state/invite-github-user-path index) :checked) %)}))))}]
+                                                                                :striped? true
+                                                                                :fixed-header? true})]]
+                                                                       :actions [(button/button {:on-click #(om/set-state! owner :invite-teammates? false)} "Cancel")
+                                                                                (forms/managed-button
+                                                                                [:button.btn.btn-success {:data-success-text "Sent"
+                                                                                ;; :on-click #(raise! owner [:invited-github-users {:invitees (invitees users)}])
+                                                                                :on-click #(.log js/console "Send the emails in this on-click!" (seq (invitees users)))
+                                                                                :disabled (or (empty? (invitees users))
+                                                                                (not (every? #(utils/valid-email? (:email %)) (invitees users))))}
+                                                                                "Send Invites "
+                                                                                [:i.fa.fa-envelope-o]])]
+                                                                       :close-fn #(om/set-state! owner :invite-teammates? false)})))
+                                     (button/button
+                                         {:disabled? (nil? (:users selected-org))
+                                          :primary? true
+                                          :on-click (fn []
+                                                        ;; TODO -ac Add tracking back in before merging
+                                                        #_((om/get-shared owner :track-event)
+                                                           {:event-type :invite-teammates-clicked
+                                                            :properties {:view :team}})
+                                                        (om/set-state! owner :invite-teammates? (not (:invite-teammates? (om/get-render-state owner)))))}
+                                         "Invite Teammates")]))}
                 (if-let [users (:users selected-org)]
                   (table (add-follow-counts users (:projects selected-org)))
                   (html [:div.loading-spinner common/spinner])))


Clean up invite-button-text fn

Clean up invite-button-text fn

--- src-cljs/frontend/components/pages/team.cljs
+++ src-cljs/frontend/components/pages/team.cljs
@@ -104,8 +104,8 @@
         vcs-users))

 (defn- invite-button-text [number-of-invites]
-  (case number-of-invites
-    0 "Send Invite"
+  (if (zero? number-of-invites)
+    "Send Invite"
     (gstr/format "Send %s %s"
                  number-of-invites
                  (inflections/pluralize number-of-invites "Invite"))))


ad for SSH

ad for SSH

--- frontend/components/build_head.cljs
+++ frontend/components/build_head.cljs
@@ -139,30 +139,49 @@
                 (om/build-all commit-line (drop 3 (map #(assoc % :build build)
                                                        (:all_commit_details build)))))))]])))))

-(defn build-ssh [nodes owner]
-  (reify
-    om/IRender
-    (render [_]
-      (html
-       [:div.ssh-info-container
-        [:div.build-ssh-title
-         [:p "You can SSH into this build. Use the same SSH public key that you use for GitHub. SSH boxes will stay up for 30 minutes."]
-         [:p "This build takes up one of your concurrent builds, so cancel it when you are done."]]
-        [:div.build-ssh-list
-         [:dl.dl-horizontal
-          (map (fn [node i]
-                 (list
-                  [:dt (when (< 1 (count nodes)) [:span (str "container " i " ")])]
-                  [:dd {:class (when (:ssh_enabled node) "connected")}
-                   [:span (gstring/format "ssh -p %s %s@%s " (:port node) (:username node) (:public_ip_addr node))]
-                   (when-not (:ssh_enabled node)
-                     [:span.loading-spinner common/spinner])]))
-               nodes (range))]]
-        [:div.build-ssh-doc
-         "Debugging Selenium browser tests? "
-         [:a {:href "/docs/browser-debugging#interact-with-the-browser-over-vnc"}
-          "Read our doc on interacting with the browser over VNC"]
-         "."]]))))
+(defn ssh-ad [build owner]
+  (let [build-id (build-model/id build)
+        vcs-url (:vcs_url build)
+        build-num (:build_num build)]
+    [:div.ssh-ad
+     [:p "Often the best way to troubleshoot problems is to ssh into a running or finished build to look at log files, running processes, and so on."]
+     (forms/stateful-button
+      [:button.ssh_build
+       {:data-loading-text "Starting SSH build...",
+        :title "Retry with SSH in VM",
+        :on-click #(raise! owner [:ssh-build-clicked {:build-id build-id
+                                                      :vcs-url vcs-url
+                                                      :build-num build-num}])}
+       "Retry this build with SSH enabled"])
+     [:p "More information " [:a {:href (routes/v1-doc-subpage {:subpage "ssh-build"})} "in our docs"] "."]]))
+
+(defn build-ssh [build owner]
+  (reify
+    om/IRender
+    (render [_]
+      (let [nodes (:node build)]
+        (html
+         (if-not (build-model/ssh-enabled-now? build)
+           (ssh-ad build owner)
+           [:div.ssh-info-container
+            [:div.build-ssh-title
+             [:p "You can SSH into this build. Use the same SSH public key that you use for GitHub. SSH boxes will stay up for 30 minutes."]
+             [:p "This build takes up one of your concurrent builds, so cancel it when you are done."]]
+            [:div.build-ssh-list
+             [:dl.dl-horizontal
+              (map (fn [node i]
+                     (list
+                      [:dt (when (< 1 (count nodes)) [:span (str "container " i " ")])]
+                      [:dd {:class (when (:ssh_enabled node) "connected")}
+                       [:span (gstring/format "ssh -p %s %s@%s " (:port node) (:username node) (:public_ip_addr node))]
+                       (when-not (:ssh_enabled node)
+                         [:span.loading-spinner common/spinner])]))
+                   nodes (range))]]
+            [:div.build-ssh-doc
+             "Debugging Selenium browser tests? "
+             [:a {:href "/docs/browser-debugging#interact-with-the-browser-over-vnc"}
+              "Read our doc on interacting with the browser over VNC"]
+             "."]]))))))

 (defn cleanup-artifact-path [path]
   (-> path
@@ -291,7 +310,7 @@
             user (:user data)
             logged-in? (not (empty? user))
             build (:build build-data)
-            show-ssh-info? (and logged-in? (utils/inspect (build-model/ssh-enabled-now? build)))
+            show-ssh-info? (and (has-scope :write-settings data) (build-model/ssh-enabled-now? build))
             ;; default to ssh-info for SSH builds if they haven't clicked a different tab
             selected-tab (get build-data :selected-header-tab (if show-ssh-info? :ssh-info :commits))
             build-id (build-model/id build)
@@ -330,7 +349,7 @@
                                                        :stop (or (:start_time build) (:stop_time build))})
                    ")"])]])

-            (when show-ssh-info?
+            (when (has-scope :write-settings data)
               [:li {:class (when (= :ssh-info selected-tab) "active")}
                [:a {:on-click #(raise! owner [:build-header-tab-clicked {:tab :ssh-info}])}
                 "SSH info"]])
@@ -366,7 +385,7 @@
              :usage-queue (om/build build-queue {:build build
                                                  :builds (:builds usage-queue-data)
                                                  :plan plan})
-             :ssh-info (om/build build-ssh (:node build)))]])))))
+             :ssh-info (om/build build-ssh build))]])))))

 (defn build-head [data owner]
   (reify


Arity checker just checks a list of argument-matchers against the actual value.

--- src/midje/checking/checkers/simple.clj
+++ src/midje/checking/checkers/simple.clj
@@ -24,7 +24,8 @@
   (not actual))
 (defalias FALSEY falsey)

-(defchecker & "Any arity" [])
+(defchecker & "Any arity" [actual argument-matchers]
+  (reduce #(extended-= actual %) argument-matchers))

 (defchecker anything
   "Accepts any value."


minor improvements

minor improvements

--- src/neversleep_clojure_client/core.clj
+++ src/neversleep_clojure_client/core.clj
@@ -25,16 +25,6 @@
     (s/connect stream-out-ch s)
     {:in stream-in-ch
      :out stream-out-ch}))
-
-(defn send-byte-array [^bytes b-a]
-  (let [stream-out-ch (:out @client)]
-    (if stream-out-ch
-      (>!! stream-out-ch b-a)
-      false)))
-
-(defn receive-byte-array []
-  (let [stream-in-ch (:in @client)]
-    (<!! stream-in-ch)))

 (def pending-requests (atom {}))
@@ -93,11 +83,6 @@
 (defn dispatch-to-type [value]
   (util/serialize value))

-(defn tcp-request-responce [{:keys [^bytes b-a request-uuid]}]
-  (send-byte-array b-a)
-  (let [responce (receive-byte-array)]
-    (clojure.walk/keywordize-keys (cheshire/decode (String. (byte-array responce))))))
-
 (def callback-count (atom 0))

 (defn callback-test [responce-data]
@@ -172,7 +157,10 @@

 (defn io-assoc
   ([^String entity-id key value]
-   (tcp-request-responce (io-assoc-base entity-id key value)))
+   (let [callback (chan 1)
+         {:keys [b-a request-uuid]} (io-assoc-base entity-id key value)]
+     (>!! tcp-request-ch {:b-a b-a :request-uuid request-uuid :callback callback})
+     (<!! callback)))
   ([^String entity-id key value callback]
    (let [{:keys [b-a request-uuid]} (io-assoc-base entity-id key value)]
      (>!! tcp-request-ch {:b-a b-a :request-uuid request-uuid :callback callback}))))
@@ -180,28 +168,42 @@

 (defn io-dissoc
   ([^String entity-id key]
-    (tcp-request-responce (io-dissoc-base entity-id key)))
+   (let [callback (chan 1)
+         {:keys [b-a request-uuid]} (io-dissoc-base entity-id key)]
+     (>!! tcp-responce-ch {:b-a b-a :request-uuid request-uuid :callback callback})
+     (<!! callback)))
   ([^String entity-id key callback]
    (let [{:keys [b-a request-uuid]} (io-dissoc-base entity-id key)]
      (>!! tcp-responce-ch {:b-a b-a :request-uuid request-uuid :callback callback}))))

 (defn io-get-key-as-of
   ([^String entity-id key timestamp]
-   (tcp-request-responce (io-get-key-as-of-base entity-id key timestamp)))
+   (let [callback (chan 1)
+         {:keys [b-a request-uuid]} (io-get-key-as-of-base entity-id key timestamp)]
+     (>!! tcp-request-ch {:b-a b-a :request-uuid request-uuid :callback callback})
+     (<!! callback)))
   ([^String entity-id key timestamp callback]
    (let [{:keys [b-a request-uuid]} (io-get-key-as-of-base entity-id key timestamp)]
      (>!! tcp-request-ch {:b-a b-a :request-uuid request-uuid :callback callback}))))

 (defn io-get-entity-as-of
   ([^String entity-id timestamp]
-    (tcp-request-responce (io-get-entity-as-of-base entity-id timestamp)))
+   (let [callback (chan 1)
+         {:keys [b-a request-uuid]} (io-get-entity-as-of-base entity-id timestamp)]
+     (>!! tcp-request-ch {:b-a b-a :request-uuid request-uuid :callback callback})
+     (<!! callback)))
   ([^String entity-id timestamp callback]
    (let [{:keys [b-a request-uuid]} (io-get-entity-as-of-base entity-id timestamp)]
      (>!! tcp-request-ch {:b-a b-a :request-uuid request-uuid :callback callback}))))

 (defn io-get-all-versions-between
   ([^String entity-id timestamp-start timestamp-end limit]
-    (tcp-request-responce (io-get-all-versions-between-base entity-id timestamp-start timestamp-end limit)))
+   (let [callback (chan 1)
+         {:keys [b-a request-uuid]} (io-get-all-versions-between-base entity-id timestamp-start timestamp-end limit)]
+     (>!! tcp-request-ch {:b-a      b-a
+                          :request-uuid request-uuid
+                          :callback callback})
+     (<!! callback)))
   ([^String entity-id timestamp-start timestamp-end limit callback]
    (let [{:keys [b-a request-uuid]} (io-get-all-versions-between-base entity-id timestamp-start timestamp-end limit)]
      (>!! tcp-request-ch {:b-a      b-a


stub functions

stub functions

--- src/video_feed_transformer/transform_feed.clj
+++ src/video_feed_transformer/transform_feed.clj
@@ -51,6 +51,16 @@

 (defn- find-closest-match-by-argb-l2 [img-argb corpus-argb]
   "")
+
+(defn- step-with-new-frame [frame]
+  "")
+
+(defn- persist-frame [frame]
+  "")
+
+(defn- re-mosaic [new-frame]
+  "")
+

 (defn- move-file [src-file dest-dir] ""
   (fs/copy+ src-file dest-dir))


Separate handle-selected from handle-editing

--- src/constraint/edit.cljs
+++ src/constraint/edit.cljs
@@ -10,7 +10,7 @@
     (map - click-position rect-position)))

-(defn move-the-vertex [world-state event]
+(defn move-the-vertex [event world-state]
   (let [moving (:selected world-state)
         position-to-update [:vertices moving 1]
         where (where-svg-was-clicked event)]
@@ -62,14 +62,20 @@
       (toggle-vertex-size selected world-state)
       (add-or-delete-edge selected clicked-vertex world-state))))

+
+(defn handle-selected [clicked-what event world-state]
+  (let [clicked-vertex? (re-matches #"vertex.*" clicked-what)]
+    (if clicked-vertex?
+      (edit-vertex-or-connections clicked-what world-state)
+      (move-the-vertex event world-state))))
+
+
 (defn handle-editing [clicked-what event world-state]
-  (let [clicked-edge? (re-matches #"edge.*" clicked-what)
-        clicked-vertex? (re-matches #"vertex.*" clicked-what)]
+  (let [unselect #(merge % {:selected nil})
+        clicked-edge? (re-matches #"edge.*" clicked-what)
+        clicked-vertex? (re-matches #"vertex.*" clicked-what) ]
     (if (:selected world-state)
-      (merge (if clicked-vertex?
-               (edit-vertex-or-connections clicked-what world-state)
-               (move-the-vertex world-state event))
-        {:selected nil})
+      (unselect (handle-selected clicked-what event world-state))
       (cond
         clicked-edge? (update-in world-state [:edges clicked-what 2]
                                  #(if (= :blue %) :red :blue))


Fix syntax error introduced by previous merge

--- test/clj/lambdacd/internal/execution_test.clj
+++ test/clj/lambdacd/internal/execution_test.clj
@@ -10,9 +10,7 @@
             [lambdacd.testsupport.test-util :as tu]
             [lambdacd.execution.internal.execute-steps :as execute-steps]
             [clj-time.core :as t]
-            [lambdacd.internal.execution :as execution]
             [lambdacd.state.core :as state]
-            [lambdacd.util :as util]
             [lambdacd.execution.internal.execute-step :as execute-step]
             [lambdacd.util.internal.temp :as temp-util])
   (:import java.lang.IllegalStateException))


Clean up sites list tests

Clean up sites list tests

Use the idiom of `sut' to refer to the ns being tested.

--- test/cljs/comic_reader/ui/site_list_test.cljs
+++ test/cljs/comic_reader/ui/site_list_test.cljs
@@ -3,18 +3,18 @@
             [devcards.core :refer-macros [deftest defcard-rg]]
             [re-frame.core :as re-frame]
             [comic-reader.ui.base :as base]
-            [comic-reader.ui.site-list :as ui]
+            [comic-reader.ui.site-list :as sut]
             [comic-reader.test-helper :refer [strip-classes]]))

-(ui/setup-site-list!)
+(sut/setup-site-list!)

 (deftest test-site-list
   (is (= [:div [:h1 "Comic Sites"]]
-         (ui/site-list nil)))
+         (sut/site-list nil)))

   (is (= [:div [:h1 "Comic Sites"]
           [base/loading]]
-         (ui/site-list :loading)))
+         (sut/site-list :loading)))

   (is (= [:div [:h1 "Comic Sites"]
           [:ul
@@ -22,12 +22,12 @@
            [:li [base/large-button "B"]]
            [:li [base/large-button "C"]]]]
          (strip-classes
-          (ui/site-list [{:name "A" :id "a"}
+          (sut/site-list [{:name "A" :id "a"}
                          {:name "B" :id "b"}
                          {:name "C" :id "c"}])))))

 (deftest test-set-site-list
-  (is (= (ui/set-site-list {} [:site-site-list []])
+  (is (= (sut/set-site-list {} [:_ []])
          {:site-list []})))

 (defcard-rg site-list
@@ -35,4 +35,4 @@
     (re-frame/dispatch [:set-site-list
                         [{:id :a :name "Comic A"}
                          {:id :b :name "Comic B"}]])
-    [ui/site-list-container]))
+    [sut/site-list-container]))


Use soft-masking trick to antialias hue gauge.

Wow, it looks so much better now. Next stop, saturation gauge.

--- src/afterglow/controllers/ableton_push_2.clj
+++ src/afterglow/controllers/ableton_push_2.clj
@@ -765,6 +765,47 @@
     (.setAngleExtent arc 0.0)
     (.draw graphics arc)))

+(defonce ^:private
+  ^{:doc "The circle of hues around which a hue gauge indicator
+  rolls. This is a constant image regardless of the current hue,
+  so we can draw it once and reuse it."}
+  hue-track
+  (let [gauge-image (java.awt.image.BufferedImage. 50 50 java.awt.image.BufferedImage/TYPE_INT_ARGB)
+        gauge-graphics (.createGraphics gauge-image)
+        mask-image (java.awt.image.BufferedImage. 50 50 java.awt.image.BufferedImage/TYPE_INT_ARGB)
+        mask-graphics (.createGraphics mask-image)
+        arc (java.awt.geom.Arc2D$Double. 5.0 5.0 40.0 40.0 270.0 -5.0 java.awt.geom.Arc2D/OPEN)]
+
+    ;; Color "outside the lines" that we will be masking so the mask can smoothe the edges
+    (.setStroke gauge-graphics (java.awt.BasicStroke. 5.0 java.awt.BasicStroke/CAP_ROUND
+                                                      java.awt.BasicStroke/JOIN_ROUND))
+    (dotimes [i 72]  ; Draw the circle of hues
+      (.setAngleStart arc (- 270.0 (* i 5)))
+      (set-graphics-color gauge-graphics (colors/create-color :h (* i 5) :s 100.0 :l 50.0))
+      (.draw gauge-graphics arc))
+
+    ;; Draw a mask we can use to soft clip the color hue track. Start by clearing it so all pixels have zero alpha.
+    (.setComposite mask-graphics java.awt.AlphaComposite/Clear)
+    (.fillRect mask-graphics 0 0 50 50)
+
+    ;; Render the gauge track mask, an anti-aliased circle
+    (.setComposite mask-graphics java.awt.AlphaComposite/Src)
+    (.setRenderingHint mask-graphics java.awt.RenderingHints/KEY_ANTIALIASING
+                       java.awt.RenderingHints/VALUE_ANTIALIAS_ON)
+    (.setColor mask-graphics java.awt.Color/WHITE)
+    (.draw mask-graphics (java.awt.geom.Ellipse2D$Double. 5.0 5.0 40.0 40.0))
+
+    ;; Render the track into the mask using SrcAtop, which effectively uses the alpha value as
+    ;; a covereage value for each pixel stored in the destination. For the areas outside our clip
+    ;; shape, the destination alpha will be zero, so nothing is rendered in those areas. For the
+    ;; areas inside our clip shape, the destination alpha will be fully opaque, so the full color
+    ;; is rendered. At the edges, the original antialiasing is carried over to give us the desired
+    ;; soft clipping effect.
+    (.setComposite mask-graphics java.awt.AlphaComposite/SrcAtop)
+    (.drawImage mask-graphics gauge-image 0 0 nil)
+
+    mask-image))  ; Return the masked track image
+
 (defn draw-hue-gauge
   "Draw a graphical gauge whose colors are the hues of the color
   circle, with an indicator that rides around an circle (starting at
@@ -772,17 +813,16 @@
   [controller index encoder-count value active?]
   (let [graphics (create-graphics controller)
         x-center (+ (* index button-cell-width) (* encoder-count 0.5 button-cell-width))
-        arc (java.awt.geom.Arc2D$Double. (- x-center 20.0) 50.0 40.0 40.0 270.0 -5.0 java.awt.geom.Arc2D/OPEN)]
-    (dotimes [i 72]
-      (.setAngleStart arc (- 270.0 (* i 5)))
-      (set-graphics-color graphics (colors/create-color :h (* i 5) :s 100.0 :l 50.0))
-      (.draw graphics arc))
+        arc (java.awt.geom.Arc2D$Double. (- x-center 20.0) 50.0 40.0 40.0 (- 270.0 value) 0.0 java.awt.geom.Arc2D/OPEN)]
+
+    ;; Draw the precomputed hue track image
+    (.drawImage graphics hue-track (math/round (- x-center 25)) 45 nil)
+
+    ;; Then draw the larger knob at the current hue value
     (.setStroke graphics (java.awt.BasicStroke. 6.0 java.awt.BasicStroke/CAP_ROUND java.awt.BasicStroke/JOIN_ROUND))
     (if active?
       (set-graphics-color graphics (colors/create-color :h value :s 100.0 :l 50.0))
       (set-graphics-color graphics (colors/create-color :h value :s 100.0 :l 25.0)))
-    (.setAngleStart arc (- 270.0 value))
-    (.setAngleExtent arc 0.0)
     (.draw graphics arc)))

 (defn draw-saturation-gauge


template function can resolve prefs

template function can resolve prefs

--- src/devtools/format.cljs
+++ src/devtools/format.cljs
@@ -23,11 +23,14 @@
     (aget config "prevent-recursion")))

 (defn template [tag style & children]
-  (let [js-array #js [tag (if (empty? style) #js {} #js {"style" style})]]
+  (let [resolve-pref (fn [pref-or-val] (if (keyword? pref-or-val) (pref pref-or-val) pref-or-val))
+        tag (resolve-pref tag)
+        style (resolve-pref style)
+        js-array #js [tag (if (empty? style) #js {} #js {"style" style})]]
     (doseq [child children]
       (if (coll? child)
         (.apply (aget js-array "push") js-array (into-array child)) ; convenience helper to splat cljs collections
-        (.push js-array child)))
+        (.push js-array (resolve-pref child))))
     js-array))

 (defn reference
@@ -41,17 +44,17 @@
    (js-obj
      (pref :surrogate-key) true
      "target" object
-     "header" (template (pref :span) (pref :cljs-style) header)
+     "header" (template :span :cljs-style header)
      "hasBody" has-body
      "bodyTemplate" body-template)))

 (defn index-template [value]
-  (template (pref :span) (pref :index-style) value (pref :line-index-separator)))
+  (template :span :index-style value :line-index-separator))

 (defn number-template [value]
   (if (integer? value)
-    (template (pref :span) (pref :integer-style) value)
-    (template (pref :span) (pref :float-style) value)))
+    (template :span :integer-style value)
+    (template :span :float-style value)))

 (defn abbreviate-long-string [string]
   (str
@@ -65,12 +68,12 @@
         inline-string (.replace source-string re-nl (pref :new-line-string-replacer))
         max-inline-string-size (+ (pref :string-prefix-limit) (pref :string-postfix-limit))]
     (if (<= (count inline-string) max-inline-string-size)
-      (template (pref :span) (pref :string-style) (str dq inline-string dq))
-      (let [abbreviated-string-template (template (pref :span) (pref :string-style) (str dq (abbreviate-long-string inline-string) dq))
+      (template :span :string-style (str dq inline-string dq))
+      (let [abbreviated-string-template (template :span :string-style (str dq (abbreviate-long-string inline-string) dq))
             string-with-nl-markers (.replace source-string re-nl (str (pref :new-line-string-replacer) "\n"))
-            body-template (template (pref :ol) (pref :standard-ol-style)
-                            (template (pref :li) (pref :standard-li-style)
-                              (template (pref :span) (pref :string-style) (str dq string-with-nl-markers dq))))]
+            body-template (template :ol :standard-ol-style
+                            (template :li :standard-li-style
+                              (template :span :string-style (str dq string-with-nl-markers dq))))]
         (reference (surrogate source-string abbreviated-string-template true body-template))))))

 (defn bool? [value]
@@ -78,13 +81,13 @@

 (defn atomic-template [value]
   (cond
-    (nil? value) (template (pref :span) (pref :nil-style) (pref :nil-label))
-    (bool? value) (template (pref :span) (pref :bool-style) value)
+    (nil? value) (template :span :nil-style :nil-label)
+    (bool? value) (template :span :bool-style value)
     (string? value) (string-template value)
     (number? value) (number-template value)
-    (keyword? value) (template (pref :span) (pref :keyword-style) (str value))
-    (symbol? value) (template (pref :span) (pref :symbol-style) (str value))
-    (fn? value) (template (pref :span) (pref :fn-style) (reference value))))
+    (keyword? value) (template :span :keyword-style (str value))
+    (symbol? value) (template :span :symbol-style (str value))
+    (fn? value) (template :span :fn-style (reference value))))

 (defn abbreviated? [template]
   (some #(= (pref :more-marker) %) template))
@@ -98,7 +101,7 @@

 (defn wrap-group-in-reference-if-needed [group obj]
   (if (abbreviated? group)
-    #js [(reference (surrogate obj (.concat (template (pref :span) "") group)))]
+    #js [(reference (surrogate obj (.concat (template :span "") group)))]
     group))

 ; default printer implementation can do this:
@@ -125,7 +128,7 @@
       (.merge writer (wrap-group-in-reference-if-needed inner-tmpl obj) obj))))

 (defn managed-pr-str [value style print-level]
-  (let [tmpl (template (pref :span) style)
+  (let [tmpl (template :span style)
         writer (TemplateWriter. tmpl)]
     (binding [*print-level* print-level]                    ; when printing do at most print-level deep recursion
       (pr-seq-writer [value] writer {:alt-impl     alt-printer-impl
@@ -134,16 +137,16 @@
     tmpl))

 (defn build-header [value]
-  (managed-pr-str value (pref :cljs-style) (inc (pref :max-print-level))))
+  (managed-pr-str value :cljs-style (inc (pref :max-print-level))))

 (defn standard-body-template
-  ([lines margin?] (let [ol-style (if margin? (pref :standard-ol-style) (pref :standard-ol-no-margin-style))
-                         li-style (if margin? (pref :standard-li-style) (pref :standard-li-no-margin-style))]
-                     (template (pref :ol) ol-style (map #(template (pref :li) li-style %) lines))))
+  ([lines margin?] (let [ol-style (if margin? :standard-ol-style :standard-ol-no-margin-style)
+                         li-style (if margin? :standard-li-style :standard-li-no-margin-style)]
+                     (template :ol ol-style (map #(template :li li-style %) lines))))
   ([lines] (standard-body-template lines true)))

 (defn body-line-template [index value]
-  [(index-template index) (pref :spacer) (managed-pr-str value (if cljs-value? (pref :cljs-style) "") 3)])
+  [(index-template index) (pref :spacer) (managed-pr-str value (if cljs-value? :cljs-style "") 3)])

 (defn prepare-body-lines [data starting-index]
   (loop [work data
@@ -176,7 +179,7 @@
       (if (seqable? target)
         (let [starting-index (or (aget value "startingIndex") 0)]
           (build-body target starting-index))
-        (template (pref :ol) (pref :standard-ol-style) (template (pref :li) (pref :standard-li-style) (reference target)))))))
+        (template :ol :standard-ol-style (template :li :standard-li-style (reference target)))))))

 ;;;;;;;;; PROTOCOL SUPPORT


Refer some functions form the 'extended' ns

--- src/cljs/cglossa/search_inputs/cwb/core.cljs
+++ src/cljs/cglossa/search_inputs/cwb/core.cljs
@@ -4,7 +4,10 @@
             [goog.dom :as dom]
             [cglossa.search-inputs.cwb.shared :refer [on-key-down search!
                                                       remove-row-btn]]
-            [cglossa.search-inputs.cwb.extended :as ext :refer [interval multiword-term]]))
+            [cglossa.search-inputs.cwb.extended :refer [interval multiword-term
+                                                        split-query
+                                                        construct-query-terms
+                                                        wrapped-term-changed]]))

 (def ^:private headword-query-prefix "<headword>")
 (def ^:private headword-query-suffix-more-words "[]{0,}")
@@ -67,14 +70,13 @@

 (defn- wrapped-query-changed [queries index query]
   "Takes a changed query, performs some cleanup on it, and swaps it into
-  the appropriate position in the vector of queries that constitute the
+  the appropriate position in the vector of queries that constitutes the
   current search."
   (let [query* (as-> (:query query) $
-                     (if (get-in @queries [index :headword-search])
+                     (if (:headword-search query)
                        (->headword-query $)
                        (->non-headword-query $))
-                     ;; Simplify the query (".*" is used in the
-                     ;; simplified search instead of [])
+                     ;; Simplify the query (".*" is used in the simple search instead of [])
                      (str/replace $ #"\[\(?word=\"\.\*\"(?:\s+%c)?\)?\]" "[]")
                      (str/replace $ #"^\s*\[\]\s*$" ""))]
     (swap! queries assoc-in [index :query] query*)
@@ -179,8 +181,8 @@
   "Search view component with text inputs, checkboxes and menus
   for easily building complex and grammatically specified queries."
   [corpus wrapped-query show-remove-row-btn? remove-row-handler]
-  (let [parts           (ext/split-query (:query @wrapped-query))
-        terms           (ext/construct-query-terms parts)
+  (let [parts           (split-query (:query @wrapped-query))
+        terms           (construct-query-terms parts)
         last-term-index (dec (count terms))]
     (.log js/console (str terms))
     [:div.multiword-container


Fixed typo.

Fixed typo.

--- src/cljs/clj_templates/pages/about/page.cljs
+++ src/cljs/clj_templates/pages/about/page.cljs
@@ -9,7 +9,7 @@
     While Clojars has its own search function, clj-templates makes it easier to find project
      templates by searching only the template population rather than all artficats. In addition,
      it indexes any GitHub README:s that the template has, thereby making it possible to search any
-     term mentioned in either the template name, it's description, or its GitHub README. This enables
+     term mentioned in either the template name, its description, or its GitHub README. This enables
      searching for technologies and other topics, such as \"sass\", \"music\", or \"game\"."]

    [:div.question "Which templates work with which build system?"]


Retrieve recurring expenses after upload

--- src/cljs/my_money/app/controller/upload.cljs
+++ src/cljs/my_money/app/controller/upload.cljs
@@ -19,7 +19,8 @@
   UploadFinished
   (process-event [{response :response} app]
     (tuck/action! (fn [e!]
-                    (e! (ec/->RetrieveEvents))))
+                    (e! (ec/->RetrieveEvents))
+                    (e! (ec/->RetrieveRecurringExpenses))))
     (session/update! :alerts conj {:string    (str "Added " response " events")
                                    :timestamp (.getTime (js/Date.))})
     (session/remove! :modal)


Improve header look a little

Improve header look a little

Still a bit too static so it’ll look bad at times

--- src/cljs/onyx_dashboard/components/main.cljs
+++ src/cljs/onyx_dashboard/components/main.cljs
@@ -28,11 +28,14 @@
                    (g/row {}
                           (r/page-header {:class "page-header, main-header"}
                                          (g/grid {}
-                                                 (g/col {:xs 8 :md 2}
+                                                 (g/col {:xs 4 :md 2}
                                                         (dom/a {:href "https://github.com/MichaelDrogalis/onyx"}
-                                                               (dom/img {:class "logo" :src "/img/high-res.png" :height "50%" :width "50%"})))
+                                                               (dom/img {:class "logo"
+                                                                         :src "/img/high-res.png"
+                                                                         :height "50%"
+                                                                         :width "50%"})))
                                                  (g/col {:xs 12 :md 8}
-                                                        (dom/div {:style {:margin-top "50px" :margin-left "200px" :font-size "50px"}}
+                                                        (dom/div {:style {:font-size "50px"}}
                                                                  "Onyx Dashboard")))))
                     (g/grid {}
                             (g/row {}


name that function

name that function

--- src/cljx/jamesmacaulay/async_tools/core.cljx
+++ src/cljx/jamesmacaulay/async_tools/core.cljx
@@ -30,12 +30,13 @@
 (defn- async-future-state-atom
   [f]
   (let [state-atom (atom {:boxed-value nil
-                          :handlers []})]
-    (f (fn [value]
-         (let [state (swap! state-atom assoc :boxed-value (channels/box value))]
-           (doseq [handler (:handlers state)]
-             ((impl/commit handler) value))
-           (swap! state-atom dissoc :handlers))))
+                          :handlers []})
+        resolve! (fn [value]
+                   (let [state (swap! state-atom assoc :boxed-value (channels/box value))]
+                     (doseq [handler (:handlers state)]
+                       ((impl/commit handler) value))
+                     (swap! state-atom dissoc :handlers)))]
+    (f resolve!)
     state-atom))

 (defrecord AsyncFuture [state-atom]


PCP-147 Add unit test for process-inventory-message

Here we add a missing unit test for process-inventory-message

--- test/unit/puppetlabs/pcp/broker/core_test.clj
+++ test/unit/puppetlabs/pcp/broker/core_test.clj
@@ -277,6 +277,17 @@
             (is (= :associated (:state connection)))
             (is (= ["ws" 4002 "association unsuccessful"] @@closed))))))))

+(deftest process-inventory-message-test
+  (let [broker (make-test-broker)
+        message (-> (message/make-message :sender "pcp://test.example.com/test")
+                    (message/set-json-data  {:query ["pcp://*/*"]}))
+        capsule (capsule/wrap message)
+        connection (connection/make-connection "ws1")
+        accepted (atom nil)]
+    (with-redefs [puppetlabs.pcp.broker.core/accept-message-for-delivery (fn [broker capsule] (reset! accepted capsule))]
+      (process-inventory-message broker capsule connection)
+      (is (= [] (:uris (message/get-json-data (:message @accepted))))))))
+
 (deftest validate-certname-test
   (testing "simple match, no exception"
     (is (validate-certname "pcp://lolcathost/agent" "lolcathost")))


fix wrong hashmap on validate

fix wrong hashmap on validate

--- src/dwc_services/api.clj
+++ src/dwc_services/api.clj
@@ -65,7 +65,7 @@

   (POST "/validate" req
     (if-let [data (:body req)]
-      (safe #({:headers {"Content-Type" "application/json"} :body ( write-str (validation data) ) }))
+      (safe #(write-str (validation data)))
       {:status 400 :body "Must provide occurrence json of data as input."}))

   (GET "/fix" {params :params}


clojure: small fixes in graphs.clj

clojure: small fixes in graphs.clj

--- clojure/org/gavrog/clojure/common/graphs.clj
+++ clojure/org/gavrog/clojure/common/graphs.clj
@@ -20,7 +20,7 @@
   "Performs a lazy breadth first traversal of the directed graph determined by
   the list 'sources' of source nodes and the adjacency function 'adj'."
   ([adj & sources]
-    (traversal adj #{} (into empty-queue sources) conj first pop)))
+    (traversal adj #{} (into util/empty-queue sources) conj first pop)))

 (defn bfs-radius [adj source]
   (loop [seen #{source}, maxdist 0, q (conj util/empty-queue [source 0])]
@@ -38,7 +38,8 @@
 (defn bfs-shells [adj source]
   (let [next
         (fn [[prev this]]
-          [this (set (for [u this, v (adj u) :when (not (prev v))] v))])]
+          [this (set (for [u this, v (adj u)
+                           :when (not (or (this v) (prev v)))] v))])]
     (conj
       (map second (iterate next [#{source} (set (adj source))]))
       #{source})))


Adds spec to function

Adds spec to function

--- src/expound/alpha.cljc
+++ src/expound/alpha.cljc
@@ -1095,10 +1095,14 @@
   (swap! registry-ref assoc k error-message)
   nil)

+(s/fdef undefmsg
+  :args (s/cat :k qualified-keyword?)
+  :ret nil?)
 (defn undefmsg
-  "dissociate the message for spec named `k`"
+  "Dissociate the message for spec named `k`."
   [k]
-  (swap! registry-ref dissoc k))
+  (swap! registry-ref dissoc k)
+  nil)

 #?(:clj
    (defmacro def


skip denorm upserts if unnecessary

skip denorm upserts if unnecessary

--- src/er_cassandra/model/alia/relationship.clj
+++ src/er_cassandra/model/alia/relationship.clj
@@ -16,7 +16,8 @@
    [er-cassandra.model.types :as t]
    [er-cassandra.model.error :as e]
    [er-cassandra.model.alia.fn-schema :as fns]
-   [er-cassandra.model.util :refer [combine-responses create-lookup-record]])
+   [er-cassandra.model.util :refer [combine-responses create-lookup-record]]
+   [taoensso.timbre :refer [info warn]])
   (:import
    [er_cassandra.model.types Entity]
    [er_cassandra.model.model_session ModelSession]))
@@ -103,11 +104,18 @@
       :upsert
       (let [new-target-record (merge denorm-vals
                                      fk-map
-                                     target-uberkey-map)]
-        (m/upsert session
-                  target-entity
-                  new-target-record
-                  (fns/denormalize-opts->upsert-opts opts)))
+                                     target-uberkey-map)
+            otr (select-keys
+                 target-record
+                 (keys new-target-record))]
+        (if (= otr new-target-record)
+          (do
+            ;; (warn "skipping update")
+            (return deferred-context true)) ;; nothing to update
+          (m/upsert session
+                    target-entity
+                    new-target-record
+                    (fns/denormalize-opts->upsert-opts opts))))

       :delete
       (let [cascade (:cascade denorm-rel)]
@@ -123,11 +131,16 @@
                                       (into {}))
                 new-target-record (merge null-denorm-vals
                                          fk-map
-                                         target-uberkey-map)]
-            (m/upsert session
-                      target-entity
-                      new-target-record
-                      (fns/denormalize-opts->upsert-opts opts)))
+                                         target-uberkey-map)
+                otr (select-keys
+                     target-record
+                     (keys new-target-record))]
+            (if (= otr new-target-record)
+              (return deferred-context true) ;; nothing to update
+              (m/upsert session
+                        target-entity
+                        new-target-record
+                        (fns/denormalize-opts->upsert-opts opts))))

           :delete
           (m/delete session


nix the mongoose test

nix the mongoose test

--- clojure/src/hello_world/core.cljs
+++ clojure/src/hello_world/core.cljs
@@ -5,18 +5,8 @@
     )
   )

-(def mongoose (nodejs/require "mongoose"))
-(.connect mongoose "mongodb://localhost/test")
-(defonce Cat (.model mongoose "cat" #js {:name js/String}))
-
-(defn crap []
-  (let [kitty (Cat. #js {:name "Interesting" :size 200 })
-        promise (.save kitty)]
-    (.then promise (fn [& args]
-                     (println args)))))
-
 (nodejs/enable-util-print!)

-(defn -main [] (show/demo))
+(defn -main [] nil)

 (set! *main-cli-fn* -main)


simplify tokenization by using a diff regex and re-seq instead of \W.

--- clojure/word-count/word-count.clj
+++ clojure/word-count/word-count.clj
@@ -1,11 +1,7 @@
-(ns phrase
-  (:use [clojure.string :only [lower-case split blank?]]))
+(ns phrase)

-(defn- tokenize [str]
-  (split (lower-case str) #"\W"))
+(defn- tokenize [s]
+  (re-seq #"\w+" (clojure.string/lower-case s)))

-(defn- filter-words [str]
-  (remove blank? (tokenize str)))
-
-(defn word-count [str]
-  (frequencies (filter-words str)))
+(defn word-count [s]
+  (frequencies (tokenize s)))


Enable sass. Disable less

Enable sass. Disable less

--- build.boot
+++ build.boot
@@ -96,11 +96,13 @@
     (comp
      (watch)
      (speak :theme "ordinance")
-     #_(sass :sass-file "app.scss"
-           :output-dir "."
-           :line-numbers true
-           :source-maps true)
      (with-env
+       {:directories #{"sass"}}
+       (sass :sass-file "app.scss"
+             :output-dir "."
+             :line-numbers true
+             :source-maps true))
+     #_(with-env
        {:directories #{"sass"}}
        (less :source-map true))
      (reload :on-jsload 'edge.main/init)


Changed version 0.0.1

Changed version 0.0.1

--- build.boot
+++ build.boot
@@ -5,7 +5,7 @@
     (list)
     s))

-(def version "0.0.1-SNAPSHOT")
+(def version "0.0.1")
 (def prefix "META-INF/resources")
 (def distribution-path (str prefix "/webjars/collie/" version "/dist/"))
 (def js-distribution-path (str distribution-path "js/"))


Option for running tests with different optimiztation levels

--- build.boot
+++ build.boot
@@ -22,9 +22,10 @@
        :license     {"EPL" "http://www.eclipse.org/legal/epl-v10.html"}})

 (deftask run-tests
-  [j junit-output-to JUNIT str ""]
+  [O optimizations   LEVEL kw  "Compiler optimization level."
+   j junit-output-to JUNIT str "Test report destination."]
   (comp (serve)
-        (cljs :optimizations :whitespace)
+        (cljs :optimizations (or optimizations :whitespace))
         (test :namespaces #{'adzerk.boot-cljs-test 'adzerk.boot-cljs.util-test}
               :junit-output-to junit-output-to)))


Updated deps

Updated deps

--- build.boot
+++ build.boot
@@ -1,20 +1,20 @@
 (set-env!
   :source-paths #{"src/cljs" "src/cljx" "src/less"}
   :resource-paths #{"src/clj"}
-  :dependencies '[[adzerk/boot-cljs       "0.0-2411-5"]
+  :dependencies '[[adzerk/boot-cljs       "0.0-2629-1"]
                   [adzerk/boot-cljs-repl  "0.1.7"]
-                  [adzerk/boot-reload     "0.2.1"]
+                  [adzerk/boot-reload     "0.2.3"]
                   [deraen/boot-cljx       "0.2.1"]
                   [deraen/boot-less       "0.2.0"]
-                  [cljsjs/boot-cljsjs     "0.3.0"]
+                  [cljsjs/boot-cljsjs     "0.3.1"]

                   [org.clojure/clojure "1.6.0"]
                   [org.clojure/tools.namespace "0.2.8"]
-                  [ring "1.3.1"]
+                  [ring "1.3.2"]
                   [metosin/ring-http-response "0.5.2"]
-                  [compojure "1.2.1"]
-                  [om "0.8.0-beta5" :exclusions [com.facebook/react]]
-                  [cljsjs/react "0.12.2-1"]
+                  [compojure "1.3.1"]
+                  [om "0.8.0-rc1" :exclusions [com.facebook/react]]
+                  [cljsjs/react "0.12.2-2"]
                   [http-kit "2.1.19"]
                   [org.webjars/bootstrap "3.3.1"]])

@@ -22,7 +22,7 @@
   '[adzerk.boot-cljs      :refer :all]
   '[adzerk.boot-cljs-repl :refer :all]
   '[adzerk.boot-reload    :refer :all]
-  '[cljsjs.app            :refer :all]
+  '[cljsjs.boot-cljsjs    :refer :all]
   '[deraen.boot-cljx      :refer :all]
   '[deraen.boot-less      :refer :all]
   '[saapas.boot           :refer :all])


Add a "boot release" task to generate optimized JS/CSS

--- build.boot
+++ build.boot
@@ -36,3 +36,10 @@
           :optimizations :none
           :compiler-options {:devcards true})
     (serve :dir "target")))
+
+(deftask release
+  []
+  (comp
+    (less :compression true)
+    (cljs :optimizations :advanced
+          :compiler-options {:devcards true})))


Fix deployment problem

Fix deployment problem

--- build.boot
+++ build.boot
@@ -1,5 +1,4 @@
 (set-env!
- :resource-paths #{"resources"}
  :source-paths #{"src/clj" "src/cljs"}
  :dependencies '[[adzerk/boot-cljs "1.7.228-1"]
                  [adzerk/boot-reload "0.4.12"]
@@ -41,7 +40,7 @@

 (deftask build []
   (comp
-   #_ (cljs :optimizations :advanced)
+   (cljs :optimizations :advanced)
    (css)
    (aot :namespace '#{chili-dog-night.core})
    (pom :project 'chili-dog-night


Update reagent dependency

Update reagent dependency

--- build.boot
+++ build.boot
@@ -21,7 +21,7 @@
                  ;; Dev deps
                  [org.clojure/clojure         "1.7.0"]
                  [org.clojure/clojurescript   "1.7.228"]
-                 [reagent                     "0.5.0"]
+                 [reagent                     "0.6.0-alpha"]
                  [re-frame                    "0.7.0-alpha-3"]])

 (require


Boot plugin dependencies in test scope

Boot plugin dependencies in test scope

--- build.boot
+++ build.boot
@@ -1,12 +1,12 @@
 (set-env!
   :source-paths #{"src/cljs" "src/cljx" "src/less"}
   :resource-paths #{"src/clj"}
-  :dependencies '[[adzerk/boot-cljs       "0.0-2629-1"]
-                  [adzerk/boot-cljs-repl  "0.1.7"]
-                  [adzerk/boot-reload     "0.2.3"]
-                  [deraen/boot-cljx       "0.2.1"]
-                  [deraen/boot-less       "0.2.0"]
-                  [cljsjs/boot-cljsjs     "0.3.1"]
+  :dependencies '[[adzerk/boot-cljs       "0.0-2629-1" :scope "test"]
+                  [adzerk/boot-cljs-repl  "0.1.7"      :scope "test"]
+                  [adzerk/boot-reload     "0.2.3"      :scope "test"]
+                  [deraen/boot-cljx       "0.2.1"      :scope "test"]
+                  [deraen/boot-less       "0.2.0"      :scope "test"]
+                  [cljsjs/boot-cljsjs     "0.4.0"      :scope "test"]

                   [org.clojure/clojure "1.6.0"]
                   [org.clojure/tools.namespace "0.2.8"]
@@ -14,7 +14,7 @@
                   [metosin/ring-http-response "0.5.2"]
                   [compojure "1.3.1"]
                   [om "0.8.0-rc1" :exclusions [com.facebook/react]]
-                  [cljsjs/react "0.12.2-2"]
+                  [cljsjs/react "0.12.2-3"]
                   [http-kit "2.1.19"]
                   [org.webjars/bootstrap "3.3.1"]])


0.0-2411-4 -- Emit output as resources

0.0-2411-4 -- Emit output as resources

--- build.boot
+++ build.boot
@@ -6,7 +6,7 @@

 (require '[adzerk.bootlaces :refer :all])

-(def +version+ "0.0-2411-3")
+(def +version+ "0.0-2411-4")

 (bootlaces! +version+)


Formatting

Formatting

--- modules/less/src/modular/less.clj
+++ modules/less/src/modular/less.clj
@@ -72,12 +72,12 @@
   (assert (io/resource (format "META-INF/resources/webjars/bootstrap/%s/less/bootstrap.less" version))
           "Bootstrap resources not found on classpath")
   (->> opts
-       (merge {:engine :nashorn
-               :resource-dir "resources/less"
-               :version version
-               :target-path "target/css/bootstrap.css"})
-       (s/validate {:engine (s/enum :javascript :rhino :nashorn)
-                    :resource-dir s/Str
-                    :version s/Str
-                    :target-path s/Str})
-       map->CustomBootstrapLessCompiler))
+    (merge {:engine :nashorn
+            :resource-dir "resources/less"
+            :version version
+            :target-path "target/css/bootstrap.css"})
+    (s/validate {:engine (s/enum :javascript :rhino :nashorn)
+                 :resource-dir s/Str
+                 :version s/Str
+                 :target-path s/Str})
+    map->CustomBootstrapLessCompiler))


changed min cut comment

changed min cut comment

--- src/gecf/connected.clj
+++ src/gecf/connected.clj
@@ -18,11 +18,7 @@
   (apply min-key first (#(if (empty? %) [[-1 :empty]] %) (max-flows g))))

-
-
-;; def: min-cut
-
-#_"
+#_"  min cut

 DFS: stop on saturated, remeber them (it's cut)
  - nonsaturated: recursively repeat


Message queue: add handler-fn interpretable return TODO

--- src/taoensso/carmine/message_queue.clj
+++ src/taoensso/carmine/message_queue.clj
@@ -178,6 +178,7 @@
     * `throttle-msecs` specifies thread sleep period between each poll.
     * `backoff-msecs` specifies thread sleep period each time end of queue is
       reached. Backoff is synchronized between all dequeue workers."
+  ;; TODO Allow handler-fn to return e/o #{:success :error :retry}, etc.
   [connection-pool connection-spec qname
    & {:keys [handler-fn handler-ttl-msecs throttle-msecs backoff-msecs auto-start?]
       :or   {handler-fn (fn [msg] (timbre/info (str "Message received from queue: "


fix position saving in db

fix position saving in db

--- src/greybear/utils.clj
+++ src/greybear/utils.clj
@@ -15,7 +15,7 @@

 (defn position-in-vec
   [[x y]]
-  (+ (* 19 x) y))
+  (+ x (* 19 y)))

 (defn place-stone
   "Place a stone on a board represented by a list of strings"


Replace eval

Replace eval

--- src/javascript_externs_generator/extern.cljs
+++ src/javascript_externs_generator/extern.cljs
@@ -45,6 +45,7 @@
   (when (seq prototype)
     (str namespace ".prototype = {" (string/join "," (for [p prototype]
                                                                (build-function (:name p)))) "};")))
+
 (defn build-prototype-extern [obj namespace]
   (let [{:keys [name props prototype]} obj
         prototype-extern (build-prototype namespace prototype)
@@ -53,7 +54,7 @@
     (str prototype-extern (string/join child-prototype-externs))))

 (defn extract [name]
-  (let [tree (assoc (build-tree (js/eval name) name) :top true)
+  (let [tree (assoc (build-tree (aget js/window name) name) :top true)
         props-extern (build-props-extern tree)
         prototype-extern (build-prototype-extern tree name)
         output (str props-extern prototype-extern)


Copying sharing details from base file to segments

--- src/kixi/datastore/segmentation/inmemory.clj
+++ src/kixi/datastore/segmentation/inmemory.clj
@@ -95,7 +95,9 @@
                                        [::ms/type
                                         ::ms/name
                                         ::ss/id
-                                        ::ms/header])
+                                        ::ms/header
+                                        ::ms/file-sharing
+                                        ::ms/file-metadata-sharing])
                           ::ms/id (:id segment-data)
                           ::ms/size-bytes (:size-bytes segment-data)
                           ::ms/provenance {::ms/source "segmentation"


hist data shaping cont

hist data shaping cont

--- statspop/src/statspop/charts/hist.cljs
+++ statspop/src/statspop/charts/hist.cljs
@@ -1,5 +1,4 @@
-(ns statspop.charts.hist
-  (:require [cljs.pprint :as pprint]))
+(ns statspop.charts.hist)

 ;; test data

@@ -115,9 +114,12 @@
     (into (sorted-map) (frequencies binned-data))))

 (defn make-hist [data nbins]
-  (let [hist-data (make-hist-data data nbins)]
-    ))
+  (let [hist-data (make-hist-data data nbins)
+        ks (mapv (comp str #(js/Math.round %)) (keys hist-data))]
+    {:labels ks :vals (vec (vals hist-data))}))

-;; on test data, result is: {0 27, 9.8 26, 19.6 20, 29.400000000000002 17, 39.2 10}.  need to visually verify that between 0 and 9.8 is 27, between 9.8 and 19.6 is 26, etc.  Then need to map a rounding function over the keys and then to string, and I've got the x axis labels of the chart (need to note to users that it's rounded); get the values
+;; ABSOLUTELY MUST warn users that histogram is rough, because bin numbers
+;; often don't match well to dataset sizes and shapes, uses lots of rounding
+;; and might well mislead for small datasets. should be fine for big ones though.

-;; to trunc, use (pp/cl-format nil  "~,-0f" 1.2345) but strip trailing period?  or just use round from js?
+;; I should also use transducers to make this more efficient. Way too many intermediate collections in here now.


finished macro

finished macro

--- src/language/macro.clj
+++ src/language/macro.clj
@@ -349,6 +349,12 @@
 (deref (var simplify));useful for obtaining value of a private var

 (@#'simplify nil {'x 1} '(inc x))
+
+(defmacro image
+  [expr]
+  expr)
+
+(image (range 10))

 (defmacro ontology
@@ -372,14 +378,63 @@
                                (-> &form meta :line)))))
           triples))

-(ontology [1 2])
-
-(defmacro xyz
-  []
-    `(prn ~@(meta &form)))
-
-(let [u 5]
-  (xyz))
+;(ontology [1 2])
+
+(defn macroexpand-1-env
+  [env form]
+  (if-let [[x & xs] (and (seq? form) (seq form))]
+    (if-let [v (and (symbol? x) (resolve x))]
+      (if (-> v meta :macro)
+        (apply @v form env xs)
+        form)
+      form)
+    form))
+
+(defmacro spy
+  [expr]
+  `(let [value# ~expr]
+     (println (str "line #:" ~(-> &form meta :line) ";"))
+     value#
+     ))
+
+(let [a 1
+      a (spy (inc a))
+      a (spy (inc a))]
+  a)
+
+(macroexpand-1-env '{range 1} '(simplify (range 10)))
+
+((deref (resolve 'simplify)) nil '{range 1} '(range 10))
+(defmacro aby
+  [x]
+  (+ x 2))
+(simplify  (range 10))
+
+(defmacro abd
+  [body]
+  `(+ 2 ~@body)
+  `(symbol? ~@body))
+
+(defmacro abe
+  [exp]
+  (symbol? exp))
+
+(abd (1))
+
+(abe a)
+
+(@#'aby 1)
+
+
+
+('+ '1 '2)
+(+ '1 '2)
+
+(@#'aby nil nil '2)
+
+helloha
+
+(seq? (quote #(+ 2 %)))

 ;;;;;;;;;;;tips;;;;;;;;;;;;


Fixed Launchpad.update

Fixed Launchpad.update

oldstate was not bound correctly, therefore (= old new) was always false. This
caused update to send excessive MIDI traffic to the Launchpad. This seems to
trigger a bug in the firmware of the Launchpad S, causing it responds with
erratic note-on events.

--- src/launchpad/core.clj
+++ src/launchpad/core.clj
@@ -68,7 +68,7 @@
     ;; enough not to warrant double-buffering here, so I haven't
     ;; implemented it. But if flickering becomes an issue, that's an
     ;; option.
-    (let [oldstate state
+    (let [oldstate (.state this)
                                         ; Any IState will do.
           newstate (.state newstate)]
       ;; grid


housekeeping

housekeeping

--- src/launchpad/core.clj
+++ src/launchpad/core.clj
@@ -2,7 +2,7 @@
   (:require midi))

 ;; helpers
-(declare color->velocity coord->note)
+(declare color->velocity coord->note -update!)

 (defprotocol Protocol
   (reset
@@ -35,48 +35,16 @@
 ;; In all of the above, the value is a color (2-element vector of red and green
 ;; values, ranging from 0 to 3)
 (defrecord State [grid top right])
+
 (def initial-state
+  "The quintessentially quiescent Launchpad."
   (let [octet (vec (repeat 8 [0 0]))]
     (State. (vec (repeat 8 octet))
             octet
             octet)))

-(defn -update!
-  "Update launchpad to pad new state, wholesale."
-  [pad newstate]
-  ;; The Launchpad Mini, and probably therefore the S, updates quickly enough
-  ;; not to warrant double-buffering here, so I haven't implemented it. But if
-  ;; flickering becomes an issue, that's an option.
-  (let [oldstate (.state pad)
-        dev (.device pad)]
-    (dotimes [x 8]
-      (dotimes [y 8]
-        (when (not= (get-in @oldstate [:grid x y])
-                (get-in newstate [:grid x y]))
-          (.send dev
-             (midi/note-on (coord->note [x y])
-                   (color->velocity (get-in newstate
-                                         [:grid x y])))
-             -1)))
-      (when (not= (get-in @oldstate [:top x])
-              (get-in newstate [:top x]))
-        (.send dev
-           (midi/control-change (+ 0x68 x)
-                 (color->velocity (get-in newstate [:top x])))
-           -1))
-      (let [y x]
-        (when (not= (get-in @oldstate [:right y])
-                (get-in newstate [:right y]))
-
-          (.send dev
-             (midi/note-on (coord->note [8 y])
-                   (color->velocity (get-in newstate [:right y])))
-             -1))))
-    (reset! oldstate newstate)))
-
-
 ;; combine the state, the midi device, and the actions on them
-(defrecord Launchpad [state device]
+(defrecord Launchpad [^clojure.lang.Atom state device]
   Protocol
   (grid [this [x y] [red green]]
     (-update! this (assoc-in @(.state this)
@@ -130,13 +98,49 @@

 ;; helpers
 (defn color->velocity
-  ;; convert the (red,green) pair to the appropriate MIDI velocity
+  "Convert the (red,green) pair to the appropriate MIDI velocity"
   [[red green]]
   (bit-or red
           0xC
           (bit-shift-left green 4)))

 (defn coord->note [[x y]]
-  ;; convert the (x,y) coordinate to the appropriate MIDI note
+  "Convert the (x,y) coordinate to the appropriate MIDI note"
   (+ x
      (* 0x10 y)))
+
+(defn -update!
+  "Update launchpad to pad new state, wholesale."
+  [pad newstate]
+  ;; The Launchpad Mini, and probably therefore the S, updates quickly enough
+  ;; not to warrant double-buffering here, so I haven't implemented it. But if
+  ;; flickering becomes an issue, that's an option.
+  (let [oldstate (.state pad)
+        dev (.device pad)]
+    (dotimes [x 8]
+      (dotimes [y 8]
+        ; update the grid
+        (when (not= (get-in @oldstate [:grid x y])
+                (get-in newstate [:grid x y]))
+          (.send dev
+             (midi/note-on (coord->note [x y])
+                   (color->velocity (get-in newstate
+                                         [:grid x y])))
+             -1)))
+      ; update the top row
+      (when (not= (get-in @oldstate [:top x])
+              (get-in newstate [:top x]))
+        (.send dev
+           (midi/control-change (+ 0x68 x)
+                 (color->velocity (get-in newstate [:top x])))
+           -1))
+      ; update the right side column
+      (let [y x]
+        (when (not= (get-in @oldstate [:right y])
+                (get-in newstate [:right y]))
+
+          (.send dev
+             (midi/note-on (coord->note [8 y])
+                   (color->velocity (get-in newstate [:right y])))
+             -1))))
+    (reset! oldstate newstate)))


Fix dependency unpacking to use right directory.

--- src/leiningen/deps.clj
+++ src/leiningen/deps.clj
@@ -1,7 +1,6 @@
 (ns leiningen.deps
   (:require [lancet])
-  (:use [leiningen]
-        [clojure.contrib.java-utils :only [file]])
+  (:use [clojure.contrib.java-utils :only [file]])
   (:import [org.apache.maven.model Dependency]
            [org.apache.maven.artifact.ant DependenciesTask]
            [org.apache.tools.ant.util FlatFileNameMapper]))
@@ -24,7 +23,7 @@
       (.addDependency deps-task (make-dependency dep)))
     (.execute deps-task)
     (.mkdirs (file (:root project) "lib"))
-    (lancet/copy {:todir "lib/"}
+    (lancet/copy {:todir (str (:root project) "/lib/")}
                  (.getReference lancet/ant-project
                                 (.getFilesetId deps-task))
                  (FlatFileNameMapper.))))


Fix help task for leiningen 2.0.

Fix help task for leiningen 2.0.

--- src/leiningen/ring.clj
+++ src/leiningen/ring.clj
@@ -5,12 +5,18 @@
         [leiningen.ring.war :only (war)]
         [leiningen.ring.uberwar :only (uberwar)]))

+(defn- nary? [v n]
+  (some #{n} (map count (:arglists (meta v)))))
+
 (defn ring
   "Manage a Ring-based application."
   {:help-arglists '([server server-headless war uberwar])
    :subtasks [#'server #'server-headless #'war #'uberwar]}
   ([project]
-     (println (help-for "ring")))
+     (println (if (nary? #'help-for 2)
+                ;; lein2 help-for
+                (help-for project "ring")
+                (help-for "ring"))))
   ([project subtask & args]
      (case subtask
        "server"          (apply server project args)


Shut down agents after test run.

Shut down agents after test run.

--- src/leiningen/test.clj
+++ src/leiningen/test.clj
@@ -30,4 +30,4 @@
                      (find-namespaces-in-dir (file (:test-path project)))
                      (map symbol namespaces))]
     (eval-in-project project (form-for-testing-namespaces namespaces))
-    (println (System/getProperty "leiningen.test"))))
+    (shutdown-agents)))


Small optimizations to only rebind the vars once and track the innermost exception

--- src/io/aviso/tracker.clj
+++ src/io/aviso/tracker.clj
@@ -5,21 +5,15 @@
     [clojure.tools.logging.impl :as impl]
     [io.aviso.exception :as exception]))

-;; Contains a list of messages (or functions that return messages) used to log the route to the exception.
-(def ^:dynamic ^:private operation-traces [])
+;;; Contains a vector of messages (or functions that return messages) used to log the route to the exception.
+(def ^:dynamic ^:private operation-traces)
+
+(def ^:dynamic ^:private trace-applied)

 (defn- trace-to-string
   "Converts a trace to a string; a trace may be a function which is invoked."
   [message]
   (str (if (fn? message) (message) message)))
-
-(defn- contains-operation-trace
-  "Checks to see if an exception (or any of the exception's causes) is an IExceptionInfo containing an :operation-trace."
-  [^Throwable e]
-  (cond
-    (nil? e) false
-    (some-> e ex-data :operation-trace) true
-    :else (recur (.getCause e))))

 (defn- error [logger message]
   (l/log* logger :error nil message))
@@ -31,26 +25,32 @@
   (error logger (format "%s%n%s" message (exception/format-exception e))))

 (defn track*
-  "Traces the execution of a function of no arguments. The trace macro converts into a call to track-function.
+  "Tracks the execution of a function of no arguments. The trace macro converts into a call to track*.

   logger - SLF4J Logger where logging should occur
   trace-message - String, object, or function. Function evaulation is deferred until an exception is actually thrown.
   f - function to invoke."
   [logger trace f]
-  (binding [operation-traces (conj operation-traces trace)]
+  (if (bound? #'operation-traces)
     (try
+      (swap! operation-traces conj trace)
       (f)
       (catch Throwable e
-        ;; By nature, the track calls get deeply nested. We want to create an exception only at the initial failure,
-        (if (contains-operation-trace e)
+        (if @trace-applied
           (throw e)
-          ;; This is the initial exception thrown so we'll wrap the original exception with the exception info.
-          (let [trace-strings (map trace-to-string operation-traces)
+          (let [trace-strings (mapv trace-to-string @operation-traces)
                 message (or (.getMessage e) (-> e .getClass .getName))]
             (log-trace logger trace-strings message e)
+            (reset! trace-applied true)
             (throw (ex-info message
                             {:operation-trace trace-strings}
-                            e))))))))
+                            e)))))
+      (finally
+        (swap! operation-traces pop)))
+    ;; Else, if not yet bound..
+    (binding [operation-traces (atom [])
+              trace-applied (atom false)]
+      (track* logger trace f))))

 (defn get-logger
   "Determines the logger instance for a namespace (by leveraging some clojure.tools.logging internals)."
@@ -58,7 +58,7 @@
   (impl/get-logger l/*logger-factory* namespace))

 (defmacro track
-  "Tracks the execution of an operation, associating the trace (which describes the opeation) with the execution of the body.
+  "Tracks the execution of an operation, associating the trace (which describes the operation) with the execution of the body.

   If an exception occurs inside the body, then all trace messages leading up to the
   point of the exception will be logged (the logger is determined from the current namespace); thus logging only occurs at the


Make the operation-traces var private

Make the operation-traces var private

--- src/io/aviso/tracker.clj
+++ src/io/aviso/tracker.clj
@@ -5,7 +5,7 @@
             [io.aviso.exception :as exception]))

 ;; Contains a list of messages (or functions that return messages) used to log the route to the exception.
-(def ^:dynamic operation-traces [])
+(def ^:dynamic ^:private operation-traces [])

 (defn- trace-to-string
   "Converts a trace to a string; a trace may be a function which is invoked."