Added dark regression tests for most elements

--- src/visuals/untangled/ui/element_visuals.cljs
+++ src/visuals/untangled/ui/element_visuals.cljs
@@ -14,21 +14,26 @@
 (defcard avatar-visual-regressions
   (dom/div nil
     (for [color [:none :primary :accent]
-          kind [:none :bordered]
-          size  [:regular :medium :large :xlarge :huge]]
-      (dom/span #js {:key (str "id" color kind size)}
+          kind  [:none :bordered]
+          size  [:regular :medium :large :xlarge :huge]
+          dark  [false true]]
+      (dom/div #js {:className (if dark "t-dark" "") :style #js {:display "inline-block"} :key (str "id-" color kind size dark)}
         (e/ui-avatar {:color color :kind kind :size size} "AV")
-        (e/ui-avatar {:color color :kind kind :size size} (icon :supervisor_account))))))
+        (e/ui-avatar {:color color :kind kind :size size} (icon :supervisor_account))
+        ))))

 (defcard badges-visual-regressions
   (dom/div nil
-    (e/ui-button {} "Notifications " (e/ui-badge {} "8"))
-    (e/ui-button {:color :primary} "Notifications " (e/ui-badge {} "8"))
-    (e/ui-button {:color :accent} "Notifications " (e/ui-badge {} "5"))
-    (e/ui-badge {:className "hello"} "7")
-    (e/ui-badge {} (icon :arrow_back))
-    (e/ui-badge {} (icon :arrow_back) (icon :arrow_forward))))
+    (for [color [:none :primary :accent]
+          dark [false true]]
+     (dom/div #js {:className (if dark "t-dark" "") :style #js {:display "inline-block"} :key (str "badge-" color dark)}
+       (e/ui-button {:color color} "Notifications " (e/ui-badge {} "8"))
+       (e/ui-badge {:color color :className "hello"} "7")
+       (e/ui-badge {:color color} (icon :arrow_back))
+       (e/ui-badge {:color color} (icon :arrow_back) (icon :arrow_forward))
+       )))
+  )

 (defcard buttons-visual-regression-testing
@@ -37,12 +42,17 @@
           color    [:neutral :primary :accent]
           size     [:normal :small]
           disabled [false true]
-          active   [false true]]
-      (e/ui-button {:className "extra" :color color :active active :disabled disabled
-                    :shape     shape :size size :key (str "btn-" shape color size disabled active)}
-        (str shape " " color " " size " " (when disabled "disabled ") (when active "active "))))
+          active   [false true]
+          dark     [false true]]
+      (dom/span #js {:className (if dark "t-dark" "") :style #js {:display "inline-block"} :key (str "btn-" shape color size disabled active dark)}
+        (e/ui-button {:className "extra" :color color :active active :disabled disabled
+                     :shape     shape :size size}
+         (str shape " " color " " size " " (when disabled "disabled ") (when active "active ")))))
     (e/ui-button {} "Label" (icon :arrow_forward))
-    (e/ui-button {} (icon :arrow_back) "Label")))
+    (e/ui-button {} (icon :arrow_back) "Label")
+    (dom/div #js {:className "t-dark"}
+      (e/ui-button {} "Label" (icon :arrow_forward))
+      (e/ui-button {} (icon :arrow_back) "Label"))))

 (defcard flat-buttons-visual-regression-testing
   (dom/div nil
@@ -50,36 +60,38 @@
           color    [:neutral :primary :accent]
           size     [:normal :small]
           disabled [false true]
-          active   [false true]]
-      (e/ui-flat-button {:className "extra" :color color :active active :disabled disabled
-                         :shape     shape :size size  :key (str "btn-flat-" shape color size disabled active)}
-        (str shape " " color " " size " " (when disabled "disabled ") (when active "active "))))
+          active   [false true]
+          dark     [false true]]
+      (dom/span #js {:className (if dark "t-dark" "") :style #js {:display "inline-block"}  :key (str "btn-flat-" shape color size disabled active dark)}
+        (e/ui-flat-button {:className "extra" :color color :active active :disabled disabled
+                          :shape     shape :size size}
+         (str shape " " color " " size " " (when disabled "disabled ") (when active "active ")))))
     (e/ui-flat-button {} "Label" (icon :arrow_forward))
-    (e/ui-flat-button {} (icon :arrow_back) "Label")))
+    (e/ui-flat-button {} (icon :arrow_back) "Label")
+    (dom/div #js {:className "t-dark"}
+      (e/ui-flat-button {} "Label" (icon :arrow_forward))
+      (e/ui-flat-button {} (icon :arrow_back) "Label"))))

 (defcard circular-buttons-visual-regression-testing
   (dom/div nil
     (for [color    [:neutral :primary :accent]
           size     [:normal :small]
           disabled [false true]
-          active   [false true]]
-      (e/ui-circular-button {:className "extra" :color color :active active :disabled disabled
-                             :title     (str (name color) " " (name size) " " (when disabled "disabled ") (when active "active "))
-                             :size      size  :key (str "btn-circular-" color size disabled active)}
-        (icon :add)))))
+          active   [false true]
+          dark     [false true]]
+      (dom/span #js {:className (if dark "t-dark" "") :style #js {:display "inline-block"} :key (str "btn-circular-" color size disabled active dark)}
+        (e/ui-circular-button {:className "extra" :color color :active active :disabled disabled
+                              :title     (str (name color) " " (name size) " " (when disabled "disabled ") (when active "active "))
+                              :size      size}
+         (icon :add))))))

 (defcard checkbox-visual-regressions
   (dom/div nil
-    (dom/div nil
-      (dom/label #js {:className "is-optional" :style #js {:width "80px"}} "Normal ")
-      (e/ui-checkbox {:id "checkbox-1"})
-      (e/ui-checkbox {:id "checkbox-3" :checked true})
-      (e/ui-checkbox {:id "checkbox-3" :checked :partial}))
-    (dom/div nil
-      (dom/label #js {:className "is-optional" :style #js {:width "80px"}} "Disabled ")
-      (e/ui-checkbox {:id "checkbox-2" :disabled true})
-      (e/ui-checkbox {:id "checkbox-3" :checked true :disabled true})
-      (e/ui-checkbox {:id "checkbox-4" :checked :partial :disabled true}))))
+    (for [checked  [false true :partial]
+          dark     [false true]
+          disabled [false true]]
+      (dom/div #js {:className (if dark "t-dark" "") :style #js {:display "inline-block"} :key (str "id-" checked dark disabled)}
+        (e/ui-checkbox {:id (str "id-" checked dark disabled) :checked checked :disabled disabled})))))

 (defcard empty-state-visual-regressions
@@ -90,101 +102,126 @@
         (dom/link #js {:rel "stylesheet" :href "css/untangled-ui.css"})
         (e/ui-empty-state {})))

