Stream id now dynamic, generated via range

--- src/onyx/messaging/aeron.clj
+++ src/onyx/messaging/aeron.clj
@@ -18,8 +18,6 @@
            [uk.co.real_logic.agrona.concurrent IdleStrategy BackoffIdleStrategy BusySpinIdleStrategy]
            [java.util.function Consumer]
            [java.util.concurrent TimeUnit]))
-
-(def send-stream-id 1)

 (defn aeron-channel [addr port]
   (format "udp://%s:%s" addr port))


[bot] markers not required because tmbre adds namepsace markers

--- src/open_company/lib/bot.clj
+++ src/open_company/lib/bot.clj
@@ -61,9 +61,9 @@
                     :stakeholder-update {:type :all-members})}))

 (defn send-trigger! [trigger]
-  (timbre/info "[bot] request to send " trigger " to " c/aws-sqs-queue)
+  (timbre/info "Request to send msg to " c/aws-sqs-queue "\n" trigger)
   (s/validate BotTrigger trigger)
-  (timbre/info "[bot] sending")
+  (timbre/info "Sending")
   (sqs/send-message
    {:access-key c/aws-access-key-id
     :secret-key c/aws-secret-access-key}


simplify stacked bar logic

simplify stacked bar logic

--- src/cljc/gyptis/vega_templates.cljc
+++ src/cljc/gyptis/vega_templates.cljc
@@ -54,35 +54,44 @@
   [facet-mark [datum & more :as data]]
   (let [first-facet-x (->> *facet-x* (get datum) u/->json)
         last-facet-y (->> *facet-y* (get (last more)) u/->json)
-        unlabelled-facet-mark (-> facet-mark
-                                  (update-in [:axes] #(mapv suppress-axis-labels %))
-                                  (update-in [:from :transform] conj {:type "filter"
-                                                                      :test (str "datum." (name *facet-x*) "!==" first-facet-x
-                                                                                " && datum." (name *facet-y*) "!==" last-facet-y)}))
-        x-labelled-facet-mark (-> unlabelled-facet-mark
-                                (assoc-in [:from :transform 1] {:type "filter"
-                                                                :test (str "datum." (name *facet-x*) "!==" first-facet-x
-                                                                           " && datum." (name *facet-y*) "===" last-facet-y)})
-                                (merge-spec {:axes ^:replace [{:type "x"
-                                                               :scale "x"}
-                                                              {:type "y"
-                                                               :scale "y" :properties {:labels {:text {:value ""}}}}]}))
-        y-labelled-facet-mark (-> unlabelled-facet-mark
-                                  (assoc-in [:from :transform 1] {:type "filter"
-                                                                  :test (str "datum." (name *facet-x*) "===" first-facet-x
-                                                                           " && datum." (name *facet-y*) "!==" last-facet-y)})
-                                  (merge-spec {:axes ^:replace [{:type "x"
-                                                                 :scale "x" :properties {:labels {:text {:value ""}}}}
-                                                                {:type "y"
-                                                                 :scale "y"}]}))
-        xy-labelled-facet-mark (-> unlabelled-facet-mark
-                                  (assoc-in [:from :transform 1] {:type "filter"
-                                                                  :test (str "datum." (name *facet-x*) "===" first-facet-x
-                                                                             " && datum." (name *facet-y*) "===" last-facet-y)})
-                                  (merge-spec {:axes ^:replace [{:type "x"
-                                                                 :scale "x"}
-                                                                {:type "y"
-                                                                 :scale "y"}]}))]
+        unlabelled-facet-pred (str "datum." (name *facet-x*) "!==" first-facet-x
+                                   " && datum." (name *facet-y*) "!==" last-facet-y)
+        x-label-facet-pred (str "datum." (name *facet-x*) "!==" first-facet-x
+                                " && datum." (name *facet-y*) "!==" last-facet-y)
+        y-label-facet-pred   (str "datum." (name *facet-x*) "===" first-facet-x
+                                  " && datum." (name *facet-y*) "!==" last-facet-y)
+        xy-label-facet-pred (str "datum." (name *facet-x*) "===" first-facet-x
+                                   " && datum." (name *facet-y*) "===" last-facet-y)
+
+        unlabelled-facet-mark
+        (-> facet-mark
+            (update-in [:axes] #(mapv suppress-axis-labels %))
+            (update-in [:from :transform] conj {:type "filter"
+                                                :test unlabelled-facet-pred}))
+        x-labelled-facet-mark
+        (-> unlabelled-facet-mark
+            (assoc-in [:from :transform 1] {:type "filter"
+                                            :test x-label-facet-pred})
+            (merge-spec {:axes ^:replace [{:type "x"
+                                           :scale "x"}
+                                          {:type "y"
+                                           :scale "y" :properties {:labels {:text {:value ""}}}}]}))
+        y-labelled-facet-mark
+        (-> unlabelled-facet-mark
+            (assoc-in [:from :transform 1] {:type "filter"
+                                            :test y-label-facet-pred})
+            (merge-spec {:axes ^:replace [{:type "x"
+                                           :scale "x" :properties {:labels {:text {:value ""}}}}
+                                          {:type "y"
+                                           :scale "y"}]}))
+        xy-labelled-facet-mark
+        (-> unlabelled-facet-mark
+            (assoc-in [:from :transform 1] {:type "filter"
+                                            :test xy-label-facet-pred})
+            (merge-spec {:axes ^:replace [{:type "x"
+                                           :scale "x"}
+                                          {:type "y"
+                                           :scale "y"}]}))]
     [unlabelled-facet-mark x-labelled-facet-mark y-labelled-facet-mark xy-labelled-facet-mark]))

 (defn facet
@@ -123,7 +132,7 @@

 (defn assoc-hover
   [vg hover-spec]
-  (assoc-in [:marks 0 :properties :hover] hover-spec))
+  (assoc-in vg [:marks 0 :properties :hover] hover-spec))

 (defn bar
   [data]
@@ -157,40 +166,39 @@
 (defn stacked-bar
   "Stacks bars on the `fill' field"
   [[datum & more :as data]]
-  (if-not (contains? datum *fill*) (bar data)
-          (let [mark {:type "rect"
-                      :from {:transform [stack-transform]}
-                      :properties {:update {:x {:scale "x" :field *x*}
-                                           :width {:scale "x" :band true :offset -1}
-                                           :y {:scale "y" :field "layout_start"}
-                                           :y2 {:scale "y" :field "layout_end"}
-                                           :fill {:scale "fill" :field *fill*}}}}
-                sum_y_data {:name "stats"
-                            :source *table*
-                            :transform [{:type "aggregate"
-                                         :groupby [*x*]
-                                         :summarize [{:field *y* :ops "sum"}]}]}]
-            (merge-spec (bar data)
-                        {:data [sum_y_data]
-                         :scales
-                         ^:replace [{:name "x",
-                                     :type "ordinal",
-                                     :domain {:data *table*, :field *x*},
-                                     :range "width"}
-                                    {:name "y",
-                                     :type "linear",
-                                     :domain {:data "stats", :field (str "sum_" (name *y*))},
-                                     :range "height",
-                                     :round true,
-                                     :nice true}
-                                    {:name "fill",
-                                     :type "ordinal",
-                                     :domain {:data *table*, :field *fill*},
-                                     :range "category20"}],
-                         :axes ^:replace [{:type "x", :scale "x"}
-                                          {:type "y", :scale "y"}],
-                         :legends [{:fill "fill"}]
-                         :marks ^:replace [mark]}))))
+  (let [mark {:type "rect"
+              :from {:transform [stack-transform]}
+              :properties {:update {:x {:scale "x" :field *x*}
+                                    :width {:scale "x" :band true :offset -1}
+                                    :y {:scale "y" :field "layout_start"}
+                                    :y2 {:scale "y" :field "layout_end"}
+                                    :fill {:scale "fill" :field *fill*}}}}
+        sum_y_data {:name "stats"
+                    :source *table*
+                    :transform [{:type "aggregate"
+                                 :groupby [*x*]
+                                 :summarize [{:field *y* :ops "sum"}]}]}]
+    (merge-spec (bar data)
+                {:data [sum_y_data]
+                 :scales
+                 ^:replace [{:name "x",
+                             :type "ordinal",
+                             :domain {:data *table*, :field *x*},
+                             :range "width"}
+                            {:name "y",
+                             :type "linear",
+                             :domain {:data "stats", :field (str "sum_" (name *y*))},
+                             :range "height",
+                             :round true,
+                             :nice true}
+                            {:name "fill",
+                             :type "ordinal",
+                             :domain {:data *table*, :field *fill*},
+                             :range "category20"}],
+                 :axes ^:replace [{:type "x", :scale "x"}
+                                  {:type "y", :scale "y"}],
+                 :legends (if (contains? datum *fill*) [{:fill "fill"}] [])
+                 :marks ^:replace [mark]})))

 (defn dodged-bars-mark
   "Dodges bars on the fill. Assumes that a x, y and fill scales have been previously defined."


Hide HUD after 3s

Hide HUD after 3s

--- src/cljs/asciinema_player/core.cljs
+++ src/cljs/asciinema_player/core.cljs
@@ -330,7 +330,7 @@
   [state]
   (let [events (chan)
         mouse-moves (chan (dropping-buffer 1))
-        user-activity (activity-chan mouse-moves 2000)
+        user-activity (activity-chan mouse-moves 3000)
         dispatch (fn [[event-name & args :as event]]
                    (if (= event-name :mouse-move)
                      (put! mouse-moves true)


select last modified deck after deck delete

--- src/cljs/netrunner/deckbuilder.cljs
+++ src/cljs/netrunner/deckbuilder.cljs
@@ -108,7 +108,7 @@
   (let [deck (om/get-state owner :deck)]
     (go (let [response (<! (POST "/data/decks/delete" deck :json))]))
     (om/transact! cursor :decks (fn [ds] (remove #(= deck %) ds)))
-    (om/set-state! owner :deck (first (:decks @cursor)))))
+    (om/set-state! owner :deck (first (sort-by :date > (:decks @cursor))))))

 (defn handle-keydown [owner event]
   (let [selected (om/get-state owner :selected)


fixed decks with e.g. 6 Sure Gambles being valid in deckbuilder

--- src/cljs/netrunner/deckbuilder.cljs
+++ src/cljs/netrunner/deckbuilder.cljs
@@ -62,10 +62,20 @@
         qty (js/parseInt (first tokens))
         cardname (join " " (rest tokens))]
     (when-not (js/isNaN qty)
-      {:qty (min qty 3) :card (lookup side cardname)})))
-
-(defn parse-deck [side deck]
-  (reduce #(if-let [card (parse-line side %2)] (conj %1 card) %1) [] (split-lines deck)))
+      {:qty (min qty 6) :card (lookup side cardname)})))
+
+(defn parse-deck
+  "Parses a string containing cardlist and returns a list of line card maps {:qty num :card cardmap}"
+  [side deck]
+  (let [base-list (reduce #(if-let [card (parse-line side %2)] (conj %1 card) %1) [] (split-lines deck))
+        ;; in case there were e.g. 2 lines with Sure Gambles, we need to sum them up in deduplicate
+        duphelper (fn [currmap line]
+                    (let [title (:title :card line)
+                          qty (:qty line)]
+                      (if (contains? currmap title)
+                        (assoc-in currmap [title :qty] (+ (get-in currmap [title :qty]) qty))
+                        (assoc currmap title line))))]
+    (vals (reduce duphelper {} base-list))))

 (defn faction-label
   "Returns faction of a card as a lowercase label"
@@ -185,11 +195,16 @@
   (reduce #(if-let [point (get-in %2 [:card :agendapoints])]
              (+ (* point (:qty %2)) %1) %1) 0 cards))

+(defn legal-num-copies?
+  "Returns true if there is a legal number of copies of a particular card."
+  [{:keys [qty card] :as line}]
+  (<= qty (or (:limited card) 3)))
+
 (defn valid? [{:keys [identity cards] :as deck}]
   (and (>= (card-count cards) (:minimumdecksize identity))
        (<= (influence-count deck) (id-inf-limit identity))
        (every? #(and (allowed? (:card %) identity)
-                     (<= (:qty %) (or (get-in % [:card :limited]) 3))) cards)
+                     (legal-num-copies? %)) cards)
        (or (= (:side identity) "Runner")
            (let [min (min-agenda-points deck)]
              (<= min (agenda-points deck) (inc min))))))
@@ -503,7 +518,9 @@
                                infaction (noinfcost? identity card)
                                wanted (mostwanted? card)]
                            [:span
-                            [:span {:class (if (allowed? card identity) "fake-link" "invalid")
+                            [:span {:class (if (and (allowed? card identity)
+                                                    (legal-num-copies? line))
+                                             "fake-link" "invalid")
                                     :on-mouse-enter #(put! zoom-channel card)
                                     :on-mouse-leave #(put! zoom-channel false)} name]
                             (when (or wanted (not infaction))


More implementations.

More implementations.

--- src/clojure/cav/mtj/core/matrix.clj
+++ src/clojure/cav/mtj/core/matrix.clj
@@ -780,12 +780,159 @@
         (error "column has a incompatible shape."))
       (error "column must be a 1D vector."))))

+(extend-protocol PElementCount
+  Vector
+  (element-count [m] (.size m))
+
+  Matrix
+  (element-count [m] (* (.numRows m) (.numColumns m))))
+
+(extend-protocol PFunctionalOperations
+  Vector
+  (element-seq [m] (map #(.get m %) (range (.size m))))
+  (element-map
+    ([m f] (element-map! (.copy m) f))
+    ([m f a] (element-map! (.copy m) f a))
+    ([m f a more] (element-map! (.copy m) f a more)))
+  (element-map!
+    ([m f]
+     (dotimes [i (.size m)]
+       (.set m i (double (f (.get m i)))))
+     m)
+    ([m f ^Vector a]
+     (dotimes [i (.size m)]
+       (.set m i (double (f (.get m i) (.get a i)))))
+     m)
+    ([m f a more]
+     (let [ms (cons m (cons a more))]
+       (dotimes [i (.size m)]
+         (.set m i (double (apply f (mapv #(.get ^Vector % i) ms)))))
+       m)))
+  (element-reduce
+    ([m f] (reduce f (element-seq m)))
+    ([m f init] (reduce f init (element-seq m))))
+
+  Matrix
+  (element-seq [m]
+    (for [i (range (.numRows m))
+          j (range (.numColumns m))]
+      (.get m i j)))
+  (element-map
+    ([m f] (element-map! (.copy m) f))
+    ([m f a] (element-map! (.copy m) f a))
+    ([m f a more] (element-map! (.copy m) f a more)))
+  (element-map!
+    ([m f]
+     (dotimes [i (.numRows m)]
+       (dotimes [j (.numColumns m)]
+         (.set m i j (double (f (.get m i j))))))
+     m)
+    ([m f ^Matrix a]
+     (dotimes [i (.numRows m)]
+       (dotimes [j (.numColumns m)]
+         (.set m i j (double (f (.get m i j) (.get a i j))))))
+     m)
+    ([m f a more]
+     (let [ms (cons m (cons a more))]
+     (dotimes [i (.numRows m)]
+       (dotimes [j (.numColumns m)]
+         (.set m i j (double (apply f (mapv #(.get ^Matrix % i j) ms))))))
+       m)))
+  (element-reduce
+    ([m f] (reduce f (element-seq m)))
+    ([m f init] (reduce f init (element-seq m)))))
+
+(extend-protocol PSelect
+  Vector
+  (select [m [index]]
+    (cond
+      (number? index) (.get m (int index))
+      (sequential? index) (Matrices/getSubVector m (int-array index))
+      (= index :all) m))
+
+  Matrix
+  (select [m [row col]]
+    (let [row-index (cond
+                      (number? row) (int-array [row])
+                      (sequential? row) (int-array row)
+                      (= row :all) (int-array (range (.numRows m))))
+          col-index (cond
+                      (number? col) (int-array [col])
+                      (sequential? col) (int-array col)
+                      (= col :all) (int-array (range (.numColumns m))))]
+      (Matrices/getSubMatrix m row-index col-index))))
+
+(extend-protocol PSetSelection
+  Vector
+  (set-selection [m args values]
+    (let [res (.copy m)]
+      (assign! (select res args) values)
+      res))
+
+  Matrix
+  (set-selection [m args values]
+    (let [res (.copy m)]
+      (assign! (select res args) values)
+      res)))
+
+(extend-protocol PIndicesAccess
+  Vector
+  (get-indices [m indices]
+    (let [size (count indices)
+          res (DenseVector. size)]
+      (loop [i 0, indices indices]
+        (when-let [idx (first indices)]
+          (if (sequential? idx)
+            (if (= (count idx) 1)
+              (.set res i (.get m (first idx)))
+              (error "Incompatible shape of index."))
+            (.set res i (.get m idx)))
+          (recur (inc i) (rest indices))))
+      res))
+
+  Matrix
+  (get-indices [m indices]
+    (let [size (count indices)
+          res (DenseVector. size)]
+      (loop [i 0, indices indices]
+        (when-let [[row col] (first indices)]
+          (.set res i (.get m row col))
+          (recur (inc i) (rest indices))))
+      res)))
+
+(extend-protocol PIndicesSetting
+  Vector
+  (set-indices [m indices values] (set-indices! (.copy m) indices values))
+  (set-indices! [m indices values]
+    (loop [indices indices, values values]
+      (when-let [idx (first indices)]
+        (if (sequential? idx)
+          (if (= (count idx) 1)
+            (.set m (int (first idx)) (double (first values)))
+            (error "Incompatible shape of index."))
+          (.set m (int idx) (double (first values))))
+        (recur (rest indices) (rest values))))
+    m)
+
+  Matrix
+  (set-indices [m indices values] (set-indices! (.copy m) indices values))
+  (set-indices! [m indices values]
+    (loop [indices indices, values values]
+      (when-let [[row col] (first indices)]
+        (.set m row col (first values))
+        (recur (rest indices) (rest values))))
+    m))
+
 (register-implementation imp)

 (comment

 (m/set-current-implementation :mtj)
-(m/div 2 (m/matrix :mtj [1 2 3]))
-(m/sqrt (m/matrix :mtj [[1 2] [3 4]]))
+(m/select-indices (m/matrix :vectorz [[1 2 3] [4 5 6] [7 8 9]]) [[0 1] [2 2] [1 2]])
+(m/select-indices (m/matrix :mtj [1 2 3 4 5 6]) [0 3])
+(m/select-indices (m/matrix :mtj [1 2 3 4 5 6]) [0 3])
+(m/set-indices! (m/matrix :mtj [1 2 3 4 5 6]) [[0] [3]] [100 200])
+(m/set-indices (m/matrix :mtj [[1 2 3] [4 5 6] [7 8 9]]) [[0 1] [2 2] [1 2]] [100 200 300])
+(m/select-indices (m/matrix :mtj [1 2 3 4 5 6]) [0 3])

   )


Fix graphql for JS

Fix graphql for JS

--- src/com/wsscode/pathom/graphql.cljc
+++ src/com/wsscode/pathom/graphql.cljc
@@ -1,7 +1,8 @@
 (ns com.wsscode.pathom.graphql
   (:require
+    #?(:clj [clojure.data.json :as json])
     [clojure.string :as str]
-    [clojure.data.json :as json]
+
     [om.next :as om]))

 (defn pad-depth [depth]
@@ -13,7 +14,9 @@
                                 (and (= :join type)
                                      (symbol? dispatch-key)))) children))))

-(defn stringify [x] (json/write-str x))
+(defn stringify [x]
+  #?(:clj (json/write-str x)
+     :cljs (js/JSON.stringify (clj->js x))))

 (defn params->graphql
   ([x js-name] (params->graphql x js-name true))


Apply function with sorted order parameters.

--- src/app/clj/fnx/meta/expose.clj
+++ src/app/clj/fnx/meta/expose.clj
@@ -34,14 +34,36 @@
 (fact "resolve-str"
   (resolve-str "fnx.meta.expose/resolve-str") => #'fnx.meta.expose/resolve-str)

+(unfinished )
+
+(defn- parameters "Given a map of parameters and a list of ordered parameters, return the valued parameters from the map in order."
+  [arglists args]
+  (let [arities (group-by count arglists)
+        n (count (vals args))
+        arity (first (arities n))]
+    (map args arity)))
+
+(fact "parameters"
+  (parameters [['a] ['a 'b] ['a 'b 'c]]
+              {'c :30 'b :20 'a :10}) => [:10 :20 :30])
+
 (defn apply-fn "Apply the function f to the map args (with the help of arglists order)"
-  [f arglists args]
-  (apply (resolve-str f) (vals args)))
-
-;; FIXME will need to deal with the arglists' order
+  ([f v-arglists m-args]
+     (apply-fn f (parameters v-arglists m-args)))
+  ([f v-args]
+     (apply (resolve-str f) v-args)))
+
+(fact "apply-fn"
+  (apply-fn :fq-fn :arglists :args) => :some-res
+  (provided
+    (parameters :arglists :args) => :parameter-in-order
+    (apply-fn :fq-fn :parameter-in-order) => :some-res))

 (fact "apply-fn"
   (apply-fn "clojure.core/print" [['x]] {:x "test"}) => nil)
+
+(fact "apply-fn"
+  (apply-fn "clojure.core/print" ["test"]) => nil)

 (defn- load-file-ns "Load the file into a list"
   [f]


chore(handler): wrap restful middleware

chore(handler): wrap restful middleware

--- src/busa_server/api/handler.clj
+++ src/busa_server/api/handler.clj
@@ -2,10 +2,13 @@
   (:require
     [compojure.core :refer :all]
     [compojure.handler :as handler]
+    [ring.middleware.format :refer [wrap-restful-format]]
     [busa-server.api.connection-api :refer :all]))

 (defroutes busa-routes
   (context "/api" [] connection-api))

 (def busa-handler
-  (-> (handler/site busa-routes)))
+  (->
+    (handler/site busa-routes)
+    (wrap-restful-format :formats [:json-kw])))


complete interface

complete interface

--- src/ca_recipe/components/ke.clj
+++ src/ca_recipe/components/ke.clj
@@ -1,4 +1,13 @@
 (ns ca-recepie.components.ke)

+;; read
 (defn get-rules [ke])
 (defn find-rules [ke criterial])
+
+;;update
+(defn add-rule [ke rule])
+(defn replace-rule [ke old-rule new-role])
+(defn delete-rule [ke rule])
+
+;;processing
+(defn fire-rules [ke request])


Fix render reset by handling state outside

Local component state depending on input arguments is a sign that the
state should be handled by the calling environment.

--- src/cljs/hacker_agent/core.cljs
+++ src/cljs/hacker_agent/core.cljs
@@ -94,7 +94,7 @@
   (if (nil? id)
     [:p "Nothing to render"]
     (let [data (fb->atom (id->fbref id))]
-      (fn [id] [item data]))))
+      [item data])))

 (defmethod item "story" [data]
   (let [{:keys [id by title kids type time url score]} @data]
@@ -130,8 +130,7 @@
 (defn hacker [id]
   [:div
    [:h2 "Hacker News"]
-   [(with-meta render {}) id]
-   ])
+   [render id]])

 ;; -------------------------
 ;; Views


Use last discussion url for posting statements

--- src/discuss/communication/main.cljs
+++ src/discuss/communication/main.cljs
@@ -4,7 +4,8 @@
             [discuss.references.integration :as rint]
             [discuss.communication.lib :as comlib]
             [discuss.components.search.statements :as search]
-            [discuss.utils.logging :as log]))
+            [discuss.utils.logging :as log]
+            [discuss.history.discussion :as hdis]))

 ;; Handler
 (defn process-url-handler
@@ -42,14 +43,15 @@
   "Takes statement, an optional reference and maybe a search-result from EDEN to
   post it to the backend."
   [{:keys [statement reference search/selected]}]
-  (if (seq (lib/get-last-api))
-    (let [url (lib/get-last-api)
+  (if (seq (hdis/get-last-discussion-url))
+    (let [url (hdis/get-last-discussion-url)
           headers (merge {"Content-Type" "application/json"} (comlib/token-header))
           body {:reason (if (nil? selected) statement (:text selected))
                 :reference reference
                 :origin (build-origin-body selected)}]
       (post-json url body process-url-handler headers))
-    (log/error ":api/last-call is empty, cannot post statement to empty URL.")))
+    (log/error "Can't determine last used discussion step, cannot post statement
+    to empty URL.")))

 (defn post-position
   "Add new position, its reason and an optional reference to post it to the


Use refresh-control instead of a custom loading component

--- src/elfeed_cljsrn/android/core.cljs
+++ src/elfeed_cljsrn/android/core.cljs
@@ -254,17 +254,6 @@
      [rn/text {:style (:text styles)}
       (str "LAST UPDATE: ") (format-update-time update-time)]]))

-(defn loading-component []
-  (let [styles {:wrapper {:height 34
-                          :align-items "center"
-                          :padding-left 20
-                          :flex-direction "row"
-                          :background-color (:secondary-text palette)}
-                :text {:margin-left 20 :color "white"}}]
-    [rn/view {:style (:wrapper styles)}
-     [rn/activity-indicator {:color "white"}]
-     [rn/text {:style (:text styles)} "Loading entries..."]]))
-
 (defn no-entries-component []
   (let [styles {:wrapper {:height 400
                           :justify-content "center"
@@ -296,8 +285,6 @@
                         (clj->js '("s1")))
             hack @recent-reads]
         [rn/view {:style (:wrapper styles)}
-         (when @loading
-           [loading-component])
          [rn/view {:style {:flex 1}}
           (when @remote-error
             [remote-error-message])
@@ -306,7 +293,7 @@
               [rn/swipeable-list-view {:dataSource datasource
                                        :max-swipe-distance 50
                                        :bounceFirstRowOnMount false
-                                       :refresh-control (r/as-element [rn/refresh-control {:refreshing false
+                                       :refresh-control (r/as-element [rn/refresh-control {:refreshing @loading
                                                                                :on-refresh #(dispatch [:fetch-content])}])
                                        :style (:list styles)
                                        :enableEmptySections true


analyze-form redef

analyze-form redef

an experiment related to warnings, might remove this soon.

with-redef was called in the wrong location and blew up in par-compile

--- src/main/shadow/cljs/build.clj
+++ src/main/shadow/cljs/build.clj
@@ -682,12 +682,18 @@
     'ns (hijacked-parse-ns env form name opts)
     (default-parse op env form name opts)))

-(defn hijacked-analyze-form [orig-analyze-form env form name opts]
+(def default-analyze-form ana/analyze-form)
+
+;; FIXME: doing this so I can access the form that caused a warning
+;; some warnings do not include it, should really provide patches to add them
+;; but this is simpler and an experiment anyways
+(defn shadow-analyze-form
+  [env form name opts]
   (let [warnings-before
         @*cljs-warnings-ref*

         result
-        (orig-analyze-form env form name opts)
+        (default-analyze-form env form name opts)

         warnings-after
         @*cljs-warnings-ref*]
@@ -722,10 +728,6 @@
              ;; so we keep hijacking
              ana/*cljs-ns* ns
              ana/*cljs-file* name]
-
-     #_(let [orig-analyze-form ana/analyze-form]
-         (with-redefs [ana/analyze-form #(hijacked-analyze-form orig-analyze-form %1 %2 %3 %4)]
-           ))

      (-> (ana/empty-env) ;; this is anything but empty! requires *cljs-ns*, env/*compiler*
          (assoc :context context)
@@ -1650,7 +1652,8 @@
   (with-compiler-env state
     (ana/load-core)
     (with-redefs [ana/parse shadow-parse
-                  ana/load-core load-core-noop]
+                  ana/load-core load-core-noop
+                  ana/analyze-form shadow-analyze-form]

       (reduce
         (fn [state source-name]
@@ -1717,7 +1720,8 @@
   (with-compiler-env state
     (ana/load-core)
     (with-redefs [ana/parse shadow-parse
-                  ana/load-core load-core-noop]
+                  ana/load-core load-core-noop
+                  ana/analyze-form shadow-analyze-form]

       (let [;; namespaces that are ready to be used
             ready


add timing to the dev pipeline run

add timing to the dev pipeline run

--- dev-src/dev/core.clj
+++ dev-src/dev/core.clj
@@ -29,7 +29,7 @@
   (let [file (if (zip/xml-file? filename)
                (java.nio.file.Paths/get filename (into-array [""]))
                (java.io.File. filename))
-        result (pipeline/process pipeline file)]
+        result (time (pipeline/process pipeline file))]
     (when-let [xml-output-file (:xml-output-file result)]
       (println "XML:" (.toString xml-output-file))
       (psql/complete-run result))))


Rollback

Rollback

--- src/oc/storage/api/entries.clj
+++ src/oc/storage/api/entries.clj
@@ -256,7 +256,8 @@
                               moving-board?        (assoc :board-uuid (:uuid new-board))
                               (not moving-board?)  (dissoc :board-uuid)
                               true                 (dissoc :publisher-board)
-                              entry-publish?       (assoc (entry-res/ignore-props) :status :published)
+                              entry-publish?       (-> (entry-res/ignore-props)
+                                                       (assoc :status :published))
                               (not entry-publish?) (entry-res/clean))
           updated-entry (-> existing-entry
                          (merge clean-entry-props)


always return error

always return error

--- src/oc/storage/util/ziggeo.clj
+++ src/oc/storage/util/ziggeo.clj
@@ -39,6 +39,4 @@
         (cb (-> body
                 json/parse-string
                 keywordize-keys) error)
-        (cb {} (if-not error
-                 true
-                 error))))))+        (cb {} true)))))


Use restart-pred-fn to ensure job isn't killed by peer exceptions

--- src/onyx_jepsen/simple_job.clj
+++ src/onyx_jepsen/simple_job.clj
@@ -42,7 +42,7 @@
                          :lifecycle/calls :onyx.plugin.bookkeeper/read-ledgers-calls})
                       read-ledger-task-names)))))

-(defn build-job [batch-size zk-addr ledgers-root-path ledger-ids]
+(defn build-job [{:keys [batch-size] :as params} zk-addr ledgers-root-path ledger-ids]
   (let [password (.getBytes "INSECUREDEFAULTPASSWORD")
         job {:catalog [{:onyx/name :persist
                         :onyx/plugin :onyx.plugin.bookkeeper/write-ledger
@@ -59,6 +59,7 @@
                         :onyx/doc "Writes messages to a BookKeeper ledger"}
                        {:onyx/name :identity-log
                         :onyx/fn :onyx-peers.functions.functions/identity-log
+                        :onyx/restart-pred-fn :onyx-peers.functions.functions/restartable?
                         :onyx/type :function
                         :onyx/batch-size batch-size}]
              :lifecycles [{:lifecycle/task :persist


Give kitchen more start time in deployment error tests (#277)

--- waiter/integration/waiter/deployment_errors_test.clj
+++ waiter/integration/waiter/deployment_errors_test.clj
@@ -52,7 +52,7 @@
 (deftest ^:parallel ^:integration-slow test-invalid-health-check-response
   (testing-using-waiter-url
     (let [headers {:x-waiter-name (rand-name)
-                   :x-waiter-grace-period-secs 15
+                   :x-waiter-grace-period-secs 45
                    ; health check endpoint always returns status 402
                    :x-waiter-health-check-url "/bad-status?status=402"
                    :x-waiter-health-check-interval-secs 5
@@ -80,7 +80,7 @@
     (let [headers {:x-waiter-name (rand-name)
                    ; health check endpoint sleeps for 300000 ms (= 5 minutes)
                    :x-waiter-health-check-url "/sleep?sleep-ms=300000&status=400"
-                   :x-waiter-grace-period-secs 15
+                   :x-waiter-grace-period-secs 45
                    :x-waiter-health-check-interval-secs 5
                    :x-waiter-health-check-max-consecutive-failures 1
                    :x-waiter-queue-timeout 600000}


Caught exceptions when page not found

Caught exceptions when page not found

--- src/video_server/util.clj
+++ src/video_server/util.clj
@@ -154,13 +154,14 @@
   [cache url & {:keys [auth key-fn]}]
   (if (cache/has? @cache url)
     (swap! cache #(cache/hit % url))
-    (do
+    (try
       (log/trace "fetching" url)
       (let [resp (client/get (if auth (auth url) url) {:accept :json})]
         (when (= (:status resp) 200)
           (log/trace "fetched" url)
           (let [json (json/read-str (:body resp) :key-fn (or key-fn (comp keyword str/lower-case)))]
-            (swap! cache #(cache/miss % url json)))))))
+            (swap! cache #(cache/miss % url json)))))
+      (catch Exception _ nil)))
   (get @cache url))

 (defn get-xml
@@ -168,12 +169,13 @@
   [cache url]
   (if (cache/has? @cache url)
     (swap! cache #(cache/hit % url))
-    (do
+    (try
       (log/trace "fetching" url)
       (let [resp (client/get url)]
         (when (= (:status resp) 200)
           (log/trace "fetched" url)
           (let [xml (xml/parse (ByteArrayInputStream. (.getBytes (:body resp))))]
-            (swap! cache #(cache/miss % url xml)))))))
+            (swap! cache #(cache/miss % url xml)))))
+      (catch Exception _ nil)))
   (get @cache url))


[#838] Remove akvo.lumen.lib.keycloak namespace

--- backend/src/akvo/lumen/lib/keycloak.clj
+++ backend/src/akvo/lumen/lib/keycloak.clj
@@ -1,78 +0,0 @@
-(ns akvo.lumen.lib.keycloak)
-
-(comment
-  (ns akvo.lumen.lib.keycloak
-    (:require [clojure.pprint :refer [pprint]])
-    (:import [org.keycloak.admin.client Keycloak]
-             [org.keycloak.representations.idm
-              RealmRepresentation
-              UserRepresentation]))
-  (defn instance
-    [server-url realm username password client-id client-secret]
-    (Keycloak/getInstance
-     server-url realm username password client-id client-secret))
-
-  (def keycloak-instance
-    (instance
-     "http://localhost:8080/auth"
-     "akvo"
-     "lumen"
-     "password"
-     "akvo-lumen-confidential"
-     "caed3964-09dd-4752-b0bb-22c8e8ffd631"))
-
-
-  (-> keycloak-instance
-      (.realm "akvo")
-      .users)
-
-
-  (defn realm [keycloak-instance]
-    (-> keycloak-instance
-        (.realm "akvo")
-        (RealmRepresentation/.toRepresentation)))
-
-  (defn users [keycloak-instance]
-    (-> keycloak-instance
-        (.realm "akvo")
-        q.users)
-    )
-
-  (let [realm (realm (instance
-                      "http://localhost:8080/auth"
-                      "akvo"
-                      "lumen"
-                      "password"
-                      "akvo-lumen-confidential"
-                      "caed3964-09dd-4752-b0bb-22c8e8ffd631")
-                     )]
-    (prn (.users realm))
-    )
-
-
-  (defn realm [keycloak-instance]
-    (-> keycloak-instance
-        (.realm "akvo")
-        (RealmRepresentation/.toRepresentation)
-        .getRealm))
-
-  (defn instance
-    [server-url realm username password client-id client-secret]
-    (Keycloak/getInstance
-     server-url realm username password client-id client-secret))
-
-  (def k2
-    (instance
-     "http://localhost:8080/auth"
-     "akvo"
-     "lumen"
-     "password"
-     "akvo-lumen-confidential"
-     "caed3964-09dd-4752-b0bb-22c8e8ffd631"))
-
-  (-> k2
-      (.realm "akvo")
-      (RealmRepresentation/.toRepresentation)
-      .getUsers)
-
-  (realm k2))


Replace error throwing with console warn in debug mode when a command is sent to a controller that is not running

--- src/keechma/controller_manager.cljs
+++ src/keechma/controller_manager.cljs
@@ -23,7 +23,8 @@
         controller (get controllers controller-name)]
     (if controller
       (send-command-to reporter controller command-name command-args cmd-info)
-      (throw (ex-info "Trying to send command to a controller that is not running" {:controller controller-name :command command-name :args command-args})))))
+      (when (.-DEBUG js/goog)
+        (.warn js/console "Trying to send command to a controller that is not running" {:controller controller-name :command command-name :args command-args})))))

 (defn report-running-controllers [app-db-atom]
   (let [running-controllers (get-in @app-db-atom [:internal :running-controllers])]


quick println remove before server stuff

--- src/kushana/examples/tictactoe.cljs
+++ src/kushana/examples/tictactoe.cljs
@@ -55,7 +55,6 @@
   (let [new-color   (cond (= :x winner) (c3 0.5 0.2 0.2)
                           (= :o winner) (c3 0 0 1))
         [lid light] (->name scene "light")]
-    (println (get-in scene [:scene-graph lid]))
     (assoc-in scene [:scene-graph lid :groundColor] new-color)))

 (defn three-in-row [key


remove (future? <model>) handling: should be dealt with here

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -42,8 +42,7 @@
                         lexicon nil
                         truncate-children true}}]
   "Returns a single expression generated by the given language model, constrained by the given spec."
-  (let [language-model (if (future? language-model) @language-model language-model)
-        lexicon (if lexicon lexicon (:lexicon language-model))
+  (let [lexicon (if lexicon lexicon (:lexicon language-model))
         morph (:morph language-model)
         morph-ps (:morph-ps language-model)]
     (log/debug (str "generate: generating from spec: "
@@ -71,8 +70,7 @@
                             truncate-children true}}]
   (log/trace (str "generate-all: spec:" (strip-refs spec)))

-  (let [language-model (if (future? language-model) @language-model language-model)
-        total-depth (if total-depth total-depth 0)]
+  (let [total-depth (if total-depth total-depth 0)]
     (if truncate-children
       (->
        (lightning-bolts language-model spec 0 total-depth :max-total-depth max-total-depth)


add check for [:head :phrasal]

add check for [:head :phrasal]

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -198,7 +198,8 @@
                                      (over/overh parent (mapfn copy (shuffle candidate-lexemes)))))))
                        parents)
           phrasal ;; 2. generate list of all phrases where the head child of each parent is itself a phrase.
-          (if (< depth max-total-depth)
+          (if (and (< depth max-total-depth)
+                   (= true (get-in spec [:head :phrasal] true)))
             (lazy-mapcat (fn [parent]
                            (over/overh parent
                                        (lightning-bolts grammar lexicon (get-in parent [:head])


cleanup

cleanup

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -34,7 +34,6 @@

 (declare candidate-parents)
 (declare comp-path-to-complements)
-(declare comp-paths-to-complements)
 (declare do-defaults)
 (declare find-comp-paths)
 (declare get-lexemes)


all values in map that is returned by (defn create-mapping) should be lazy-seqs

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -69,7 +69,7 @@
                    bolt path model depth max-depth))
                 comp-paths))
    {[]
-    [bolt]}))
+    (lazy-seq [bolt])}))

 (defn comp-path-to-bolts
   "return a lazy sequence of bolts for all possible complements that can be added to the end of the _path_ within _bolt_."


add stubbed-out lazy-shuffle (again)

add stubbed-out lazy-shuffle (again)

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -180,6 +180,9 @@
                  rules)))

 (declare morph-with-recovery)
+
+(defn lazy-shuffle [seq]
+  seq)

 (defn lightning-bolts [grammar lexicon spec depth index morph total-depth]
   "Returns a lazy-sequence of all possible trees given a spec, where
@@ -268,8 +271,8 @@
                                                      (= true (get-in spec [:phrasal] true)))
                                               (generate-all spec grammar lexicon cache morph (+ depth total-depth)))]
                     (if (lexemes-before-phrases total-depth)
-                      (lazy-cat filtered-lexical-complements phrasal-complements)
-                      (lazy-cat phrasal-complements filtered-lexical-complements)))))))
+                      (lazy-cat (lazy-shuffle filtered-lexical-complements) phrasal-complements)
+                      (lazy-cat phrasal-complements (lazy-shuffle filtered-lexical-complements))))))))

 (defn path-to-map [path val]
   (let [feat (first path)]


add invariant that checks that at least one parent implements IQuery

same as Om d3a0a16e954a7619e93bc7490b588cbfe122baaf

--- src/cellophane/next.clj
+++ src/cellophane/next.clj
@@ -868,6 +868,13 @@
             (cond-> expr
               (util/mutation? expr) (vary-meta assoc :mutator ident)))]
     (into [] (map #(annotate % ident)) tx)))
+
+(defn some-iquery? [c]
+  (loop [c c]
+    (cond
+      (nil? c) false
+      (iquery? c) true
+      :else (recur (parent c)))))

 (defn transact!
   "Given a reconciler or component run a transaction. tx is a parse expression


Adds drop-while, drop-last, take-last, replicate, iterate, and zipmap

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -22,7 +22,7 @@
     (-index [coll]))

 (defprotocol IIndexed
-  (-nth [coll n] [coll n not-found]) )
+  (-nth [coll n] [coll n not-found]))

 (defprotocol ISeq
   (-first [coll])
@@ -43,8 +43,7 @@
 (defprotocol ISet
   (-contains? [coll v])
   (-disjoin [coll v])
-  #_(-get [coll v])
-  )
+  #_(-get [coll v]))

 (defprotocol IStack
   (-peek [coll])
@@ -216,10 +215,44 @@
                    s)))]
     (lazy-seq (step n coll))))

+(defn drop-last
+  "Return a lazy sequence of all but the last n (default 1) items in coll"
+  ([s] (drop-last 1 s))
+  ([n s] (map (fn [x _] x) s (drop n s))))
+
+(defn take-last
+  "Returns a seq of the last n items in coll.  Depending on the type
+  of coll may be no better than linear time.  For vectors, see also subvec."
+  [n coll]
+  (loop [s (seq coll), lead (seq (drop n coll))]
+    (if lead
+      (recur (next s) (next lead))
+      s)))
+
+(defn drop-while
+  "Returns a lazy sequence of the items in coll starting from the first
+  item for which (pred item) returns nil."
+  [pred coll]
+  (let [step (fn [pred coll]
+               (let [s (seq coll)]
+                 (if (and s (pred (first s)))
+                   (recur pred (rest s))
+                   s)))]
+    (lazy-seq (step pred coll))))
+
 (defn repeat
   "Returns a lazy (infinite!, or length n if supplied) sequence of xs."
   ([x] (lazy-seq (cons x (repeat x))))
   ([n x] (take n (repeat x))))
+
+(defn replicate
+  "Returns a lazy seq of n xs."
+  [n x] (take n (repeat x)))
+
+(defn iterate
+  "Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
+  {:added "1.0"}
+  [f x] (cons x (lazy-seq (iterate f (f x)))))

 (defn interleave
   "Returns a lazy seq of the first item in each coll, then the second etc."
@@ -374,6 +407,18 @@
   [coll k v]
   (when-not (nil? coll)
     (-assoc coll k v)))
+
+(defn zipmap
+  "Returns a map with the keys mapped to the corresponding vals."
+  [keys vals]
+    (loop [map {}
+           ks (seq keys)
+           vs (seq vals)]
+      (if (and ks vs)
+        (recur (assoc map (first ks) (first vs))
+               (next ks)
+               (next vs))
+        map)))

 (defn dissoc
   "dissoc[iate]. Returns a new map of the same (hashed/sorted) type,


Added a lookup sentinel to contains? to ensure the proper handling of nil

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -136,6 +136,8 @@
 (defn nil? [x]
   "Returns true if x is nil, false otherwise."
   (identical? x nil))
+
+(def ^:private lookup-sentinel (goog.global.Object.))

 ;;;;;;;;;;;;;;;;;;; protocols on primitives ;;;;;;;;
 (declare hash-map list equiv-sequential)
@@ -518,7 +520,9 @@
   range of indexes. 'contains?' operates constant or logarithmic time;
   it will not perform a linear search for a value.  See also 'some'."
   [coll v]
-  (boolean (-lookup coll v)))
+  (if (identical? (-lookup coll v lookup-sentinel) lookup-sentinel)
+    false
+    true))

 (defn distinct?
   "Returns true if no two of the arguments are ="


metadata support on fns did not work under advanced compilation in some cases as the implementation was relying on undefined behavior - rest args on protocol fns. Add a MetaFn deftype and use instead.

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -1038,18 +1038,63 @@
 (defn ^boolean fn? [f]
   (or ^boolean (goog/isFunction f) (satisfies? Fn f)))

+(deftype MetaFn [afn meta]
+  IMeta
+  (-meta [_] meta)
+  IWithMeta
+  (-with-meta [_ new-meta]
+    (MetaFn. afn new-meta))
+  Fn
+  IFn
+  (-invoke [_ a]
+    (afn a))
+  (-invoke [_ a b]
+    (afn a b))
+  (-invoke [_ a b c]
+    (afn a b c))
+  (-invoke [_ a b c d]
+    (afn a b c d))
+  (-invoke [_ a b c d e]
+    (afn a b c d e))
+  (-invoke [_ a b c d e f]
+    (afn a b c d e f))
+  (-invoke [_ a b c d e f g]
+    (afn a b c d e f g))
+  (-invoke [_ a b c d e f g h]
+    (afn a b c d e f g h))
+  (-invoke [_ a b c d e f g h i]
+    (afn a b c d e f g h i))
+  (-invoke [_ a b c d e f g h i j]
+    (afn a b c d e f g h i j))
+  (-invoke [_ a b c d e f g h i j k]
+    (afn a b c d e f g h i j k))
+  (-invoke [_ a b c d e f g h i j k l]
+    (afn a b c d e f g h i j k l))
+  (-invoke [_ a b c d e f g h i j k l m]
+    (afn a b c d e f g h i j k l m))
+  (-invoke [_ a b c d e f g h i j k l m n]
+    (afn a b c d e f g h i j k l m n))
+  (-invoke [_ a b c d e f g h i j k l m n o]
+    (afn a b c d e f g h i j k l m n o))
+  (-invoke [_ a b c d e f g h i j k l m n o p]
+    (afn a b c d e f g h i j k l m n o p))
+  (-invoke [_ a b c d e f g h i j k l m n o p q]
+    (afn a b c d e f g h i j k l m n o p q))
+  (-invoke [_ a b c d e f g h i j k l m n o p q r]
+    (afn a b c d e f g h i j k l m n o p q r))
+  (-invoke [_ a b c d e f g h i j k l m n o p q r s]
+    (afn a b c d e f g h i j k l m n o p q r s))
+  (-invoke [_ a b c d e f g h i j k l m n o p q r s t]
+    (afn a b c d e f g h i j k l m n o p q r s t))
+  (-invoke [_ a b c d e f g h i j k l m n o p q r s t rest]
+    (apply afn a b c d e f g h i j k l m n o p q r s t rest)))
+
 (defn with-meta
   "Returns an object of the same type and value as obj, with
   map m as its metadata."
   [o meta]
   (if (and (fn? o) (not (satisfies? IWithMeta o)))
-    (with-meta
-      (reify
-        Fn
-        IFn
-        (-invoke [_ & args]
-          (apply o args)))
-      meta)
+    (MetaFn. o meta)
     (when-not (nil? o)
       (-with-meta o meta))))


WIP: sending messages

WIP: sending messages

--- src/cljs/virt/chat.cljs
+++ src/cljs/virt/chat.cljs
@@ -28,7 +28,11 @@
                 om/IRender
                 (render [_] (dom/li nil message))))
             (:messages channel)))
-        (dom/input nil)))))
+        (dom/form #js {:onSubmit (fn [e]
+                                   (put! comm [:message (om/get-state owner :value)])
+                                   (.preventDefault e))}
+                  (dom/input #js {:onChange (fn [e] (om/set-state! owner :value (.-value (.-target e))))
+                                  :value (om/get-state owner :value)}))))))

 (defn branch-channel [app owner {:keys [channel]}]
   (reify
@@ -63,6 +67,7 @@
                 (case msg
                   :navigate (om/set-state! owner :page-stack (conj (om/get-state owner :page-stack) value))
                   :set-header-text (go (>! (om/get-shared owner :api-comm) [msg value]))
+                  :message (.log js/console value)
                   nil))))
         (set! (.-onmessage ws)
           (fn [e]


Add condense function and click-to-toggle

--- src/cljs_formatter.cljs
+++ src/cljs_formatter.cljs
@@ -1,10 +1,12 @@
 (ns cljs-formatter
   (:require [domina :as d]
+            [domina.xpath :as dx]
             [clojure.string :as string]
             [goog.dom :as gdom]
             [goog.style :as style]
             [goog.color :as color]
-            [goog.dom.classes :as classes]))
+            [goog.dom.classes :as classes]
+            [goog.events :as events]))

 ;;; Data to HTML strings

@@ -73,7 +75,7 @@

 ;; Colors chosen with the help of Adobe Kuler
 ;; http://kuler.adobe.com/
-(def initial-state
+(def initial-arrange-state
   (cycle ["#e6f3f7" "#f2ffff" "#e5f2ff" "#ebf7f4" "#e5fff1"]))

 (def color first)
@@ -118,8 +120,17 @@
         (do (arrange-element! (next-state state) child container)
             (d/set-styles! child {:display "block"}))))))

+(defn remove-all-styles! [elem]
+  ;; remove-attr! doesn't always work
+  (d/set-attr! elem :style "")
+  (doseq [child (d/children elem)]
+    (remove-all-styles! child)))
+
 (defn arrange-element! [state elem container]
+  (remove-all-styles! elem)
   (d/set-styles! elem {:white-space "pre"})
+  (d/remove-class! elem "condensed")
+  (d/add-class! elem "arranged")
   (when (overflow? elem container)
     (cond
      (d/has-class? elem "collection")
@@ -128,5 +139,52 @@
      (arrange-keyval! state elem container))))

 (defn arrange! [elem container]
-  (arrange-element! initial-state elem container))
+  (arrange-element! initial-arrange-state elem container))

+(defn max-inline-width [elem container]
+  (let [child (d/single-node elem)
+        parent (.-parentNode (d/single-node elem))
+        container-node (d/single-node container)
+        left-bound (.-left (.toBox (style/getBounds child)))
+        parent-right-bound (.-right (.toBox (style/getBounds parent)))
+        container-right-bound (.-right (.toBox (style/getBounds container-node)))]
+    (- (min parent-right-bound container-right-bound) left-bound)))
+
+(defn width [elem]
+  (.-width (style/getBounds (d/single-node elem))))
+
+(defn condense-collection! [elem container]
+  (let [[opener contents closer] (d/children elem)
+        w (- (max-inline-width elem container)
+             (* 2 (+ (width opener) (width closer))))]
+    (d/set-styles! opener {:font-weight "bold"})
+    (d/set-styles! closer {:font-weight "bold"})
+    (d/set-styles! contents {:color "gray"
+                             :display "inline-block"
+                             :max-width (str w "px")
+                             :overflow "hidden"
+                             :text-overflow "ellipsis"})))
+
+(defn condense! [elem container]
+  (remove-all-styles! elem)
+  (d/set-styles! elem {:white-space "pre"})
+  (d/remove-class! elem "arranged")
+  (d/add-class! elem "condensed")
+  (when (overflow? elem container)
+    (when (d/has-class? elem "collection")
+      (condense-collection! elem container))))
+
+(defn toggle! [elem container]
+  (cond (d/has-class? elem "condensed")
+        (arrange! elem container)
+        (d/has-class? elem "arranged")
+        (condense! elem container)
+        :else
+        (condense! elem container)))
+
+(defn set-toggle-on-click! [elem container]
+  (events/listen (d/single-node elem) "click"
+                 (fn [e]
+                   (.stopPropagation e)
+                   (.preventDefault e)
+                   (toggle! elem container))))


[n.ui] Add get-screen-orientation

[n.ui] Add get-screen-orientation

--- src/clojure/neko/ui.clj
+++ src/clojure/neko/ui.clj
@@ -3,7 +3,9 @@
   (:require [neko.ui.mapping :as kw]
             [neko.ui.traits :refer [apply-trait]]
             [neko.-utils :refer [keyword->setter reflect-setter
-                                 reflect-constructor]]))
+                                 reflect-constructor]])
+  (:import android.content.res.Configuration
+           neko.App))

 ;; ## Attributes

@@ -107,3 +109,16 @@
       (from activity)
       (inflate ^Integer id nil)))

+;; ## Utilities
+
+(defn get-screen-orientation
+  "Returns either :portrait, :landscape, :square, or :undefined depending on the
+  current orientation of the device."
+  ([]
+   (get-screen-orientation App/instance))
+  ([context]
+   (condp = (.. context (getResources) (getConfiguration) orientation)
+     Configuration/ORIENTATION_PORTRAIT :portrait
+     Configuration/ORIENTATION_LANDSCAPE :landscape
+     Configuration/ORIENTATION_SQUARE :square
+     :undefined)))


Replace tag func codegen with macro

Replace tag func codegen with macro

--- src/hyjinks.clj
+++ src/hyjinks.clj
@@ -128,19 +128,20 @@

 ;; Declaring a whole bunch of tags

-(defn declare-tag [sym] (eval `(def ~sym (tag ~(str sym)))))
-
-(dorun (map declare-tag [
-	'h1 'h2 'h3 'h4 'h5 'h6 'hr
-	'b 'i 'u 's 'del 'ins 'small 'sup 'sub 'pre 'q 'cite 'mark 'dbo
-	'a 'img 'embed 'object 'param 'iframe 'audio 'video
-	'ul 'ol 'li 'dl 'dt 'dd
-	'p 'span 'div 'nav 'br 'canvas 'textarea 'blockquote
-	'table 'thead 'tbody 'tfoot 'th 'tr 'td 'caption 'col 'colgroup
-	'address 'article 'header 'footer 'main 'section 'aside 'figure 'figcaption
-	'form 'legend 'select 'option 'optgroup
-	'fieldset 'label 'input 'button 'progress
-	'html 'head 'title 'link 'style 'script 'base 'body 'noscript]))
+(defmacro deftag
+	([sym] `(def ~sym (tag ~(str sym))))
+	([sym0 & syms] `(do ~@(map (fn [sym] `(deftag ~sym)) (conj syms sym0)))))
+
+(deftag h1 h2 h3 h4 h5 h6 hr)
+(deftag b i u s del ins small sup sub pre q cite mark dbo)
+(deftag a img hr embed object param iframe audio video)
+(deftag ul ol li dl dt dd)
+(deftag p span div nav br canvas textarea blockquote)
+(deftag table thead tbody tfoot th tr td caption col colgroup)
+(deftag address article header footer main section aside figure figcaption)
+(deftag form legend select option optgroup)
+(deftag fieldset label input button progress)
+(deftag html head title link style script base body noscript)

 (defn !-- [& content] (literal (str-join "<!-- " content " -->")))


Fix get-from-service-registry to actually work.

--- wildfly/src/immutant/wildfly.clj
+++ wildfly/src/immutant/wildfly.clj
@@ -84,13 +84,13 @@
     ((u/require-resolve 'immutant.wildfly.repl/start) nrepl)))

 (defn get-from-service-registry [k]
-  (if-let [registry (wu/service-registry)]
-    (if-let [servicename-class (u/try-import 'org.jboss.msc.service.ServiceName)]
-      (.getService registry
-        (if-let [service (if (instance? servicename-class k)
-                           k
-                           (. servicename-class parse k))]
-          (.getValue service))))))
+  (when-let [registry (wu/service-registry)]
+    (when-let [servicename-class (u/try-import 'org.jboss.msc.service.ServiceName)]
+      (when-let [service (.getService registry
+                           (if (instance? servicename-class k)
+                             k
+                             (eval `(ServiceName/parse ~k))))]
+        (.getValue service)))))

 (defn port
   "Returns the (possibly offset) port from the socket-binding in standalone.xml"


fancy tree printing

fancy tree printing

--- boot/aether/src/boot/aether.clj
+++ boot/aether/src/boot/aether.clj
@@ -138,11 +138,15 @@
           (mapcat (comp jar-entries jars)))))))

 (defn- print-tree
-  [tree & [depth]]
-  (let [depth (or depth 0)]
-    (doseq [[coord branch] tree]
-      (println (apply str (repeat (* depth 4) \space)) coord)
-      (when branch (print-tree branch (inc depth))))))
+  [tree & [prefixes]]
+  (loop [[[coord branch] & more] (seq tree)]
+    (when coord
+      (let [pfx (cond (not prefixes) "" (seq more) "├── " :else "└── ")]
+        (println (str (apply str prefixes) pfx coord)))
+      (when branch
+        (let [pfx (cond (not prefixes) "" (seq more) "│   " :else "    ")]
+          (print-tree branch (concat prefixes (list pfx)))))
+      (recur more))))

 (defn dep-tree
   "Returns the printed dependency graph as a string."


fix bad tid indexing/order assumption in repness/consensus-stats

--- src/polismath/math/repness.clj
+++ src/polismath/math/repness.clj
@@ -284,7 +284,7 @@
        nm/get-matrix
        mat/columns
        (map comment-stats)
-       (map #(assoc %2 :tid %1) (range))))
+       (map #(assoc %2 :tid %1) (nm/colnames data))))

 (defn select-consensus-comments


repl-interrupt now calls Thread/stop

repl-interrupt now calls Thread/stop

which is not a good idea but the only way I'm aware of to interrupt the
repl-thread.

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

--- src/conexp/gui/repl.clj
+++ src/conexp/gui/repl.clj
@@ -96,13 +96,10 @@
     result))

 (defn repl-interrupt [rpl]
-  (.interrupt (:repl-thread rpl)))
+  (.stop (:repl-thread rpl)))

 (defn repl-alive? [rpl]
   (.isAlive (:repl-thread rpl)))
-
-(defn repl-stop [rpl]
-  (.stop (:repl-thread rpl)))

 ;;; Display


Add collapse key. Fix use of debug client key.

--- src/forces_assemble/handler.clj
+++ src/forces_assemble/handler.clj
@@ -26,6 +26,7 @@
   [event client]
   {:to client
    :priority "high"
+   :collapse_key (:id event)
    :data (or (:data event) {})
    :notification {:title (or (:title event) "")
                   :body (or (:body event) "")
@@ -42,7 +43,7 @@
                   (http/post firebase-send-uri
                              {:content-type :json
                               :headers {"Authorization" api-key}
-                              :form-params (build-notification event debug-client-token)
+                              :form-params (build-notification event client-token)
                               :connection-manager cm}))
                 (db/get-user-notification-tokens-on-channel channel-id)))
     (shutdown-manager cm)


prevent excessive database trace logging during test

--- src/integration/clojure/com/xebia/visualreview/mock.clj
+++ src/integration/clojure/com/xebia/visualreview/mock.clj
@@ -28,7 +28,7 @@

 (def ^:dynamic *conn* {:classname      "org.h2.Driver"
                        :subprotocol    "h2"
-                       :subname        "file:./target/temp/vrtest.db;TRACE_LEVEL_FILE=4"
+                       :subname        "file:./target/temp/vrtest.db;TRACE_LEVEL_FILE=2"
                        :user           ""
                        :init-pool-size 1
                        :max-pool-size  1})


Update project.clj

Update project.clj

--- src/jarkeeper/views/project.clj
+++ src/jarkeeper/views/project.clj
@@ -130,5 +130,4 @@
                 "/status.svg\"></a>"))]
         ]
        ]
-     (common-views/common-footer)
-    ]))
+     (common-views/common-footer)]))


Add grimoire examples tab

Add grimoire examples tab

--- src/lt/plugins/inc_clojure.cljs
+++ src/lt/plugins/inc_clojure.cljs
@@ -4,9 +4,10 @@
             [clojure.string :as s]
             [lt.objs.editor.pool :as pool]
             [lt.plugins.clojure :as clojure]
+            [lt.objs.tabs :as tabs]
             [lt.objs.notifos :as notifos]
             [lt.objs.command :as cmd])
-  (:require-macros [lt.macros :refer [behavior]]))
+  (:require-macros [lt.macros :refer [defui behavior]]))

 ;; Util
 ;; ====
@@ -48,26 +49,34 @@
       (s/replace #"_*$" "")))

 (defn ->grimoire-url [ns var]
+  ;; Latest supported namespaces: https://github.com/clojure-grimoire/grimoire/blob/master/namespaces
+  (when-not (.startsWith ns "clojure")
+    (throw (ex-info (str ns " is not a valid namespace for grimoire") {})))
+
   ;; Hardcode latest version - not worth calculating version and
   ;; determing if grimoire supports it
   (str "http://grimoire.arrdem.com/1.6.0/" ns "/" (munge-grimoire-var var)))

-(defn open-resolved-var [->var-url {:keys [result]}]
+(defn for-resolved-var [action {:keys [result]}]
   (let [[_ ns var] (re-find #"^#'(\S+)/(\S+)$" result)]
     (if (and ns var)
-      (tab-open-url (->var-url ns var))
+      (action ns var)
       (notifos/set-msg! (str "Invalid clojure var: " result) {:class "error"}))))

-(def open-crossclj (partial open-resolved-var ->crossclj-url))
-(def open-grimoire (partial open-resolved-var ->grimoire-url))
+(def open-crossclj (partial for-resolved-var (comp tab-open-url ->crossclj-url)))
+(def open-grimoire (partial for-resolved-var (comp tab-open-url ->grimoire-url)))

 (behavior ::clj-result.callback
           :triggers #{:editor.eval.clj.result.callback}
           :reaction (fn [editor result]
-                      (if-let [callback (some->> (get-in result [:meta :callback])
+                      (try
+                        (if-let [callback (some->> (get-in result [:meta :callback])
                                                  (resolve-fn lt.plugins.inc-clojure))]
                         (callback (-> result :results first))
-                        (notifos/set-msg! (str "No callback provided for clj result: " result) {:class "error"}))))
+                        (notifos/set-msg! (str "No callback provided for clj result: " result) {:class "error"}))
+                        ;; Consider only catching invalid grimoire ns error
+                        (catch js/Error e
+                          (notifos/set-msg! (str e) {:class "error"})))))

 (defn eval-code
   "Evals code and returns result with given callback which is a keyword for callback fn"
@@ -94,8 +103,49 @@
                                    (str "(resolve '" (current-word ed) ")")
                                    :open-grimoire)))})

+;; (def url "http://grimoire.arrdem.com/1.5.0/clojure.string/blank_QMARK/examples")
+(defn GET [url cb]
+  (let [req (.get (js/require "http") url
+                  (fn [resp]
+                    (.on resp "data" cb)))]
+    (.on req "error" (fn [err]
+                       (println "Request" url "failed with:" (.-message err))))))
+
+(defui examples-panel [{:keys [body]}]
+  [:pre body])
+
+(behavior ::on-close-destroy
+          :triggers #{:close}
+          :reaction (fn [this]
+                      (object/raise this :destroy)))
+
+(object/object* ::grimoire-examples
+                :tags [:grimoire-examples]
+                :behaviors [::on-close-destroy]
+                :name "Grimoire Examples"
+                :init (fn [this]
+                        (examples-panel (apply hash-map (:args @this)))))
+
+(def ->grimoire-examples-url (comp #(str % "/examples") ->grimoire-url))
+
+(defn ->examples-tab [url]
+  (notifos/working)
+  (GET url (fn [body]
+             (tabs/add-or-focus!
+              (object/create ::grimoire-examples :body (str body)))
+             (notifos/done-working))))
+
+(def grimoire-examples-tab
+  (partial for-resolved-var (comp ->examples-tab ->grimoire-examples-url)))
+
+(cmd/command {:command :inc-clojure.grimoire-examples-tab
+              :desc "IncClojure: Open grimoire examples tab for current symbol"
+              :exec (fn []
+                      (let [ed (pool/last-active)]
+                        (eval-code ed
+                                   (str "(resolve '" (current-word ed) ")")
+                                   :grimoire-examples-tab)))})
 (comment
-
   (object/raise editor :editor.eval.clj.result.callback "OK?")
   (-> @editor :client :default deref)
   (def editor (first (pool/containing-path "core.clj")))


Add a delete function to grafter.rdf to remove quads from repos

--- src/rdf-common/grafter/rdf.clj
+++ src/rdf-common/grafter/rdf.clj
@@ -89,6 +89,21 @@
    (pr/add target graph base-uri format triple-stream)
    target))

+(defn delete
+  "Deletes a sequence of statements from the specified repository.
+
+  Takes an optional string/URI to use as a graph.
+
+  Returns target."
+
+  ([target quads]
+   (pr/delete target quads)
+   target)
+
+  ([target graph triples]
+   (pr/delete target graph triples)
+   target))
+
 (defn statements
   "Attempts to coerce an arbitrary source of RDF statements into a
   sequence of grafter Statements.


Docstrings.

Docstrings.

--- clojure/src/advent2018/day3.clj
+++ clojure/src/advent2018/day3.clj
@@ -24,6 +24,8 @@
     (aset fabric idx (inc v))))

 (defn solve-1
+  "Mark all rectangles in an array, counting the area with at least one
+  intersection."
   [input]
   (let [fabric (int-array (* 1000 1000) 0)]
     (doseq [c input]
@@ -37,14 +39,14 @@
        (> (:y2 a) (:y1 b))))

 (defn solve-2
+  "Remove all intersecting pairs of rectangles from the set of all rectangles."
   [input]
   (let [xs (transient (set (map :id input)))]
     (doseq [a input
             b input
             :when (and (not= a b)
                        (intersects? a b))]
-      (disj! xs (:id a) (:id b))
-      )
+      (disj! xs (:id a) (:id b)))
     (persistent! xs)))

 (comment


fix(docstring): do not throw exception if docstring has only one line

--- ccw.core/src/clj/ccw/core/doc_utils.clj
+++ ccw.core/src/clj/ccw/core/doc_utils.clj
@@ -85,12 +85,15 @@
    This function finds the minimum number of spaces of each line but the first,
    and removes this number of spaces from the head of each line, but the first."
   [d]
-  (let [lines (str/split-lines d)
-        padding (apply min (map #(- (count %) (count (str/triml %))) (remove str/blank? (rest lines))))]
-    (str/join "\n"
-      (concat
-        [(first lines)]
-        (map #(subs % (min padding (count %))) (rest lines))))))
+  (let [lines (str/split-lines d)]
+    (if-let [paddings (seq (map #(- (count %) (count (str/triml %)))
+                                (remove str/blank? (rest lines))))]
+      (let [padding (apply min paddings)]
+        (str/join "\n"
+                  (concat
+                    [(first lines)]
+                    (map #(subs % (min padding (count %))) (rest lines)))))
+      d)))

 (defn doc-doc [renderer {:keys [doc]}]
   (when-not (str/blank? doc)


Fix contributions endpoint.

Fix contributions endpoint.

--- src/oc/storage/api/activity.clj
+++ src/oc/storage/api/activity.clj
@@ -393,7 +393,7 @@
                              board-slugs-and-names (map #(array-map :slug (:slug %) :access (:access %) :name (:name %)) boards)
                              board-by-uuids (zipmap board-uuids board-slugs-and-names)
                              activity (assemble-contributions conn params org board-by-uuids allowed-boards author-uuid)]
-                          (activity-rep/render-activity-list params org "replies" activity boards user))))
+                          (activity-rep/render-activity-list params org "contributions" activity boards user))))

 ;; ----- Routes -----


defui-devtools: removing highlighting when we move off of a data-untangled-ui div & adding a test figwheel heads up message

--- src/untangled/client/ui.cljs
+++ src/untangled/client/ui.cljs
@@ -12,29 +12,34 @@
   (fn [e]
     (let [possible-nodes (array-seq (js/document.elementsFromPoint (.-clientX e) (.-clientY e)))
           current-node (first (filter #(.getAttribute % "data-untangled-ui") possible-nodes))]
-      (when-not (or (not current-node)
-                    (#{js/document.documentElement js/document.body} current-node)
-                    (= current-node @last-node))
-        (when (.-classList @last-node)
-          (when (.getAttribute @last-node "onclick")
-            (reset! prev-on-click (.getAttribute @node-clone "onclick"))
-            (.setAttribute @last-node "onclick" @prev-on-click))
-          (.. @last-node -classList (remove "highlight-element")))
-        (reset! node-clone (.cloneNode current-node))
-        (when (.getAttribute current-node "onclick")
-          (.setAttribute current-node "onclick" (constantly false)))
-        (.. current-node -classList (add "highlight-element"))
-        (reset! last-node current-node)))))
+      (if current-node
+        (when-not (or (#{js/document.documentElement js/document.body} current-node)
+                      (= current-node @last-node))
+          (when (.-classList @last-node)
+            (when (.getAttribute @last-node "onclick")
+              (reset! prev-on-click (.getAttribute @node-clone "onclick"))
+              (.setAttribute @last-node "onclick" @prev-on-click))
+            (.. @last-node -classList (remove "highlight-element")))
+          (reset! node-clone (.cloneNode current-node))
+          (when (.getAttribute current-node "onclick")
+            (.setAttribute current-node "onclick" (constantly false)))
+          (.. current-node -classList (add "highlight-element"))
+          (reset! last-node current-node))
+        (do
+          (when (.-classList @last-node)
+            (when (.getAttribute @last-node "onclick")
+              (reset! prev-on-click (.getAttribute @node-clone "onclick"))
+              (.setAttribute @last-node "onclick" @prev-on-click))
+            (.. @last-node -classList (remove "highlight-element")))
+          (reset! node-clone #js {}))))))

-(defn inspect-element [{:keys [node-clone select-file]}]
+(defn inspect-element [{:keys [node-clone select-file show-panel]}]
   (fn [evt]
-    ;TODO: ?? disable all other clicks?
-    ;(let [e (.getBrowserEvent evt)]
-    ;  (.preventDefault e)
-    ;  (.stopPropagation e)
-    ;  (.stopImmediatePropagation e))
-    (js/console.log @node-clone)
-    (select-file (cljs.reader/read-string (.getAttribute @node-clone "data-untangled-ui")))))
+    (when (and (.-getAttribute @node-clone)
+            (.getAttribute @node-clone "data-untangled-ui"))
+      (js/console.log @node-clone)
+      (select-file (cljs.reader/read-string (.getAttribute @node-clone "data-untangled-ui")))
+      (show-panel "test data please ignore"))))

 (defn toggle-devtools [{:keys [last-node node-clone prev-on-click remove-all-listeners install-listeners]}]
   (fn [e]
@@ -57,7 +62,7 @@
           (gobj/set js/window "attached-listeners" (atom #{})))
     (gobj/get js/window "attached-listeners")))

-(defn install-listeners [& {:keys [select-file]}]
+(defn install-listeners [& {:keys [select-file show-panel]}]
   (let [add-listener (fn [et f] (swap! attached-listeners conj (gevt/listen js/document et f)))
         remove-and-add-listener
         (fn [et f]
@@ -78,7 +83,11 @@
                                   #js {:figwheelEvent "file-selected"
                                        :fileName file
                                        :fileLine (str line)
-                                       :fileColumn (str column)})))}]
+                                       :fileColumn (str column)})))
+             :show-panel (or show-panel
+                             (fn [msg]
+                               (figwheel.client.heads-up/display-heads-up
+                                 {} (str (figwheel.client.heads-up/close-link) msg))))}]
     (remove-all-listeners)
     (add-listener EventType.MOUSEMOVE (highlight-element ctx))
     (add-listener EventType.CLICK (inspect-element ctx))


Remove useless requirement

Remove useless requirement

--- src/whisper2cyanite/core.clj
+++ src/whisper2cyanite/core.clj
@@ -4,7 +4,6 @@
             [clojure.string :as str]
             [clojure.set :as set]
             [com.climate.claypoole :as cp]
-            [clojure.java.io :as io]
             [clj-progress.core :as prog]
             [clojure.contrib.humanize :as humanize]
             [clojure.tools.logging :as log]


Cleaning up

Cleaning up

--- src/wishlistd/cljs/main.cljs
+++ src/wishlistd/cljs/main.cljs
@@ -3,9 +3,9 @@
   (:use [jayq.core :only [$ append empty delegate data]])
   (:use-macros [crate.macros :only [defpartial]]))

-(def $create ($ "#create-wishlist"))
+(def $create  ($ "#create-wishlist"))
 (def $content ($ "#box"))
-(def $header ($ "#title-box"))
+(def $header  ($ "#title-box"))

 (defpartial wish-li [{:keys [description url]}]
   [:li.wish


Only show [<number>] in text format deps if the namespace showed children

--- src/dolly/namespace.clj
+++ src/dolly/namespace.clj
@@ -195,8 +195,11 @@
                                      ns-info))
         ns-number (atom 1)
         shown-namespaces (atom {})
-        show (fn show [ns level]
+        namespace-showed-children (atom #{})
+        show (fn show [ns level parent-ns]
                (when (should-show-namespace? ns show-opts)
+                 (when parent-ns
+                   (swap! namespace-showed-children conj parent-ns))
                  (let [ns-already-printed-number (@shown-namespaces ns)
                        next-ns-number @ns-number]
                    (if ns-already-printed-number
@@ -208,16 +211,16 @@
                    (dotimes [i level] (print "  "))
                    (print ns)
                    (when (and ns-already-printed-number
-                              (not (empty? (dependencies ns))))
+                              (contains? @namespace-showed-children ns))
                      (print (format "  [%d]" ns-already-printed-number)))
                    (println)
                    (when-not ns-already-printed-number
                      (doseq [child-ns (sort (dependencies ns))]
-                       (show child-ns (inc level)))
+                       (show child-ns (inc level) ns))
                      (swap! shown-namespaces assoc ns next-ns-number)))))]
     (doseq [ns nss-unload-order]
       (when-not (@shown-namespaces ns)
-        (show ns 0)))))
+        (show ns 0 nil)))))

 (defn ns-info->graph-args [ns-info]


Fixed loadfile

Fixed loadfile

--- yaw/yaw/world.clj
+++ yaw/yaw/world.clj
@@ -563,7 +563,7 @@

 (defn loadFile [filename world]
 	"Removes the world and loads the items, cameras, lights and skybox contained in the given file in a new world."
-	(.close oldworld)
+	(.close world)
 	(Thread/sleep 200)
 	(let [universe (start-yaw)
 				world (:world @universe)


Use XDG_CONFIG_HOME if available

Use XDG_CONFIG_HOME if available

--- desktop/src/nightweb_desktop/core.clj
+++ desktop/src/nightweb_desktop/core.clj
@@ -1,6 +1,7 @@
 (ns nightweb-desktop.core
   (:gen-class)
   (:require [clojure.java.io :as java.io]
+            [clojure.string :as string]
             [nightweb.router :as router]
             [nightweb-desktop.server :as server]
             [nightweb-desktop.utils :as utils]
@@ -9,15 +10,19 @@
 (defn get-data-dir
   []
   (let [home-dir (System/getProperty "user.home")
-        osx-dir (java.io/file home-dir "Library" "Application Support")
-        win-dir (java.io/file home-dir "AppData" "Roaming")
-        app-name (utils/get-string :app_name)]
+        app-name "Nightweb"
+        app-name-lower (string/lower-case app-name)
+        osx-dir (java.io/file home-dir "Library" "Application Support" app-name)
+        win-dir (java.io/file home-dir "AppData" "Roaming" app-name)
+        lin-dir (java.io/file home-dir (str "." app-name-lower))]
     (.getCanonicalPath
       (cond
-        (.exists osx-dir) (java.io/file osx-dir app-name)
-        (.exists win-dir) (java.io/file win-dir app-name)
-        :else (->> (str "." (clojure.string/lower-case app-name))
-                   (java.io/file home-dir))))))
+        (.exists (.getParentFile osx-dir)) osx-dir
+        (.exists (.getParentFile win-dir)) win-dir
+        (.exists lin-dir) lin-dir
+        :else (if-let [config-dir (System/getenv "XDG_CONFIG_HOME")]
+                (java.io/file config-dir app-name-lower)
+                (java.io/file home-dir ".config" app-name-lower))))))

 (defn -main
   []


Upgrades some lein plugins.

Upgrades some lein plugins.

--- .lein/profiles.clj
+++ .lein/profiles.clj
@@ -1,7 +1,7 @@
 {:user {:plugins [[lein-tarsier "0.9.1"]
                   [lein-swank "1.4.4"]
                   [lein-difftest "1.3.7"]
-                  [lein-clojars "0.8.0"]
+                  [lein-clojars "0.9.0"]
                   ;[jark/jark-server "0.4.0"]
                   [clj-stacktrace "0.2.4"]
                   [lein-pprint "1.1.1"]
@@ -9,13 +9,11 @@
                   [lein-cljsbuild "0.1.9"]
                   [lein-deps-tree "0.1.1"]
                   ;[lein-autodoc "0.9.0"]
-                  [lein-marginalia "0.7.0"]
-                  [lein-noir "1.2.0"]]
+                  [lein-marginalia "0.7.1"]]
         :repl-options {:timeout 60000}
-        :injections [(let [orig (ns-resolve (doto 'clojure.stacktrace require)
-                                            'print-cause-trace)
-                           new (ns-resolve (doto 'clj-stacktrace.repl require)
-                                           'pst)]
-                       (alter-var-root orig (constantly @new)))]
-        :vimclojure-opts {:repl true
-                          :port 2113}}}
+        ;:injections [(let [orig (ns-resolve (doto 'clojure.stacktrace require)
+                                            ;'print-cause-trace)
+                           ;new (ns-resolve (doto 'clj-stacktrace.repl require)
+                                           ;'pst)]
+                       ;(alter-var-root orig (constantly @new)))]
+        :vimclojure-opts {:repl true}}}


Improve from and subject for news email

Improve from and subject for news email

--- src/servisne_info/notifications.clj
+++ src/servisne_info/notifications.clj
@@ -6,7 +6,7 @@
             [servisne-info.event :as event]
             [servisne-info.views.email :as email]))

-(def default-from "info@servisne.info")
+(def default-from "Servisne Informacije <info@servisne.info>")

 (defn send-email
   [to subject body]
@@ -22,7 +22,7 @@
 (defn send-news-email [user news]
   (event/record "Sending news email" {:user (:email user)})
   (send-email (:email user)
-              "Servisne informacije"
+              "[servisne.info] Nove Servisne Informacije"
               (email/render "new_links.txt"
                             {:links (map :url news)})))


Increase history requesting the last 200 activities

--- src/strava_activity_graphs/core.clj
+++ src/strava_activity_graphs/core.clj
@@ -9,7 +9,9 @@
   (json/read-str
     ((http-client/get
        "https://www.strava.com/api/v3/activities"
-       {:query-params {:access_token token}})
+       {:query-params
+        {:access_token token
+         :per_page 200}})
       :body)))

 (defn to-millis [str-date]


Test for further parsing deactived

Test for further parsing deactived

--- test/analyze_runs/gpx_test.clj
+++ test/analyze_runs/gpx_test.clj
@@ -25,7 +25,7 @@
   (let [first-point (first points-from-sample-file)]
     (is (= (:lon first-point) 7.187874))))

-(deftest assert-heart-rate-first-point
+(comment deftest assert-heart-rate-first-point
   (let [first-point (first points-from-sample-file)]
     (is (= (:heart-rate first-point) 114))))


remove fluff file

remove fluff file


fixing build

fixing build

--- test/celestial/test/puppet.clj
+++ test/celestial/test/puppet.clj
@@ -1,4 +1,5 @@
 (ns celestial.test.puppet
+  (:require proxmox.provider aws.provider celestial.puppet_standalone); loading defmethods
   (:use
     midje.sweet
     [celestial.model :only (pconstruct)]


another test

another test

--- ccw.core/src/ccw/editors/antlrbased/ClojureFormat.clj
+++ ccw.core/src/ccw/editors/antlrbased/ClojureFormat.clj
@@ -111,6 +111,6 @@
                     cmindent))))
       (apply str out))))

-
 (deftest code-formatting
-  (is (= "#\"something\"" (format-code "#\"something\""))))
+  (is (= "#\"something\"" (format-code "#\"something\"")))
+  (is (= "(resourcefully/put url {\"Content-Type\" \"multipart/form-data\" \"Encoding\" \"UTF-8\"} request)))" (format-code "(resourcefully/put url {\"Content-Type\" \"multipart/form-data\" \"Encoding\" \"UTF-8\"} request)))"))))


cjl - Finish get games test

cjl - Finish get games test


re-fix a unit test

re-fix a unit test

--- cimi/test/com/sixsq/slipstream/auth/utils/db_test.clj
+++ cimi/test/com/sixsq/slipstream/auth/utils/db_test.clj
@@ -38,7 +38,7 @@
       (is (= false (:deleted user)))
       (is (= "st@s.com" (:emailAddress user)))
       (is (= false (:isSuperUser user)))
-      (is (= uuid (:username user)))
+      (is (= "st" (:username user)))
       (is (= "ACTIVE" (:state user)))
       (is (= "first" (:firstName user)))
       (is (= "last" (:lastName user)))


Minor changes on extend with custom types experiments.

--- test/suricatta/extend_test.clj
+++ test/suricatta/extend_test.clj
@@ -21,31 +21,55 @@

 (use-fixtures :each my-fixture)

-(defn jsonfield
+(defn json
   [data]
   (proxy [org.jooq.impl.CustomField] [nil, org.jooq.util.postgres.PostgresDataType/JSON]
-    (toSQL [^org.jooq.RenderContext rctx]
-      (doto rctx
-        (.sql "'")
-        (.sql (generate-string data))
-        (.sql "'::json")))
+    (accept [ctx]
+      (cond
+       (instance? org.jooq.RenderContext ctx)
+       (doto ctx
+         (.sql "'")
+         (.sql (generate-string data))
+         (.sql "'::json"))

-    (bind [^org.jooq.BindContext bctx]
-      (let [obj (doto (PGobject.)
-                  (.setType "json")
-                  (.setValue (generate-string data)))
-            statement (.statement bctx)]
-        (.setObject statement
-                    (.nextIndex bctx)
-                    obj)))))
+       (instance? org.jooq.BindContext ctx)
+       (let [obj        (doto (PGobject.)
+                          (.setType "json")
+                          (.setValue (generate-string data)))
+             statement  (.statement ctx)
+             _          (println 454545 (class (.getDelegate statement)))
+             paramcount (.getParameterCount (.getParameterMetaData statement))]
+        (when (<= (.peekIndex ctx) paramcount)
+          (.setObject statement
+                      (.nextIndex ctx)
+                      obj)))))))

-(deftest inserting-json-fields
-  (sc/execute *ctx* "create table t1 (data json)")
-  (sc/execute *ctx* ["insert into t1 (data) values (?)" (jsonfield {:foo "bar"})])
+
+(deftest inserting-json
+  (sc/execute *ctx* "create table t1 (data json, k int)")
+  (sc/execute *ctx* ["insert into t1 (data, k) values (?, ?)" (json {:foo "bar"}) 2])
   (-> (sc/fetch *ctx* "select * from t1")
       (println)))

-(deftest json-fields-in-dsl
-  (let [q (-> (dsl/select (jsonfield {:a 1}))
-              (dsl/from "dual"))]
-    (println (get-sql q))))
+
+(deftest inserting-json-dsl
+  (sc/execute *ctx* "create table t1 (data json)")
+  (let [q (-> (dsl/insert-into :t1)
+              (dsl/insert-values {:data (json {:foo 1})})
+              (dsl/insert-values {:data (json {:bar 2})}))]
+    (sc/execute *ctx* q))
+  (-> (sc/fetch *ctx* "select * from t1")
+      (println)))
+
+
+(deftest inserting-arrays
+  (sc/execute *ctx* "create table t1 (data int[])")
+  (let [data [1 2 3]]
+    (sc/execute *ctx* ["insert into t1 (data) values (?)" data])
+    (-> (sc/fetch *ctx* "select * from t1")
+        (println))))
+
+(deftest json-select
+  (let [q (dsl/select (.as (json {:a 1}) "dd"))]
+    (-> (sc/fetch *ctx* q)
+        (println))))


freeze chrome profile test (#297)

freeze chrome profile test (#297)

--- test/etaoin/api_test2.clj
+++ test/etaoin/api_test2.clj
@@ -31,14 +31,14 @@
         (is (= ["geckodriver" "--port" 1234 "--marionette-port" 2821]
                (:args @driver)))))))

-(deftest test-chrome-profile
-  (let [profile-path (str (Files/createTempDirectory
-                            "chrome-profile"
-                            (into-array FileAttribute [])))]
-    (with-chrome {:profile profile-path} driver
-      (go driver "chrome://version")
-      (is profile-path
-          (get-element-text driver :profile_path)))))
+#_(deftest test-chrome-profile
+    (let [profile-path (str (Files/createTempDirectory
+                              "chrome-profile"
+                              (into-array FileAttribute [])))]
+      (with-chrome-headless {:profile profile-path :args ["--no-sandbox"]} driver
+        (go driver "chrome://version")
+        (is profile-path
+            (get-element-text driver :profile_path)))))

 (deftest test-fail-run-driver
   (is (thrown-with-msg?


add multi note play attempt

add multi note play attempt

--- ohack/src/ohack/core.clj
+++ ohack/src/ohack/core.clj
@@ -134,11 +134,6 @@
 (def playguitar320
   (partial guitar-pick-note-sequence 320))  ;; 320ms delay between picked strings

-;; now we can play a sequence of notes defined by
-;; [string-index fret-value]
-(playguitar320 [[0 8] [0 10] [0 12] [0 13] [0 15]]) ;;C scale on low E
-(playguitar320 [[4 1] [4 3] [4 5] [4 6] [4 8]])     ;;C scale on b string
-
 (def everybody-hurts
  "
   ;; Guitar Tab for Everybody Hurts by REM
@@ -152,6 +147,7 @@
   ;; E:0]---------------------------3-----------3-----------[
 ")

-;; the first 12 notes from the above tab can be played so:
-(playguitar320 [[2 0] [3 2] [4 3] [5 2] [4 3] [3 2]
-                [0 3] [3 0] [4 0] [5 3] [4 0] [3 0]])
+;; suppose now we want to play a multiple notes together so every
+;; sequence within the input sequence contains pairs of numbers of
+;; string-index fret-value, e.g.
+(playguitar320 [[0 3, 3 0, 4 0, 5 3]])


uncommenting and refactoring tests for board, initialize cards, and shuffle cards

--- test/cartagena/core_test.clj
+++ test/cartagena/core_test.clj
@@ -9,39 +9,28 @@

 #_(use-fixtures :each reset-cards!)

-#_(deftest initialize-board!-test
+(deftest initialize-board-test
   (testing "Returns the right number of spaces as well as icons"
-    (let [board-spaces (initialize-board!)]
+    (let [board-spaces (initialize-board)]
       (is (= 36 (count board-spaces)))
       (doseq [icon [:bottle :gun :hat :key :knife :skull]]
         (is (= 6 (count (filter #(= icon %) board-spaces)))))))
   (testing "Boards are not exactly alike"
-    (is (not (= (initialize-board!) (initialize-board!))))))
+    (is (not (= (initialize-board) (initialize-board))))))

-#_(deftest place-cards!-test
-  (testing "Placing cards populates the discard pile"
-    (is (= 0 (count @discard-pile)))
-    (place-cards!)
-    (is (= 102 (count @discard-pile)))))
+(deftest initialize-cards-test
+  (testing "Returns a pile of 102 cards, 17 of each icon"
+    (let [cards (initialize-cards)]
+      (is (= 102 (count cards)))
+      (doseq [icon icons]
+        (is (= 17 (count (filter #(= icon %) cards))))))))

-#_(deftest shuffle-cards!-test
-  (testing "Shuffles the cards in the discard pile and places them in the draw pile"
-    (place-cards!)
-    (is (= 0 (count @draw-pile)))
-    (let [discards (vec @discard-pile)]
-      (shuffle-cards!)
-      (is (= 102 (count @draw-pile)))
-      (is (= 0 (count @discard-pile)))
-      (is (not (= discards @draw-pile)))))
-  (testing "Shuffling cards when the draw pile is empty does nothing"
-    (place-cards!)
-    (reset! draw-pile @discard-pile)
-    (reset! discard-pile [])
-    (is (= 0 (count @discard-pile)))
-    (is (= 102 (count @draw-pile)))
-    (let [draws @draw-pile]
-      (shuffle-cards!)
-      (is (= draws @draw-pile)))))
+(deftest shuffle-cards-test
+  (testing "Returns the same count but in different (random) order"
+    (let [cards [:key :key :knife :knife :skull :skull :gun :gun :bottle :bottle :hat :hat]
+          shuffled (shuffle-cards cards)]
+      (is (= (count cards) (count shuffled)))
+      (is (not (= cards shuffled))))))

 #_(deftest draw-cards!-test
   (testing "Drawing n cards removes them from the draw pile"


Two tests for NPE in startsWith and endsWith

--- test/clouseau/test_utils.clj
+++ test/clouseau/test_utils.clj
@@ -238,8 +238,14 @@
             true  (startsWith "Hello world!" "H")
             true  (startsWith "Hello world!" ""))))

-(deftest test-ends-with-1
-    "Check the function clouseau.utils/ends-with."
+(deftest test-starts-with-NPE
+    "Check the function clouseau.utils/starts-with."
+    (testing "the function clouseau.utils/starts-with."
+        (is (thrown? NullPointerException (startsWith nil nil)))
+        (is (thrown? NullPointerException (startsWith "text" nil)))
+        (is (thrown? NullPointerException (startsWith nil "text")))))
+
+(deftest test-ends-with-1 "Check the function clouseau.utils/ends-with."
     (testing "the function clouseau.utils/ends-with."
         (are [x y] (= x y)
             true  (endsWith "Hello world!" "Hello world!")
@@ -248,3 +254,10 @@
             true  (endsWith "Hello world!" "!")
             true  (endsWith "Hello world!" ""))))

+(deftest test-ends-with-NPE
+    "Check the function clouseau.utils/ends-with."
+    (testing "the function clouseau.utils/ends-with."
+        (is (thrown? NullPointerException (endsWith nil nil)))
+        (is (thrown? NullPointerException (endsWith "text" nil)))
+        (is (thrown? NullPointerException (endsWith nil "text")))))
+


Dash -> dot

Dash -> dot

--- test/onyx/test_helper.clj
+++ test/onyx/test_helper.clj
@@ -52,6 +52,6 @@
             (assoc-in cfg [:peer-config :onyx.messaging/impl] :aeron)
             (= impl "netty")
             (assoc-in cfg [:peer-config :onyx.messaging/impl] :netty)
-            (= impl "core-async")
+            (= impl "core.async")
             (assoc-in cfg [:peer-config :onyx.messaging/impl] :core.async)
             :else cfg))))


fixed reflection issues

fixed reflection issues

--- clj/src/bucket_distributor_clj/core.clj
+++ clj/src/bucket_distributor_clj/core.clj
@@ -8,7 +8,8 @@
             [langohr.consumers :as lc]
             [langohr.basic     :as lb]
             [midje.sweet       :as t])
-  (:import [java.util.concurrent LinkedBlockingQueue TimeUnit Executors ScheduledExecutorService]))
+  (:import [java.util.concurrent BlockingQueue LinkedBlockingQueue TimeUnit Executors
+            ScheduledExecutorService Future]))

 (defn require-ch
   [conn]
@@ -82,7 +83,7 @@
           (lq/declare ch bucket-queue {:durable false
                                        :exclusive false,
                                        :auto-delete false})
-          (doseq [bucket buckets]
+          (doseq [^String bucket buckets]
             (lb/publish ch "" bucket-queue (.getBytes bucket))))))))

 ;;
@@ -92,7 +93,7 @@
 (defn- bucket-consumer-shutdown-handler!
   "Cleans up resources on consumer shutdown based on observing changes to
    the consumer state."
-  [old-state {:keys [instance-id status active empty-signal ch consumer-tag]}]
+  [old-state {:keys [instance-id status active ^BlockingQueue empty-signal ch consumer-tag]}]

   (cond
     ;; Let the shutdown thread know (via blockingqueue) when all the active
@@ -159,7 +160,7 @@
   [state-atom & {:keys [force-stop]}]

     (loop []
-      (let [{:keys [status empty-signal]} (swap! state-atom stop-swap force-stop)]
+      (let [{:keys [status ^BlockingQueue empty-signal]} (swap! state-atom stop-swap force-stop)]
         (when (not= status :stopped)
           (log/debugf "[%s] waiting for empty signal" (:instance-id @state-atom))
           (.take empty-signal) ;; wait for a message indicating we should try again
@@ -207,10 +208,12 @@
 ;; broadcast sender and consumer
 ;;

-(defn send-broadcast! [conn exchange-name peer-id message]
-  (with-open [ch (require-ch conn)]
+(defn send-broadcast! [conn exchange-name peer-id ^String message]
+  (with-chan [ch conn]
     (lb/publish ch exchange-name "" (.getBytes message)
                 {:headers {"peer-id" peer-id}})))
+
+(defrecord BroadcastConsumer [ch consumer-tag])

 (defn start-broadcast-consumer!
   "Creates and starts a broadcast consumer, returns a record that contains
@@ -221,7 +224,8 @@
   (let [ch (require-ch conn)
         queue-name (-> ch lq/declare :queue)
         handler (fn [ch {:keys [delivery-tag headers]} ^bytes payload]
-                  (let [sender-id (-> (get headers "peer-id")
+                  (let [^com.rabbitmq.client.LongString sender-wrapper (get headers "peer-id") ; rabbit driver weirdness
+                        sender-id (-> sender-wrapper
                                       (.getBytes)
                                       (String.))
                         broadcast (String. payload)]
@@ -236,8 +240,8 @@
     (le/declare ch exchange-name "fanout")
     (lq/bind ch queue-name exchange-name)

-    {:ch ch
-     :consumer-tag (lc/subscribe ch queue-name handler)}))
+    (map->BroadcastConsumer {:ch ch
+                             :consumer-tag (lc/subscribe ch queue-name handler)})))

 (defn stop-broadcast-consumer!
   "Shuts down the broadcast consumer. Returns nil."
@@ -265,7 +269,7 @@
     (assoc state :peers (dissoc peers peer-id)))

 (defn- handle-broadcast!
-  [{:keys [peer-id state-atom broadcast!] :as distributor} sender-id msg]
+  [{:keys [peer-id state-atom broadcast!] :as distributor} sender-id ^String msg]

   (when-not (= peer-id sender-id)
     (log/debugf "[%s] received [%s]" peer-id msg))
@@ -284,7 +288,7 @@

 ;; handle periodic self-announce and peer expiration

-(defn- expire-swap [expiration-period expiration-units peer-id {:keys [peers] :as state}]
+(defn- expire-swap [expiration-period ^TimeUnit expiration-units peer-id {:keys [peers] :as state}]
   (let [now (System/currentTimeMillis)
         oldest-permitted (- now (.toMillis expiration-units expiration-period))
         expired (->> peers
@@ -365,6 +369,9 @@

 ;; bucket distributor main entry point

+(defrecord RabbitBucketDistributor [options default-buckets peer-id state-atom
+                              broadcast! broadcast-consumer peers-future partition-future])
+
 (defn start-bucket-distributor!
   [conn bucket-name default-buckets ^ScheduledExecutorService scheduler options]

@@ -393,11 +400,11 @@
           broadcast! #(send-broadcast! conn broadcast-exchange peer-id %)

           ; core stuff that gets passed around
-          distributor {:options options
-                       :default-buckets default-buckets
-                       :peer-id peer-id
-                       :state-atom state-atom
-                       :broadcast! broadcast!}
+          distributor (map->RabbitBucketDistributor {:options options
+                                                     :default-buckets default-buckets
+                                                     :peer-id peer-id
+                                                     :state-atom state-atom
+                                                     :broadcast! broadcast!})

           broadcast-consumer (start-broadcast-consumer! conn broadcast-exchange
                                                         #(handle-broadcast! distributor %1 %2))
@@ -415,7 +422,7 @@
                                  partition-delay partition-period partition-units)))))

 (defn stop-bucket-distributor!
-  [{:keys [broadcast! broadcast-consumer peers-future partition-future peer-id state-atom]}]
+  [{:keys [broadcast! broadcast-consumer ^Future peers-future ^Future partition-future peer-id state-atom]}]

   (log/infof "[%s] stopping distributor" peer-id)

@@ -445,7 +452,27 @@

   (dist-add)
   (dist-remove)
-  (clojure.pprint/pprint distributors))
+  (clojure.pprint/pprint distributors)
+
+  (do
+    (doseq [dist @distributors]
+      (let [consumer (-> @distributors first :state-atom deref :bucket-consumer)
+            buckets (buckets! consumer)]
+        (release! consumer buckets)))
+
+    (Thread/sleep 1000)
+
+    (doseq [dist @distributors]
+      (let [consumer (-> dist :state-atom deref :bucket-consumer)
+            buckets (buckets! consumer)]
+        (prn buckets))))
+
+  (count @distributors)
+
+  (def consumer (-> @distributors first :state-atom deref :bucket-consumer))
+  (buckets! consumer)
+  (release! consumer (buckets! consumer))
+  )

 (defprotocol BucketDistributor "A mechanism for coordinated distribution of
                                 hash buckets."


cleanup

cleanup

--- ccw.core/src/ccw/debug/serverrepl.clj
+++ ccw.core/src/ccw/debug/serverrepl.clj
@@ -10,9 +10,7 @@
 ; *******************************************************************************/
 ; Totally footprint free embedded evaluation server
 ; (do not have any namespace / symbol presence)
-(ns ccw.debug.serverrepl
-  (:require [clojure.contrib.duck-streams :as cocks])
-  (:use clojure.contrib.repl-utils))
+(ns ccw.debug.serverrepl)

 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; library code


Clean up error handling to catch exceptions and return ErrorResponse messages over the Avro channel

--- sherpa-clojure/src/main/clojure/sherpa/sherpa_server.clj
+++ sherpa-clojure/src/main/clojure/sherpa/sherpa_server.clj
@@ -31,10 +31,7 @@

 (defmulti sherpa-rpc (fn [msg listener request] msg))
 (defmethod sherpa-rpc :default [msg listener request]
-           (throw {:sherpa-type "ErrorResponse"
-                   :code {:sherpa-type :ReasonCode
-                          :symbol :Error}
-                   :message (str "Unknown message type: " msg)}))
+           (throw (RuntimeException. (str "Unknown message type: " msg))))

 (defmacro add-rpc [msg return-type]
   `(defmethod sherpa-rpc ~msg [m# listener# avro-request#]
@@ -54,6 +51,15 @@
 (add-rpc "cancel" "CloseResponse")
 (add-rpc "close" "CloseResponse")

+(defn- error-response [exception-or-message]
+  (let [msg (if (instance? Throwable exception-or-message)
+              (.getMessage exception-or-message)
+              exception-or-message)]
+    (to-avro {:sherpa-type :ErrorResponse
+              :code {:sherpa-type :ReasonCode
+                     :symbol :Error}
+              :message msg} PROTOCOL)))
+
 (defn responder
   "Adapt a SherpaListener into an Avro Responder."
   [listener]
@@ -65,8 +71,7 @@
                                          (sherpa-rpc msg-name listener (.get request msg-name)))
                                        (catch Throwable t
                                          (do (.printStackTrace t)
-                                             ;; TODO throw ErrorResponse
-                                             (throw t))))))))
+                                             (error-response t))))))))

 (defn run-sherpa
   "Run a sherpa server that directs calls to the listener, which should


Add link to equations of motion wiki page

--- src/uk/co/tombooth/pollock.cljs
+++ src/uk/co/tombooth/pollock.cljs
@@ -140,7 +140,8 @@

 ;; Now that we can generate a random point in space we want to project
 ;; this to the canvas. We are going to use [Newtonian equations of
-;; motion](http://wiki), we know the position, velocity and acceleration of the
+;; motion](https://en.wikipedia.org/wiki/Equations_of_motion),
+;; we know the position, velocity and acceleration of the
 ;; point and we want to know what the position and velocity are when y
 ;; is 0. In order to work out final positions we need to know the
 ;; total time the point spent falling, we can do this using the y


Add install-deps key to cljs_options (#588)

--- sidecar/src/figwheel_sidecar/schemas/cljs_options.clj
+++ sidecar/src/figwheel_sidecar/schemas/cljs_options.clj
@@ -509,6 +509,13 @@
 https://anmonteiro.com/2017/03/requiring-node-js-modules-from-clojurescript-namespaces/

   :npm-deps {:left-pad \"1.1.3\" }")
+
+(def-key ::install-deps boolean?
+
+  "When set to true, the Clojurescript compiler will handle downloading
+the Javascript dependencies defined in the :npm-deps section of the config.
+
+  :install-deps true")

 (def-key ::closure-extra-annotations
   (s/every non-blank-string? :min-count 1 :into [] :kind sequential?)
@@ -1025,6 +1032,7 @@
      ::language-in
      ::language-out
      ::npm-deps
+     ::install-deps
      ::closure-defines
      ::closure-extra-annotations
      ::anon-fn-naming-policy