Log a number of migrated points

Log a number of migrated points

--- src/whisper2cyanite/core.clj
+++ src/whisper2cyanite/core.clj
@@ -51,14 +51,20 @@
     (reify
       Processor
       (process-metrics [this rollup period retention points path file series]
-        (doseq [point series]
-          (let [time (first point)
-                value (last point)
-                ttl (calc-ttl time retention)]
-            (when (> ttl min-ttl)
-              (log-point "Migrating point" rollup period path time value ttl)
-              (mstore/insert mstore tenant rollup period path time value
-                             ttl file)))))
+        (let [points-processed (atom 0)]
+          (doseq [point series]
+            (let [time (first point)
+                  value (last point)
+                  ttl (calc-ttl time retention)]
+              (when (> ttl min-ttl)
+                (log-point "Migrating point" rollup period path time value ttl)
+                (swap! points-processed inc)
+                (mstore/insert mstore tenant rollup period path time value
+                               ttl file))))
+          (log/debug (format (str "Metric migrated: path %s, rollup %s, "
+                                  "period: %s, points migrated: %s") file
+                                  rollup period @points-processed))
+          @points-processed))
       (process-path [this path file]
         (pstore/insert pstore tenant path file))
       (fetch-data? [this]
@@ -89,7 +95,8 @@
   (let [min-ttl (:min-ttl options default-min-ttl)
         validators [[#(not= %2 nil) "Point not found"]
                     [#(= (count %2) 1) "Array size is not equal to 1"]
-                    [#(= %1 (first %2)) "Values are not equal"]]]
+                    [#(= %1 (first %2)) "Values are not equal"]]
+        points-processed (atom 0)]
     (reify
       Processor
       (process-metrics [this rollup period retention points path file series]
@@ -143,7 +150,8 @@
               rows-size (* row-size points)
               archive-size (+ index-size rows-size)]
           (swap! cassandra-data-size + archive-size)
-          (swap! points-count + points)))
+          (swap! points-count + points))
+        points)
       (process-path [this path file])
       (fetch-data? [this]
         false))))


I think this is what the HTTP looks like

--- src/icecap/handlers/http.clj
+++ src/icecap/handlers/http.clj
@@ -1,9 +1,11 @@
 (ns icecap.handlers.http
-  (:require [clojure.core.async :refer [to-chan]]
+  (:require [aleph.http :refer [request]]
+            [clojure.core.async :refer [chan]]
             [icecap.handlers.core :refer [defstep]]
+            [manifold.stream :refer [connect]]
             [schema-contrib.core :refer [URI]]))

 (defstep :http
   {:url URI}
   [step]
-  (to-chan step))
+  (connect (request step) (chan)))


Add note that a test is flaky

Add note that a test is flaky

--- test/clj/lambdacd/steps/support_test.clj
+++ test/clj/lambdacd/steps/support_test.clj
@@ -115,7 +115,7 @@
                (testing "that overlapping string-outputs get concatenated"
                  (is (map-containing {:status :success
                                       :out    "hello\nworld"} (unit-under-test {} (some-ctx) some-step-saying-hello some-step-saying-world))))
-               (testing "that intermediate outputs are kept while step is running"
+               (testing "that intermediate outputs are kept while step is running (flaky)"
                  (let [result-channel (async/chan 100)
                        ctx (some-ctx-with :result-channel result-channel
                                           :pipeline-state-component (noop-pipeline-state/new-no-op-pipeline-state)


Sort through why echo test has EOF failures (WIP)

Now I need to decide what to do about them.

--- test/frereth_cp/message/message_test.clj
+++ test/frereth_cp/message/message_test.clj
@@ -101,10 +101,24 @@
                                      (utils/get-stack-trace (Exception.)))
                           (let [new-state
                                 (swap! parent-state inc)]
-                            ;; Should get 3 message packets:
+                            ;; I'd like to get 3 message packets here:
                             ;; 1. ACK
                             ;; 2. message being echoed
                             ;; 3. EOF
+                            ;; What I'm getting instead is:
+                            ;; 1. ACK
+                            ;; 2. message being echoed
+                            ;; 3. message being echoed because I havent responded with an ACK
+                            ;; There may be ways around this, but none of the ones that come
+                            ;; to mind just now seem worth the time/effort.
+                            ;; This test pretty obviously isn't about a
+                            ;; realistic message exchange. It's really
+                            ;; just about verifying that I got the echo.
+                            ;; Everything else going on in here is really just
+                            ;; a distraction from that fundamental point.
+                            ;; They're good distractions, and the system's gotten
+                            ;; much more robust because of them.
+                            ;; FIXME: Revisit this soon.
                             (when (= 3 new-state)
                               (log/info prelog
                                         "Echo sent. Pretending other child triggers done")
@@ -184,6 +198,7 @@
             io-handle (message/start! initialized  parent-cb child-cb)]
         (dfrd/on-realized child-finished
                           (fn [success]
+                            (log/info "Child just signalled EOF")
                             (is (= success ::specs/normal)))
                           (fn [failure]
                             (is (not failure) "Child echoer failed")))
@@ -249,13 +264,10 @@
                       ;; There's nothing on the other side to send back
                       ;; an ACK. But it should have been sent.
                       (is (= msg-len (from-child/buffer-size outgoing)))
-                      ;; This isn't getting sent.
-                      ;; I suspect this is a testing artifact.
-                      ;; Though I could be doing something dumb like
-                      ;; closing the outgoing pipe before I've written the
-                      ;; EOF signal (actually, if that happened, it should
-                      ;; never reach here).
-                      ;; FIXME: Need to rectify this.
+                      ;; The EOF still doesn't look like it's getting sent.
+                      ;; Although it must be for the parent to have signaled
+                      ;; that it's done.
+                      ;; TODO: Figure out what's going on.
                       (is (= 0 (count (::specs/un-sent-blocks outgoing))))
                       ;; This includes both the packet we're echoing back
                       ;; and the EOF signal.


to see if jar gets copied

to see if jar gets copied

--- src/main/cawala/api/read.clj
+++ src/main/cawala/api/read.clj
@@ -6,7 +6,7 @@
                      :person/relation :friend}
                  2  {:db/id 2 :person/name "Sally" :person/age 22
                      :person/relation :friend}
-                 3  {:db/id 3 :person/name "Allie" :person/age 56
+                 3  {:db/id 3 :person/name "Allie" :person/age 55
                      :person/relation :enemy}
                  4  {:db/id 4 :person/name "Zoe" :person/age 32
                      :person/relation :friend}


revert previous commit, when compiled none of the dependency machinery exists

--- src/main/cljs/cljs/core.cljs
+++ src/main/cljs/cljs/core.cljs
@@ -9898,12 +9898,16 @@
               (nil? ctxt) nil
               (nil? xs) ctxt
               :else (recur (gobject/get ctxt (first xs)) (next xs))))]
-    (let [segs (-> ns str (.split "."))]
-      (when (gobject/get (. goog/dependencies_ -nameToPath) (str ns))
-        (condp identical? *target*
-          "nodejs" (find-ns* js/global segs)
-          "default" (find-ns* js/window segs)
-          (throw (js/Error. (str "find-ns-obj not supported for target " *target*))))))))
+    (if-not js/COMPILED
+      (let [segs (-> ns str (.split "."))]
+        (when (gobject/get (. goog/dependencies_ -nameToPath) (str ns))
+          (condp identical? *target*
+            "nodejs" (find-ns* js/global segs)
+            "default" (find-ns* js/window segs)
+            (throw (js/Error. (str "find-ns-obj not supported for target " *target*))))))
+      (throw
+        (js/Error.
+          "find-ns-obj not supported when Closure optimization applied")))))

 (defn ns-interns* [sym]
   (let [ns-obj (find-ns-obj sym)


make eval more robust

make eval more robust

--- figwheel-repl/src/figwheel/repl.cljc
+++ figwheel-repl/src/figwheel/repl.cljc
@@ -687,27 +687,62 @@
 (defn connection-send [{:keys [send-fn] :as conn} data]
   (send-fn conn data))

+(defn send-for-response* [prom conn msg]
+  (let [uuid (str (java.util.UUID/randomUUID))
+        listener (fn listen [msg]
+                   (when (= uuid (:uuid msg))
+                     (when-let [result (:response msg)]
+                       (deliver prom
+                                (if (instance? clojure.lang.IMeta result)
+                                  (vary-meta result assoc ::message msg)
+                                  result)))
+                     (remove-listener listen)))]
+    (add-listener listener)
+    (try
+      (connection-send
+       conn
+       (json/write-str
+        (-> (select-keys conn [:session-id :session-name])
+            (merge msg)
+            (assoc :uuid uuid))))
+      (catch Throwable t
+        (remove-listener listener)
+        (throw t)))))
+
+(def no-connection-result
+  (vary-meta
+   {:status :exception
+    :value "Expected REPL Connections Evaporated!"
+    :stacktrace "No stacktrace available."}
+   assoc ::no-connection-made true))
+
+(defn broadcast-for-response [connections msg]
+  (let [prom (promise)
+        cnt  (->> connections
+                  (mapv #(try
+                           (send-for-response* prom % msg)
+                           true
+                           (catch Throwable t
+                             nil)))
+                  (filter some?)
+                  count)]
+    (when (zero? cnt)
+      (deliver prom no-connection-result))
+    prom))
+
 (defn send-for-response [connections msg]
-  ;; TODO remove all listeners after single response?
-  ;; or have one listener and one uuid
-  (let [prom (promise)]
-    (doseq [conn connections]
-      (let [uuid (str (java.util.UUID/randomUUID))
-            listener (fn listen [msg]
-                       (when (= uuid (:uuid msg))
-                         (when-let [result (:response msg)]
-                           (deliver prom
-                                    (if (instance? clojure.lang.IMeta result)
-                                      (vary-meta result assoc ::message msg)
-                                      result)))
-                         (remove-listener listen)))]
-        (add-listener listener)
-        (connection-send
-         conn
-         (json/write-str
-          (-> (select-keys conn [:session-id :session-name])
-              (merge msg)
-              (assoc :uuid uuid))))))
+  (let [prom (promise)
+        sent (loop [[conn & xc] connections]
+               (when conn
+                 (if-not (try
+                           (send-for-response* prom conn msg)
+                           true
+                           (catch Throwable t
+                             false))
+                   (recur xc)
+                   true)))]
+    (when-not sent
+      (deliver prom no-connection-result))
     prom))

 (defn http-long-polling-connect [ring-request respond raise]
@@ -770,7 +805,9 @@

 (defn open-connections []
   (filter (fn [{:keys [is-open-fn] :as conn}]
-            (or (nil? is-open-fn) (is-open-fn conn)))
+            (try (or (nil? is-open-fn) (is-open-fn conn))
+                 (catch Throwable t
+                   false)))
           (vals @*connections*)))

 (defn connections-available [repl-env]
@@ -786,11 +823,17 @@
       (Thread/sleep 500)
       (recur))))

-(defn send-for-eval [connections js]
-  (send-for-response connections {:op :eval :code js}))
-
-(defn eval-connections [{:keys [focus-session-name
-                                broadcast] :as repl-env}]
+
+
+
+
+(defn send-for-eval [{:keys [focus-session-name ;; just here for consideration
+                             broadcast] :as repl-env} connections js]
+  (if broadcast
+    (broadcast-for-response connections {:op :eval :code js})
+    (send-for-response connections {:op :eval :code js})))
+
+(defn eval-connections [{:keys [focus-session-name] :as repl-env}]
   (let [connections (connections-available repl-env)
           ;; session focus
         connections (if-let [focus-conn
@@ -803,7 +846,7 @@
                       (do
                         (reset! focus-session-name nil)
                         connections))]
-    (if broadcast connections (take 1 connections))))
+    connections))

 (defn trim-last-newline [args]
   (if-let [args (not-empty (filter string? args))]
@@ -838,14 +881,22 @@
               (print-to-stream stream args)))
     (wait-for-connection repl-env)
     (let [ev-connections (eval-connections repl-env)
-          result (let [v (deref (send-for-eval ev-connections js)
+          result (let [v (deref (send-for-eval repl-env ev-connections js)
                                 (or repl-timeout 8000)
                                 timeout-val)]
-                   (if (= timeout-val v)
-                     {:status :exception
-                      :value "Eval timed out!"
-                      :stacktrace "No stacktrace available."}
-                     v))]
+                   (cond (= timeout-val v)
+                     (do
+                       (when @focus-session-name
+                         (reset! focus-session-name nil))
+                       {:status :exception
+                        :value "Eval timed out!"
+                        :stacktrace "No stacktrace available."})
+                     (::no-connection-made (meta v))
+                     (do
+                       (when @focus-session-name
+                         (reset! focus-session-name nil))
+                       v)
+                     :else v))]
       (when-let [out (:out result)]
         (when (not (string/blank? out))
           (repl-env-print repl-env :out [(string/trim-newline out)])))
@@ -1113,16 +1164,15 @@

   scratch

-
   (do
     (cljs.repl/-tear-down re)
     (def re (repl-env* {:output-to "dev-resources/public/out/main.js"}))
     (cljs.repl/-setup re {}))

-
   (connections-available re)
   (open-connections)
-  (evaluate re "33")
+  (evaluate (assoc re :broadcast true)
+            "88")

   (evaluate re "setTimeout(function() {cljs.core.prn(\"hey hey\")}, 1000);")


PR feedback addressed

PR feedback addressed

--- src/cljs/org/broadinstitute/firecloud_ui/page/workspaces_list.cljs
+++ src/cljs/org/broadinstitute/firecloud_ui/page/workspaces_list.cljs
@@ -35,7 +35,8 @@
               (when (:creating-wf @state)
                 [comps/Blocker {:banner "Creating Workspace..."}])
               (style/create-form-label "Google Project")
-              (style/create-select {:onChange #(swap! state assoc :selected-project (-> % .-target .-value))}
+              (style/create-select {:value (:selected-project @state)
+                                    :onChange #(swap! state assoc :selected-project (-> % .-target .-value))}
                 (:billing-projects props))
               (style/create-form-label "Name")
               [input/TextField {:ref "wsName" :style {:width "100%"}


fix comment

fix comment

--- src/metabase/api/session.clj
+++ src/metabase/api/session.clj
@@ -32,7 +32,7 @@
 ;;  ["cam@metabase.com" #inst "2015-07-27T23:34:32.783-00:00"]
 ;;  ["cam@metabase.com" #inst "2015-07-27T23:34:31.666-00:00"])
 ;;
-;; Every time they're a failed login, push a new pair of [email timestamp] to the front of the list. The list is thus
+;; Every time there's a failed login, push a new pair of [email timestamp] to the front of the list. The list is thus
 ;; automatically ordered by date, and we can drop the portion of the list with failed logins that are over an hour
 ;; old as needed.
 ;;


Fix for executing on heroku

Fix for executing on heroku

--- src/cine/server.clj
+++ src/cine/server.clj
@@ -38,7 +38,7 @@
 (defn -main
   "Starting the immutant server"
   []
-  (let [PORT (Integer . (or (System/getenv "PORT") "8080"))]  ;; getting PORT number form env-variable $PORT
+  (let [PORT (Integer/parseInt (or (System/getenv "PORT") "9003"))]  ;; getting PORT number form env-variable $PORT
                                                               ;;for deploying to heroku
     (run app {:host "localhost" :port PORT})))


update envelope docs

update envelope docs

--- src/overtone/sc/envelope.clj
+++ src/overtone/sc/envelope.clj
@@ -9,7 +9,7 @@
           These are the typical envelope functions found in SuperCollider, and
           they output a series of numbers that is understood by the SC synth
           engine."
-     :author "Jeff Rose"}
+     :author "Jeff Rose, Sam Aaron"}
   overtone.sc.envelope
   (:use [overtone.util lib]
         [overtone.sc.machinery.ugen fn-gen]))
@@ -36,7 +36,7 @@
   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-vale.
+  curve-value.
   Mirrors *shapeNumber in supercollider/SCClassLibrary/Common/Audio/Env.sc"
   [s]
   (if (keyword? s)
@@ -69,25 +69,26 @@
 ;;    <segment-N...> ]

 (defn envelope
-  "Create an envelope curve description array suitable for the EnvGen ugen.
+  "Create an envelope curve description array suitable for the env-gen ugen.
    Requires a list of levels (the points that the envelope will pass 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:
    * :step              - flat segments
-   * :linear'           - linear segments, the default
+   * :linear            - linear segments, the default
    * :exponential       - natural exponential growth and decay. In this case,
                           the levels must all be nonzero and the have the same
                           sign.
    * :sine              - sinusoidal S shaped segments.
    * :welch             - sinusoidal segments shaped like the sides of a Welch
                           window.
-   * a Float            - a curvature value for all segments.
-   * an Array of Floats - curvature values for each segments.
+   * a Float            - a curvature value to be repeated for all segments.
+   * an Array of Floats - individual curvature values for each segment.

    If a release-node is specified (an integer index) the envelope will sustain
-   at the release node until released.
+   at the release node until released which occurs when the gate input of the
+   env-gen is set to zero.

    If a loop-node is specified (an integer index) the output will loop through
    those nodes starting at the loop node to the node immediately preceeding the


Key-code erronously accepted symbol as argument

Fixed issues #103 and #104 on oakes/play-clj

--- src/play_clj/core_basics.clj
+++ src/play_clj/core_basics.clj
@@ -107,7 +107,7 @@
     :point-y (game :y arg)
     (u/throw-key-not-found k)))

-(defmacro key-code
+(defn key-code
   "Returns a static field from [Input.Keys](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/Input.Keys.html).

     (key-code :a)


And an obsolete REPL option had to go away

Deleted commented-out references to ritz debugging middleware. That project
isn't ever coming back.

--- lein/profiles.clj
+++ lein/profiles.clj
@@ -90,11 +90,7 @@
                   [lein-pprint "1.1.1"]
                   [mvxcvi/whidbey "1.3.0" :exclusions [org.clojure/clojure]]]
         :repl-options {:nrepl-middleware
-                       [inspector.middleware/wrap-inspect
-                        ;;ritz.nrepl.middleware.apropos/wrap-apropos
-                        ;;ritz.nrepl.middleware.javadoc/wrap-javadoc
-                        ;;ritz.nrepl.middleware.simple-complete/wrap-simple-complete
-                        ]}
+                       []}
         :whidbey {:width 180
                   :map-delimiter ""
                   :extend-notation true


Add clj-http and lein-ancient to lein profile

--- lein/profiles.clj
+++ lein/profiles.clj
@@ -3,8 +3,9 @@
   :jvm-opts ["-Dclojure.server.repl={:port 5555 :accept clojure.core.server/repl}"]
  ;; for all that repl goodness
  :user { :dependencies [[org.clojure/tools.namespace "0.3.0-alpha4"]
+                        [clj-http "3.9.0"]
                         [eftest "0.5.1"]]
         :plugins [[lein-cljfmt "0.4.1" :exclusions [org.clojure/clojure]]
                   [lein-cloverage "1.0.6" :exclusions [org.clojure/clojure]]
-                  [lein-ancient "0.6.10", :exclusions [org.clojure/clojure]]]}
+                  [lein-ancient "0.6.15", :exclusions [org.clojure/clojure]]]}
 }


use http redirect after post

use http redirect after post

--- src/restful_clojure/core.clj
+++ src/restful_clojure/core.clj
@@ -32,6 +32,7 @@
       [:fieldset
        [:legend "New post - bbcode is not yet supported"]
        ;[:input {:type 'text :name "newpost"}]
+       [:input {:type 'hidden :name "redirecturl" :value (:url request)}]
        [:textarea {:rows 10 :cols 56 :name "newpost"}]
        [:br]
        [:input {:type 'submit :value "Send"}]]]]]])
@@ -57,6 +58,13 @@
     [request]
     (db/db-add-row! (:newpost (:params request)) (str request)))

+(defn html-redirect
+    [newurl]
+    {:status 303
+       :headers {"Location" newurl}
+       :body (html [:html [:body [:a {:href newurl} newurl]]])})
+
+
 (defroutes app-routes
   ;(GET "/" [] (resource-response "index.html" {:root "public"}))
   ;(ANY "/*" request (html (html-from-request request)))
@@ -64,7 +72,8 @@
     (do
       ;(println request)
       (record-post! request)
-      (html (html-from-request request))))
+      (html-redirect (:redirecturl (:params request)))
+      ))
   (GET "/*" request (html (html-from-request request)))
   (route/resources "/")
   (route/not-found "<h1>Page not found<h1>"))


fix download-tsv url

fix download-tsv url

--- src/cljs/org/broadinstitute/firecloud_ui/page/workspace/data/tab.cljs
+++ src/cljs/org/broadinstitute/firecloud_ui/page/workspace/data/tab.cljs
@@ -61,7 +61,7 @@
                 (when-let [selected-entity-type (or (:selected-entity-type @state) (:initial-entity-type @state) (first (:entity-types @state)))]
                   [:a {:style {:textDecoration "none" :float "left" :margin "7px 0 0 1em"}
                        :href (str "/service/api/workspaces/" (:namespace (:workspace-id props)) "/"
-                               (:name (:workspace-id props)) "/" selected-entity-type "/tsv")
+                               (:name (:workspace-id props)) "/entities/" selected-entity-type "/tsv")
                        :target "_blank"}
                    (str "Download '" selected-entity-type "' data")])
                 [:div {:style {:float "right" :paddingRight "2em"}}


make it a snapshot release

make it a snapshot release

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

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

-(def +version+ "0.3.3")
+(def +version+ "0.3.3-SNAPSHOT")

 (bootlaces! +version+)


Fix indentation

Fix indentation

--- build.boot
+++ build.boot
@@ -75,4 +75,10 @@

 (deftask uberjar
   []
-  (comp (uber) (aot) (pom) (jar) (sift) (target)))
+  (comp
+   (uber)
+   (aot)
+   (pom)
+   (jar)
+   (sift)
+   (target)))


Bump Om dependency to 1.0.0-alpha26

Bump Om dependency to 1.0.0-alpha26

--- build.boot
+++ build.boot
@@ -41,7 +41,7 @@
                  ;; Web app
                  [com.cognitect/transit-cljs "0.8.232"]
                  [org.clojure/core.async "0.2.374"]
-                 [org.omcljs/om "1.0.0-alpha25"]
+                 [org.omcljs/om "1.0.0-alpha26"]
                  [cljsjs/showdown "0.4.0-1"]])

 (task-options!


Revert klipse regex change [skip ci]

Revert klipse regex change [skip ci]

--- build.boot
+++ build.boot
@@ -231,8 +231,8 @@
             :exclude-vars #"^((map)?->\p{Upper}|[?!].*\*)"
             :themes       [:default
                            [:klipse
-                            #:klipse{:cached-macro-ns-regexp #"mikron\..*"
-                                     :cached-ns-regexp       #"mikron\..*"
+                            #:klipse{:cached-macro-ns-regexp #"/mikron\..*/"
+                                     :cached-ns-regexp       #"/mikron\..*/"
                                      :cached-ns-root         "cache-cljs"
                                      :require-statement      ns-str}]])
           (sift :move {#"docs" "../docs"})


Remove one extra let.

Remove one extra let.

--- src/cbfg/npr.cljs
+++ src/cbfg/npr.cljs
@@ -29,26 +29,25 @@
   (client-snapshot-item [this actx stream-request snapshot-beg snapshot-item]))

 (defn handle-npr-server-stream-request [actx server stream-request-in to-client-ch]
-  (let [snapshot-in (server-take-snapshot server actx stream-request-in nil)]
-    (act-loop npr-server-session actx
-              [stream-request stream-request-in
-               snapshot snapshot-in
-               num-snapshots 0]
-              (cond
-               (nil? snapshot) (aput-close npr-server-session to-client-ch
-                                           (assoc stream-request :status :ok))
-               (snapshot-rollback? snapshot) (aput-close npr-server-session to-client-ch
-                                                         (stream-request-rollback-msg stream-request snapshot))
-               :else (when (aput npr-server-session to-client-ch
-                                 (stream-request-snapshot-beg-msg stream-request snapshot))
-                       (doseq [item (snapshot-items snapshot)]
-                         (aput npr-server-session to-client-ch
-                               (stream-request-snapshot-item-msg stream-request snapshot item)))
-                       (when (aput npr-server-session to-client-ch
-                                   (stream-request-snapshot-end-msg stream-request snapshot))
-                         (recur stream-request
-                                (server-take-snapshot server actx stream-request snapshot)
-                              (inc num-snapshots))))))))
+  (act-loop npr-server-session actx
+            [stream-request stream-request-in
+             snapshot (server-take-snapshot server actx stream-request-in nil)
+             num-snapshots 0]
+            (cond
+             (nil? snapshot) (aput-close npr-server-session to-client-ch
+                                         (assoc stream-request :status :ok))
+             (snapshot-rollback? snapshot) (aput-close npr-server-session to-client-ch
+                                                       (stream-request-rollback-msg stream-request snapshot))
+             :else (when (aput npr-server-session to-client-ch
+                               (stream-request-snapshot-beg-msg stream-request snapshot))
+                     (doseq [item (snapshot-items snapshot)]
+                       (aput npr-server-session to-client-ch
+                             (stream-request-snapshot-item-msg stream-request snapshot item)))
+                     (when (aput npr-server-session to-client-ch
+                                 (stream-request-snapshot-end-msg stream-request snapshot))
+                       (recur stream-request
+                              (server-take-snapshot server actx stream-request snapshot)
+                              (inc num-snapshots)))))))

 (defn npr-client-stream-loop [actx client stream-request snapshot-beg-in out from-server-ch]
   (act-loop npr-client-stream-loop actx


layout: implement dagre layout.

layout: implement dagre layout.

--- src/cfg/core.cljs
+++ src/cfg/core.cljs
@@ -148,7 +148,11 @@
                            (hex-format (:offset function)))
                  ": "
                  (dom/span {:class "name"}
-                           (:name function)))))))))
+                           (:name function))
+                 " ("
+                 (dom/span {:class "basic-block-count"}
+                           (:nbbs function))
+                 ")")))))))

 (def function-list (om/factory FunctionList))