+    (e/ui-iframe {:width "100%" :height "400px"}
+      (dom/div #js {:className "t-dark" :style #js {:height "100%"}}
+        (dom/link #js {:rel "stylesheet" :href "css/untangled-ui.css"})
+        (e/ui-empty-state {})))
+
     (dom/h1 nil "Custom specification")
     (e/ui-iframe {:width "100%" :height "400px"}
-     (dom/div nil
-       (dom/link #js {:rel "stylesheet" :href "css/untangled-ui.css"})
-       (e/ui-empty-state {:glyph :widgets :title "No widgets yet" :message "Create a widget to get started"}))))
+      (dom/div nil
+        (dom/link #js {:rel "stylesheet" :href "css/untangled-ui.css"})
+        (e/ui-empty-state {:glyph :widgets :title "No widgets yet" :message "Create a widget to get started"})))
+
+    (e/ui-iframe {:width "100%" :height "400px"}
+      (dom/div #js {:className "t-dark" :style #js {:height "100%"}}
+        (dom/link #js {:rel "stylesheet" :href "css/untangled-ui.css"})
+        (e/ui-empty-state {:glyph :widgets :title "No widgets yet" :message "Create a widget to get started"}))))
   )

 (defcard field-visual-regressions
   (dom/div nil
-    (for [size [:normal :small :medium :large]
-          states [:valid :invalid :error]]
-      (e/ui-field {:size size :state states :key (str size states (rand-int 256))} (str (name size) " " (name states) " field")))))
+    (for [size   [:normal :small :medium :large]
+          states [:valid :invalid :error]
+          dark   [false true]]
+      (dom/div #js {:className (when dark "t-dark") :style #js {:display "inline-block"} :key (str "field-" size states dark (rand-int 256))}
+        (e/ui-field {:size size :state states} (str (name size) " " (name states) " field"))))))

 (defcard icon-colors-visual-regressions
   (dom/div nil
-    (e/ui-icon {} (icon :alarm))
-    (e/ui-icon {:color :active} (icon :alarm))
-    (e/ui-icon {:color :passive} (icon :alarm))
-    (e/ui-icon {:size :huge :color :passive} (icon :alarm))))
+    (for [color [:none :active :passive]
+          size  [:normal :huge]
+          dark  [false true]]
+      (dom/div #js {:className (when dark "t-dark") :style #js {:display "inline-block"} :key (str "icon-" color size dark)}
+        (e/ui-icon {:color color :size size} (icon :alarm))))))

 (defcard icon-sizes-visual-regressions
   (dom/div nil
-    (e/ui-icon {:size :small} (icon :alarm))
-    (e/ui-icon {} (icon :alarm))
-    (e/ui-icon {:size :medium} (icon :alarm))
-    (e/ui-icon {:size :large} (icon :alarm))
-    (e/ui-icon {:size :xlarge} (icon :alarm))
-    (e/ui-icon {:size :huge} (icon :alarm))))
+    (for [size [:small :normal :medium :large :xlarge :huge]
+         dark [false true]]
+     (dom/div #js {:className (when dark "t-dark") :style #js {:display "inline-block"} :key (str "icon-" size dark)}
+       (e/ui-icon {:size size} (icon :alarm))))))

 (defcard icon-bar-visual-regressions
   (dom/div nil
-    (e/ui-icon-bar {}
-      (e/ui-icon-bar-item {:glyph :home :label "Home" :active true})
-      (e/ui-icon-bar-item {:glyph :description :label "Docs" :color :passive})
-      (e/ui-icon-bar-item {:glyph :feedback :label "Support"})
-      )
-    (e/ui-icon-bar {:shifting true}
-      (e/ui-icon-bar-item {:glyph :home :label "Home" :active true})
-      (e/ui-icon-bar-item {:glyph :description :label "Docs" :color :passive})
-      (e/ui-icon-bar-item {:glyph :feedback :label "Support"})
-      )
-    (dom/br nil)
-    (e/ui-icon-bar {:orientation :vertical}
-      (e/ui-icon-bar-item {:glyph :home :label "Home" :active true})
-      (e/ui-icon-bar-item {:glyph :description :label "Docs" :color :passive})
-      (e/ui-icon-bar-item {:glyph :feedback :label "Support"}))))
+    (for [shifting    [false true]
+          orientation [:horizontal :vertical]
+          dark        [false true]]
+     (dom/div #js {:className (when dark "t-dark") :key (str "iconbar-" shifting orientation dark)}
+       (e/ui-icon-bar {:shifting shifting :orientation orientation}
+         (e/ui-icon-bar-item {:glyph :home :label "Home" :active true})
+         (e/ui-icon-bar-item {:glyph :description :label "Docs" :color :passive})
+         (e/ui-icon-bar-item {:glyph :feedback :label "Support"}))
+       (dom/br nil)
+       ))))

 (defcard labels-visual-regressions
   (dom/div nil
     (for [color [:none :primary :accent]
-          icon ["" (icon :add)]]
-      (e/ui-label {:color color :key (str color icon (rand-int 256))} icon "Default"))))
+          icon  ["" (icon :add)]
+          dark  [false true]]
+      (dom/div #js {:className (when dark "t-dark")
+                    :style #js {:display "inline-block"}
+                    :key (str "label-" color icon (rand-int 256))}
+        (e/ui-label {:color color} icon "Default")))))

 (defcard loader-visual-regressions
+  (dom/div nil
   (l/row {}
     (l/col {:width 4 :halign :center}
       (e/ui-loader {}))
     (l/col {:width 4 :halign :center}
       (e/ui-loader {:color :primary}))
     (l/col {:width 4 :halign :center}
-      (e/ui-loader {:color :accent}))))
+      (e/ui-loader {:color :accent})))
+  (l/row {:className "t-dark"}
+     (l/col {:width 4 :halign :center}
+       (e/ui-loader {}))
+     (l/col {:width 4 :halign :center}
+       (e/ui-loader {:color :primary}))
+     (l/col {:width 4 :halign :center}
+       (e/ui-loader {:color :accent})))))

 (defcard messages-visual-regressions
   (dom/div nil
     (for [color [:none :primary :accent]
-          class ["" "u-font-size--semi-medium"]]
-      (e/ui-message {:color color :className class :key (str "messages-" (name color) (name class))}
-        (str "This is a " (name color) " message.")))
-    (e/ui-message {}
-      (str "This is a message with an icon.") (e/ui-icon {:size :small :glyph :arrow_forward}))))
-
-
-(defcard modal
-  (dom/div nil
-    (e/ui-iframe {:height "200" :width "100%"}
-      (dom/div #js {}
-        (dom/link #js {:rel "stylesheet" :href "css/untangled-ui.css"})
-        (e/ui-dialog {:visible true}
-          (e/ui-dialog-title {} "Informative")
-          (e/ui-dialog-body {} "You have been notified.")
-          (e/ui-dialog-actions {}
-            (e/ui-flat-button {:color :primary} "Cancel")
-            (e/ui-flat-button {:color :primary} "Ok")))))))
+          size  [:normal :medium]
+          icon  [false true]
+          dark  [false true]]
+      (dom/div #js {:className (when dark "t-dark") :key (str "messages-" color size icon dark)}
+        (e/ui-message {:color     color
+                      :className (when (= size :medium) "u-font-size--semi-medium")}
+         (str "This is a " (name color) " message.")
+          (when icon (e/ui-icon {:size (when (= size :normal) :small) :glyph :arrow_forward})))))))
+
+
+(defcard modal-visual-regressions
+  (dom/div nil
+    (for [modal [false true]
+          dark  [false true]]
+     (dom/div #js {:key (str "dialog-" modal dark)}
+       (e/ui-iframe {:height "200" :width "100%"}
+         (dom/div #js {:className (when dark "t-dark") :style #js {:height "100%"}}
+           (dom/link #js {:rel "stylesheet" :href "css/untangled-ui.css"})
+           (e/ui-dialog {:visible true :modal modal}
+             (e/ui-dialog-title {} "Informative")
+             (e/ui-dialog-body {} "You have been notified.")
+             (e/ui-dialog-actions {}
+               (e/ui-flat-button {:color :primary} "Cancel")
+               (e/ui-flat-button {:color :primary} "Ok")))))))))

 (defcard notifications-visual-regressions
   (dom/div nil
     (for [kind [:normal :informative :success :warning :error]
-          width [:normal :wide]]
-      (dom/div #js {:key (str "id-" kind width)}
+          width [:normal :wide]
+          dark  [false true]]
+      (dom/div #js {:className (when dark "t-dark") :key (str "id-" kind width dark)}
         (e/ui-notification {:kind kind :width width}
          ;; TODO Warning key prop needed on NotificationTitle but simply setting one doesn't suppress the error.
          (e/ui-notification-title {} (str (when (= width :wide) (str/capitalize (name width))) " " (str/capitalize (name kind))))
@@ -197,23 +234,31 @@
     (e/ui-progress {:className "u-trailer--half"})
     (for [value [0 25 50 75 100]
           size  [:regular :dense]]
-      (e/ui-progress {:max "100" :value value :size size :className "u-trailer--half" :key (str "id-" value size)}))))
+      (dom/div nil
+        (e/ui-progress {:max "100" :value value :size size :className "u-trailer--half" :key (str "id-" value size)})
+        ))
+    (dom/div #js {:className "t-dark"}
+      (for [value [0 25 50 75 100]
+           size  [:regular :dense]]
+        (e/ui-progress {:max "100" :value value :size size :className "u-trailer--half" :key (str "id-" value size)})))))

 (defcard radio-visual-regressions
   (dom/div nil
-    (e/ui-radio {:id "radio-1"})
-    (e/ui-radio {:id "radio-1" :checked true})
-    (e/ui-radio {:id "radio-2" :disabled true})
-    (e/ui-radio {:id "radio-2" :disabled true :checked true})))
+    (for [checked  [false true]
+         disabled [false true]
+         dark     [false true]]
+     (dom/div #js {:className (when dark "t-dark") :key (str "radio-" checked disabled dark) :style #js {:display "inline-block"}}
+       (e/ui-radio {:id "radio-1" :checked checked :disabled disabled})))))

 (defcard switch-visual-regressions
   (dom/div nil
-    (e/ui-switch {:checked false :id "switch-1"})
-    (e/ui-switch {:checked true :id "switch-1"})
-    (e/ui-switch {:checked false :id "switch-1" :disabled true})
-    (e/ui-switch {:checked true :id "switch-1" :disabled true})))
+    (for [checked  [false true]
+         disabled [false true]
+         dark     [false true]]
+     (dom/div #js {:className (when dark "t-dark") :key (str "switch-" checked disabled dark) :style #js {:display "inline-block"}}
+       (e/ui-switch {:checked checked :id "switch-1" :disabled disabled})))))

 (defcard tab-visual-regressions


Fix resource access when happening through a packaged uberjar

--- src/greenyet/core.clj
+++ src/greenyet/core.clj
@@ -28,10 +28,10 @@

 (defn- page-template []
-  (-> "index.template.html" io/resource io/file slurp))
+  (-> "index.template.html" io/resource slurp))

 (defn- environment-names []
-  (-> "environment_names.yaml" io/resource io/file slurp yaml/parse-string))
+  (-> "environment_names.yaml" io/resource slurp yaml/parse-string))

 (defn- query-param-as-vec [params key]
   (let [value (get params key)


Do not deref nil.

Do not deref nil.

--- src/onyx/messaging/aeron.clj
+++ src/onyx/messaging/aeron.clj
@@ -256,9 +256,9 @@

 (defmethod extensions/close-peer-connection AeronConnection
   [messenger event peer-link]
-  (when-let [pub @(get-in peer-link [:send-pub :pub])]
-    (.close pub))
-  (when-let [pub @(get-in peer-link [:send-pub :aux-pub])]
-    (.close pub))
+  (when-let [pub (get-in peer-link [:send-pub :pub])]
+    (.close @pub))
+  (when-let [pub (get-in peer-link [:send-pub :aux-pub])]
+    (.close @pub))
   (.close (:conn peer-link))
   {})


Allow envelope curves to be a heterogeneous list of both keywords and floats.

--- src/overtone/sc/envelope.clj
+++ src/overtone/sc/envelope.clj
@@ -30,32 +30,41 @@
    :cubed       7
    })

-
-(defn- shape->id
+(defn- curve->shape-id
+    "Map curve to envelope shape. If curve is a keyword, look it up in
+     ENV-SHAPES, otherwise assume it to be the generic cuve shape id of
+     5"
+    [curve]
+    (get ENV-SHAPES curve 5))
+
+(defn- curve->curve-id
+    "Map curve to curve id. If curve is a keyword, assume the curve id
+     is a generic shape (0) otherwise, preserve curve id"
+    [curve]
+    (if-let [id (get ENV-SHAPES curve)]
+      0
+      curve))
+
+(defn- curves->shape-ids
   "Create a repeating shapes list corresponding to a specific shape type.
   Looks shape s up in ENV-SHAPES if it's a keyword. If not, it assumes the
   val represents the bespoke curve vals for a generic curve shape (shape
   type 5). the bespoke curve vals aren't used here, but are picked up in
   curve-value.
   Mirrors *shapeNumber in supercollider/SCClassLibrary/Common/Audio/Env.sc"
-  [s]
-  (if (keyword? s)
-    (repeat (s ENV-SHAPES))
-    (repeat 5)))
-
-(defn- curve-value
-  "Create the curves list for this curve type. For all standard shapes this
+  [curves]
+  (cycle (map curve->shape-id curves)))
+
+(defn- curves->curve-ids
+  "Create the curves id list for the specified curves. For all standard shapes this
   list of vals isn't used. It's only required when the shape is a generic
   'curve' shape when the curve vals represent the curvature value for each
   segment. A single float is repeated for all segments whilst a list of floats
   can be used to represent the curvature value for each segment individually.
   Mirrors curveValue in supercollider/SCClassLibrary/Common/Audio/Env.sc"
-  ;;
-  [c]
-  (cond
-   (sequential? c)  c
-   (number? c) (repeat c)
-   :else (repeat 0)))
+  [curves]
+  (cycle (map curve->curve-id curves)))
+

 ;; Envelope specs describe a series of segments of a line, which can be used to automate
 ;; control values in synths.
@@ -74,7 +83,12 @@
    through and a list of durations (the duration in time of the lines
    between each point).

-   Optionally a curve may be specified. This may be one of:
+   Optionally a curve or list of curves may be specified. A single
+   curve (as a keyword or float) will be repeated for all segments. A
+   list of keywords or floats will be cycled through for all segments.
+
+   Options are:
+
    * :step              - flat segments
    * :linear            - linear segments, the default
    * :exponential       - natural exponential growth and decay. In this
@@ -83,10 +97,14 @@
    * :sine              - sinusoidal S shaped segments.
    * :welch             - sinusoidal segments shaped like the sides of a
                           Welch window.
-   * a Float            - a curvature value to be repeated for all segments.
-   * an Array of Floats - individual curvature values for each segment.
+   * :squared           - Squared segments
+   * :cubed             - Cubed segments
+   * a float            - a curvature value to be repeated for all segments.
                           Positive numbers curve the segment up whilst
                           negative numbers curve the segment down.
+   * a list of keywords - individual values for each segment. To be cycled
+     and or floats        through for all segments.
+

    If a release-node is specified (an integer index) the envelope will sustain
    at the release node until released which occurs when the gate input of the
@@ -102,16 +120,19 @@
   ;;See prAsArray in supercollider/SCClassLibrary/Common/Audio/Env.sc
   ([levels durations]
      (envelope levels durations :linear))
-  ([levels durations curve]
-     (envelope levels durations curve -99))
-  ([levels durations curve release-node]
-     (envelope levels durations curve release-node -99))
-  ([levels durations curve release-node loop-node]
-     (let [shapes (shape->id curve)
-           curves (curve-value curve)]
+  ([levels durations curves]
+     (envelope levels durations curves -99))
+  ([levels durations curves release-node]
+     (envelope levels durations curves release-node -99))
+  ([levels durations curves release-node loop-node]
+     (let [curves    (if (sequential? curves)
+                       curves
+                       [curves])
+           shape-ids (curves->shape-ids curves)
+           curve-ids (curves->curve-ids curves)]
        (apply vector
               (concat [(first levels) (count durations) release-node loop-node]
-                      (interleave (rest levels) durations shapes curves))))))
+                      (interleave (rest levels) durations shape-ids curve-ids))))))

 (defunk triangle
   "Create a triangle envelope description array suitable for use with the


(PDB-3272) Test trgm-indexes! index creation

--- test/puppetlabs/puppetdb/scf/migrate_test.clj
+++ test/puppetlabs/puppetdb/scf/migrate_test.clj
@@ -828,3 +828,32 @@
             (println "Unexpected differences:")
             (clojure.pprint/pprint unex))))
       (is (= expected diff)))))
+
+(deftest trgm-indexes-as-expected
+  ;; Assume the current *db* supports trgm
+  (clear-db-for-testing!)
+  (migrate! *db*)
+  (indexes! (:database *db*))
+  (let [idxs (:indexes (schema-info-map *db*))]
+    (is (= {:schema "public"
+            :table "fact_paths"
+            :index "fact_paths_path_key"
+            :index_keys ["path"]
+            :type "btree"
+            :unique? true
+            :functional? false
+            :is_partial false
+            :primary? false
+            :user "pdb_test"}
+           (get idxs ["fact_paths" ["path"]])))
+    (is (= {:schema "public"
+            :table "facts"
+            :index "facts_value_string_trgm"
+            :index_keys ["value_string"]
+            :type "gin"
+            :unique? false
+            :functional? false
+            :is_partial false
+            :primary? false
+            :user "pdb_test"}
+           (get idxs ["facts" ["value_string"]])))))


IWatchable, cleanup, better upsert behavior

--- src/derive/nativestore.cljs
+++ src/derive/nativestore.cljs
@@ -1,7 +1,8 @@
 (ns derive.nativestore
   (:require [goog.object :as obj]
             [purnam.native]
-            [purnam.native.functions :refer [js-lookup js-assoc js-dissoc js-merge js-map]]
+            [purnam.native.functions :refer [js-lookup js-assoc js-dissoc js-merge js-map
+                                             js-copy]]
             [derive.protocols :as p :refer [index! unindex! key-fn comparator-fn scan
                                             insert! delete! add-index! rem-index! get-index]]))

@@ -9,14 +10,27 @@
 ;; Native object store
 ;;

+(defn upsert-merge
+  ([o1 o2]
+     (doseq [k (js-keys o2)]
+       (if-not (nil? (aget o2 k))
+         (aset o1 k (aget o2 k))
+         (js-delete o1 k)))
+     o1)
+  ([o1 o2 & more]
+     (apply upsert-merge (upsert-merge o1 o2) more)))
+
+
 ;; Hash KV Index, meant to be for a root store index (unique keys)
 ;; - Merging upsert against existing if keyfn output matches
+;; - Nil values in provided object deletes keys
+;; - Original object maintains identity
 (deftype HashIndex [keyfn hashmap]
   ILookup
   (-lookup [idx val]
     (-lookup idx val nil))
   (-lookup [idx val not-found]
-    (js-lookup (.-hashmap idx) val not-found))
+    (js-lookup hashmap val not-found))

   IFn
   (-invoke [idx k]
@@ -25,18 +39,16 @@
     (-lookup idx k not-found))

   ICounted
-  (-count [idx] (.-length (obj/getValues (.-hashmap idx))))
+  (-count [idx] (alength (js-keys hashmap)))

   p/IIndex