@@ -237,17 +241,70 @@
                 [:src (:addr bb) :dst (:fail bb) :type :fail])))))

+(def dagre (js* "dagre"))
+
+
+(defn make-dagre
+  []
+  (let [Graph (aget dagre "graphlib" "Graph")
+        g (Graph.)]
+    (.setGraph g #js{"nodesep" 100
+                     "edgesep" 50
+                     "ranksep" 75})
+    (.setDefaultEdgeLabel g (fn [x] #js{}))
+    g))
+
+
+(defn add-node!
+  [g bb]
+  (.setNode g (str (:addr bb)) #js{"width" (* 13 (:width bb))
+                                   "height" (* 13 (:height bb))
+                                   "label" (str (:addr bb))}))
+
+
+(defn add-edge!
+  [g edge]
+  (.setEdge g (str (:src edge)) (str (:dst edge))))
+
+
+(defn scale-props
+  [bb]
+  (merge bb {"x" (/ (get bb "x") 13)
+             "y" (/ (get bb "y") 13)
+             "height" (/ (get bb "height") 13)
+             "width" (/ (get bb "width") 13)}))
+
+
+(defn get-nodes
+  [g]
+  (map scale-props (vals (js->clj (aget g "_nodes")))))
+
+
+(defn get-edges
+  [g]
+  (vals (js->clj (aget g "_edgeLabels"))))
+
+
+(def layout! (aget dagre "layout"))
+
+
 (defn layout-cfg
   [basic-blocks]
-  (cmn/d basic-blocks)
-  (let [edges (compute-edges basic-blocks)]
-    (cmn/d edges))
-  (map-indexed (fn [i bb]
-                 (merge bb {:x i :y i
-                            :width (compute-bb-width bb)
-                            :height (compute-bb-height bb)}))
-               basic-blocks))
-
+  (when (< 0 (count (remove nil? basic-blocks)))
+    (let [edges (compute-edges basic-blocks)
+          bbs (map #(assoc % :width (compute-bb-width %)) basic-blocks)
+          bbs (map #(assoc % :height (compute-bb-height %)) bbs)
+          g (make-dagre)]
+      (doseq [bb bbs]
+        (add-node! g bb))
+      (doseq [edge edges]
+        (add-edge! g edge))
+      (layout! g)
+      (let [positions (cmn/index-by #(js/parseInt (get % "label")) (get-nodes g))]
+        (for [bb bbs]
+          (let [pos (get positions (:addr bb))]
+            (merge bb {:x (get pos "x")
+                       :y (get pos "y")})))))))

 (defn positioned
   [props children]
@@ -257,7 +314,6 @@
         h (:height props)
         top (str y "em")
         left (str x "em")]
-    (prn x y top left w h)
     (dom/div {:class "laid-out"
               :style {:top top
                       :left left}}


Do not call wrap-reagent with empty vectors

--- src/fqcss/core.cljc
+++ src/fqcss/core.cljc
@@ -39,7 +39,7 @@
 (declare wrap-reagent)

 (defn- maybe-wrap-reagent [child]
-  (if (vector? child)
+  (if (and (vector? child) (>= (count child) 1))
     (wrap-reagent child)
     child))


fixing tests

fixing tests

--- test/hydrox/meta_test.clj
+++ test/hydrox/meta_test.clj
@@ -4,9 +4,9 @@

 ^{:refer hydrox.meta/selector :added "0.1"}
 (fact "builds a selector for functions"
-
+
   (selector 'hello)
-  => '[(#{defn defmulti} | hello ^:%?- string? ^:%?- map? & _)])
+  => '[(#{defn defmacro defmulti} | hello ^:%?- string? ^:%?- map? & _)])

 ^{:refer hydrox.meta/edit-file :added "0.1"}
 (fact "helper function for file manipulation used by import and purge")


Add getter and setter for loading? and logged-in?

--- frontend/src/cruncher/utils/lib.cljs
+++ frontend/src/cruncher/utils/lib.cljs
@@ -8,7 +8,8 @@
            {:pokemon []
             :user {:view :default
                    :logged-in? false}
-            :error {:message nil}}))
+            :error {:message nil}
+            :app {:loading? false}}))

 ;;;; React compatibility
@@ -45,9 +46,17 @@
   [{:keys [state]} _ {:keys [view]}]
   {:action (fn [] (swap! state update-in [:user :view] (fn [] view)))})

+(defmethod mutate 'app/loading
+  [{:keys [state]} _ {:keys [status]}]
+  {:action (fn [] (swap! state update-in [:app :loading?] (fn [] status)))})
+
 (defmethod mutate 'update/error
     [{:keys [state]} _ {:keys [message]}]
     {:action (fn [] (swap! state update-in [:error :message] (fn [] message)))})
+
+(defmethod mutate 'user/logged-in
+  [{:keys [state]} _ {:keys [status]}]
+  {:action (fn [] (swap! state update-in [:user :logged-in?] (fn [] status)))})

 (defonce reconciler
          (om/reconciler
@@ -70,6 +79,11 @@
   []
   (get-in @app-state [:user :logged-in?]))

+(defn logged-in!
+  "Set boolean if user is logged in or not. If no parameters are given, set logged-in to true."
+  ([bool]
+   (om/transact! reconciler `[(user/logged-in {:status ~bool})]))
+  ([] (logged-in! true)))

 ;;;; About views
 (defn current-view
@@ -82,6 +96,16 @@
   [key]
   (om/transact! reconciler `[(change/view {:view ~key})]))

+(defn loading?
+  "Return boolean if ajax request is still in process."
+  []
+  (get-in @app-state [:app :loading?]))
+
+(defn loading!
+  "Set boolean if ajax request is still in process. Defaults to true without parameters."
+  ([bool]
+   (om/transact! reconciler `[(app/loading {:status ~bool})]))
+  ([] (loading! true)))

 ;;;; Error messages
 (defn error?


Only render shape if it is not nil.

Only render shape if it is not nil.

--- frontend/src/uxbox/main/exports.cljs
+++ frontend/src/uxbox/main/exports.cljs
@@ -44,7 +44,7 @@

 (mx/defc shape-component
   [sid]
-  (let [shape (get-in @*state* [:shapes sid])]
+  (when-let [shape (get-in @*state* [:shapes sid])]
     (shape-wrapper shape)))

 (mx/defc page-svg


test listen-to-keybaord-inputs more thoroughly

--- test/voke/input_test.cljs
+++ test/voke/input_test.cljs
@@ -11,30 +11,36 @@
     (go
       (let [event-chan (chan)
             event-handlers (atom [])]
-
         (with-redefs [events/listen (fn [_ _ event-handler-fn]
                                       (swap! event-handlers conj event-handler-fn))]
           (input/listen-to-keyboard-inputs event-chan)

           (let [[down-handler up-handler] @event-handlers
-                call-handler (fn [handler key-code]
+                send-event-to-handler (fn [handler key-code]
                                (handler #js {:keyCode        key-code
-                                             :preventDefault (fn [])}))
+                                             :preventDefault (fn [])})) ]

-                _ (call-handler down-handler KeyCodes.W)
+                (testing "basic keydown functionality"
+                  (send-event-to-handler down-handler KeyCodes.W)
+                  (send-event-to-handler down-handler KeyCodes.A)
+                  (is (= (<! event-chan)
+                           {:type      :move-key-down
+                            :direction :up}))
+                  (is (= (<! event-chan)
+                           {:type      :move-key-down
+                            :direction :left})))

-                voke-input-event (<! event-chan)]
-            (is (= voke-input-event
-                   {:type      :move-key-down
-                    :direction :up})))))
-
-      (done))
-    )
-
-
-  )
+                (testing "basic keyup functionality"
+                  (send-event-to-handler up-handler KeyCodes.W)
+                  (send-event-to-handler up-handler KeyCodes.A)
+                  (is (= (<! event-chan)
+                           {:type      :move-key-up
+                            :direction :up}))
+                  (is (= (<! event-chan)
+                           {:type      :move-key-up
+                            :direction :left}))))))
+      (done))))

 (deftest handle-keyboard-events
-
   )


Updated to use new key name and renamed function.

--- src/simulacrum/inventory.clj
+++ src/simulacrum/inventory.clj
@@ -22,9 +22,9 @@
     (util/display \newline)
     (cond
       (question :reversed?)
-        [(question :type) (- 6 answer)]
+        [(question :domain-key) (- 6 answer)]
       :else
-        [(question :type) answer])))
+        [(question :domain-key) answer])))

 (defn get-groups
   "This is used when processing the results."
@@ -42,7 +42,7 @@
   (/ (reduce + tuple) (float (count tuple))))

 (defn group-average
-  "Given a group, determine the average and associate it with its type."
+  "Given a group, determine the average and associate it with its domain."
   [group]
   [(first group) (average-tuple (gather-subgroups group))])

@@ -71,7 +71,7 @@
       (process-results
         (map #(get-answer prefix %) (questions :questions))))))

-(defn run-inventory
+(defn run
   "The required positional parameter (not one of the named parameters) needs to
   be a keyword that maps to a defined module for personality traits. For
   instance, if simulacrum.bigfive is defined (and it is) and you wanted to run
@@ -92,4 +92,4 @@
           (-run-inventory (eval (symbol type "questions-long")))
         :else (throw
                 (exceptions/param-error
-                  (util/get-last-line ((meta #'run-inventory) :doc)))))))
+                  (util/get-last-line ((meta #'run) :doc)))))))


resolve-uri now just prepends base

resolve-uri now just prepends base

--- src/hiccup/core.clj
+++ src/hiccup/core.clj
@@ -296,13 +296,10 @@
 (defmacro with-base-url
   "Add a base-url that will be added to the output of the resolve-uri function."
   [base-url & body]
-  `(binding [*base-url* ~(str base-url "/")]
+  `(binding [*base-url* ~base-url]
      ~@body))

 (defn resolve-uri
-  "If a base-url is set, returns a URL relative to the base. Otherwise, returns
-  the URL as-is."
+  "Prepends the base-url to the supplied URI."
   [uri]
-  (if *base-url*
-    (str (.resolve (URI. *base-url*) uri))
-    uri))
+  (str *base-url* uri))


I don't know why this was base64'd

I don't know why this was base64'd

--- src/icecap/core.clj
+++ src/icecap/core.clj
@@ -1,12 +1,12 @@
 (ns icecap.core
   (:require [caesium.core :refer [sodium-init]]
-            [icecap.codec :refer [safebase64-decode]]
+            [icecap.codec :refer [safebase64-encode]]
             [icecap.crypto :as crypto]
             [icecap.rest :as rest]
             [icecap.store.mem :refer [mem-store]]
             [aleph.http :refer [start-server]]
             [aleph.netty :refer [self-signed-ssl-context]]
-            [taoensso.timbre :refer [info]])
+            [taoensso.timbre :refer [info spy]])
   (:gen-class))

 (def port
@@ -14,10 +14,8 @@

 (defn run
   []
-  (let [[seed-key salt] (map (comp safebase64-decode
-                                   crypto/nul-byte-array)
-                             [crypto/seed-key-bytes
-                              crypto/salt-bytes])
+  (let [[seed-key salt] (map crypto/nul-byte-array
+                             [crypto/seed-key-bytes crypto/salt-bytes])
         components {:store (mem-store)
                     :kdf (crypto/blake2b-kdf seed-key salt)
                     :scheme (crypto/secretbox-scheme)}


require for side effects

require for side effects

--- src/icecap/rest.clj
+++ src/icecap/rest.clj
@@ -6,6 +6,8 @@
             [icecap.crypto :as crypto]
             [icecap.handlers.core :refer [execute]]
             [icecap.store.api :refer [create! retrieve delete!]]
+            [icecap.handlers.http]
+            [icecap.handlers.delay]
             [taoensso.timbre :refer [info spy]]
             [taoensso.nippy :as nippy]
             [prone.middleware :refer [wrap-exceptions]]


Use gen-class in incise-core.

Use gen-class in incise-core.

--- src/incise/core.clj
+++ src/incise/core.clj
@@ -6,7 +6,8 @@
             [incise.deployer.core :refer [deploy]]
             [taoensso.timbre :as timbre]
             [clojure.string :as s]
-            [clojure.tools.cli :refer [parse-opts]]))
+            [clojure.tools.cli :refer [parse-opts]])
+  (:gen-class))

 (def ^:private valid-methods #{:serve :once :deploy})


Replace cli-options with get-cli-options fn.

Fix #12.

--- src/incise/core.clj
+++ src/incise/core.clj
@@ -10,7 +10,7 @@

 (def ^:private valid-methods #{:serve :once :deploy})

-(def cli-options
+(defn get-cli-options []
   [["-h" "--help" "Print this help."]
    ["-m" "--method METHOD" "serve, once, or deploy"
     :default :serve
@@ -48,7 +48,7 @@
   4.  Handle help or call body-fn with options and cli arguments"
   [args body-fn]
   (let [{:keys [options arguments
-                summary errors]} (parse-opts args cli-options)]
+                summary errors]} (parse-opts args (get-cli-options))]
     (when (seq errors)
       (apply exit
              (count errors)


update testend enodes to use floating IPs too

Signed-off-by: Jakub Sokołowski <1d3764b91b902f6b45836e2498da81fe35caf6d6@status.im>

--- src/status_im/constants.cljs
+++ src/status_im/constants.cljs
@@ -88,15 +88,15 @@
   {:testnet {"mailserver-a" {:id      "mailserver-a" ;mail-01.do-ams3.eth.beta
                              :name    "Status mailserver A"
                              :password inbox-password
-                             :address "enode://c42f368a23fa98ee546fd247220759062323249ef657d26d357a777443aec04db1b29a3a22ef3e7c548e18493ddaf51a31b0aed6079bd6ebe5ae838fcfaf3a49@206.189.108.78:30504"}
+                             :address "enode://c42f368a23fa98ee546fd247220759062323249ef657d26d357a777443aec04db1b29a3a22ef3e7c548e18493ddaf51a31b0aed6079bd6ebe5ae838fcfaf3a49@206.189.243.162:30504"}
              "mailserver-b" {:id      "mailserver-b" ;mail-02.do-ams3.eth.beta
                              :name    "Status mailserver B"
                              :password inbox-password
-                             :address "enode://7aa648d6e855950b2e3d3bf220c496e0cae4adfddef3e1e6062e6b177aec93bc6cdcf1282cb40d1656932ebfdd565729da440368d7c4da7dbd4d004b1ac02bf8@206.189.108.63:30504"}
+                             :address "enode://7aa648d6e855950b2e3d3bf220c496e0cae4adfddef3e1e6062e6b177aec93bc6cdcf1282cb40d1656932ebfdd565729da440368d7c4da7dbd4d004b1ac02bf8@206.189.243.169:30504"}
              "mailserver-c" {:id      "mailserver-c" ;mail-03.do-ams3.eth.beta
                              :name    "Status mailserver C"
                              :password inbox-password
-                             :address "enode://8a64b3c349a2e0ef4a32ea49609ed6eb3364be1110253c20adc17a3cebbc39a219e5d3e13b151c0eee5d8e0f9a8ba2cd026014e67b41a4ab7d1d5dd67ca27427@206.189.7.30:30504"}
+                             :address "enode://8a64b3c349a2e0ef4a32ea49609ed6eb3364be1110253c20adc17a3cebbc39a219e5d3e13b151c0eee5d8e0f9a8ba2cd026014e67b41a4ab7d1d5dd67ca27427@206.189.243.168:30504"}
              "mailserver-d" {:id      "mailserver-d" ;mail-01.gc-us-central1-a.eth.beta
                              :name    "Status mailserver D"
                              :password inbox-password


♻ Interrupt current thread instead of rethrow InterruptedException

--- src/territory_bro/poller.clj
+++ src/territory_bro/poller.clj
@@ -30,8 +30,8 @@
 (defn- run-safely! [task]
   (try
     (task)
-    (catch InterruptedException e
-      (throw e))
+    (catch InterruptedException _
+      (.interrupt (Thread/currentThread)))
     (catch Throwable e
       (let [t (Thread/currentThread)]
         (when-let [handler (.getUncaughtExceptionHandler t)]


split definition of component from naming of component

This allows the creation of anonymous components.

--- src/pump/macros.clj
+++ src/pump/macros.clj
@@ -26,7 +26,16 @@
       (assoc body-map :render
              (apply list 'fn (first render-form) (rest render-form))))))

-(defmacro defr
+
+(defmacro component
+  "Returns an anonymous component"
+  [& forms]
+  (let [body# (body-map forms)
+        cameled# (dash-to-camel-keys body#)
+        body# (assoc cameled# :displayName (str name))]
+    `(pump/react ~body#)))
+
+(defmacro defr
   "Macro for defining React components

    In most basic forms takes a map of function names to functions, converts them
@@ -48,9 +57,6 @@
        :component-will-mount #(.log js/console \"component on duty\")
        [C P S]
        [:div.class (:text P)])
-"
+ "
   [name & forms]
-  (let [body# (body-map forms)
-        cameled# (dash-to-camel-keys body#)
-        body# (assoc cameled# :displayName (str name))]
-    `(def ~name (pump/react ~body#))))
+  `(def ~name (component ~@forms)))


:db/add behavior on cardinality/many? - only add one at a time, ie handle sequential values same as non-seq values

--- src/re_db/core.cljs
+++ src/re_db/core.cljs
@@ -8,19 +8,6 @@
 (def get-in* cljs.core/get-in)
 (def get* cljs.core/get)
 (def update* cljs.core/update)
-
-(def error-messages
-  {:add!-missing-entity
-   (fn [attr id]
-     (str "The entity you want to add a " attr " to, " id ", does not exist.\n"
-          (when (sequential? id)
-            (str "To upsert a new entity, call add! with a map, like {"
-                 (first id) " " (second id) " :other-attr other-val}"))))})
-
-(defn err [[k & args]]
-  (throw (js/Error
-           (some-> (get* error-messages k) (apply args)))))
-

 (defn create
   "Create a new db, with optional schema."
@@ -57,7 +44,7 @@
       (sequential? id)
       (let [[a v] id]
         (if-not (unique? db-snap a)
-          (throw (js/Error (str "Not a unique attribute: " a v)))
+          (throw (js/Error (str "Not a unique attribute: " a ", with value: " v)))
           (get-in* db-snap [:index a v])))
       id)))

@@ -89,9 +76,6 @@
    (unlisten-path! db [:listeners :entity id] f))
   ([db id attr f]
    (unlisten-path! db [:listeners :entity-attr id attr] f)))
-
-(defn upsert-attr? [id]
-  (and (number? id) (neg? id)))

 (defn entity [db-snap id]
   (when-let [id (resolve-id db-snap id)]
@@ -178,19 +162,17 @@
    (when-let [{:keys [f message] :as validation} (get-in* db-snap [:schema attr :validate])]
      (or (f val) (throw js/Error (str "Validation failed for " attr ": " message " on " val))))

-   (let [id (resolve-id db-snap id)
-         ;; TODO - clarify when we upsert, etc._ (assert (has? db-snap id))
-         many? (many? db-snap attr)
-         multi-many? (and many? (sequential? val))
+   (let [many? (many? db-snap attr)
+         ;multi-many? (and many? (sequential? val))
          no-op? (if many?
                   (contains? (get* (entity db-snap id) attr) val)
                   ;; some invalid values throw when compared, eg `(map inc (take 2))`
-                  (try (= val (get* (entity db-snap id) attr))
+                  (try (= val (get db-snap id attr))
                        (catch js/Error e false)))]
      (cond
        no-op? [db-snap reports]

-       multi-many? (reduce #(add %1 id attr %2) [db-snap reports] val)
+       ;multi-many? (reduce #(add %1 id attr %2) [db-snap reports] val)

        many? (-> [(update-in db-snap [:data id attr] (fnil conj #{}) val)
                   (conj reports [id attr val nil])]
@@ -240,18 +222,20 @@
       out)))

 (defn notify-listeners [db-snap reports]
-  (when (seq (get-in* db-snap [:listeners :entity]))
-    (doseq [eid (set (map first reports))]
-      (doseq [f (get-in* db-snap [:listeners :entity (get db-snap eid :id)])]
-        (f (entity db-snap eid)))))
-
-  (when (seq (get-in* db-snap [:listeners :entity-attr]))
-    (doseq [[eid attr] (set (map #(do [(first %) (second %)]) reports))]
-      (doseq [f (get-in* db-snap [:listeners :entity-attr (get db-snap eid :id) attr])]
-        (f (get db-snap eid attr)))))
-
-  (doseq [listener (get-in* db-snap [:listeners :tx-log])]
-    (listener (remove nil? reports))))
+  (when (seq reports)
+    (when (seq (get-in* db-snap [:listeners :entity]))
+      (doseq [id (set (map first reports))]
+        (doseq [f (get-in* db-snap [:listeners :entity id])]
+          (f (entity db-snap id)))))
+
+    (when (seq (get-in* db-snap [:listeners :entity-attr]))
+      (doseq [[id attr] (set (map #(do [(first %) (second %)]) reports))]
+        (let [listeners (get-in* db-snap [:listeners :entity-attr id attr])]
+          (doseq [f listeners]
+            (f (get db-snap id attr))))))
+
+    (doseq [listener (get-in* db-snap [:listeners :tx-log])]
+      (listener (remove nil? reports)))))

 (defn transact! [db txs]
   (let [txs (->> txs


include both hashes

include both hashes


Test a "sparse" BallotMeasureContest

Test a "sparse" BallotMeasureContest

--- test/vip/data_processor/db/translations/v5_0/ballot_measure_contests_test.clj
+++ test/vip/data_processor/db/translations/v5_0/ballot_measure_contests_test.clj
@@ -41,3 +41,38 @@
                :parent_with_id index-path
                :value "ABBREVIATION"})
              (transform-fn idx-fn bmc-path bmc))))))
+
+(deftest bmc->ltree-entries-test
+  (testing "index numbers follow the order from the spec, skipping missing attributes"
+    (let [bmc {:name "NAME"
+               :full_text "FULL TEXT"
+               :id "bmc002"
+               :external_identifier_type "TYPE"
+               :external_identifier_value "VALUE"}
+          idx-fn (util/index-generator 1)
+          ltree-paths (bmc/bmc->ltree-entries idx-fn bmc)]
+      (is (= (set ltree-paths)
+             #{{:path "VipObject.0.BallotMeasureContest.1.id"
+                :simple_path "VipObject.BallotMeasureContest.id"
+                :parent_with_id "VipObject.0.BallotMeasureContest.1.id"
+                :value "bmc002"}
+               {:path "VipObject.0.BallotMeasureContest.1.ExternalIdentifiers.0.ExternalIdentifier.0.Type.0"
+                :simple_path "VipObject.BallotMeasureContest.ExternalIdentifiers.ExternalIdentifier.Type"
+                :parent_with_id "VipObject.0.BallotMeasureContest.1.id"
+                :value "TYPE"}
+               {:path "VipObject.0.BallotMeasureContest.1.ExternalIdentifiers.0.ExternalIdentifier.0.Value.1"
+                :simple_path "VipObject.BallotMeasureContest.ExternalIdentifiers.ExternalIdentifier.Value"
+                :parent_with_id "VipObject.0.BallotMeasureContest.1.id"
+                :value "VALUE"}
+               {:path "VipObject.0.BallotMeasureContest.1.Name.1"
+                :simple_path "VipObject.BallotMeasureContest.Name"
+                :parent_with_id "VipObject.0.BallotMeasureContest.1.id"
+                :value "NAME"}
+               {:path "VipObject.0.BallotMeasureContest.1.FullText.2.Text.0"
+                :simple_path "VipObject.BallotMeasureContest.FullText.Text"
+                :parent_with_id "VipObject.0.BallotMeasureContest.1.id"
+                :value "FULL TEXT"}
+               {:path "VipObject.0.BallotMeasureContest.1.FullText.2.Text.0.language"
+                :simple_path "VipObject.BallotMeasureContest.FullText.Text.language"
+                :parent_with_id "VipObject.0.BallotMeasureContest.1.id"
+                :value "en"}})))))


take in 'system for helmsman-assets

take in 'system for helmsman-assets

--- src/timber/core.clj
+++ src/timber/core.clj
@@ -3,7 +3,7 @@
             [timber.selectors :as select]
             [timber.assets :as asset]))

-(def helmsman-assets
+(defn helmsman-assets [_]
   [^{:id :timber/assets}
    [:resources "/timber/public" {:root "/timber/public"}]])


remove comment

remove comment

--- src/tween/core.cljs
+++ src/tween/core.cljs
@@ -30,15 +30,15 @@

 (defn create-circle
   [base {:keys [fill r x y] :as props}]
-  ;; use js interop w/ constructor to call shape fn
-  ;; gen circle
   (.. base
       -graphics
       (beginFill fill)
       (drawCircle 0 0 r))
   ;; set pos
-  (aset base "x" x)
-  (aset base "y" y)
+  (when x
+    (aset base "x" x))
+  (when y
+    (aset base "y" y))
   base)

 (defn shape-maker


Slightly clearer implementation of multi-hinted-let

--- src/useful/java.clj
+++ src/useful/java.clj
@@ -52,7 +52,7 @@
   (let [x (gensym)]
     `(let [~x ~expr]
        (condp instance? ~x
-         ~@(for [class classes
-                 clause [class `(let [~(with-meta name {:tag class}) ~x] ~@body)]]
-             clause)
+         ~@(interleave classes
+                       (for [class classes]
+                         `(let [~(vary-meta name assoc :tag class) ~x] ~@body)))
          (throw (IllegalArgumentException. (str "No matching class for " ~x " in " '~classes)))))))


Display a summary message after running all tests

--- dev/bake/test.clj
+++ dev/bake/test.clj
@@ -3,7 +3,8 @@
         [cake :only [*config*]]
         [bake.core :only [verbose? log]]
         [bake.reload :only [last-reloaded last-modified reload]]
-        [bake.notify :only [notify]])
+        [bake.notify :only [notify]]
+        [useful.string :only [pluralize]])
   (:import [java.io StringWriter IOException]))

 (def last-passed    (atom (System/currentTimeMillis)))
@@ -68,12 +69,12 @@
   (let [start    (System/currentTimeMillis)
         results  (doall (map (partial run-ns-tests opts) namespaces))
         failures (count (filter identity results))]
-    (when (= 0 failures)
-      (when (and (:autotest opts)
+    (if (:autotest opts)
+      (when (and (zero? failures)
                  (< @last-passed @last-tested))
         (notify "All tests passed"))
-      (reset! last-passed start))
-    (reset! last-tested start)
-    (when-not (:autotest opts)
-      (println "----")
-      (println "Finished in" (/ (- (System/currentTimeMillis) start) 1000.0) "seconds.\n"))))
+      (do (println "----")
+          (println (if (zero? failures)
+                     "All tests passed"
+                     (str (pluralize failures "test") " FAILED")))
+          (println "Finished in" (/ (- (System/currentTimeMillis) start) 1000.0) "seconds.\n")))))


column ordering on mobile devices

column ordering on mobile devices

--- src/site/core.clj
+++ src/site/core.clj
@@ -139,18 +139,25 @@
    (for [[idx feat] (map-indexed (fn [x y] [x y]) (get-in data [:scenarios]))]
      [:div.box
       [:div.container
-       (let [txt [:.col-md-6 [:h3 (:title feat)]
+       (let [txt [:div [:h3 (:title feat)]
                   [:p [:$md  (:text feat)]]]
-             img [:.col-md-6 [:img.img {:src (es/url "imgs" (:img feat))}]]]
+             img [:div [:img.img {:src (es/url "imgs" (:img feat))}]]]
          (if (even? idx)
-           [:div.row txt img]
-           [:div.row img txt]))]])])
+           [:div.row
+            [:div.col-sm-6.col-sm-push-6 img]
+            [:div.col-sm-6.col-sm-pull-6 txt]]
+           [:div.row
+            [:div.col-sm-6 img]
+            [:div.col-sm-6 txt] ]
+           ))]])])

 (defn footer [{data :data :as opts}]
   [:div#footer
+
    [:$style
     [:#footer {:$bg-color :bereza :$height 20 :text-align "center"
                :$padding [3 0] }
+
      [:.footer-container {:$width 40 :text-align "center" :margin "0 auto"}]
      [:p {:$text 1 :$color :gray :$push-bottom 0.5}]
      [:h2 {:$color :blue}]
@@ -158,6 +165,9 @@
       [:.btn-wrap {:display "block"}]
       [:.btn {:$push-bottom 0.5} ] ] ] ]

+   [:$media {:max-width "400px"}
+      [:#footer [:.footer-container {:width "75%" :margin "0 auto"}]]]
+
    [:div.footer-container
     [:h2 (get-in data [:text :footer :header])]
     [:p (get-in data [:text :footer :text])]


support ipad

support ipad

--- src/site/core.clj
+++ src/site/core.clj
@@ -30,6 +30,9 @@
       [:&:hover {:text-decoration "none"
                  :$border [:bottom :solid 1 :blue]}] ]]]

+   [:$media {:max-width "480px"}
+    [:.btn-wrap {:display "block"}] ]
+
    [:span.btn-wrap
     [:a.btn.moto-btn {:href "https://aidbox.io/ui#/signup"} "TRY IN CLOUD"]]
    [:span.or " or "]
@@ -43,6 +46,9 @@
                    :$padding [1.5 0 1.5 0]
                    :margin 0
                    :$color [:blue :bereza]}
+     [:.desctop {:$flex-row [:baseline :space-between]}]
+     [:.navbar-header {:$flex-row [:center :space-between]}]
+     [:.icon-bar {:$bg-color :gray}]
      [:.brand {:$flex-full  true}
       [:a {:text-transform "uppercase" :$color :white :$text [1.5 1.5 :uppercase] }
        [:&:hover {:text-decoration "none"}]] ]
@@ -54,15 +60,46 @@
                  :$border [:solid 2  :blue]
                  :$push-left 1
                  :$padding [0.3 2.2]
-                 :border-radius "20px"}]
-     [:.navigation {:$flex-row [:baseline :space-between]}] ]]
-   [:div.container.navigation
-    [:div.brand
-     [:a {:href "/index"} (get-in data [:text :title])]]
+                 :border-radius "20px"}] ]]
+   [:$media {:min-width "479px"}
+    [:#navigation
+     [:.mobile {:display "none"}] ]]
+
+   [:$media {:max-width "480px"}
+    [:#navigation {:padding "15px 0 0"}
+     [:.brand {:padding-left "15px"}]
+     [:ul {:margin-bottom "10px" :display "none"}]
+     [(keyword "#group:checked + ul") {:display "block !important"}]
+     [:.sign-in {:margin-left "10px"}]
+     [:.desctop {:display "none"}]
+     [:.sign-in-li-item {:margin-top "10px"}]
+     [:li {:width "100%"}] ] ]
+
+   [:div.container.navigation.desctop
+     [:div.brand
+      [:a {:href "/index"} (get-in data [:text :title])]]
     [:ul.list-inline
      (for [x (data :menu)]
        [:li [:a {:href (es/url (:href x))} (:title x)]])]
-    [:a.sign-in {:href "https://aidbox.io/ui"} "SIGN IN"]    ]])
+    [:a.sign-in {:href "https://aidbox.io/ui"} "SIGN IN"] ]
+
+   [:div.container.navigation.mobile
+    [:.navbar-header
+     [:div.brand
+      [:a {:href "/index"} (get-in data [:text :title])]]
+     [:label {:for "group"}
+      [:div.navbar-toggle
+       [:span {:class "sr-only"} "Toggle navigation"]
+       [:span {:class "icon-bar"}]
+       [:span {:class "icon-bar"}]
+       [:span {:class "icon-bar"}]] ] ]
+    [:input#group.hidden {:type "checkbox"}]
+    [:ul.list-inline
+     (for [x (data :menu)]
+       [:li [:a {:href (es/url (:href x))} (:title x)]])
+     [:li.sign-in-li-item
+      [:a.sign-in {:href "https://aidbox.io/ui"} "SIGN IN"]]]]
+   ])

 (defn layout [{data :data :as opts} cnt]
   [:html
@@ -122,6 +159,12 @@
      [:.moto {:height "auto" :padding 0 :padding-bottom "310px"}]
      [:p {:width "auto"}]]
     ]
+
+   [:$media {:min-width "750px" :max-width "1020px"}
+    [:#moto
+    [:.moto {:padding 0}]
+    [:.chevron {:display "none"}]
+    [:.molecule {:width "280px"}]]]
    [:div.container
     [:div.moto
      [:h1 (get-in data [:text :moto :subheader])]
@@ -143,6 +186,9 @@
               :margin-left "auto"
               :margin-right "auto"
               :$push-top 4}]]]]
+
+   [:$media {:max-width "480px"}
+    [:#index [:.box {:padding 0}]] ]

    (for [[idx feat] (map-indexed (fn [x y] [x y]) (get-in data [:scenarios]))]
      [:div.box


Added info-box to cljs hiccup

Added info-box to cljs hiccup

--- src/wishlistd/cljs/main.cljs
+++ src/wishlistd/cljs/main.cljs
@@ -41,6 +41,12 @@
     [:p "Create your wishlist by clicking the icon above. Add wished and url to the page. Save the unique link in your
           browsers address field to visit and update the wishlist. Share it with your friends so that they can get you all the things
           you wish for!"]]])
+
+(defpartial info-box []
+  [:div [:div#info-box
+   [:div#info-close]
+   [:p#info-text "Wishlist is created by Stina Qvarnström and Erik Kronberg. Bla bla. osv."]]
+  [:div#info-container]])

 ; GETTING AND SETTING

@@ -60,6 +66,12 @@
   (append $content (wish-ul wish))
   (append $header  (wishlist-title title))
   (set-path! code))
+
+(defn show-info! []
+  (append $body ($ info-box)))
+
+(defn hide-info! []
+  (remove ($ info-box)))

 (defn show-arrow! []
   (append $body (arrow)))
@@ -165,6 +177,15 @@
           (remove $parent)
           (delete-wish-rem $parent))))))

+(delegate $body "#icon-about" :click
+  (fn [e]
+    (when-not (empty? ($ info-box))
+      (show-info!))))
+
+(delegate $body "#info-close" :click
+  (fn [e]
+    (hide-info!)))
+
 ; START IT UP

 (defn start-up []


(PDB-2955) Don't call move with replace and atomic

The documentation indicates that atomic is exclusive.  Specifying both
may not hurt anything, but is unnecessary at best.

--- src/stockpile.clj
+++ src/stockpile.clj
@@ -300,8 +300,7 @@
    (let [^Path src (entry-path q entry)
          ^Path destination (as-path destination)
          moved? (try
-                  (Files/move src destination
-                              (copts [copt-atomic copt-replace]))
+                  (Files/move src destination (copts [copt-atomic]))
                   true
                   (catch UnsupportedOperationException ex
                     false)


Small renaming

Small renaming

--- src/tick/core.clj
+++ src/tick/core.clj
@@ -56,7 +56,10 @@
   (#{DayOfWeek/SATURDAY DayOfWeek/SUNDAY} (day-of-week zdt)))

 (defn- easter-sunday-by-year
-  "Return a pair containing [month day] of Easter Sunday given the year."
+  "Return a pair containing [month day] of Easter Sunday given the
+  year. Copyright © 2016 Eivind Waaler. EPL v1.0. From
+  https://github.com/eivindw/clj-easter-day, using Spencer Jones
+  formula."
   ;; TODO: From what year does this algorithm makes sense from, need
   ;; to throw an exception outside this range.
   [year]
@@ -77,10 +80,8 @@
     [n (+ p 1)]))

 (defn easter-sunday? [dt]
-  "Copyright © 2016 Eivind Waaler. EPL v1.0. Given a ZoneId, return a
-  predicate that tests if the instant falls on an Easter Sunday. From
-  https://github.com/eivindw/clj-easter-day, using Spencer Jones
-  formula."
+  "Given a ZoneId, return a predicate that tests if the instant falls
+  on an Easter Sunday."
   (let [year (.getYear dt)
         month (.getMonthValue dt)]
     (and
@@ -95,18 +96,15 @@
 (defn easter-monday? [dt]
   (easter-sunday? (.minusDays dt 1)))

-(defn drop-past [now]
+(defn past? [now]
   (fn [d] (.isBefore d now)))

 (defn easter-sundays
-  "Copyright © 2016 Eivind Waaler. EPL v1.0. Given a
-  java.time.LocalDate (defaults to now), return a sequence of Easter
-  Sundays as LocalData instances. From
-  https://github.com/eivindw/clj-easter-day, using Spencer Jones
-  formula."
+  "Given a java.time.LocalDate (defaults to now), return a sequence of Easter
+  Sundays as LocalData instances. "
   ([^LocalDate from-local-date]
    (let [year (.getYear from-local-date)]
-     (drop-while (drop-past from-local-date)
+     (drop-while (past? from-local-date)
                  (for [year (range year 2200)]
                    (let [[month day] (easter-sunday-by-year year)]
                      (LocalDate/of year month day))))))
@@ -229,7 +227,7 @@

   (timeline [_]
     (:timeline @state))
-  (timeline [_]
+  (clock [_]
     (:clock @state)))

 (defn schedule
@@ -242,7 +240,7 @@
                            :state (atom {})
                            :executor (or executor (new ScheduledThreadPoolExecutor 16))})))

-(defrecord FixedClockAdvancingTicker []
+(defrecord ImpatientTicker []
   ITicker
   (start [this clock] nil)
   (pause [this] nil)
@@ -252,7 +250,7 @@

 ;; ???
 (defn simulate []
-  ;; Create a map->FixedClockAdvancingTicker
+  ;; Create a map->ImpatientTicker
   )


Clean up console clutter

Clean up console clutter

--- src/yada/core.clj
+++ src/yada/core.clj
@@ -290,13 +290,10 @@
                         ;; instead? It's virtually the same logic for
                         ;; url encoded forms
                         (when-let [schema (get-in parameters [method :form])]
-                          (infof "Decoding form...")
                           (when (urlencoded-form? req)
-                            (infof "Decoding urlencoded form...")
                             (let [fp (keywordize-keys
                                       (form-decode (read-body (-> ctx :request))
                                                    (character-encoding req)))]
-                              (infof "fp is %s" fp)
                               (rs/coerce schema fp :json))))

                         :header


Reverted patch to delete/undelete words on search page

--- src/zg/server.clj
+++ src/zg/server.clj
@@ -75,6 +75,24 @@
     [request title emender-page]
     (let [params         (:params request)]
         (finish-processing request nil nil nil nil title emender-page :whitelist)))
+
+(defn process-whitelist
+    "Function that prepares data for the whitelist front page."
+    [request title emender-page]
+    (let [params         (:params request)
+          word           (get params "word")
+          search-results (if (not (empty? word))
+                             (db-interface/read-words-for-pattern word :whitelist))]
+        (finish-processing request search-results nil nil nil title emender-page :whitelist)))
+
+(defn process-blacklist
+    "Function that prepares data for the blacklist front page."
+    [request title emender-page]
+    (let [params         (:params request)
+          word           (get params "word")
+          search-results (if (not (empty? word))
+                             (db-interface/read-words-for-pattern word :blacklist))]
+        (finish-processing request search-results nil nil nil title emender-page :blacklist)))

 (defn process-atomic-typos
     "Function that prepares data for the Atomic typos front page."
@@ -175,26 +193,6 @@
               (db-interface/delete-word to-delete mode))
           (if to-undelete
               (db-interface/undelete-word to-undelete mode))))
-
-(defn process-whitelist
-    "Function that prepares data for the whitelist front page."
-    [request title emender-page]
-    (perform-operation request :whitelist)
-    (let [params         (:params request)
-          word           (get params "word")
-          search-results (if (not (empty? word))
-                             (db-interface/read-words-for-pattern word :whitelist))]
-        (finish-processing request search-results nil nil nil title emender-page :whitelist)))
-
-(defn process-blacklist
-    "Function that prepares data for the blacklist front page."
-    [request title emender-page]
-    (perform-operation request :blacklist)
-    (let [params         (:params request)
-          word           (get params "word")
-          search-results (if (not (empty? word))
-                             (db-interface/read-words-for-pattern word :blacklist))]
-        (finish-processing request search-results nil nil nil title emender-page :blacklist)))

 (defn process-all-words
     "Read all words from the selected dictionary and display them to user on generated page."


Layout manager #41

Layout manager #41

--- test/flatgui/layout_test.clj
+++ test/flatgui/layout_test.clj
@@ -193,6 +193,21 @@
                      {:element :f :min (m/defpoint 0.1 0.1) :pref (m/defpoint 0.2 0.1) :stch-weight 0.0 :flags nil}))
         actual (layout/assoc-constraints main cfg \- + max)]
     (test/is (= expected (map num->double actual)))))
+
+(test/deftest assoc-constraints-test8
+  (let [cfg [[:a :b]
+             [:a :c]]
+        main test-component-1
+        expected (list
+                   (list
+                     {:element :a :min (m/defpoint 0.1 0.1) :pref (m/defpoint 0.2 0.1) :stch-weight 0.0 :flags nil}
+                     {:element :b :min (m/defpoint 0.1 0.1) :pref (m/defpoint 0.2 0.1) :stch-weight 0.0 :flags nil})
+                   (list
+                     {:element :a :min (m/defpoint 0.1 0.1) :pref (m/defpoint 0.2 0.1) :stch-weight 0.0 :flags nil}
+                     {:element :c :min (m/defpoint 0.1 0.1) :pref (m/defpoint 0.3 0.1) :stch-weight 0.0 :flags nil}))
+        actual (layout/assoc-constraints main cfg \- + max)]
+    (test/is (= expected (map num->double actual)))))
+

 ;;; compute-x-dir


Make two tests independent of whitespace.

--- test/midje/util/t_report.clj
+++ test/midje/util/t_report.clj
@@ -81,18 +81,18 @@
 		     :position ["foo.clj" 3]
 		     :function odd?}
 	raw-report (with-identity-renderer (clojure.test/old-report failure-map))]
-    (nth raw-report 0) => (re #"FAIL at .*foo.clj:3")
-    (nth raw-report 1) => (re #"never said odd\? would be needed")
-    (nth raw-report 2) => "(nil)"))
+    (nth raw-report 0) => #"FAIL at .*foo.clj:3"
+    (nth raw-report 1) => #"never said odd\? would be needed"
+    (nth raw-report 2) => #"\(nil\)"))

 (fact "mock called an incorrect number of times"
   (let [failure-map {:type :mock-incorrect-call-count
 		     :position ["foo.clj" 3]
 		     :expected "(f a)"}
 	raw-report (with-identity-renderer (clojure.test/old-report failure-map))]
-    (nth raw-report 0) => (re #"FAIL at .*foo.clj:3")
-    (nth raw-report 1) => (re #"claimed the following was needed")
-    (nth raw-report 2) => "(f a)"))
+    (nth raw-report 0) => #"FAIL at .*foo.clj:3"
+    (nth raw-report 1) => #"claimed the following was needed"
+    (nth raw-report 2) => #"\(f a\)"))

 (fact "ordinary bad result from equality"
   (let [failure-map {:type :mock-expected-result-failure


Fixing bulk index test so that it passes required fields.

--- system-int-test/test/cmr/system_int_test/bootstrap/bulk_index_test.clj
+++ system-int-test/test/cmr/system_int_test/bootstrap/bulk_index_test.clj
@@ -100,6 +100,7 @@
                                            :metadata xml
                                            :extra-fields {:short-name (str "short-name" x)
                                                           :entry-title (str "title" x)
+                                                          :entry-id (str "entry-id" x)
                                                           :version-id "v1"}
                                            :provider-id "PROV1"
                                            :native-id (str "coll" x)
@@ -107,20 +108,21 @@
                               {:keys [concept-id revision-id]} (ingest/save-concept concept-map)]
                           (assoc umm :concept-id concept-id :revision-id revision-id)))
           granules1 (mapcat (fn [collection]
-                              (doall
-                                (for [x (range 1 4)]
-                                  (let [pid (:concept-id collection)
-                                        umm (dg/granule collection)
-                                        xml (echo10/umm->echo10-xml umm)
-                                        concept-map {:concept-type :granule
-                                                     :provider-id "PROV1"
-                                                     :native-id (str "gran-" pid "-" x)
-                                                     :extra-fields {:parent-collection-id pid}
-                                                     :format "application/echo10+xml"
-                                                     :metadata xml}
-                                        {:keys [concept-id revision-id]} (ingest/save-concept concept-map)]
-                                    (assoc umm :concept-id concept-id :revision-id revision-id)))))
-                            collections)
+                                     (doall
+                                       (for [x (range 1 4)]
+                                         (let [pid (:concept-id collection)
+                                               umm (dg/granule collection)
+                                               xml (echo10/umm->echo10-xml umm)
+                                               concept-map {:concept-type :granule
+                                                            :provider-id "PROV1"
+                                                            :native-id (str "gran-" pid "-" x)
+                                                            :extra-fields {:parent-collection-id pid
+                                                                           :granule-ur (str "ur" x)}
+                                                            :format "application/echo10+xml"
+                                                            :metadata xml}
+                                               {:keys [concept-id revision-id]} (ingest/save-concept concept-map)]
+                                           (assoc umm :concept-id concept-id :revision-id revision-id)))))
+                                   collections)
           ;; granules2 and f (the future) are used to ingest ten granules five times each in
           ;; a separate thread to verify that bulk indexing with concurrent ingest does the right
           ;; thing.
@@ -150,12 +152,12 @@
           (let [{:keys [concept-id revision-id]} granule
                 response (search/find-refs :granule {:concept-id concept-id})
                 es-revision-id (:revision-id (first (:refs response)))]
-            (is (= es-revision-id revision-id))))
+            (is (= es-revision-id revision-id) (str "Failure for granule " concept-id))))
         (doseq [granule (last @f)]
           (let [{:keys [concept-id]} granule
                 response (search/find-refs :granule {:concept-id concept-id})
                 es-revision-id (:revision-id (first (:refs response)))]
-            (is (= 5 es-revision-id))))))))
+            (is (= 5 es-revision-id) (str "Failure for granule " concept-id))))))))

 (deftest invalid-provider-bulk-index-validation-test
   (s/only-with-real-database


Deleting redundant code (content-tab)

Deleting redundant code (content-tab)

--- src-cljs/kixi/hecuba/main.cljs
+++ src-cljs/kixi/hecuba/main.cljs
@@ -127,26 +127,6 @@
   [_ item owner]
   (om/build table item {:opts (om/get-state owner :event-chan)}))

-(defn content-tab
-  "A component that knows how to render from a list of content directives."
-  [data owner]
-  (reify
-    om/IWillMount
-    (will-mount [_]
-      (let [ch (chan (sliding-buffer 1))]
-        (om/set-state! owner :event-chan ch)
-        (go-loop [] (when-let [e (<! ch)]
-                      (println e)
-                      (recur)))))
-    om/IRender
-    (render [_]
-      (dom/div nil
-           (dom/h1 nil (:title data))
-           (into-array
-            (for [[itemtype item] (:content data)]
-              (render-content-directive itemtype item owner)
-              ))))))
-
 (defn console-sink [label ch]
   (go-loop []
    (when-let [v (<! ch)]


Reformatted format_date_test.clj by zprint

--- test/zg/format_date_test.clj
+++ test/zg/format_date_test.clj
@@ -19,51 +19,51 @@
 ;

 (defn callable?
-    "Test if given function-name is bound to the real function."
-    [function-name]
-    (clojure.test/function? function-name))
+  "Test if given function-name is bound to the real function."
+  [function-name]
+  (clojure.test/function? function-name))

 ;
 ; Tests for various functions existence
 ;

 (deftest test-format-date-existence
-    "Check that the zg.format-date/format-date definition exists."
-    (testing "if the zg.format-date/format-date definition exists."
-        (is (callable? 'zg.format-date/format-date))))
+  "Check that the zg.format-date/format-date definition exists."
+  (testing "if the zg.format-date/format-date definition exists."
+           (is (callable? 'zg.format-date/format-date))))

 (deftest test-format-current-date-existence
-    "Check that the zg.format-date/format-current-date definition exists."
-    (testing "if the zg.format-date/format-current-date definition exists."
-        (is (callable? 'zg.format-date/format-current-date))))
+  "Check that the zg.format-date/format-current-date definition exists."
+  (testing "if the zg.format-date/format-current-date definition exists."
+           (is (callable? 'zg.format-date/format-current-date))))

 ;
 ; Test function behaviours
 ;

 (deftest test-format-date-1
-    "Check the function zg.format-date/format-date"
-    (testing "the function zg.format-date/format-date."
-        (let [date (new java.util.Date 116 01 01 12 00)]
-            (is (not (nil? (format-date date))))
-            (is (= (type (format-date date)) java.lang.String))
-            (is (= (count (format-date date)) 19)))))
+  "Check the function zg.format-date/format-date"
+  (testing "the function zg.format-date/format-date."
+           (let [date (new java.util.Date 116 01 01 12 00)]
+             (is (not (nil? (format-date date))))
+             (is (= (type (format-date date)) java.lang.String))
+             (is (= (count (format-date date)) 19)))))

 (deftest test-format-date-2
-    "Check the function zg.format-date/format-date"
-    (testing "the function zg.format-date/format-date."
-        (let [date (new java.util.Date 116 01 01 12 00)]
-            (is (= "2016-02-01 12:00:00" (format-date date))))
-        (let [date (new java.util.Date 100 01 01 12 00)]
-            (is (= "2000-02-01 12:00:00" (format-date date))))
-        (let [date (new java.util.Date 0 00 01 00 00)]
-            (is (= "1900-01-01 00:00:00" (format-date date))))))
+  "Check the function zg.format-date/format-date"
+  (testing "the function zg.format-date/format-date."
+           (let [date (new java.util.Date 116 01 01 12 00)]
+             (is (= "2016-02-01 12:00:00" (format-date date))))
+           (let [date (new java.util.Date 100 01 01 12 00)]
+             (is (= "2000-02-01 12:00:00" (format-date date))))
+           (let [date (new java.util.Date 0 00 01 00 00)]
+             (is (= "1900-01-01 00:00:00" (format-date date))))))

 (deftest test-format-current-date
-    "Check the function zg.format-date/format-current-date"
-    (testing "the function zg.format-date/format-current-date."
-        (is (not (nil? (format-current-date))))
-        (is (= (type (format-current-date))))
-        (is (= (count (format-current-date)) 19))))
+  "Check the function zg.format-date/format-current-date"
+  (testing "the function zg.format-date/format-current-date."
+           (is (not (nil? (format-current-date))))
+           (is (= (type (format-current-date))))
+           (is (= (count (format-current-date)) 19))))


GAWB-2189: unsure why this happened

GAWB-2189: unsure why this happened

--- src/cljs/main/broadfcui/page/workspace/method_configs/method_config_editor.cljs
+++ src/cljs/main/broadfcui/page/workspace/method_configs/method_config_editor.cljs
@@ -123,7 +123,7 @@
                                                          " to the Google Bucket associated with this workspace."))
                                    :on-success (:on-submission-success props)})])
          (this :-render-main)
-         (common/clear-both)]]))
+         (clear-both)]]))
    :-render-sidebar
    (fn [{:keys [props state this]}]
      (let [{:keys [editing? loaded-config inputs-outputs]} @state
@@ -136,7 +136,7 @@
                   :top (when-not (:sidebar-visible? @state) 4)
                   :width 290}}
          (let [{:keys [locked?]} @state
-               can-edit? (common/access-greater-than? (:access-level props) "READER")
+               can-edit? (access-greater-than? (:access-level props) "READER")
                snapshot-id (get-in config [:methodRepoMethod :methodVersion])
                config-id (ws-common/config->id config)]
            [:div {}
@@ -198,7 +198,7 @@
            (style/create-identity-select {:ref "rootentitytype"
                                           :defaultValue (:rootEntityType config)
                                           :style {:width 500}}
-                                         common/root-entity-types)
+                                         root-entity-types)
            [:div {:style {:padding "0.5em 0 1em 0"}} (:rootEntityType config)]))
         [:datalist {:id "inputs-datalist"}
          [:option {:value "this."}]
@@ -247,11 +247,11 @@
    (fn [{:keys [props state refs]}]
      (let [{:keys [workspace-id]} props
            config (-> @state :loaded-config :methodConfiguration)
-           [name root-entity-type] (common/get-text refs "confname" "rootentitytype")
+           [name root-entity-type] (get-text refs "confname" "rootentitytype")
            deref-vals (fn [io-key ref-prefix]
                         (->> (io-key (:inputs-outputs @state))
                              (map :name)
-                             (map (juxt identity #(common/get-text refs (str ref-prefix "_" %))))
+                             (map (juxt identity #(get-text refs (str ref-prefix "_" %))))
                              (remove (comp empty? val))
                              (into {})))]
        (swap! state assoc :blocker "Updating...")


fix bug that showed up when I started using real types instead of seqs to hold data

--- dada-core/src/main/clojure/org/dada/core/dql.clj
+++ dada-core/src/main/clojure/org/dada/core/dql.clj
@@ -645,7 +645,7 @@
 				  ;; surround the single split model
 				  ;; and make it look like it is a
 				  ;; singleton..
-				  single-data-metamodel (model (.getName split-model) split-metadata)
+				  single-data-metamodel (model (.getName split-model) result-metadata)
 				  single-data-fn (fn []
 						     (Result.
 						      single-data-metamodel


CMR-2089 Updates translate logic to use concept-type variable.

--- ingest-app/src/cmr/ingest/api/translation.clj
+++ ingest-app/src/cmr/ingest/api/translation.clj
@@ -37,9 +37,9 @@
       ;; If there were no errors, then proceed to convert it to UMM and check for UMM schema
       ;; validation errors.
       (let [umm (umm-spec/parse-metadata concept-type input-format body)
-            umm-json (umm-spec/generate-metadata :collection :umm-json umm)]
+            umm-json (umm-spec/generate-metadata concept-type :umm-json umm)]

-        (if-let [umm-errors (seq (umm-spec/validate-metadata :collection :umm-json umm-json))]
+        (if-let [umm-errors (seq (umm-spec/validate-metadata concept-type :umm-json umm-json))]
           (errors/throw-service-errors :invalid-data umm-errors)
           ;; Otherwise, if the parsed UMM validates, return a response with the metadata in the
           ;; requested XML format.


Whitespace

Whitespace

--- worker/src/clinicico/worker/consumer.clj
+++ worker/src/clinicico/worker/consumer.clj
@@ -16,7 +16,7 @@
 (defprotocol Protocol
   (send! [this socket messages]))

-(defn insert [vec pos item]
+(defn insert [vec pos item]
     (apply merge (subvec vec 0 pos) item (subvec vec pos)))

 (defrecord MessageProtocol [method]
@@ -55,7 +55,7 @@
         pong (fn [_] (do (reset! reconnecter (create-reconnecter consumer))
                         (swap! consumer assoc :liveness heartbeat-liveness)))
         ping #(do (send! (@consumer :protocol) (@consumer :socket) [q/MSG-PING]))
-        heartbeat (fn []
+        heartbeat (fn []
                     (when (contains? @consumer :socket)
                       (let [next-liveness (dec (get @consumer :liveness (inc heartbeat-liveness)))]
                         (swap! consumer assoc :liveness next-liveness)
@@ -74,7 +74,7 @@
           response (handler (nippy/thaw request))]
       (send! protocol socket [q/MSG-REP address (nippy/freeze response)])
       (send! protocol socket [q/MSG-READY]))))
-
+
 (defn- handle-incoming
   [consumer]
   (fn []
@@ -109,7 +109,7 @@
     ((@consumer :initialize))
     (.start (Thread. #(.start zloop)))
     consumer))
-
+
 (defn start
   [method handler]
   (with-heartbeat (create-consumer method handler)))


fix failing test

fix failing test

--- test/cellophane/dom-test.clj
+++ test/cellophane/dom-test.clj
@@ -49,5 +49,5 @@
     (dom/div nil "Hello World")))

 (deftest test-render-defui
-  (let [c (SimpleComponent)]
+  (let [c (->SimpleComponent nil nil nil)]
     (is (= (dom/render-to-string c) "
Hello World
"))))


fi test

fi test

--- test/ci3/agent/core_test.clj
+++ test/ci3/agent/core_test.clj
@@ -1,6 +1,10 @@
 (ns ci3.agent.core-test
-  (:require [unifn.core :as u]
-            [clojure.test :refer :all]))
+  (:require
+   [ci3.agent.core :as sut]
+   [matcho.core :refer [match]]
+   [unifn.core :as u]
+   [ci3.k8s :as k8s]
+   [clojure.test :refer :all]))

 (def bid "build-112233")
 (def bid-src "build-223344")
@@ -42,7 +46,6 @@
                :root "src"
                :type "bitbucket"
                :fullName "Aitem/ci3-public"
-
                :url "https://bitbucket.org/Aitem/ci3-public"})

   ;; github
@@ -81,7 +84,7 @@
              :env {:build-id bid :BUILD_ID bid}})
    {::sut/build  {:metadata {:name bid}
                   :repository rid}
-    ::ci3.repo.core/repository {:metadata {:name rid}}
+    :ci3.repo.core/repository {:metadata {:name rid}}
     :checkout   hashcommit
     ::sut/build-config {:description "build in root"}})

@@ -90,7 +93,7 @@
              :env {:build-id bid-src :BUILD_ID bid-src}})
    {::sut/build  {:metadata {:name bid-src}
                   :repository rid-src}
-    ::ci3.repo.core/repository {:metadata {:name rid-src}}
+    :ci3.repo.core/repository {:metadata {:name rid-src}}
     :checkout   hashcommit
     ::sut/build-config {:description "build in src"}})

@@ -99,7 +102,7 @@
              :env {:build-id ghbid :BUILD_ID ghbid}})
    {::sut/build  {:metadata {:name ghbid}
                   :repository ghrid}
-    ::ci3.repo.core/repository {:metadata {:name ghrid}}
+    :ci3.repo.core/repository {:metadata {:name ghrid}}
     :checkout   github-hashcommit
     ::sut/build-config {:description "build in src"}})


bolt in test

bolt in test

--- test/infinitelives/test.cljs
+++ test/infinitelives/test.cljs
@@ -6,6 +6,7 @@
             [infinitelives.utils.math-test]
             [infinitelives.utils.spatial-test]
             [infinitelives.utils.geom2-test]
+            [infinitelives.utils.pathfind-test]
 ))

 (enable-console-print!)


Update Hello World.

Update Hello World.

--- examples/hello-world/project.clj
+++ examples/hello-world/project.clj
@@ -1,10 +1,10 @@
-(defproject hello-world "0.44.0"
+(defproject hello-world "0.45.0"
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
   :dependencies [[org.clojure/clojure "1.10.3"]
-                 [uncomplicate/neanderthal "0.44.0"]
+                 [uncomplicate/neanderthal "0.45.0"]
                  ;;Optional. If bytedeco is not present, a system-wide MKL is used.
-                 [org.bytedeco/mkl-platform-redist "2022.0-1.5.7"]]
+                 [org.bytedeco/mkl-platform-redist "2020.3-1.5.4"]]
   ;; Nvidia doesn't ship CUDA for macOS; you have to add this to your project
   :exclusions [[org.jcuda/jcuda-natives :classifier "apple-x86_64"]
                [org.jcuda/jcublas-natives :classifier "apple-x86_64"]]


stub test for duration

stub test for duration

--- test/ontrail/test/mutate.clj
+++ test/ontrail/test/mutate.clj
@@ -19,9 +19,9 @@
 (deftest basic-exercise-is-valid
   (is (valid? basic-exercise)))

-(deftest test-parse-distance
-  (let [hour (* 60 60 100)]
-    (is (= hour (parse-distance "1h")))))
+;(deftest test-parse-distance
+;  (let [hour (* 60 60 100)]
+;    (is (= hour (parse-distance "1h")))))

 (deftest test-db-insertable-from-basic-user-ex
   (is (= {:title "A title"


FIXME wrt. testing pattern/binding->value

--- test/oxcart/pattern_test.clj
+++ test/oxcart/pattern_test.clj
@@ -126,6 +126,12 @@
     (is (= 'x__#0 (p/binding->symbol b)))))

+;; FIXME:
+;;   Tests for binding->value should go here, however as with
+;;   binding->symbol it's a pretty worthless and definitional
+;;   test. Omitted for now, fix later.
+
+
 (def private-defn
   (ast
    (defn ^:private baz [x]


working on French grammar that handles reflexive sentences

--- src/babel/francais/grammar.clj
+++ src/babel/francais/grammar.clj
@@ -1,6 +1,7 @@
 (ns babel.francais.grammar
   (:refer-clojure :exclude [get-in merge resolve])
   (:require
+   [clojure.set :refer :all]
    [clojure.tools.logging :as log]
    [babel.cache :refer (build-lex-sch-cache create-index spec-to-phrases)]
    [babel.francais.lexicon :refer [lexicon]]
@@ -463,6 +464,13 @@
                  (morph/analyze arg lexicon))
        :enrich enrich
        :grammar grammar
+
+       ;; Will throw exception if more than 1 rule has the same :rule value:
+       :grammar-map (zipmap
+                     (map #(keyword (get-in % [:rule]))
+                          grammar)
+                     grammar)
+
        :lexicon lexicon
        :morph fo
        :index (create-index grammar (flatten (vals lexicon)) head-principle)})))
@@ -477,18 +485,42 @@
                 (for [[k v] @lexicon]
                   (let [filtered-v v]
                     (if (not (empty? filtered-v))
-                      [k filtered-v]))))]
+                      [k filtered-v]))))
+
+          grammar ;; small grammar + a few other things:
+          (seq (union (set (:grammar @small))
+                      (set (filter #(or (= (:rule %) "vp-pronoun-nonphrasal")
+                                        (= (:rule %) "s-present-phrasal"))
+                                   grammar))))]
       {:name "medium"
        :enrich enrich
        :grammar grammar
+
+       ;; Will throw exception if more than 1 rule has the same :rule value:
+       :grammar-map (zipmap
+                     (map #(keyword (get-in % [:rule]))
+                          grammar)
+                     grammar)
+
        :lexicon lexicon
        :index (create-index grammar (flatten (vals lexicon)) head-principle)
+
+       :morph-walk-tree (fn [tree]
+                          (do
+                            (merge tree
+                                   (morph-walk-tree tree))))
+       :language "fr"
+       :language-keyword :français
+       :lookup (fn [arg]
+                 (morph/analyze arg lexicon))
+       :morph fo
+
        })))

 (defn parse [surface]
   (parse/parse surface
-               (:lexicon @small)
-               (:lookup @small)
-               (:grammar @small)))
+               (:lexicon @medium)
+               (:lookup @medium)
+               (:grammar @medium)))

 (log/info "Français grammar defined.")


Remove unnecessary subscriptions

Remove unnecessary subscriptions

--- src/braid/ui/views/header.cljs
+++ src/braid/ui/views/header.cljs
@@ -104,16 +104,13 @@
                     :title "Group Settings"}]]))))

 (defn header-view []
-  (let [group-id (subscribe [:open-group-id])
-        admin? (subscribe [:current-user-is-group-admin?] [group-id])]
-    (fn []
-    [:div.header
-     [clear-inbox-button-view]
-     [inbox-page-button-view]
-     [recent-page-button-view]
-     [help-page-pane-view]
-     [users-online-pane-view]
-     [tags-pane-view]
-     [group-settings-view]
-     [search-bar-view]
-     [current-user-button-view]])))
+  [:div.header
+   [clear-inbox-button-view]
+   [inbox-page-button-view]
+   [recent-page-button-view]
+   [help-page-pane-view]
+   [users-online-pane-view]
+   [tags-pane-view]
+   [group-settings-view]
+   [search-bar-view]
+   [current-user-button-view]])


reduced speed

reduced speed

--- src/amindblowingworld/civs.clj
+++ src/amindblowingworld/civs.clj
@@ -127,7 +127,7 @@
              biome (.get b (:x pos) (:y pos))]
         (not (= (.name biome) "OCEAN"))))))

-(def fastness 100)
+(def fastness 10000)

 (defn settlements-around [pos radius]
   (let [cx (:x pos)


Handle go-junit-report XML.

Handle go-junit-report XML.

This tool produces a file with multiple test suite reports in it, whereas it's
usually the case that we encounter a single testsuite per XML file. We now
handle this scenario, as well as cases where the test report may not contain
information about how many tests were skipped, or how many errors there were.

--- src/clj/runbld/tests/junit.clj
+++ src/clj/runbld/tests/junit.clj
@@ -6,6 +6,10 @@
             [clojure.string :as str]
             [net.cgrand.enlive-html :as x]))

+(defn maybe-update [m ks f & x]
+  (into m (for [[k v] (select-keys m ks)]
+            [k (apply f v x)])))
+
 (defn testcase-meta [xml]
   (-> xml
       (x/select [[(x/attr= :errors)
@@ -13,11 +17,9 @@
                   (x/attr= :tests)]])
       first
       :attrs
-      (rename-keys {:skip :skipped}) ;; for nosetest
-      (update :errors   #(Integer/parseInt %))
-      (update :failures #(Integer/parseInt %))
-      (update :tests    #(Integer/parseInt %))
-      (update :skipped  #(Integer/parseInt %))))
+      (rename-keys {:skip :skipped})
+      (maybe-update [:errors :failures :tests :skipped]
+                    #(Integer/parseInt %))))

 (defn content-text [xml]
   (apply str (map x/text xml)))
@@ -69,6 +71,15 @@
       (clojure.pprint/pprint testsuite)
       (throw t))))

+(def default-failure-report
+  {:errors 0
+   :failures 0
+   :tests 0
+   :skipped 0})
+
+(defn merge-default [m]
+  (merge default-failure-report m))
+
 (defn find-failures [dir]
   (when dir
     (->> dir
@@ -81,8 +92,10 @@
          (map #(.toURI %))
          (map #(.toURL %))
          (map x/xml-resource)
+         (mapcat #(x/select % [[(x/tag= :testsuite)]]))
          (map make-failure-report)
          (filter identity)
+         (map merge-default)
          (reduce combine-failure-reports {:errors 0
                                           :failures 0
                                           :tests 0


revocation list

revocation list

--- src/clj/salava/badge/parse.clj
+++ src/clj/salava/badge/parse.clj
@@ -301,7 +301,7 @@
                                 :url (:url issuer)
                                 :email (:email issuer)
                                 :image_file (:image issuer)
-                                :revocation_list_url nil
+                                :revocation_list_url (:revocationList issuer)
                                 :endorsement (get-endorsement issuer)}]
                     :creator (when creator-url
                                (let [data (http/json-get creator-url)]
@@ -432,7 +432,7 @@
                              :email (:email issuer)
                              :image_file nil
                              :endorsement []
-                             :revocation_list_url nil}]
+                             :revocation_list_url (:revocationList issuer)}]
                    :creator creator
                    :endorsement []
                    :published 0


add name to accounts show

add name to accounts show

--- src/clj_money/web/accounts.clj
+++ src/clj_money/web/accounts.clj
@@ -127,19 +127,20 @@
   "Renders account details, including transactions"
   ([id] (show id {}))
   ([id options]
-   (layout
-     "Account" options
-     [:div.row
-      [:div.col-md-6
-       [:table.table.table-striped.table-hover
-        [:tr
-         [:th "Date"]
-         [:th "Description"]
-         [:th "Amount"]
-         [:th "Balance"]
-         [:th " "]]
-        (map transaction-item-row
-             (transactions/items-by-account (env :db) id))]]])))
+   (let [account (accounts/find-by-id (env :db) id)]
+     (layout
+       (format "Account - %s" (:name account)) options
+       [:div.row
+        [:div.col-md-6
+         [:table.table.table-striped.table-hover
+          [:tr
+           [:th "Date"]
+           [:th "Description"]
+           [:th "Amount"]
+           [:th "Balance"]
+           [:th " "]]
+          (map transaction-item-row
+               (transactions/items-by-account (env :db) id))]]]))))

 (defn- form-fields
   "Renders the form fields for an account"


More flexible text enriching for enriching with subset of all enrichers

--- src/cljs/sloth/views/text.cljs
+++ src/cljs/sloth/views/text.cljs
@@ -5,7 +5,7 @@
             [clojure.set :refer [subset?]])
   (:import [goog Uri]))

-(def enrichers (atom []))
+(def all-enrichers (atom []))

 (defn make-enricher
   [regex match-converter]
@@ -17,20 +17,21 @@
                   (concat (map match-converter (persistent! matches)) [""])))))

 (defn register-enricher!
-  [regex match-converter]
-  (swap! enrichers conj (make-enricher regex match-converter)))
-
-(defn enrich-text
-  [s]
+  [enricher]
+  (swap! all-enrichers conj enricher))
+
+(defn enrich-text-with
+  [enrichers s]
   (let [result (atom [s])]
-    (doseq [f @enrichers]
+    (doseq [f enrichers]
       (swap! result #(mapcat (fn [v]
                                (if (string? v)
                                  (f v)
                                  [v])) %)))
     (filter (complement empty?) @result)))

-(def enrich-text (memoize enrich-text))
+(def enrich-text (memoize (fn [s]
+                            (enrich-text-with @all-enrichers s))))

 (defn make-external-link
   [url]
@@ -62,7 +63,8 @@

 (def img-regex #"https?://.*\.(?:jpe?g|gif|png)")

-(register-enricher! img-regex make-image-message)
+(def img-enricher (make-enricher img-regex make-image-message))
+(register-enricher! img-enricher)

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Videos
@@ -78,7 +80,8 @@

 (def video-regex #"https?://.*\.(?:webm|mp4|ogv)")

-(register-enricher! video-regex make-video-message)
+(def video-enricher (make-enricher video-regex make-video-message))
+(register-enricher! video-enricher)

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -164,7 +167,8 @@
   [url]
   (make-external-link url))

-(register-enricher! http-url-regex convert-http-url)
+(def http-url-enricher (make-enricher http-url-regex convert-http-url))
+(register-enricher! http-url-enricher)

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Rooms
@@ -183,7 +187,8 @@
        room-name]
       [:span room-name])))

-(register-enricher! room-regex room-converter)
+(def room-enricher (make-enricher room-regex room-converter))
+(register-enricher! room-enricher)

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Contacts
@@ -204,7 +209,8 @@
        contact-name]
       [:span contact-name])))

-(register-enricher! contact-regex contact-converter)
+(def contact-enricher (make-enricher contact-regex contact-converter))
+(register-enricher! contact-enricher)

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Emoji
@@ -1102,7 +1108,8 @@
              :class-name "emoji"}]
       e)))

-(register-enricher! emoji-regex emoji-converter)
+(def emoji-enricher (make-enricher emoji-regex emoji-converter))
+(register-enricher! emoji-enricher)

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Markup
@@ -1114,18 +1121,21 @@
   [s]
   [:strong (unsurround s)])

-(register-enricher! bold-regex bold-converter)
+(def bold-enricher (make-enricher bold-regex bold-converter))
+(register-enricher! bold-enricher)

 (def cursive-regex #"/[^/\n]+/")
 (defn cursive-converter
   [s]
   [:em (unsurround s)])

-(register-enricher! cursive-regex cursive-converter)
+(def cursive-enricher (make-enricher cursive-regex cursive-converter))
+(register-enricher! cursive-enricher)

 (def cross-out-regex #"-[^/\n]+-")
 (defn cross-out-converter
   [s]
   [:i.cross-out (unsurround s)])

-(register-enricher! cross-out-regex cross-out-converter)
+(def cross-out-enricher (make-enricher cross-out-regex cross-out-converter))
+(register-enricher! cross-out-enricher)