-  (key-fn [idx] (.-keyfn idx))
+  (key-fn [idx] keyfn)
   (index! [idx obj]
-    (let [key ((.-keyfn idx) obj)
-          hashmap (.-hashmap idx)
+    (let [key (keyfn obj)
           old (js-lookup hashmap key)]
-      (js-assoc hashmap key (if old (js-merge old obj) obj))))
+      (js-assoc hashmap key (if old (upsert-merge old obj) obj))))
   (unindex! [idx obj]
-    (let [key ((.-keyfn idx) obj)
-          hashmap (.-hashmap idx)]
+    (let [key (keyfn obj)]
       (js-dissoc hashmap key obj))))

 (defn root-index [keyfn]
@@ -50,10 +62,7 @@
   (-lookup [idx val]
     (-lookup idx val nil))
   (-lookup [idx val not-found]
-    (let [compfn (.-compfn idx)
-          keyfn (.-keyfn idx)
-          arry (.-arry idx)
-          index (goog.array.binarySearch arry val #(compfn %1 (keyfn %2)))]
+    (let [index (goog.array.binarySearch arry val #(compfn %1 (keyfn %2)))]
       (if (>= index 0)
         (loop [end index]
           (if (= (compfn val (keyfn (aget arry end))) 0)
@@ -68,54 +77,33 @@
     (-lookup idx k not-found))

   p/IIndex
-  (key-fn [idx] (.-keyfn idx))
+  (key-fn [idx] keyfn)
   (index! [idx obj]
-    (let [compfn (.-compfn idx)
-          keyfn (.-keyfn idx)
-          arry (.-arry idx)
-          loc (goog.array.binarySearch arry obj #(compfn (keyfn %1) (keyfn %2)))]
+    (let [loc (goog.array.binarySearch arry obj #(compfn (keyfn %1) (keyfn %2)))]
       (if (>= loc 0)
         (goog.array.insertAt arry obj loc)
         (goog.array.insertAt arry obj (- (inc loc)))))
     idx)
   (unindex! [idx obj]
-    (let [compfn (.-compfn idx)
-          keyfn (.-keyfn idx)
-          arry (.-arry idx)
-          loc (goog.array.findIndex arry #(= obj %))]
+    (let [loc (goog.array.findIndex arry #(= obj %))]
       (assert (>= loc 0))
       (goog.array.removeAt arry loc))
     idx)

   p/IIndexedStore
-  (comparator-fn [idx] (.-compfn idx))
+  (comparator-fn [idx] compfn)

   p/IScannable
   (scan [idx f]
-    (let [keyfn (.-keyfn idx)
-          compfn (.-compfn idx)
-          arry (.-arry idx)
-          len (.-length arry)]
-      (loop [i 0]
-        (when-not (>= i len)
-          (f (aget arry i))
-          (recur (inc i))))))
+    (dotimes [i (alength arry)]
+      (f (aget arry i))))
   (scan [idx f start]
-    (let [keyfn (.-keyfn idx)
-          compfn (.-compfn idx)
-          arry (.-arry idx)
-          len (.-length arry)
-          head (goog.array.binarySearch arry start #(compfn %1 (keyfn %2)))
+    (let [head (goog.array.binarySearch arry start #(compfn %1 (keyfn %2)))
           head (if (>= head 0) head (- (inc head)))]
-      (loop [i head]
-        (when-not (>= i len)
-          (f (aget arry i))
-          (recur (inc i))))))
+      (dotimes [i (- (alength arry) head)]
+        (f (aget arry (+ i head))))))
   (scan [idx f start end]
-    (let [keyfn (.-keyfn idx)
-          compfn (.-compfn idx)
-          arry (.-arry idx)
-          head (goog.array.binarySearch arry start #(compfn %1 (keyfn %2)))
+    (let [head (goog.array.binarySearch arry start #(compfn %1 (keyfn %2)))
           head (if (>= head 0) head (- (inc head)))
           tail (goog.array.binarySearch arry end #(compfn %1 (keyfn %2)))
           tail (if (>= tail 0) tail (- (inc tail)))]
@@ -127,6 +115,7 @@
 (defn ordered-index [keyfn compfn]
   (BinaryIndex. keyfn compfn #js []))

+
 ;; A native, indexed, mutable/transactional store
 ;; - Always performs a merging upsert
 ;; - Secondary index doesn't index objects for key-fn -> nil
@@ -135,10 +124,10 @@
   (-lookup [store val]
     (-lookup store val nil))
   (-lookup [store id not-found]
-    (-lookup (.-root store) id not-found))
+    (-lookup root id not-found))

   ICounted
-  (-count [store] (-count (.-root store)))
+  (-count [store] (-count root))

   IFn
   (-invoke [store k]
@@ -149,32 +138,30 @@
   p/IStore
   (insert! [store obj]
     (let [key ((key-fn root) obj)
-          root (.-root store)
-          indices (obj/getValues (.-indices store))
-          ilen (.-length indices)
-          old (get root key)]
+          names (js-keys indices)
+          old (get root key)
+          oldref (js-copy old)]
       (when old
-        (loop [i 0]
-          (when-not (>= i ilen)
-            (let [idx (aget indices i)]
-              (when ((key-fn idx) old)
-                (unindex! idx old)))
-            (recur (inc i)))))
+        (doseq [name names]
+          (let [idx (aget indices name)]
+            (when ((key-fn idx) old)
+              (unindex! idx old)))))
       (index! root obj)
       (let [new (get root key)]
-        (loop [i 0]
-          (when-not (>= i ilen)
-            (let [idx (aget indices i)]
-              (when ((key-fn idx) new)
-                (index! idx new)))
-            (recur (inc i))))))
+        (doseq [name names]
+          (let [idx (aget indices name)]
+            (when ((key-fn idx) new)
+              (index! idx new))))
+        (-notify-watches store oldref new)))
     store)
   (delete! [store id]
     (assert (contains? root id) "Exists")
-    (let [obj (get root id)]
-      (unindex! root obj)
-      (doseq [idx indices]
-        (unindex! idx obj)))
+    (let [old (get root id)]
+      (doseq [name (js-keys indices)]
+        (let [idx (aget indices name)]
+          (when ((key-fn idx) old)
+            (unindex! idx old))))
+      (unindex! root old))
     store)

   p/IIndexedStore
@@ -187,7 +174,22 @@
     (js-dissoc indices iname)
     store)
   (get-index [store iname]
-    (js-lookup indices iname)))
+    (js-lookup indices iname))
+
+  IWatchable
+  (-notify-watches [store oldval newval]
+    (doseq [name (js-keys listeners)]
+      (let [listener (get listeners name)]
+        (listener oldval newval)))
+    store)
+  (-add-watch [store key f]
+    (js-assoc listeners key f)
+    store)
+  (-remove-watch [store key]
+    (js-dissoc listeners key)
+    store))
+
+

 ;  ITransactionalStore
 ;  (transact! [store f & args]


refactored a bit

refactored a bit

--- src/webdriver/dsl.clj
+++ src/webdriver/dsl.clj
@@ -26,6 +26,8 @@
 ;; skip decorator
 ;; conditinal decorator
 ;; with window decorator
+;; todo add local html test
+;;

 (def ^:dynamic *server*)
 (def ^:dynamic *session*)
@@ -40,6 +42,12 @@
   (fn [& args]
     (apply f (reverse args))))

+(defn random-port []
+  (let [max-port 65536
+        offset 1024]
+    (+ (rand-int (- max-port offset))
+       offset)))
+
 ;;
 ;; selectors
 ;;
@@ -51,6 +59,26 @@
 (defmacro with-xpath [& body]
   `(with-locator "xpath"
      ~@body))
+
+;;
+;; windowing
+;;
+
+(defmacro with-window [handler & body]
+  `(let [h# (api/get-window-handle *server* *session*)]
+     (api/switch-to-window *server* *session* ~handler)
+     (try
+       ~@body
+       (finally
+         (api/switch-to-window *server* *session* h#)))))
+
+(defmacro with-all-windows [& body]
+  `(doseq [h# (api/get-window-handles *server* *session*)]
+     (with-window h#
+       ~@body)))
+
+(defn close []
+  (api/close-window *server* *session*))

 ;;
 ;; navigation
@@ -164,7 +192,7 @@
 ;; predicates
 ;;

-(defn exists?
+(defn exists? ;; todo one form
   ([]
    (try+
     (api/element-tag-name *server* *session* *element*)
@@ -187,6 +215,7 @@
      (api/element-enabled *server* *session* *element*))))

 (defn visible? []
+  ;; todo C. Element Displayedness
   )

 ;;
@@ -238,6 +267,10 @@
   (apply wait-for-predicate
          (partial running? host port)
          args))
+
+;;
+;; proceses
+;;

 ;; todo handle exceptions
 ;; check alive
@@ -280,12 +313,6 @@
      (with-server host# port#
        (with-process host# port#
          ~@body))))
-
-(defn random-port []
-  (let [max-port 65536
-        offset 1024]
-    (+ (rand-int (- max-port offset))
-       offset)))

 (deftest simple-test
   (let [host "127.0.0.1"


Added sim code removed from storm-spec to the simulation ns [forgot in commit: 3d62874]

--- src/polismath/simulation.clj
+++ src/polismath/simulation.clj
@@ -26,3 +26,13 @@
          (random-reactions 4 4 :n-convs 3)))))

+(defn make-reaction-gen [n-convs start-n]
+  "This function creates an infinite sequence of reations which models an increasing number of comments and
+  people over time, over some number of conversations n-convs. The start-n argument sets the initial number of
+  ptpts and cmts per conversation."
+  ; I <3 clojure...
+  (mapcat
+    #(random-reactions % % :n-convs n-convs)
+    (map #(+ % start-n) (range))))
+
+


indent functions

indent functions

--- saas-dsl/src/saas_dsl/parse.clj
+++ saas-dsl/src/saas_dsl/parse.clj
@@ -7,3 +7,13 @@
   [input-str]
   (:pre [(= (class input-str) java.lang.String)])
   (split input-str #"\n+"))
+
+(defn count-space-indent
+  "Count the number of spaces used to indent."
+  [input-string]
+  (count (take-while #{\space} input-string)))
+
+(defn has-indent
+  "Does this line has an indent?"
+  [loc]
+  (pos? (count-space-indent (zip/node loc))))


great recursion

great recursion

--- src/epicea/utils/egraph.clj
+++ src/epicea/utils/egraph.clj
@@ -94,6 +94,10 @@
   (let [[m v] (add-vector dst (vec expr))]
     [m (into (empty expr) v)]))

+(defn add-node [dst expr]
+  (let [g (gensym)]
+    [(add-subexpr dst g expr) g]))
+
 (defn make-map [dst expr]
   (cond
     (node? expr) (add-node dst expr)


Return the written config.

Return the written config.

--- src/fm/simrunner/config.clj
+++ src/fm/simrunner/config.clj
@@ -111,5 +111,6 @@
         (throw (IllegalArgumentException. "Missing or empty value in config!"))
         (doto writer
           (.write value)
-          .newLine)))))
+          .newLine))))
+  config)


define js-draw before calling it

define js-draw before calling it

--- src/greybear/pages/game.clj
+++ src/greybear/pages/game.clj
@@ -9,6 +9,12 @@
   "
   [stones]
   (format "[%s]" (apply str (interpose ", " (map str stones)))))
+
+(defn js-draw
+  [stones playing last-x last-y]
+  (javascript-tag
+   (format "goboard.draw(\"goBoard\", %s, %s, greybear.draw_callback, %s, %s)"
+           (stones-to-js stones) playing last-x last-y)))

 (defn game [session game-id]
   (let [game (read-game game-id)
@@ -28,8 +34,3 @@
          (js-draw (game :stones) 1 18 17)])}
       (game-not-found game-id))))

-(defn js-draw
-  [stones playing last-x last-y]
-  (javascript-tag
-   (format "goboard.draw(\"goBoard\", %s, %s, greybear.draw_callback, %s, %s)"
-           (stones-to-js stones) playing last-x last-y)))


exclude more libraries

exclude more libraries

--- src/shuppet/core_shuppet.clj
+++ src/shuppet/core_shuppet.clj
@@ -20,7 +20,7 @@
             [slingshot.slingshot :refer [try+ throw+]]))

 (def shuppet-tester
-  (conj secure-tester-without-def (blanket "shuppet")))
+  (conj secure-tester-without-def (blanket "shuppet" "environ" "compojure")))

 (defn- make-sandbox []
   (sandbox shuppet-tester


Reduced memory consumption.

Reduced memory consumption.

--- src/luhnybin/core.clj
+++ src/luhnybin/core.clj
@@ -63,31 +63,22 @@
 (defn process-line
   "Process a line, returning the indices of any potential CC numbers."
   [line]
-  (loop [pos 0 in (seq line) to-mask #{}]
-    (if in
-      (let [c (first in)]
-        (if (digits c)
-          (let [candidates (leading-candidates in)]
-            (if-let [cc (some luhn? candidates)]
-              (recur (inc pos) (next in)
-                     (into to-mask (range pos (+ pos (count cc)))))
-              (recur (inc pos) (next in) to-mask)))
-          (recur (inc pos) (next in) to-mask)))
-      to-mask)))
-
-(defn mask-line
-  "Mask out any digits occurring at the marked positions."
-  [line to-mask mask-char]
-  (->> (seq line)
-    (map-indexed #(if (and (to-mask %1) (digits %2)) mask-char %2))
-    (apply str)))
+  (let [buf (transient (vec line))]
+    (loop [pos 0 in (seq line)]
+      (when (digits (first in))
+        (when-let [cc (some luhn? (leading-candidates in))]
+          (loop [n pos [x & xs] cc]
+            (when (digits x) (assoc! buf n \X))
+            (when xs (recur (inc n) xs)))))
+      (when (not (empty? in))
+        (recur (inc pos) (next in))))
+    (apply str (persistent! buf))))

 ;; Read from the file named in the first argument, or *stdin*.
 (defn -main [& args]
   (dorun
-    (->> nil
-      (make-reader (or (first args) *in*))
+    (->> (make-reader (or (first args) *in*) nil)
       (line-seq)
-      (pmap #(mask-line % (process-line %) \X))
+      (pmap #(process-line %))
       (map println))))


Add docstrings to math

Add docstrings to math

--- src/play_clj/math.clj
+++ src/play_clj/math.clj
@@ -9,369 +9,451 @@
 ; static methods/fields

 (defmacro geometry!
+  "Calls a single method on [GeometryUtils](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/GeometryUtils.html)"
   [k & options]
   `(~(u/static-symbol [:math :GeometryUtils k] u/key->camel) ~@options))

 (defmacro interpolation
+  "Returns a static class in [Interpolation](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Interpolation.html)
+
+    (interpolation :bounce)"
   [k]
   `~(symbol (str u/main-package ".math.Interpolation$" (u/key->pascal k))))

 (defmacro intersector!
+  "Calls a single method on [Intersector](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Intersector.html)
+
+    (intersector! :is-point-in-triangle 0 1 0 0 1 2 3 0)"
   [k & options]
   `(~(u/static-symbol [:math :Intersector k] u/key->camel) ~@options))

 (defmacro math!
+  "Calls a single method on [MathUtils](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/MathUtils.html)
+
+    (math! :ceil 0.1)"
   [k & options]
   `(~(u/static-symbol [:math :MathUtils k] u/key->camel) ~@options))

 (defmacro plane-side
+  "Returns a static field in [Plane.PlaneSide](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Plane.PlaneSide.html)
+
+    (plane-side :back)"
   [k]
   `~(symbol (str u/main-package ".math.Plane$PlaneSide/" (u/key->pascal k))))

 ; bezier

 (defn bezier*
+  "The function version of `bezier`"
   ([]
     (Bezier.))
   ([points]
     (Bezier. (into-array points) 0 (count points))))

 (defmacro bezier
+  "Returns a [Bezier](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Bezier.html)"
   [points & options]
   `(u/calls! ^Bezier (bezier* ~points) ~@options))

 (defmacro bezier!
+  "Calls a single method on a `bezier`"
   [object k & options]
   `(u/call! ^Bezier ~object ~k ~@options))

 ; bresenham2

 (defn bresenham2*
+  "The function version of `bresenham2`"
   []
   (Bresenham2.))

 (defmacro bresenham2
+  "Returns a [Bresenham2](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Bresenham2.html)"
   [& options]
   `(u/calls! ^Bresenham2 (bresenham2*) ~@options))

 (defmacro bresenham2!
+  "Calls a single method on a `bresenham2`"
   [object k & options]
   `(u/call! ^Bresenham2 ~object ~k ~@options))

 ; b-spline

 (defn b-spline*
+  "The function version of `b-spline`"
   ([]
     (BSpline.))
   ([points degree cont?]
     (BSpline. (into-array points) degree cont?)))

 (defmacro b-spline
+  "Returns a [BSpline](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/BSpline.html)"
   [points degree cont? & options]
   `(u/calls! ^BSpline (b-spline* ~points ~degree ~cont?) ~@options))

 (defmacro b-spline!
+  "Calls a single method on a `b-spline`"
   [object k & options]
   `(u/call! ^BSpline ~object ~k ~@options))

 ; catmull-rom-spline

 (defn catmull-rom-spline*
+  "The function version of `catmull-rom-spline`"
   ([]
     (CatmullRomSpline.))
   ([points cont?]
     (CatmullRomSpline. (into-array points) cont?)))

 (defmacro catmull-rom-spline
+  "Returns a [CatmullRomSpline](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/CatmullRomSpline.html)"
   [points cont? & options]
   `(u/calls! ^CatmullRomSpline (catmull-rom-spline* ~points ~cont?) ~@options))

 (defmacro catmull-rom-spline!
+  "Calls a single method on a `catmull-rom-spline`"
   [object k & options]
   `(u/call! ^CatmullRomSpline ~object ~k ~@options))

 ; circle

 (defn circle*
+  "The function version of `circle`"
   ([]
     (Circle.))
   ([x y radius]
     (Circle. x y radius)))

 (defmacro circle
+  "Returns a [Circle](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Circle.html)"
   [x y radius & options]
   `(u/calls! ^Circle (circle* ~x ~y ~radius) ~@options))

 (defmacro circle!
+  "Calls a single method on a `circle`"
   [object k & options]
   `(u/call! ^Circle ~object ~k ~@options))

 ; convex-hull

 (defn convex-hull*
+  "The function version of `convex-hull`"
   []
   (ConvexHull.))

 (defmacro convex-hull
+  "Returns a [ConvexHull](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/ConvexHull.html)"
   [& options]
   `(u/calls! ^ConvexHull (convex-hull*) ~@options))

 (defmacro convex-hull!
+  "Calls a single method on a `convex-hull`"
   [object k & options]
   `(u/call! ^ConvexHull ~object ~k ~@options))

 ; delaunay-triangulator

 (defn delaunay-triangulator*
+  "The function version of `delaunay-triangulator`"
   []
   (DelaunayTriangulator.))

 (defmacro delaunay-triangulator
+  "Returns a [DelaunayTriangulator](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/DelaunayTriangulator.html)"
   [& options]
   `(u/calls! ^DelaunayTriangulator (delaunay-triangulator*) ~@options))

 (defmacro delaunay-triangulator!
+  "Calls a single method on a `delaunay-triangulator`"
   [object k & options]
   `(u/call! ^DelaunayTriangulator ~object ~k ~@options))

 ; ear-clipping-triangulator

 (defn ear-clipping-triangulator*
+  "The function version of `ear-clipping-triangulator`"
   []
   (EarClippingTriangulator.))

 (defmacro ear-clipping-triangulator
+  "Returns an [EarClippingTriangulator](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/EarClippingTriangulator.html)"
   [& options]
   `(u/calls! ^EarClippingTriangulator (ear-clipping-triangulator*) ~@options))

 (defmacro ear-clipping-triangulator!
+  "Calls a single method on a `ear-clipping-triangulator`"
   [object k & options]
   `(u/call! ^EarClippingTriangulator ~object ~k ~@options))

 ; ellipse

 (defn ellipse*
+  "The function version of `ellipse`"
   ([]
     (Ellipse.))
   ([x y width height]
     (Ellipse. x y width height)))

 (defmacro ellipse
+  "Returns an [Ellipse](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Ellipse.html)"
   [x y width height & options]
   `(u/calls! ^Ellipse (ellipse* ~x ~y ~width ~height) ~@options))

 (defmacro ellipse!
+  "Calls a single method on an `ellipse`"
   [object k & options]
   `(u/call! ^Ellipse ~object ~k ~@options))

 ; float-counter

 (defn float-counter*
+  "The function version of `float-counter`"
   [window-size]
   (FloatCounter. window-size))

 (defmacro float-counter
+  "Returns a [FloatCounter](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/FloatCounter.html)"
   [window-size & options]
   `(u/calls! ^FloatCounter (float-counter* ~window-size) ~@options))

 (defmacro float-counter!
+  "Calls a single method on a `float-counter`"
   [object k & options]
   `(u/call! ^FloatCounter ~object ~k ~@options))

 ; frustum

 (defn frustum*
+  "The function version of `frustum`"
   []
   (Frustum.))

 (defmacro frustum
+  "Returns a [Frustum](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Frustum.html)"
   [& options]
   `(u/calls! ^Frustum (frustum*) ~@options))

 (defmacro frustum!
+  "Calls a single method on a `frustum`"
   [object k & options]
   `(u/call! ^Frustum ~object ~k ~@options))

 ; grid-point-2

 (defn grid-point-2*
+  "The function version of `grid-point-2`"
   [x y]
   (GridPoint2. x y))

 (defmacro grid-point-2
+  "Returns a [GridPoint2](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/GridPoint2.html)"
   [x y & options]
   `(u/calls! ^GridPoint2 (grid-point-2* ~x ~y) ~@options))

 (defmacro grid-point-2!
+  "Calls a single method on a `grid-point-2`"
   [object k & options]
   `(u/call! ^GridPoint2 ~object ~k ~@options))

 ; grid-point-3

 (defn grid-point-3*
+  "The function version of `grid-point-3`"
   [x y z]
   (GridPoint3. x y z))

 (defmacro grid-point-3
+  "Returns a [GridPoint3](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/GridPoint3.html)"
   [x y z & options]
   `(u/calls! ^GridPoint3 (grid-point-3* ~x ~y ~z) ~@options))

 (defmacro grid-point-3!
+  "Calls a single method on a `grid-point-3`"
   [object k & options]
   `(u/call! ^GridPoint3 ~object ~k ~@options))

 ; matrix-3

 (defn matrix-3*
+  "The function version of `matrix-3`"
   ([]
     (Matrix3.))
   ([values]
     (Matrix3. values)))

 (defmacro matrix-3
+  "Returns a [Matrix3](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Matrix3.html)"
   [values & options]
   `(u/calls! ^Matrix3 (matrix-3* ~values) ~@options))

 (defmacro matrix-3!
+  "Calls a single method on a `matrix-3`"
   [object k & options]
   `(u/call! ^Matrix3 ~object ~k ~@options))

 ; matrix-4

 (defn matrix-4*
+  "The function version of `matrix-4`"
   ([]
     (Matrix4.))
   ([^floats values]
     (Matrix4. values)))

 (defmacro matrix-4
+  "Returns a [Matrix4](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Matrix4.html)"
   [values & options]
   `(u/calls! ^Matrix4 (matrix-4* ~values) ~@options))

 (defmacro matrix-4!
+  "Calls a single method on a `matrix-4`"
   [object k & options]
   `(u/call! ^Matrix4 ~object ~k ~@options))

 ; plane

 (defn plane*
+  "The function version of `plane`"
   [^Vector3 normal ^double d]
   (Plane. normal d))

 (defmacro plane
+  "Returns a [Plane](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Plane.html)"
   [normal d & options]
   `(u/calls! ^Plane (plane* ~normal ~d) ~@options))

 (defmacro plane!
+  "Calls a single method on a `plane`"
   [object k & options]
   `(u/call! ^Plane ~object ~k ~@options))

 ; polygon

 (defn polygon*
+  "The function version of `polygon`"
   ([]
     (Polygon.))
   ([vertices]
     (Polygon. vertices)))

 (defmacro polygon
+  "Returns a [Polygon](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Polygon.html)"
   [vertices & options]
   `(u/calls! ^Polygon (polygon* ~vertices) ~@options))

 (defmacro polygon!
+  "Calls a single method on a `polygon`"
   [object k & options]
   `(u/call! ^Polygon ~object ~k ~@options))

 ; polyline

 (defn polyline*
+  "The function version of `polyline`"
   ([]
     (Polyline.))
   ([vertices]
     (Polyline. vertices)))

 (defmacro polyline
+  "Returns a [Polyline](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Polyline.html)"
   [vertices & options]
   `(u/calls! ^Polyline (polyline* ~vertices) ~@options))

 (defmacro polyline!
+  "Calls a single method on a `polyline`"
   [object k & options]
   `(u/call! ^Polyline ~object ~k ~@options))

 ; quaternion

 (defn quaternion*
+  "The function version of `quaternion`"
   ([]
     (Quaternion.))
   ([w x y z]
     (Quaternion. w x y z)))

 (defmacro quaternion
+  "Returns a [Quaternion](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Quaternion.html)"
   [w x y z & options]
   `(u/calls! ^Quaternion (quaternion* ~w ~x ~y ~z) ~@options))

 (defmacro quaternion!
+  "Calls a single method on a `quaternion`"
   [object k & options]
   `(u/call! ^Quaternion ~object ~k ~@options))

 ; rectangle

 (defn rectangle*
+  "The function version of `rectangle`"
   ([]
     (Rectangle.))
   ([x y width height]
     (Rectangle. x y width height)))

 (defmacro rectangle
+  "Returns a [Rectangle](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Rectangle.html)"
   [x y width height & options]
   `(u/calls! ^Rectangle (rectangle* ~x ~y ~width ~height) ~@options))

 (defmacro rectangle!
+  "Calls a single method on a `rectangle`"
   [object k & options]
   `(u/call! ^Rectangle ~object ~k ~@options))

 ; vector-2

 (defn vector-2*
+  "The function version of `vector-2`"
   ([]
     (Vector2.))
   ([x y]
     (Vector2. x y)))

 (defmacro vector-2
+  "Returns a [Vector2](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Vector2.html)"
   [x y & options]
   `(u/calls! ^Vector2 (vector-2* ~x ~y) ~@options))

 (defmacro vector-2!
+  "Calls a single method on a `vector-2`"
   [object k & options]
   `(u/call! ^Vector2 ~object ~k ~@options))

 ; vector-3

 (defn vector-3*
+  "The function version of `vector-3`"
   ([]
     (Vector3.))
   ([x y z]
     (Vector3. x y z)))

 (defmacro vector-3
+  "Returns a [Vector3](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/Vector3.html)"
   [x y z & options]
   `(u/calls! ^Vector3 (vector-3* ~x ~y ~z) ~@options))

 (defmacro vector-3!
+  "Calls a single method on a `vector-3`"
   [object k & options]
   `(u/call! ^Vector3 ~object ~k ~@options))

 ; windowed-mean

 (defn windowed-mean*
+  "The function version of `windowed-mean`"
   [window-size]
   (WindowedMean. window-size))

 (defmacro windowed-mean
+  "Returns a [WindowedMean](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/math/WindowedMean.html)"
   [window-size & options]
   `(u/calls! ^WindowedMean (windowed-mean* ~window-size) ~@options))

 (defmacro windowed-mean!
+  "Calls a single method on a `windowed-mean`"
   [object k & options]
   `(u/call! ^WindowedMean ~object ~k ~@options))


Add the rest of the fonts to the collection.

--- src/uxbox/library/fonts.cljs
+++ src/uxbox/library/fonts.cljs
@@ -46,8 +46,156 @@
              {:name "Black Italic"
               :weight "900"
               :style "italic"}]}
+   {:id "opensans"
+    :name "Open Sans"
+    :styles [{:name "Extra-Light"
+              :weight "100"
+              :style "normal"}
+             {:name "Extra-Light Italic"
+              :weight "100"
+              :style "italic"}
+             {:name "Light"
+              :weight "200"
+              :style "normal"}
+             {:name "Light Italic"
+              :weight "200"
+              :style "italic"}
+             {:name "Regular"
+              :weight "normal"
+              :style "normal"}
+             {:name "Italic"
+              :weight "normal"
+              :style "italic"}
+             {:name "Semi-Bold"
+              :weight "500"
+              :style "normal"}
+             {:name "Semi-Bold Italic"
+              :weight "500"
+              :style "italic"}
+             {:name "Bold"
+              :weight "bold"
+              :style "normal"}
+             {:name "Bold Italic"
+              :weight "bold"
+              :style "italic"}
+             {:name "Black"
+              :weight "900"
+              :style "normal"}
+             {:name "Black Italic"
+              :weight "900"
+              :style "italic"}]}
    {:id "bebas"
     :name "Bebas"
     :styles [{:name "Normal"
               :weight "normal"
-              :style "normal"}]}])
+              :style "normal"}]}
+   {:id "gooddog"
+    :name "Good Dog"
+    :styles [{:name "Normal"
+              :weight "normal"
+              :style "normal"}]}
+   {:id "caviardreams"
+    :name "Caviar Dreams"
+    :styles [{:name "Normal"
+              :weight "normal"
+              :style "normal"}
+             {:name "Normal Italic"
+              :weight "normal"
+              :style "italic"}
+             {:name "Bold"
+              :weight "bold"
+              :style "normal"}
+             {:name "Bold Italic"
+              :weight "bold"
+              :style "italic"}]}
+   {:id "ptsans"
+    :name "PT Sans"
+    :styles [{:name "Normal"
+              :weight "normal"
+              :style "normal"}
+             {:name "Normal Italic"
+              :weight "normal"
+              :style "italic"}
+             {:name "Bold"
+              :weight "bold"
+              :style "normal"}
+             {:name "Bold Italic"
+              :weight "bold"
+              :style "italic"}]}
+   {:id "roboto"
+    :name "Roboto"
+    :styles [{:name "Extra-Light"
+              :weight "100"
+              :style "normal"}
+             {:name "Extra-Light Italic"
+              :weight "100"
+              :style "italic"}
+             {:name "Light"
+              :weight "200"
+              :style "normal"}
+             {:name "Light Italic"
+              :weight "200"
+              :style "italic"}
+             {:name "Regular"
+              :weight "normal"
+              :style "normal"}
+             {:name "Italic"
+              :weight "normal"
+              :style "italic"}
+             {:name "Semi-Bold"
+              :weight "500"
+              :style "normal"}
+             {:name "Semi-Bold Italic"
+              :weight "500"
+              :style "italic"}
+             {:name "Bold"
+              :weight "bold"
+              :style "normal"}
+             {:name "Bold Italic"
+              :weight "bold"
+              :style "italic"}
+             {:name "Black"
+              :weight "900"
+              :style "normal"}
+             {:name "Black Italic"
+              :weight "900"
+              :style "italic"}]}
+   {:id "robotocondensed"
+    :name "Roboto Condensed"
+    :styles [{:name "Extra-Light"
+              :weight "100"
+              :style "normal"}
+             {:name "Extra-Light Italic"
+              :weight "100"
+              :style "italic"}
+             {:name "Light"
+              :weight "200"
+              :style "normal"}
+             {:name "Light Italic"
+              :weight "200"
+              :style "italic"}
+             {:name "Regular"
+              :weight "normal"
+              :style "normal"}
+             {:name "Italic"
+              :weight "normal"
+              :style "italic"}
+             {:name "Semi-Bold"
+              :weight "500"
+              :style "normal"}
+             {:name "Semi-Bold Italic"
+              :weight "500"
+              :style "italic"}
+             {:name "Bold"
+              :weight "bold"
+              :style "normal"}
+             {:name "Bold Italic"
+              :weight "bold"
+              :style "italic"}
+             {:name "Black"
+              :weight "900"
+              :style "normal"}
+             {:name "Black Italic"
+              :weight "900"
+              :style "italic"}]}
+   ])


Add default promise config.

Add default promise config.

--- src/promesa/core.cljc
+++ src/promesa/core.cljc
@@ -44,6 +44,8 @@
               java.util.function.Function
               java.util.function.Supplier)))

+#?(:cljs (js/Promise.config #js {:cancellation true :warnings false}))
+
 #?(:clj
    (do
      (def ^:dynamic ^:no-doc


Minor optimizations

Minor optimizations

--- src/wireframes/transform.clj
+++ src/wireframes/transform.clj
@@ -39,10 +39,20 @@
 (defn dot-product [a b]
   (reduce + (map * a b)))

+;(defn ^double dot-product [[^double a0 ^double a1 ^double a2 ^double a3]
+;                           [^double b0 ^double b1 ^double b2 ^double b3]]
+;  (+
+;    (* a0 b0)
+;    (* a1 b1)
+;    (* a2 b2)
+;    (* a3 b3)))
+
+(def fourth-line [0.0  0.0  0.0  1.0])
+
 (defn concat
   ([a b]
-    (let [a (conj a [0.0  0.0  0.0  1.0])
-          b (conj b [0.0  0.0  0.0  1.0])
+    (let [a (conj a fourth-line)
+          b (conj b fourth-line)
           transposed  (apply mapv vector a)
           row-mult    (fn [x] (mapv (partial dot-product x) transposed))]
       (subvec (mapv row-mult b) 0 3)))


Only send game information to the channel joining the game (other users should have it)

--- src/wombats/sockets/game.clj
+++ src/wombats/sockets/game.clj
@@ -222,14 +222,14 @@
              [game-id :players chan-id]
              (assoc socket-user :color (:player/color player)))

-      ;; Sends the initial frame to the frontend
-      (broadcast-arena game-id arena)
+      ;; Sends the current game frame to the frontend
+      ((send-arena arena) chan-id)

       ;; TODO: Sends the players to the front end instead of fake data

       ;; Sends the game info to the front end
-      (broadcast-game-info game-id game))))
+      ((send-game-info game) chan-id))))

 (defn- leave-game
   [_]


Removed duplicate functions

Removed duplicate functions

--- src/ais/decoder.clj
+++ src/ais/decoder.clj
@@ -21,7 +21,7 @@
 ;;; There are simplifying assumptions as the primary goal is to illustrate a basic sample implementation
 ;;; of the library.
 ;;;
-;;; Multipart messages are assumed to flow in direct sequential, chronological order.
+;;; Multipart messages are assumed to flow in sequential, chronological order.

 (def buffer-size 1000)
@@ -68,7 +68,6 @@
 (defn valid-syntax? [message]
   (== (count (ais-ex/extract-envelope-checksum message)) 2))

-
 ;;---
 ;; Core
 ;;---
@@ -85,8 +84,8 @@
                 (if (and (supported-types msg-type) (= frag-num 1))
 	          (condp = frag-count
 	            1 (async/>!! out-ch [line])
-	            ;; We assume group values stream in sequential order hence sequential
-	            ;; reads from the input channel
+	            ;; Not robust!!!  Assumes multipart messages stream in sequential order.
+                    ;; In practice groups do tend to stream in proper order however.
 	            2 (async/>!! out-ch [line (async/<!! in-ch)])
 	     	    (.println *err* (str "Unexpected fragment count: " frag-count ". " line)))
 	          (.println *err* (str "Dropping [type=" msg-type "] " line)))))
@@ -109,33 +108,6 @@
           (async/close! out-ch))))
     out-ch))

-(comment
-(defn- process [format n in-ch]
-  (let [out-ch (async/chan buffer-size)
-        active-threads (atom n)]
-    (dotimes [i n]
-      (println (str "thread-" i))
-      (async/thread
-        (loop []
-          (if-let [msgs (async/<!! in-ch)]
-            (do
-              (async/>!! out-ch (apply ais-core/decode format msgs))
-              (recur))))
-        (swap! active-threads dec)
-        (if (= @active-threads 0)
-          (async/close! out-ch))))
-    out-ch))
-)
-
-(defn- collect [in-ch]
-  (let [out-ch (async/chan)]
-    (async/thread
-      (loop [acc []]
-        (if-let [msgs (async/<!! in-ch)]
-          (recur (concat acc msgs))
-          (async/>!! out-ch acc))))
-    out-ch))
-
 (defn- collect [in-ch]
   (let [out-ch (async/chan)]
     (async/thread
@@ -145,7 +117,7 @@
           (async/>!! out-ch acc))))
     out-ch))

-(defn writer [format prefix msgs]
+(defn- writer [format prefix msgs]
   (let [out-ch (async/chan)
         n (count msgs)
         active-threads (atom n)]


s/(map ..)/(mapfn ..)/

s/(map ..)/(mapfn ..)/

--- src/babel/over.cljc
+++ src/babel/over.cljc
@@ -127,25 +127,25 @@
 (defn head-pre-checks2 [parent child]
   (not (nil?
         (some #(= :fail %)
-              (map (fn [pair]
-                     (log/trace (str "head-pre-checks2: looking at pair: " pair))
-                     (let [parent-value (get-in parent (first pair) :top)
-                           child-value (get-in child (second pair) :top)
-                           result
-                           (unifyc parent-value child-value)]
-                       (log/trace (str "head-pre-checks2: result: " result))
-                       (if (fail? result)
-                         (do
-                           (log/trace (str "head precheck failed  for pair: " pair))
-                           (log/trace (str "head precheck failed: parent wanted: " (strip-refs parent-value) ";"
-                                           "child has: " (strip-refs child-value)))
-                           (log/trace (str " parent is: " (strip-refs parent)))
+              (mapfn (fn [pair]
+                       (log/trace (str "head-pre-checks2: looking at pair: " pair))
+                       (let [parent-value (get-in parent (first pair) :top)
+                             child-value (get-in child (second pair) :top)
+                             result
+                             (unifyc parent-value child-value)]
+                         (log/trace (str "head-pre-checks2: result: " result))
+                         (if (fail? result)
+                           (do
+                             (log/trace (str "head precheck failed  for pair: " pair))
+                             (log/trace (str "head precheck failed: parent wanted: " (strip-refs parent-value) ";"
+                                             "child has: " (strip-refs child-value)))
+                             (log/trace (str " parent is: " (strip-refs parent)))
                            (log/trace (str " child is: " (strip-refs child)))
                            :fail)
-                         (do
-                           (log/trace (str "head precheck success for pair: " pair))
-                           :top))))
-                   (lazy-seq head-precheck-pairs))))))
+                           (do
+                             (log/trace (str "head precheck success for pair: " pair))
+                             :top))))
+                     (lazy-seq head-precheck-pairs))))))

 (def comp-precheck-pairs
   [{:parent [:comp :synsem :cat]
@@ -171,23 +171,23 @@

 (defn comp-pre-checks2 [parent child]
   (some #(= :fail %)
-        (map (fn [pair]
-               (let [parent-value (get-in parent (:parent pair) :top)
-                     child-value (get-in parent (:childc pair) :top)
-                     result
-                     (unifyc parent-value child-value)]
-                 (log/debug (str "comp-pre-checks2: result: " result))
-                 (if (fail? result)
-                   (do
-                     (log/trace (str "comp precheck failed  for pair: " pair))
-                     (log/trace (str "comp precheck failed: parent wanted: " (strip-refs parent-value) ";"
-                                     "child has: " (strip-refs child-value)))
-                     (log/trace (str " child is: " (strip-refs child)))
-                     :fail)
-                   (do
-                     (log/trace (str "comp precheck success for pair: " pair))
-                     :top))))
-             (lazy-seq comp-precheck-pairs))))
+        (mapfn (fn [pair]
+                 (let [parent-value (get-in parent (:parent pair) :top)
+                       child-value (get-in parent (:childc pair) :top)
+                       result
+                       (unifyc parent-value child-value)]
+                   (log/debug (str "comp-pre-checks2: result: " result))
+                   (if (fail? result)
+                     (do
+                       (log/trace (str "comp precheck failed  for pair: " pair))
+                       (log/trace (str "comp precheck failed: parent wanted: " (strip-refs parent-value) ";"
+                                       "child has: " (strip-refs child-value)))
+                       (log/trace (str " child is: " (strip-refs child)))
+                       :fail)
+                     (do
+                       (log/trace (str "comp precheck success for pair: " pair))
+                       :top))))
+               (lazy-seq comp-precheck-pairs))))

 (defn comp-pre-checks [parent child]
   (or


restart when modified clojure file doesn't have a namespace

--- src/cake/server.clj
+++ src/cake/server.clj
@@ -29,7 +29,8 @@
         (println "cannot reload non-clojure file:" file)
         (if-let [ns (second (read-file-ns-decl (java.io.File. file)))]
           (when (find-ns ns) ;; don't reload namespaces that aren't already loaded
-            (load-file file)))))))
+            (load-file file))
+          (println "cannot reload file without namespace declaration"))))))

 (defn exit []
   (System/exit 0))


Use file's name, not json name when fixing json references.

--- src/cavm/cgdata.clj
+++ src/cavm/cgdata.clj
@@ -19,7 +19,7 @@
 (defn- all-json [path]
   (let [files (file-seq (io/file path))
         fnames (map str files)]
-    (map #(vector % (json/read-str (slurp %)))
+    (map #(vector (s/replace % #"\.json$" "") (json/read-str (slurp %)))
          (filter #(.endsWith ^String % ".json") fnames))))

 (defn- json-add [acc [file {n "name" t "type" :as metadata}]]
@@ -71,7 +71,8 @@
         table (json-table files)
         normalize (partial normalize-path (count root))]
     (doseq [[file data] files]
-      (write-json file (resolve-references normalize table file data)))))
+      (write-json (str file ".json")
+                  (resolve-references normalize table file data)))))

 ; apply f to values of map
 (defn- fmap [f m]


use refs to find playback canvas

use refs to find playback canvas

--- src/cellf/core.cljs
+++ src/cellf/core.cljs
@@ -224,13 +224,13 @@

 (om/root
-  (fn [{:keys [stream cells win-state moves tick tick-ms grid-size show-nums] :as app} _]
+  (fn [{:keys [stream cells win-state moves tick tick-ms grid-size show-nums] :as app} owner]
     (reify
       om/IDidMount
       (did-mount [_]
         (def playback-ctx
           (->
-            (.getElementById js/document "playback-canvas")
+            (om/get-node owner "playback")
             (.getContext "2d")))

         (defonce resize-loop
@@ -253,7 +253,7 @@
               (dom/h1 nil "cellf")
               (dom/p nil "find yourself.")
               (dom/canvas #js {
-                :id     "playback-canvas"
+                :ref    "playback"
                 :width  capture-size
                 :height (* capture-size 2)})


Remove obsolete option to start CLI with empty options map as this does not make real sense.

--- src/cli4clj/cli.clj
+++ src/cli4clj/cli.clj
@@ -258,16 +258,14 @@
   "This is the primary entry point for starting and configuring cli4clj.
    Please note that the configuration options can also be defined in a global or local var.
    However, in order to lookup arguments defined in anonymous functions, the configuration options have to be defined directly in the function call."
-  ([]
-    (start-cli {}))
-  ([user-options]
-    (let [options-with-args-info (add-args-info user-options)]
-     `(let [options# (get-cli-opts ~options-with-args-info)]
-        (repl
-          :eval ((options# :eval-factory) (options# :cmds) (options# :allow-eval) (options# :print-err))
-          :print (options# :print)
-          :prompt (options# :prompt-fn)
-          :read (*read-factory* (options# :cmds) (options# :prompt-string)))))))
+  [user-options]
+   (let [options-with-args-info (add-args-info user-options)]
+    `(let [options# (get-cli-opts ~options-with-args-info)]
+       (repl
+         :eval ((options# :eval-factory) (options# :cmds) (options# :allow-eval) (options# :print-err))
+         :print (options# :print)
+         :prompt (options# :prompt-fn)
+         :read (*read-factory* (options# :cmds) (options# :prompt-string))))))


Add 'clear' command.

Add 'clear' command.

--- src/cli4clj/cli.clj
+++ src/cli4clj/cli.clj
@@ -286,11 +286,14 @@
    The mandatory default options cannot be overridden by the user."
   []
   (let [print-exception-trace (atom false)]
-    {:cmds {:quit {:fn (fn [] (println "Error: The quit function should never be called."))
+    {:cmds {:clear {:fn (fn [] (print "\u001B[2J\n"))
+                    :short-info "Clear screen."
+                    :long-info "Clears the screen and resets the user interface."}
+            :help {:short-info "Show help."
+                   :long-info "Display a help text that lists all available commands including further detailed information about these commands."}
+            :quit {:fn (fn [] (println "Error: The quit function should never be called."))
                    :short-info "Quit the CLI."
                    :long-info "Terminate and close the command line interface."}
-            :help {:short-info "Show help."
-                   :long-info "Display a help text that lists all available commands including further detailed information about these commands."}
             :_enable-trace {:fn (fn [arg]
                                   (if (instance? java.lang.Boolean arg)
                                     (reset! print-exception-trace arg)


Minor changes to mknode and mkpol.

Minor changes to mknode and mkpol.

--- src/clj3D/fenvs.clj
+++ src/clj3D/fenvs.clj
@@ -242,15 +242,6 @@
   [geom1 geom2]
   (let [out-mesh (Mesh.)]
     (GeometryBatchFactory/mergeGeometries [geom1 geom2] out-mesh)
-    (doto (Geometry. "structured" out-mesh)
-      (.setMaterial (default-material)))))
-
-
-(defn merge-all
-
-  [geometries]
-  (let [out-mesh (Mesh.)]
-    (GeometryBatchFactory/mergeGeometries geometries out-mesh)
     (doto (Geometry. "structured" out-mesh)
       (.setMaterial (default-material)))))

@@ -280,9 +271,12 @@

 (defn mknode
+  "It takes a list or an undefined number of geometries and put them into
+   a single node. Materials are preserverd."
   [& objs]
-  (let [new-node (Node. "node")]
-    (doseq [geom objs] (.attachChild new-node geom))
+  (let [flattened-args (flatten objs)
+	new-node (Node. "node")]
+    (doseq [geom flattened-args] (.attachChild new-node geom))
     new-node))

@@ -486,24 +480,6 @@
       (.setMaterial (default-material)))))

-(defhigh mkpol
-  "Mk polyedra."
-  [vertices dim]
-
-  (cond-match
-
-   [0 dim]
-   (println "TODO")
-
-   [1 dim]
-   (let [vl1 (butlast vertices)
-	 vl2 (next vertices)]
-     (struct2 (map #(line %1 %2) vl1 vl2)))
-
-
-   [? dim] (println "TODO")))
-
-
 (defn load-obj
   "Load an .obj file and makes it available for rendering.
    Remember to load a single model with this function. For
@@ -512,4 +488,33 @@
   [filename]
   (let [imported-model ^Geometry (.loadModel asset-manager filename)]
     (doto imported-model
-      (.setMaterial (default-material)))))+      (.setMaterial (default-material)))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Other operations
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defhigh mkpol
+  "Mk polyedra.
+
+   Vertices is a list of vertices, and dim is a keyword
+   representing the dimension of the shape been created.
+   Legal values for dim: :0 , :1, :2."
+  [vertices dim]
+
+  (cond-match
+
+   [:0 dim]
+   (let [result (struct2 (map #(line %1 %2) (butlast vertices) (next vertices)))]
+     (skeleton 0 result))
+
+   [:1 dim]
+   (doto (struct2 (map #(line %1 %2) (butlast vertices) (next vertices)))
+     (.setMaterial (unlit-material)))
+
+
+   [? dim] (println "TODO")))


threadpooling in level calculation

threadpooling in level calculation

--- src/cljam/level.clj
+++ src/cljam/level.clj
@@ -1,6 +1,8 @@
 (ns cljam.level
   "Analyze level of alignments in BAM."
   (:require [clojure.java.io :refer [file]]
+            [com.climate.claypoole :as cp]
+            [cljam.common :refer [get-exec-n-threads *n-threads*]]
             [cljam.core :as core]
             [cljam.io :as io]
             [cljam.util :as util]
@@ -92,14 +94,16 @@
                            (io/write-blocks cache-wtr blocks))
                          cache-path))
                      (hdr :SQ)))
-        leval-caches (doall
-                      (pmap (fn [{:keys [SN LN]}]
-                              (let [cache-path (cache-name-fn SN)
-                                    level-cache-path (level-cache-name-fn SN)]
-                                (create-level-cache! SN LN cache-path level-cache-path)
-                                (clean! cache-path)
-                                level-cache-path))
-                            (hdr :SQ)))]
+        leval-caches (cp/with-shutdown! [pool (cp/threadpool (get-exec-n-threads))]
+                       (doall
+                        (cp/pmap pool
+                                 (fn [{:keys [SN LN]}]
+                                   (let [cache-path (cache-name-fn SN)
+                                         level-cache-path (level-cache-name-fn SN)]
+                                     (create-level-cache! SN LN cache-path level-cache-path)
+                                     (clean! cache-path)
+                                     level-cache-path))
+                                 (hdr :SQ))))]
     (doseq [cache caches]
       (clean! cache))
     ;; Merge cache files
@@ -118,6 +122,8 @@
                     {:type :bam-not-sorted}))))

 (defmethod add-level :bam
-  [rdr wtr]
+  [rdr wtr & {:keys [n-threads]
+              :or {n-threads 0}}]
   (check-bam-sorted! rdr)
-  (add-level-mt rdr wtr))
+  (binding [*n-threads* n-threads]
+    (add-level-mt rdr wtr)))


Only render when active

Only render when active

--- src/snergly/core.cljs
+++ src/snergly/core.cljs
@@ -185,25 +185,25 @@
            (not= rows (:rows grid))
            (not= columns (:columns grid)))))

+(defn handle-maze-change [component]
+  (let [{:keys [grid cell-size anim-chan active] :as maze} (om/props component)]
+    (when-not (nil? active)
+      (let [c @thecanvas
+            g (.getContext c "2d")]
+        (go
+          (image/image-grid g @grid cell-size)
+          (async/>! anim-chan true))
+        ))))
+
 (defui MazeDisplay
   static om/IQuery
   (query [this]
     '[{:maze [:grid :rows :columns :cell-size :algorithm :active :anim-chan]}])
   Object
   (componentDidMount [this]
-    (let [{:keys [grid cell-size anim-chan] :as maze} (om/props this)
-          c @thecanvas
-          g (.getContext c "2d")]
-      (image/image-grid g @grid cell-size)
-      (go (async/>! anim-chan true))
-      ))
+    (handle-maze-change this))
   (componentDidUpdate [this prev-props prev-state]
-    (let [{:keys [grid cell-size anim-chan] :as maze} (om/props this)
-          c @thecanvas
-          g (.getContext c "2d")]
-      (image/image-grid g @grid cell-size)
-      (go (async/>! anim-chan true))
-      ))
+    (handle-maze-change this))
   (render [this]
     (let [{:keys [grid rows columns algorithm cell-size active] :as maze} (om/props this)]
       (let [height (inc (* cell-size rows))


Added post data functions.

Added post data functions.

--- src/dragon/post.clj
+++ src/dragon/post.clj
@@ -1,18 +1,87 @@
 (ns dragon.post
-  (:require [clojure.string :as string]
-            [dragon.util :as util]))
+  (:require [clojure.java.io :as io]
+            [clojure.string :as string]
+            [dragon.post.rfc5322 :as rfc5322]
+            [dragon.util :as util]
+            [markdown.core :as markdown]))

 (defn get-all
   []
-  (util/get-files "posts"))
+  (map (fn [x] {:file x}) (util/get-files "posts")))

 (defn ->dst-path
-  [src-path]
-  (-> src-path
-      (string/replace-first "posts" "docs")))
+  [src-path title]
+  (let [filename (.getName src-path)]
+    (-> src-path
+        (string/replace-first "posts" "docs")
+        (string/replace-first filename title))))

 ;; get new names:
 ;; (map (comp (fn [x] (str x "/title.html")) post/->dst-path (fn [x] (.getParent x))) (post/get-all))

 ;; format dates:
 ;; (map (comp util/format-date util/path->date (fn [x] (.getPath x))) (post/get-all))
+
+(defn update-tags
+  [data]
+  (assoc data :tags (string/split (:tags data) #",\s?")))
+
+(defn convert-body
+  [data]
+  (case (keyword (:content-type data))
+    :md (assoc data :body (markdown/md-to-html-string (:body data)))))
+
+(defn add-file-data
+  [data]
+  (let [file-obj (:file data)
+        file-src (.getPath file-obj)
+        filename-old (.getName file-obj)
+        filename (format "%s.html" (util/sanitize-str (:title data)))]
+    (assoc data :filename filename
+                :file-src file-src
+                :file-dst (-> file-src
+                              (string/replace filename-old filename)
+                              (string/replace-first "posts" "docs")))))
+
+(defn add-uri
+  [data]
+  (assoc data :uri (string/replace-first (:file-dst data) "docs/" "")))
+
+(defn add-post-data
+  [data]
+  (->> data
+       :file
+       (slurp)
+       (rfc5322/parse)
+       (merge data)))
+
+(defn process-files
+  ""
+  [data]
+  ;; XXX write post to archives
+  ;; XXX update archives year page with link
+  ;; XXX update category page with link
+  ;; XXX update tags page(s) with link
+  ;; XXX update authors page with link
+  ;; XXX update front page
+  )
+
+(defn process-data
+  ""
+  [file-obj]
+  (-> file-obj
+      (add-post-data)
+      (add-file-data)
+      (add-uri)
+      (convert-body)
+      (update-tags)))
+
+(defn process
+  [file-obj]
+  (-> file-obj
+      (process-data)
+      (process-files)))
+
+(defn process-all
+  []
+  (map process (get-all)))


Implement all job related functions

Implement all job related functions

--- src/mdr2/pipeline2/core.clj
+++ src/mdr2/pipeline2/core.clj
@@ -29,7 +29,7 @@
         params {"authid" auth-id "time" timestamp "nonce" nonce}
         query-string (str uri "?" (client/generate-query-string params))
         hashcode (create-hash query-string secret)]
-    {:query-params
+    {:query-params
      {"authid" auth-id "time" timestamp "nonce" nonce "sign" hashcode}}))

 (defn job-sexp [script inputs options]
@@ -47,42 +47,65 @@
       xml/sexp-as-element
       xml/emit-str))

-(defn post [script inputs options]
+(defn wait [job])
+
+(defn jobs []
+  (let [url (str ws-url "/jobs")
+        response (client/get url (auth-query-params url))]
+    (when (client/success? response)
+      (-> response :body xml/parse-str))))
+
+(defn job [id]
+  (let [url (str ws-url "/jobs/" id)
+        response (client/get url (auth-query-params url))]
+    (when (client/success? response)
+      (-> response :body xml/parse-str))))
+
+(defn job-create [script inputs options]
   (let [url (str ws-url "/jobs")
         request (job-request script inputs options)
         auth (auth-query-params url)
         body {:body request}
         response (client/post url (merge auth body))]
     (when (client/success? response)
-      (-> response
-          :body
-          xml/parse-str))))
+      (-> response :body xml/parse-str))))

-(defn wait [job])
+(defn job-result-1 [url]
+  (let [response (client/get url (auth-query-params url))]
+    (when (client/success? response)
+      (-> response :body xml/parse-str))))

-(defn jobs []
-  (let [url (str ws-url "/jobs")
+(defn job-result
+  ([id]
+     (job-result-1 (str ws-url "/jobs/" id "/result")))
+  ([id type name]
+     (job-result-1 (str ws-url "/jobs/" id "/result/" type "/" name)))
+  ([id type name idx]
+     (job-result-1 (str ws-url "/jobs/" id "/result/" type "/" name "/idx/" idx))))
+
+(defn job-log [id]
+  (let [url (str ws-url "/jobs/" id "/log")
         response (client/get url (auth-query-params url))]
     (when (client/success? response)
-      (-> response
-          :body
-          xml/parse-str))))
+      (-> response :body))))
+
+(defn job-delete [id]
+  (let [url (str ws-url "/jobs/" id)
+        response (client/delete url (auth-query-params url))]
+    (when (client/success? response)
+      (-> response :body xml/parse-str))))

 (defn scripts []
   (let [url (str ws-url "/scripts")
         response (client/get url (auth-query-params url))]
     (when (client/success? response)
-      (-> response
-          :body
-          xml/parse-str))))
+      (-> response :body xml/parse-str))))

 (defn script [id]
   (let [url (str ws-url "/scripts/" id)
         response (client/get url (auth-query-params url))]
     (when (client/success? response)
-      (-> response
-          :body
-          xml/parse-str))))
+      (-> response :body xml/parse-str))))

 (defn alive? []
   (let [url (str ws-url "/alive")]


Remove duplication

Remove duplication

--- src/exploud/aws.clj
+++ src/exploud/aws.clj
@@ -43,16 +43,17 @@
   "The ARN of the role we want to assume."
   (env :aws-prod-role-arn))

-(defn assume-role
-  "Attempts to assume a role in the production account, returning the credentials."
-  []
-  (:credentials (sts/assume-role {:role-arn role-arn
-                                  :role-session-name "exploud"})))
-
 (defn use-current-role?
   "Whether we should use the current IAM role or should assume a role in another account."
   [environment]
   (not= :prod (keyword environment)))
+
+(defn alternative-credentials-if-necessary
+  "Attempts to assume a role, if necessary, returning the credentials or nil if current role is to be used."
+  [environment]
+  (if-not (use-current-role? environment)
+    (:credentials (sts/assume-role {:role-arn role-arn
+                                    :role-session-name "exploud"}))))

 (defn account-id
   "Get the account ID we should use for an environment. We'll default to whatever `:poke` uses in the event of not knowing."
@@ -84,26 +85,17 @@
 (defn asg-created
   "Send a message stating that an ASG has been created."
   [region environment asg-name]
-  (if (use-current-role? environment)
-    (let [config {:endpoint region}]
-      (sqs/send-message config
-                        :queue-url (announcement-queue-url region environment)
-                        :delay-seconds 0
-                        :message-body (json/generate-string (asg-created-message asg-name)))
-      (auto/put-notification-configuration config
-                                           :auto-scaling-group-name asg-name
-                                           :notification-types ["autoscaling:EC2_INSTANCE_LAUNCH" "autoscaling:EC2_INSTANCE_TERMINATE"]
-                                           :topic-arn (autoscaling-topic environment)))
-    (let [config (merge (assume-role) {:endpoint region})]
-      (sqs/send-message config
-                        :queue-url (announcement-queue-url region environment)
-                        :delay-seconds 0
-                        :message-body (json/generate-string (asg-created-message asg-name)))
-      (auto/put-notification-configuration config
-                                           :auto-scaling-group-name asg-name
-                                           :notification-types ["autoscaling:EC2_INSTANCE_LAUNCH" "autoscaling:EC2_INSTANCE_TERMINATE"]
-                                           :topic-arn (autoscaling-topic environment))))
-  nil)
+  (let [config (merge (alternative-credentials-if-necessary environment)
+                      {:endpoint region})]
+    (sqs/send-message config
+                      :queue-url (announcement-queue-url region environment)
+                      :delay-seconds 0
+                      :message-body (json/generate-string (asg-created-message asg-name)))
+    (auto/put-notification-configuration config
+                                         :auto-scaling-group-name asg-name
+                                         :notification-types ["autoscaling:EC2_INSTANCE_LAUNCH" "autoscaling:EC2_INSTANCE_TERMINATE"]
+                                         :topic-arn (autoscaling-topic environment))
+    nil))

 ;; Pre-hook attached to `asg-created` to log parameters.
 (with-pre-hook! #'asg-created
@@ -113,18 +105,13 @@
 (defn asg-deleted
   "Send a message stating that an ASG has been deleted."
   [region environment asg-name]
-  (if (use-current-role? environment)
-    (let [config {:endpoint region}]
-      (sqs/send-message config
-                        :queue-url (announcement-queue-url region environment)
-                        :delay-seconds 0
-                        :message-body (json/generate-string (asg-deleted-message asg-name))))
-    (let [config (merge (assume-role) {:endpoint region})]
-      (sqs/send-message config
-                        :queue-url (announcement-queue-url region environment)
-                        :delay-seconds 0
-                        :message-body (json/generate-string (asg-deleted-message asg-name)))))
-  nil)
+  (let [config (merge (alternative-credentials-if-necessary environment)
+                      {:endpoint region})]
+    (sqs/send-message config
+                      :queue-url (announcement-queue-url region environment)
+                      :delay-seconds 0
+                      :message-body (json/generate-string (asg-deleted-message asg-name)))
+    nil))

 ;; Pre-hook attached to `asg-deleted` to log parameters.
 (with-pre-hook! #'asg-deleted


Beginning to work on checkers for collections-of-collections.

--- src/midje/util/checkers.clj
+++ src/midje/util/checkers.clj
@@ -146,3 +146,31 @@
        {:midje/chatty-checker true, :midje/checker true})))

+
+;; Work in progress
+(defn at-least [expected-map]
+  {:midje/checker true}
+  (fn [actual-map]
+    (every? (fn [key]
+	      (and (find actual-map key)
+		   (= (get actual-map key) (get expected-map key))))
+	    (keys expected-map))))
+
+
+(defn n-of [expected-checker expected-count]
+  {:midje/checker true}
+  (chatty-checker [actual]
+    (and (= (count actual) expected-count)
+	 (every? expected-checker actual))))
+
+
+(defmacro of-functions []
+  (let [names {1 "one", 2 "two", 3 "three", 4 "four", 5 "five", 6 "six", 7 "seven",
+	       8 "eight", 9 "nine", 10 "ten"}
+	defns (map (fn [key] `(defn ~(symbol (str (get names key) "-of")) [expected-checker#]
+				{:midje/checker true}
+				(n-of expected-checker# ~key)))
+		   (keys names))]
+    `(do ~@defns)))
+(of-functions)
+


Return the entries count with every board in org.

--- src/oc/storage/api/orgs.clj
+++ src/oc/storage/api/orgs.clj
@@ -240,7 +240,8 @@
                                                       (= (:access-level ctx) :viewer)))
                              org-id (:uuid org)
                              boards (board-res/list-boards-by-org conn org-id [:created-at :updated-at :authors :viewers :access :publisher-board :author])
-                             board-access (map #(board-with-access-level org % user) boards)
+                             boards-with-entries-count (map #(assoc % :total-count (entry-res/list-entries-by-board conn (:uuid %) {:count true})) boards)
+                             board-access (map #(board-with-access-level org % user) boards-with-entries-count)
                              allowed-boards (filter :access-level board-access)
                              author-access-boards (filter #(= (:access-level %) :author) board-access)
                                                ;; Add the draft board


Only write :message to output queue.

Only write :message to output queue.

--- src/onyx/plugin/hornetq.clj
+++ src/onyx/plugin/hornetq.clj
@@ -96,7 +96,7 @@

 (defmethod p-ext/compress-batch [:output :hornetq]
   [{:keys [onyx.core/results]}]
-  (let [compress-f #(.array (fressian/write %))]
+  (let [compress-f #(.array (fressian/write (:message %)))]
     {:onyx.core/compressed (map compress-f results)}))

 (defmethod p-ext/write-batch [:output :hornetq]


Add find-first as a convenience

Add find-first as a convenience

--- src/play_clj/core_utils.clj
+++ src/play_clj/core_utils.clj
@@ -1,4 +1,12 @@
 (in-ns 'play-clj.core)
+
+(defn find-first
+  "Finds the first entity in `entities` for which `match-fn` returns true.
+
+    (find-first :player? entities)
+    (find-first #(= :menu (:id %)) entities)"
+  [match-fn entities]
+  (some #(if (match-fn %) %) entities))

 (defmacro on-gl
   "Runs the macro body on the GL thread.


Coerce Item records to maps.

Coerce Item records to maps.

--- src/smallex/parser/smlx.clj
+++ src/smallex/parser/smlx.clj
@@ -106,4 +106,4 @@
   (cond (nil? item)
         (throw (ex-info "Unexpected end of grammar." {}))
         (= (:type item) :error)
-        (throw (ex-info "Lexer returned an error item." item))))
+        (throw (ex-info "Lexer returned an error item." (conj {} item)))))


Add a helper for formatting line information

--- src/oxcart/util.clj
+++ src/oxcart/util.clj
@@ -60,3 +60,9 @@
     (if (= dat dat')
       dat
       (recur f dat'))))
+
+
+(defn line
+  [ast]
+  (let [{:keys [file line column]} (-> ast :meta :env)]
+    (format "%s:%s:%s" file line column)))


Add extensible error handling to rstore impl.

--- src/uxbox/rstore.cljs
+++ src/uxbox/rstore.cljs
@@ -86,21 +86,21 @@

 (enable-console-print!)

+(defonce ^:private error-handlers (atom {}))
+
+(defn add-error-watcher
+  [key callable]
+  (swap! error-handlers assoc key callable))
+
+(defn remove-error-watcher
+  [key]
+  (swap! error-handlers dissoc key))
+
 (defn- on-error
-  "A default error handler."
   [error]
-  (cond
-    (and (:status error)
-         (:payload error)
-         (= (:status error) 403))
-    (emit! (uxbox.data.auth/logout))
-
-    :else
-    (do
-      (uxbox.data.messages/error! (tr "errors.generic"))
-      (println "Unexpected error: " error)
-      (js/console.log (.-stack error))
-      (rx/throw error))))
+  (doseq [[key value] @error-handlers]
+    (value error))
+  (throw error))

 (defn init
   "Initializes the stream event loop and


Fixed URLs

Fixed URLs

--- src/arachnida/html_renderer.clj
+++ src/arachnida/html_renderer.clj
@@ -12,21 +12,21 @@
         [:meta {:name "Author"    :content "Pavel Tisnovsky"}]
         [:meta {:name "Generator" :content "Clojure"}]
         [:meta {:http-equiv "Content-type" :content "text/html; charset=utf-8"}]
-        (page/include-css "http://10.34.3.139/bootstrap.min.css")
-        (page/include-css "http://10.34.3.139/bootstrap.min.css")
-        (page/include-css "http://10.34.3.139/arachnida.css")
-        (page/include-js  "http://10.34.3.139/bootstrap.min.js")
-        (page/include-js  "http://10.34.3.139/flotr/lib/prototype-1.6.0.2.js")
-        (page/include-js  "http://10.34.3.139/flotr/lib/canvas2image.js")
-        (page/include-js  "http://10.34.3.139/flotr/lib/canvastext.js")
-        (page/include-js  "http://10.34.3.139/flotr/flotr.debug-0.2.0-alpha.js")
+        (page/include-css "bootstrap.min.css")
+        (page/include-css "bootstrap.min.css")
+        (page/include-css "arachnida.css")
+        (page/include-js  "bootstrap.min.js")
+        (page/include-js  "flotr/lib/prototype-1.6.0.2.js")
+        (page/include-js  "flotr/lib/canvas2image.js")
+        (page/include-js  "flotr/lib/canvastext.js")
+        (page/include-js  "flotr/flotr.debug-0.2.0-alpha.js")
     ] ; head
 )

 (defn render-html-footer
     "Renders part of HTML page - the footer."
     []
-    [:div (str "

Author: Pavel Tisnovsky <ptisnovs@redhat.com>   "
+    [:div (str "

Author: Pavel Tisnovsky <>   "
           "
")])

 (defn render-navigation-bar-section


whitespace

whitespace

--- src/babel/francais/grammar.cljc
+++ src/babel/francais/grammar.cljc
@@ -347,14 +347,15 @@
                                      :sem {:aspect :progressive
                                            :tense :present}}})
                    (unify c10
-                           root-is-head
-                           {:rule "s-present-nonphrasal"
-                            :head {:phrasal false}
-                            :synsem {:aux false
-                                     :infl :present
-                                     :cat :verb
-                                     :sem {:aspect :progressive
-                                           :tense :present}}})
+                          root-is-head
+                          {:rule "s-present-nonphrasal"
+                           :head {:phrasal false
+                                  :français {:present {:conjugated true}}}
+                           :synsem {:aux false
+                                    :infl :present
+                                    :cat :verb
+                                    :sem {:aspect :progressive
+                                          :tense :present}}})
                    (unify c21
                            root-is-head-root
                            {:head {:phrasal true


exclude "chiamarsi" from small grammar

exclude "chiamarsi" from small grammar

--- src/babel/italiano/grammar.cljc
+++ src/babel/italiano/grammar.cljc
@@ -599,7 +599,13 @@
                                        (= (get-in % [:synsem :cat]) :verb)

                                        (or (= (get-in % [:synsem :sem :obj] :unspec) :unspec) ;; exclude transitive verbs..
-                                           (= (get-in % [:synsem :sem :reflexive] false) true))) ;; ..unless they are reflexive.
+
+                                           (and
+                                            (= (get-in % [:synsem :sem :reflexive] false) true)  ;; ..but allow reflexive verbs,
+                                            (= :none (get-in % [:synsem :subcat :3] :none)) ;; but not reflexive verbs with
+                                            ;; 3 args (e.g. "chiamarsi", because the small grammar can't generate for it.
+                                            ))
+                                       )

                                       (and (= (get-in % [:synsem :propernoun]) true)
                                            (= (get-in % [:synsem :sem :city] false) false)) ;; exclude cities from the small grammar.


intransitive should not apply if {:reflexive true}

--- src/babel/italiano/lexicon.cljc
+++ src/babel/italiano/lexicon.cljc
@@ -164,6 +164,7 @@
       (new-entries ;; remove the second argument and semantic object to make verbs intransitive.
        {:synsem {:cat :verb
                  :aux false
+                 :reflexive false
                  :sem {:obj {:top :top}}
                  :subcat {:2 {:cat :noun}
                           :3 '()}}}


Add bl-html-debug input to read saved HTML from disk

--- src/bltool/data/backloggery.clj
+++ src/bltool/data/backloggery.clj
@@ -90,6 +90,13 @@
           (recur (concat games (bl-extract-games page)) (bl-extract-params page)))
         (sort-by :name games)))))

+(defmethod read-games "bl-html-debug" [_]
+  (->> (:input *opts*)
+       slurp
+       java.io.StringReader.
+       html/parse
+       bl-extract-games
+       (sort-by :name)))

 ; backloggery wishlist
 (defmethod read-games "bl-wishlist" [_]


Fix client side test

Fix client side test

--- test/cljs/t_components.cljs
+++ test/cljs/t_components.cljs
@@ -18,7 +18,7 @@
                                :version "hd"}) => truthy)

 (fact "result list should be ok"
-      (components/result-list {:query (atom "test")
-                               :items (atom [])
-                               :counter (atom 1)
-                               :totla-count (atom 10)}))
+      (components/result-list (atom "test")
+                              (atom [])
+                              (atom 1)
+                              (atom 10)))