scroll symbol pop-up when tour pop-up is visible

--- src/cljs/cljs_repl_web/views.cljs
+++ src/cljs/cljs_repl_web/views.cljs
@@ -19,7 +19,8 @@
             [re-console.core :as console]
             [re-complete.core :as re-complete]
             [cljs-repl-web.localstorage :as local-storage]
-            [re-com.buttons :refer [button]]))
+            [re-com.buttons :refer [button]]
+            [goog.dom :as dom]))

 ;; (set! re-com.box/debug true)

@@ -458,72 +459,80 @@

 (defn symbol-popover
   "A popover's body in which details of the given symbol will be shown."
-  [showing-atom position-atom sym-doc-map]
-  (let [media-query (subscribe [:media-query-size])]
-    (fn symbol-popover-form2 [showing-atom position-atom sym-doc-map]
-      (let [{name :name
-             full-name :full-name
-             desc :description
-             docstring :docstring
-             examples-htmls :examples-htmls
-             examples-strings :examples-strings
-             sign :signature
-             related :related} sym-doc-map
-            desc (or desc docstring) ; some symbols don't have a description so we use
+  ([showing-atom position-atom sym-doc-map]
+   (symbol-popover showing-atom position-atom sym-doc-map nil))
+  ([showing-atom position-atom sym-doc-map tour?]
+   (let [media-query (subscribe [:media-query-size])]
+     (fn symbol-popover-form2 [showing-atom position-atom sym-doc-map]
+       (let [{name :name
+              full-name :full-name
+              desc :description
+              docstring :docstring
+              examples-htmls :examples-htmls
+              examples-strings :examples-strings
+              sign :signature
+              related :related} sym-doc-map
+             desc (or desc docstring) ; some symbols don't have a description so we use
                                         ; the docstring instead; docstring is a regular string,
                                         ; without markdown. Nonetheless, it will be passed to
                                         ; md->react->component function to gain some basic html
                                         ; formatting (like paragraphs)
-            examples (map (fn [html string] {:html html :strings string}) examples-htmls examples-strings)
-            popover-width  (if (= :narrow @media-query) 280 400)
-            popover-height (if (= :narrow @media-query) 250 400)
-            popover-content-width (- popover-width (* 2 14) 15)] ; bootstrap padding + scrollbar width
-        [popover-content-wrapper
-         :showing? showing-atom
-         :position @position-atom
-         :on-cancel (handler-fn (reset! showing-atom false))
-         :style {:max-height (str popover-height)
-                 :max-width (str popover-width)}
-         :backdrop-opacity 0.1
-         :close-button? (= :narrow @media-query)
-         :title [h-box
-                 :gap "6px"
-                 :align :center
-                 :children [[title
-                             :label name
-                             :level :level4]
-                            [md-icon-button
-                             :md-icon-name "zmdi-info"
-                             :tooltip "See online documentation"
-                             :tooltip-position :right-center
-                             :size :smaller
-                             :style {:justify-content :center}
-                             :on-click #(utils/open-new-window (utils/symbol->clojuredocs-url full-name))]]]
-         :body [(fn []
-                  [scroller
-                   :size "1 1 auto"
-                   :max-width (str popover-width)
-                   :max-height (str (- popover-height 50))
-                   :scroll :auto
-                   :child [v-box
-                           :size "1 1 auto"
-                           :gap "8px"
-                           :width (str popover-content-width)
-                           :style {:padding "4px"}
-                           :children [(when (not-empty sign)
-                                        [api-signatures sign])
-                                      (when (not-empty desc)
-                                        [api-symbol-description desc])
-                                      (when (not-empty related)
-                                        [api-related-symbols related])
-                                      (when (not-empty examples)
-                                        [api-examples showing-atom examples])]]])]]))))
+             examples (map (fn [html string] {:html html :strings string}) examples-htmls examples-strings)
+             popover-width  (if (= :narrow @media-query) 280 400)
+             popover-height (if (= :narrow @media-query) 250 400)
+             popover-content-width (- popover-width (* 2 14) 15)] ; bootstrap padding + scrollbar width
+         [popover-content-wrapper
+          :showing? showing-atom
+          :position @position-atom
+          :on-cancel (handler-fn (reset! showing-atom false))
+          :style {:max-height (str popover-height)
+                  :max-width (str popover-width)}
+          :backdrop-opacity 0.1
+          :close-button? (= :narrow @media-query)
+          :title [h-box
+                  :gap "6px"
+                  :align :center
+                  :children [[title
+                              :label name
+                              :level :level4]
+                             [md-icon-button
+                              :md-icon-name "zmdi-info"
+                              :tooltip "See online documentation"
+                              :tooltip-position :right-center
+                              :size :smaller
+                              :style {:justify-content :center}
+                              :on-click #(utils/open-new-window (utils/symbol->clojuredocs-url full-name))]]]
+          :body [reagent/create-class
+                 {:component-did-mount (fn [this]
+                                         (let [node (reagent/dom-node this)]
+                                           (when tour?
+                                             (set! (.-scrollTop node) 133))))
+                  :reagent-render (fn []
+                                    [scroller
+                                     :size "1 1 auto"
+                                     :max-width (str popover-width)
+                                     :max-height (str (- popover-height 50))
+                                     :scroll :auto
+                                     :child [v-box
+                                             :size "1 1 auto"
+                                             :gap "8px"
+                                             :width (str popover-content-width)
+                                             :style {:padding "4px"}
+                                             :children [(when (not-empty sign)
+                                                          [api-signatures sign])
+                                                        (when (not-empty desc)
+                                                          [api-symbol-description desc])
+                                                        (when (not-empty related)
+                                                          [api-related-symbols related])
+                                                        (when (not-empty examples)
+                                                          [api-examples showing-atom examples])]]])}]])))))

 (defn api-symbol
   "Builds the UI for a single symbol. Will be a button."
   [symbol]
   (let [showing? (reagent/atom false)
-        popover-position (reagent/atom :below-center)]
+        popover-position (reagent/atom :below-center)
+        tour? (reagent/atom false)]
     (fn api-symbol-form2 [symbol]
       [box
        :size "0 1 auto"
@@ -546,32 +555,35 @@
                                     (utils/calculate-popover-position [(.-clientX event) (.-clientY event)]))
                             (reset! showing? true))}]
                    #(do (finish-tour tour)
-                        (utils/scroll-to-top))
-                   #(do (reset! showing? true)
-                        (reset! popover-position :above-center)
-                        (popover-anchor-wrapper
+                        (utils/scroll-to-top)
+                        (reset! tour? false))
+                   #(do (reset! popover-position :above-center)
+                        (reset! tour? true)
+                        (reset! showing? true)
+                        [popover-anchor-wrapper
                          :showing? showing?
                          :position @popover-position
                          :anchor [button
                                   :class "btn btn-default api-panel-symbol-button"
-                                  :label (:name "/")]
-                         :popover [symbol-popover showing? popover-position "/"]))]
-                  [popover-anchor-wrapper
-                   :showing? showing?
-                   :position @popover-position
-                   :anchor [button
-                            :class "btn btn-default api-panel-symbol-button"
-                            :label (:name symbol')
-                            ;; we use :attr's `:on-click` because button's `on-click` accepts
-                            ;; a parametless function and we need the mouse click coordinates
-                            :attr {:on-click
-                                   (handler-fn
-                                    ;; later we can refactor it into re-frame
-                                    ;; see also https://github.com/Day8/re-frame/wiki/Beware-Returning-False#user-content-usage-examples
-                                    (reset! popover-position
-                                            (utils/calculate-popover-position [(.-clientX event) (.-clientY event)]))
-                                    (reset! showing? true))}]
-                   :popover [symbol-popover showing? popover-position symbol']])
+                                  :label (:name symbol)]])]
+                  (do [popover-anchor-wrapper
+                       :showing? showing?
+                       :position @popover-position
+                       :anchor [button
+                                :class "btn btn-default api-panel-symbol-button"
+                                :label (:name symbol')
+                                ;; we use :attr's `:on-click` because button's `on-click` accepts
+                                ;; a parametless function and we need the mouse click coordinates
+                                :attr {:on-click
+                                       (handler-fn
+                                        ;; later we can refactor it into re-frame
+                                        ;; see also https://github.com/Day8/re-frame/wiki/Beware-Returning-False#user-content-usage-examples
+                                        (reset! popover-position
+                                                (utils/calculate-popover-position [(.-clientX event) (.-clientY event)]))
+                                        (reset! showing? true))}]
+                       :popover (if @tour?
+                                  [symbol-popover showing? popover-position symbol' true]
+                                  [symbol-popover showing? popover-position symbol'])]))
                 [label
                  :label (str symbol)
                  :class "api-panel-symbol-label"


Cleanup XPC API.

Cleanup XPC API.

--- src/cljs/clojure/browser/net.cljs
+++ src/cljs/clojure/browser/net.cljs
@@ -26,12 +26,13 @@
           (js->clj goog.net.EventType)))))

 (defprotocol IConnection
+  (connect [this] [this opt1])
   (transmit
-    [this uri]
-    [this uri method]
-    [this uri method content]
-    [this uri method content headers]
-    [this uri method content headers timeout])
+    [this opt]
+    [this opt opt2]
+    [this opt opt2 opt3]
+    [this opt opt2 opt3 opt4]
+    [this opt opt2 opt3 opt4 opt5])
   (close [this]))

 (extend-type goog.net.XhrIo
@@ -68,25 +69,26 @@
             v])
          (js->clj gxpc-config-fields))))

+(defn xhr-connection
+  "Returns a connection"
+  []
+  (goog.net.XhrIo.))
+
 (defprotocol CrossPageChannel
-  (register-service [this type fn] [this type fn encode-json?])
-
-  (connect [this fn])
-
-  (send-xpc [this type payload]))
+  (register-service [this type fn] [this type fn encode-json?]))

 (extend-type goog.net.xpc.CrossPageChannel

   CrossPageChannel
   (register-service [this type fn]
-    (listen-parent this type fn false))
+    (register-service this type fn false))
   (register-service [this type fn encode-json?]
-    (.registerService parent (name type) fn encode-json?))
+    (.registerService this (name type) fn encode-json?))

+  IConnection
   (connect [this fn]
     (.connect this fn))
-
-  (send-xpc [this type payload]
+  (transmit [this type payload]
     (.send this (name type) payload)))

 (defn cross-page-channel
@@ -99,8 +101,3 @@
                     (assoc (apply hash-map config)
                       :peer_uri
                       url)))))
-
-(defn xhr-connection
-  "Returns a connection"
-  []
-  (goog.net.XhrIo.))


Add IndexedDBStore.

Add IndexedDBStore.

--- src/cljs/geschichte/platform.cljs
+++ src/cljs/geschichte/platform.cljs
@@ -1,8 +1,10 @@
 (ns geschichte.platform
-  (:require [goog.net.WebSocket]
+  (:require [geschichte.protocols :refer [IAsyncKeyValueStore -get-in -assoc-in -update-in]]
+   [goog.net.WebSocket]
             [goog.events :as events]
             [cljs.reader :refer [read-string]]
-            [cljs.core.async :as async :refer (take! put! close! chan)]))
+            [cljs.core.async :as async :refer (take! put! close! chan)])
+  (:require-macros [cljs.core.async.macros :refer [<! >! go go-loop]]))

 (defn log [& s]
@@ -60,7 +62,105 @@
     opener))

 (defn start-server! [ip port]
-  (throw "No server functionality in js yet. Node port welcome."))
+  {throw "No server functionality in js yet. Node port welcome."})
+
+
+
+(defrecord IndexedDBKeyValueStore [db store-name]
+  IAsyncKeyValueStore
+  (-get-in [this key-vec]
+    (let [[fkey & rkey] key-vec
+          res (chan)
+          tx (.transaction db #js [store-name])
+          obj-store (.objectStore tx store-name)
+          req (.get obj-store (str fkey))]
+      (set! (.-onerror req)
+            (fn [e] (log e) (close! res) (throw e)))
+      (set! (.-onsuccess req)
+            (fn [e] (when-let [r (.-result req)]
+                     (put! res(-> r
+                                  .-edn_value
+                                  read-string
+                                  (get-in rkey))))
+              ;; returns nil
+              (close! res)))
+      res))
+  (-assoc-in [this key-vec value]
+    (go (let [[fkey & rkey] key-vec
+              res (chan)
+              tx (.transaction db #js [store-name] "readwrite")
+              obj-store (.objectStore tx store-name)
+              req (.get obj-store (str fkey))]
+          (set! (.-onerror req)
+                (fn error-handler [e] (log e) (close! res) (throw e)))
+          (set! (.-onsuccess req)
+                (fn read-old [e]
+                  (let [old (when-let [r (.-result req)]
+                              (-> r .-edn_value read-string))
+                        up-req (.put obj-store
+                                     (clj->js {:key (str fkey)
+                                               :edn_value
+                                               (str (if-not (empty? rkey)
+                                                      (assoc-in old rkey value)
+                                                      value))}))]
+                    (set! (.-oncomplete up-req)
+                          (fn [e] (close! res))))))
+          (<! res))))
+  (-update-in [this key-vec up-fn]
+    (go (let [[fkey & rkey] key-vec
+              res (chan)
+              tx (.transaction db #js [store-name] "readwrite")
+              obj-store (.objectStore tx store-name)
+              req (.get obj-store (str fkey))]
+          (set! (.-onerror req)
+                (fn error-handler [e] (log e) (close! res) (throw e)))
+          (set! (.-onsuccess req)
+                (fn read-old [e]
+                  (let [old (when-let [r (.-result req)]
+                              (-> r .-edn_value read-string))
+                        up-req (.put obj-store
+                                     (clj->js {:key (str fkey)
+                                               :edn_value
+                                               (str (if-not (empty? rkey)
+                                                      (update-in old rkey up-fn)
+                                                      (up-fn value)))}))]
+                    (set! (.-oncomplete up-req)
+                          (fn [e] (close! res))))))
+          (<! res)))))
+
+
+(defn new-indexeddb-store [name]
+  (let [res (chan)
+        req (.open js/window.indexedDB name 1)]
+    (set! (.-onerror req)
+          (fn error-handler [e]
+            (log (js->clj (.-target e)))
+            (close! res)
+            (throw e)))
+    (set! (.-onsuccess req)
+          (fn success-handler [e]
+            (log "db-opened:" (.-result req))
+            (put! res (.-result req))))
+    (set! (.-onupgradeneeded req)
+          (fn upgrade-handler [e]
+            (let [db (-> e .-target .-result)]
+              (.createObjectStore db name #js {:keyPath "key"}))
+            (log "db upgraded from version: " (.-oldVersion e))))
+    res))
+

 (comment
-  (client-connect! "127.0.0.1" 9090 (chan) (chan)))
+  (client-connect! "127.0.0.1" 9090 (chan) (chan))
+
+  (go (def my-db (<! (new-indexeddb-store "geschichte"))))
+
+  (def my-kv (IndexedDBKeyValueStore. my-db "geschichte"))
+
+  (go (println "get:" (<! (-get-in my-kv ["test"]))))
+
+  (go (println (<! (-assoc-in my-kv ["test2"] {:a 1 :b 4.2}))))
+
+  (go (println (<! (-assoc-in my-kv ["test" :a] 43))))
+
+  (go (println (<! (-update-in my-kv ["test" :a] inc))))
+  )


refactoring

refactoring

--- src/cljs/triboard/logic/turn.cljs
+++ src/cljs/triboard/logic/turn.cljs
@@ -26,7 +26,7 @@

 (defn- next-3-players
   [player]
-  (take 3 (iterate next-player (next-player player))))
+  (take 3 (rest (iterate next-player player))))

 (defn- with-next-player
   "Find the next player to act - dismiss those that cannot play any move"


Real implementation for buddy.crypto.keys ns.

--- src/clojure/buddy/crypto/keys.clj
+++ src/clojure/buddy/crypto/keys.clj
@@ -13,14 +13,13 @@
 ;; limitations under the License.

 (ns buddy.crypto.keys
-  (:require [buddy.codecs :refer [str->bytes]])
-  (:import java.security.Key))
+  (:require [buddy.codecs :refer [str->bytes]]))

-(defn make-secret-key
-  "Generates a Key instance from given raw string key."
-  [^String skey]
-  (let [rawkey (str->bytes skey)]
-    (proxy [Key] []
-      (getFormat [] nil)
-      (getEncoded [] rawkey)
-      (toString [] skey))))
+(defprotocol SecretKey
+  (key->bytes [key] "Normalize key to byte array")
+  (key->str [key] "Normalize key String"))
+
+(extend-protocol SecretKey
+  String
+  (key->bytes [key] (str->bytes key))
+  (key->str [key] key))


Ignore meta keys when searching

Ignore meta keys when searching

--- src/clojure/nightcode/editors.clj
+++ src/clojure/nightcode/editors.clj
@@ -209,10 +209,11 @@
           enter-key? (= key-code 10)
           find-text (s/text e)
           printable-char? (-> text-area .getFont (.canDisplay key-code))
+          meta-keys #{KeyEvent/VK_SHIFT KeyEvent/VK_CONTROL KeyEvent/VK_META}
           valid-search? (and (> (count find-text) 0)
                              printable-char?
                              (not @shortcuts/down?)
-                             (not= (.getKeyCode e) KeyEvent/VK_SHIFT))
+                             (not (contains? meta-keys (.getKeyCode e))))
           context (doto (SearchContext. find-text)
                     (.setMatchCase true))]
       (when valid-search?


Stop adding maintainer label per Docker recs

--- src/docker_clojure/dockerfile.clj
+++ src/docker_clojure/dockerfile.clj
@@ -14,7 +14,6 @@
 (defn contents [{:keys [maintainer build-tool] :as variant}]
   (str/join "\n"
             (concat [(format "FROM %s" (:base-image variant))
-                     (format "LABEL maintainer=\"%s\"" maintainer)
                      ""]
                     (case build-tool
                       "boot" (boot/contents variant)


disable auto-sorted-streams for now

disable auto-sorted-streams for now

it's causing a lot of errors in the model tests

--- src/er_cassandra/model/select.clj
+++ src/er_cassandra/model/select.clj
@@ -34,7 +34,7 @@
                         opts)
                        mi)))
             s/realize-each
-            (r.ss/maybe-sorted-stream opts)
+            ;; (r.ss/maybe-sorted-stream opts)
             return))))

   ;; can't provide an arity which auto-selects the uber-key, because it's
@@ -57,7 +57,7 @@
                         opts)
                        mi)))
             s/realize-each
-            (r.ss/maybe-sorted-stream opts)
+            ;; (r.ss/maybe-sorted-stream opts)
             return)))))

 (defn select


Remove react dep from render_loop

Remove react dep from render_loop

--- re_view/src/re_view/render_loop.cljs
+++ re_view/src/re_view/render_loop.cljs
@@ -1,6 +1,5 @@
 (ns re-view.render-loop
-  (:require [goog.object :as gobj]
-            react))
+  (:require [goog.object :as gobj]))

 (set! *warn-on-infer* true)
 (def ^:dynamic *immediate-state-update* false)
@@ -44,7 +43,7 @@
              (do (.debug js/console "No :catch method in component: " this)
                  (.error js/console e)))))))

-(defn force-update! [^react/Component this]
+(defn force-update! [this]
   (vswap! to-render disj this)
   (force-update-caught this))


Update build commit url

Update build commit url

  Build commit urls should be dependent on a project's vcs type.

    * Add vcs-url namespace
    * Update function name
    * Add vcs type case

--- src-cljs/frontend/models/build.cljs
+++ src-cljs/frontend/models/build.cljs
@@ -4,6 +4,7 @@
             [frontend.routes :as routes]
             [frontend.state :as state]
             [frontend.utils :as utils :include-macros true]
+            [frontend.utils.vcs-url :as vcs-url]
             [frontend.utils.github :as github]
             [goog.string :as gstring]
             goog.string.format)
@@ -20,9 +21,13 @@
   (when (:vcs_revision build)
     (subs (:vcs_revision build) 0 7)))

-(defn github-commit-url [build]
+(defn commit-url [build]
   (when (:vcs_revision build)
-    (gstring/format "%s/commit/%s" (:vcs_url build) (:vcs_revision build))))
+    (gstring/format
+      (case (-> build :vcs_url vcs-url/vcs-type)
+       "github" "%s/commit/%s"
+       "bitbucket" "%s/commits/%s")
+      (:vcs_url build) (:vcs_revision build))))

 (defn vcs-ref-name [build]
   (cond


Upload dialog: Automatically upload added files.

--- src-cljs/pepa/workflows/upload.cljs
+++ src-cljs/pepa/workflows/upload.cljs
@@ -10,8 +10,9 @@
             [cljs.core.async :as async])
   (:require-macros [cljs.core.async.macros :refer [go]]))

-(defn ^:private upload-file! [row owner e]
-  (.preventDefault e)
+(defn ^:private upload-file! [row & [e]]
+  (when e
+   (.preventDefault e))
   (when-not (:working? row)
     (go
       (try
@@ -42,25 +43,21 @@
             size (.-size file)]
         (html
          [:li
-          [:form {:on-submit (partial upload-file! row owner)}
-           (if document-id
-             [:a.title {:href (when document-id
-                                (nav/document-route {:id document-id}))
-                        :title name}
-              name]
-             [:span.title {:title name} name])
-           [:span.size (str (byte->kb size) "kB")]
-           (if-not document-id
-             [:button.upload {:type :submit
-                              :disabled (:working? row)}
-              "Upload"]
-             [:.hide {:on-click (fn [e]
-                                  (when (fn? hide-fn)
-                                    (hide-fn (om/value row)))
-                                  (doto e
-                                    (.preventDefault)
-                                    (.stopPropagation)))}
-              "Hide"])]])))))
+          (if document-id
+            [:a.title {:href (when document-id
+                               (nav/document-route {:id document-id}))
+                       :title name}
+             name]
+            [:span.title {:title name} name])
+          [:span.size (str (byte->kb size) "kB")]
+          (when-not document-id
+            [:.hide {:on-click (fn [e]
+                                 (when (fn? hide-fn)
+                                   (hide-fn (om/value row)))
+                                 (doto e
+                                   (.preventDefault)
+                                   (.stopPropagation)))}
+             "Hide"])])))))

 (defn ^:private remove-file! [files file]
   (om/transact! files (fn [files]
@@ -96,10 +93,22 @@
       (js/console.warn "Unsupported file type:" (.-type file) file)
       upload)
     (update-in upload [:files]
-               #(vec (conj % {:file file})))))
+               #(conj (vec %) {:file file}))))

 (defn upload-dialog [upload owner _]
   (reify
+    om/IDidUpdate
+    (did-update [_ prev-props _]
+      ;; Start upload for every new file in :files
+      (when (< (count (:files prev-props))
+               (count (:files upload)))
+        (let [new-files (filter (fn [file]
+                                  (and (not (:working? file))
+                                       (not (:document-id file))))
+                                (:files upload))]
+          (println "got new files" new-files)
+          (doseq [file new-files]
+            (upload-file! file)))))
     om/IRenderState
     (render-state [_ {:keys [mini?]}]
       (let [files (:files upload)


Removed documentation for port (see #69)

--- ring-core/src/ring/middleware/cookies.clj
+++ ring-core/src/ring/middleware/cookies.clj
@@ -162,7 +162,6 @@
   :value     - the new value of the cookie
   :path      - the subpath the cookie is valid for
   :domain    - the domain the cookie is valid for
-  :port      - the port the cookie is valid for
   :max-age   - the maximum age in seconds of the cookie
   :expires   - a date string at which the cookie will expire
   :secure    - set to true if the cookie is valid for HTTPS only


document functions in org.micromanager.mm

git-svn-id: 03a8048b5ee8463be5048a3801110fb50f378627@8809 d0ab736e-dc22-4aeb-8dc9-08def0aa14fd

--- acqEngine/src/org/micromanager/mm.clj
+++ acqEngine/src/org/micromanager/mm.clj
@@ -28,39 +28,51 @@
 (declare gui)
 (declare mmc)

-(defmacro edt [& body]
+(defmacro edt
+  "Run body on the Event Dispatch Thread."
+  [& body]
   `(SwingUtilities/invokeLater (fn [] ~@body)))

 (defn load-mm
+  "Load Micro-Manager gui and mmc objects."
   ([gui] (def mmc (.getMMCore gui)))
   ([] (def gui (MMStudioMainFrame/getInstance))
       (load-mm gui)))

 (defn rekey
+  "Change the name of key kold to knew."
   ([m kold knew]
     (-> m (dissoc kold) (assoc knew (get m kold))))
   ([m kold knew & ks]
     (reduce #(apply rekey %1 %2)
       m (partition 2 (conj ks knew kold)))))

-(defn select-and-rekey [m & ks]
-    (apply rekey (select-keys m (apply concat (partition 1 2 ks))) ks))
+(defn select-and-rekey
+  "Select certain keys and change their names. ks consists
+   of alternating old and new keys."
+  [m & ks]
+  (apply rekey (select-keys m (apply concat (partition 1 2 ks))) ks))

-(defn data-object-to-map [obj]
+(defn data-object-to-map
+  "Automatically convert a Java data object (public fields,
+   no methods) to an immutable clojure map."
+  [obj]
   (into {}
     (for [f (.getFields (type obj))
           :when (zero? (bit-and
                          (.getModifiers f) java.lang.reflect.Modifier/STATIC))]
       [(keyword (.getName f))
-       (let [val (.get f obj)]
-         (if (isa? (type val) Boolean)
-           (.booleanValue val)
-           val))])))
-
-(defn log [& x]
+       (if (= Boolean/TYPE (.getType f))
+         (.getBoolean f obj)
+         (.get f obj))])))
+
+(defn log
+  "Log form x to the Micro-Manager log output (debug only)."
+  [& x]
   (.logMessage mmc (apply pr-str x) true))

 (defmacro log-cmd
+  "Log the enclosed expr to the Micro-Manager log output (debug only)."
   ([cmd-count expr]
     (let [[cmd# args#] (split-at cmd-count expr)]
       `(let [expr# (concat '~cmd# (list ~@args#))]
@@ -74,7 +86,11 @@
    ([expr] `(log-cmd 1 ~expr)))

-(defmacro core [& args]
+(defmacro core
+  "Run args as a method and parameters on Micro-Manager core.
+   If debugging, log the command and the returned value to the
+   Micro-Manager log output."
+  [& args]
   `(log-cmd 3 (. mmc ~@args)))

 (defmacro when-lets
@@ -90,7 +106,12 @@
     (let [[a b] (map vec (split-at 2 bindings))]
       `(when-let ~a (when-lets ~b ~@body))))))

-(defmacro with-setting [gst & body]
+(defmacro with-setting
+  "gst consists of a vector containing a getter, a setter, and a temp
+   value. Calls getter to read the current value, uses setter to
+   set the temporary value, executes body, and then calls setter
+   to set the original value again."
+  [gst & body]
   (let [[getter setter temp] gst]
     `(let [perm# (~getter)
            temp# ~temp
@@ -100,7 +121,10 @@
     (do ~@body)
     (when different# (~setter perm#)))))

-(defmacro with-core-setting [gst & body]
+(defmacro with-core-setting
+  "Temporarily set a core setting to a value, and then set it back after
+   body is executed."
+  [gst & body]
   (let [[getter setter temp] gst]
     `(with-setting [#(core ~getter) #(core ~setter %) ~temp] ~@body)))

@@ -111,12 +135,16 @@
     `(when (and ~@args_)
       (~f ~@args_))))

-(defmacro if-args [f & args]
+(defmacro if-args
+  "Apply f to arguments only if all arguments are not nil."
+  [f & args]
   (let [args_ args]
     `(if (and ~@args_)
       (~f ~@args_))))

-(defn get-default-devices []
+(defn get-default-devices
+  "Get the list of default (core) devices."
+  []
   {:camera          (core getCameraDevice)
    :shutter         (core getShutterDevice)
    :focus           (core getFocusDevice)
@@ -124,54 +152,87 @@
    :autofocus       (core getAutoFocusDevice)
    :image-processor (core getImageProcessorDevice)})

-(defn config-struct [^Configuration data]
+(defn config-struct
+  "Creates a map of properties from a given Micro-Manager Configuration
+   where keys are given as [dev-name prop-name] and values are the property
+   values."
+  [^Configuration data]
   (into {}
         (for [prop (map #(.getSetting data %) (range (.size data)))]
           [[(.getDeviceLabel prop) (.getPropertyName prop)] (.getPropertyValue prop)])))

-(defn map-config [config]
+(defn map-config
+  "Creates a map of properties from a configuration map where
+   keys are strings such as \"Core-Shutter\"."
+  [config]
   (into {}
         (for [[[d p] v] (config-struct config)]
           [(str d "-" p) v])))

-(defn get-config [group config]
+(defn get-config
+  "Get a map representing a Micro-Manager configuration preset."
+  [group config]
   (config-struct (core getConfigData group config)))

-(defn get-system-config-cached []
+(defn get-system-config-cached
+  "Get the current system state cached configuration as a map."
+  []
   (config-struct (core getSystemStateCache)))

-(defn get-property-value [dev prop]
+(defn get-property-value
+  "Get a property value."
+  [dev prop]
   (when (core hasProperty dev prop)
     (core getProperty dev prop)))

-(defn get-property [dev prop]
+(defn get-property
+  "Get a property vector, given device and property. The results
+   include device, property name, and property value. Device and
+   property are grouped together in a vector: [[dev prop] value]."
+  [dev prop]
   [[dev prop] (get-property-value dev prop)])

-(defn get-positions []
+(defn get-positions
+  "Get the position list as a vector of MultiStagePositions."
+  []
   (vec (.. gui getPositionList getPositions)))

-(defn get-allowed-property-values [dev prop]
+(defn get-allowed-property-values
+  "Returns a sequence of the allowed property values
+   for a give device and property."
+  [dev prop]
   (seq (core getAllowedPropertyValues dev prop)))

-(defn select-values-match? [map1 map2 keys]
+(defn select-values-match?
+  "Checks if a particular set of values in two maps
+   are the same, give a vector of keys for comparison."
+  [map1 map2 keys]
   (= (select-keys map1 keys)
      (select-keys map2 keys)))

-(defn current-tagged-image []
+(defn current-tagged-image
+  "Get the current tagged image displayed frontmost in Micro-Manager."
+  []
   (let [img (IJ/getImage)]
     (.. img getStack (getTaggedImage (.getCurrentSlice img)))))

-(defn get-camera-roi []
+(defn get-camera-roi
+  "Returns a vector containing the [left top width height] of the roi."
+  []
   (let [r (repeatedly 4 #(int-array 1))]
     (core getROI (nth r 0) (nth r 1) (nth r 2) (nth r 3))
-    (flatten (map seq r))))
-
-(defn parse-core-metadata [^Metadata m]
+    (vec (flatten (map seq r)))))
+
+(defn parse-core-metadata
+  "Reads the metadata from a core Metadata object into a map."
+  [^Metadata m]
   (into {}
     (for [k (.GetKeys m)]
       [k (.. m (GetSingleTag k) GetValue)])))

-(defn reload-device [dev]
+(defn reload-device
+  "Unload a device, and reload it, preserving its property settings."
+  [dev]
   (when (. gui getAutoreloadOption)
     (log "Attempting to reload " dev "...")
     (let [props (filter #(= (first %) dev)
@@ -195,7 +256,9 @@
           (core defineStateLabel dev i (get state-labels i)))))
     (log "...reloading of " dev " has apparently succeeded.")))

-(defn json-to-data [json]
+(defn json-to-data
+  "Take a JSON object and convert it to a clojure data object."
+  [json]
   (condp #(isa? (type %2) %1) json
     JSONObject
       (let [keys (iterator-seq (.keys json))]
@@ -209,15 +272,24 @@
           (json-to-data (.get json i))))
     json))

-(def iso8601modified (SimpleDateFormat. "yyyy-MM-dd HH:mm:ss Z"))
-
-(defn get-current-time-str []
+(def ^{:doc "the ISO8601 data standard format modified to make it
+             slightly more human-readable."}
+       iso8601modified (SimpleDateFormat. "yyyy-MM-dd HH:mm:ss Z"))
+
+(defn get-current-time-str
+  "Get the current time and date in modified ISO8601 format."
+  []
   (. iso8601modified format (Date.)))

-(defn get-pixel-type []
+(defn get-pixel-type
+  "Get the current pixel type."
+  []
   (str ({1 "GRAY", 4 "RGB"} (int (core getNumberOfComponents))) (* 8 (core getBytesPerPixel))))

-(defn ChannelSpec-to-map [^ChannelSpec chan]
+(defn ChannelSpec-to-map
+  "Convert a Micro-Manager ChannelSpec object to a clojure data map
+   with friendly keys."
+  [^ChannelSpec chan]
   (-> chan
     (data-object-to-map)
     (select-and-rekey
@@ -231,7 +303,9 @@
     )
     (assoc :properties (get-config (core getChannelGroup) (.config_ chan)))))

-(defn MultiStagePosition-to-map [^MultiStagePosition msp]
+(defn MultiStagePosition-to-map
+  "Convert a Micro-Manager MultiStagePosition object to a clojure data map."
+  [^MultiStagePosition msp]
   (if msp
     {:label (.getLabel msp)
      :axes
@@ -243,29 +317,41 @@
                   1 [(.x stage-pos)]
                   2 [(.x stage-pos) (.y stage-pos)])])))}))

-(defn get-msp [idx]
+(defn get-msp
+  "Get a MultiStagePosition object from the Position List with the specified
+   index number."
+  [idx]
   (when idx
     (let [p-list (. gui getPositionList)]
       (when (pos? (. p-list getNumberOfPositions))
         (.getPosition p-list idx)))))

-(defn get-msp-z-position [idx z-stage]
+(defn get-msp-z-position
+  "Get the z position for a given z-stage from the MultiStagePosition
+   with the given index in the Position List."
+  [idx z-stage]
   (if-let [msp (get-msp idx)]
     (if-let [stage-pos (. msp get z-stage)]
       (. stage-pos x))))

-(defn set-msp-z-position [idx z-stage z]
+(defn set-msp-z-position
+  "Set the z position for a given z-stage from the MultiStagePosition
+   with the given index in the Position List."
+  [idx z-stage z]
   (when-let [msp (get-msp idx)]
     (when-let [stage-pos (. msp (get z-stage))]
       (set! (. stage-pos x) z))))

-(defn str-vector [str-seq]
+(defn str-vector
+  "Convert a sequence of strings into a Micro-Manager StrVector."
+  [str-seq]
   (let [v (StrVector.)]
     (doseq [item str-seq]
       (.add v item))
     v))

 (defn double-vector [doubles]
+  "Convert a sequence of numbers to a Micro-Manager DoubleVector."
   (let [v (DoubleVector.)]
     (doseq [item doubles]
       (.add v item))


Update to July

Update to July

--- scrape-n-mail/src/scrape_n_mail/core.cljs
+++ scrape-n-mail/src/scrape_n_mail/core.cljs
@@ -185,7 +185,7 @@
       [:br]
       [:p "Dear " (::submitter-name (first name-records)) ","]

-      [:p "Our general call for names for Wellbeing for June 2019 has gone out to the newDharma mailing list."]
+      [:p "Our general call for names for Wellbeing for July 2019 has gone out to the newDharma mailing list."]

       [:p "Currently, the community is holding the following names on the altar "
           "in support of their wellbeing at your request. Click "


Add new type of notifications to propagate inbox actions to CS.

--- src/oc/storage/async/notification.clj
+++ src/oc/storage/async/notification.clj
@@ -29,9 +29,14 @@

 ;; ----- Data schema -----

-(defn- notification-type? [notification-type] (#{:add :update :delete :nux} notification-type))
+(defn- notification-type? [notification-type] (#{:add :update :delete :nux :dismiss :follow :unfollow} notification-type))

 (defn- resource-type? [resource-type] (#{:org :board :entry} resource-type))
+
+(def InboxAction
+  {(schema/optional-key :dismiss-at) lib-schema/ISO8601
+   (schema/optional-key :follow) schema/Bool
+   (schema/optional-key :unfollow) schema/Bool})

 (def NotificationTrigger
   "
@@ -60,6 +65,7 @@
     (schema/optional-key :old) (schema/conditional #(= (resource-type %) :entry) common-res/Entry
                                                    #(= (resource-type %) :board) common-res/Board
                                                    :else common-res/Org)
+    (schema/optional-key :inbox-action) InboxAction
     (schema/optional-key :nux-boards) [lib-schema/NonBlankStr]}
    :user lib-schema/User
    (schema/optional-key :note) (schema/maybe schema/Str)


Added status-led pin to pins

Added status-led pin to pins

--- src/strange_coop/components/pins.clj
+++ src/strange_coop/components/pins.clj
@@ -16,7 +16,9 @@
            :roof-button   (button/button :P8 12 :normally-on)
            :light-sensor  (bb/ain 33)
            :temp-sensor   (bb/ain 35)
-           :motor-control (hb/hbridge [16 17 18] :header :P8)))
+           :motor-control (hb/hbridge [16 17 18] :header :P8)
+           :status-led    (bb/gpio :P8 14 :out)))
+
   (stop [component]
     (apply dissoc component pin-keys)))


Extract word part of tokens for written corpora

--- lib/assets/cljs/cglossa/result_views/cwb/written.cljs
+++ lib/assets/cljs/cglossa/result_views/cwb/written.cljs
@@ -34,9 +34,17 @@
    (shared/id-column result)
    (shared/text-columns result)])

+(defn- process-field [field]
+  "Processes a pre-match, match, or post-match field."
+  (as-> field $
+        (str/split $ #"\s+")
+        (map #(first (str/split % #"/")) $)
+        (str/join \space $)))
+
 (defmethod concordance-rows :default [a m res index]
   "Returns one or more rows representing a single search result."
-  (let [[s-id [pre match post]] (extract-fields res)
+  (let [[s-id fields] (extract-fields res)
+        [pre match post] (map process-field fields)
         res-info {:s-id       s-id
                   :pre-match  pre
                   :match      match


Fix errors in the throttler

Fix errors in the throttler

--- src/whisper2cyanite/metric_store.clj
+++ src/whisper2cyanite/metric_store.clj
@@ -57,8 +57,9 @@

 (defn- get-channel
   "Get store channel."
-  [session statement chan-size data-stored? stats-error-files run]
-  (let [ch (async/chan chan-size)]
+  [session statement chan-size batch-rate data-stored? stats-error-files run]
+  (let [ch-in (async/chan chan-size)
+        ch (if batch-rate (trtl/throttle-chan ch-in batch-rate :second) ch-in)]
     (utils/go-while (not @data-stored?)
                     (let [data (async/<! ch)]
                       (if data
@@ -78,7 +79,7 @@
                                          path))))
                         (when (not @data-stored?)
                           (swap! data-stored? (fn [_] true))))))
-    ch))
+    ch-in))

 (defn cassandra-metric-store
   "Cassandra metric store."
@@ -100,11 +101,8 @@
         data-stored? (atom false)
         stats-error-files (atom (sorted-set))
         stats-processed (atom 0)
-        main-channel (get-channel session insert! chan-size-batches data-stored?
-                                  stats-error-files run)
-        channel (if batch-rate
-                  (trtl/throttle-chan main-channel batch-rate :second)
-                  main-channel)]
+        channel (get-channel session insert! chan-size-batches batch-rate
+                             data-stored? stats-error-files run)]
     (log/info (str "The metric store has been created. "
                    "Keyspace: " keyspace ", "
                    "channel size: " chan-size ", "


(maint) Fix some errors being obscured

(maint) Fix some errors being obscured

If a slingshot error was thrown with a `:type` value other than `:cli-help` or
`:cli-error`, the original error would be replaced by an error about a missing
clause in the case statement. This allows those errors to just be rethrown.

--- src/puppetlabs/trapperkeeper/core.clj
+++ src/puppetlabs/trapperkeeper/core.clj
@@ -177,7 +177,9 @@
           (if (keyword? type)
             (case (without-ns (:type m))
               :cli-error (quit 1 (:message m) *err*)
-              :cli-help (quit 0 (:message m) *out*))))
+              :cli-help (quit 0 (:message m) *out*)
+              ;; By default let the throw below reraise the error
+              nil)))
         (throw+))
       (finally
         (log/debug (i18n/trs "Finished TK main lifecycle, shutting down Clojure agent threads."))


Fix admin compile issue

Fix admin compile issue

--- src/cljs-admin/sbsk_admin/views.cljs
+++ src/cljs-admin/sbsk_admin/views.cljs
@@ -5,16 +5,17 @@
             [re-com.core :as re-com]
             [re-frame-datatable.core :as dt]
             ;;
-            [sbsk.shared.data :as sbsk-data :refer
-             [ video-highlight-width
+            [sbsk.vars :as sbsk-vars :refer
+             [video-highlight-width
               video-highlight-height
               video-small-height
               video-small-width
               video-medium-width
               video-medium-height
               video-large-width
-              video-large-height
-              clip-string]]
+              video-large-height]]
+            [sbsk.shared.data :as sbsk-data :refer
+             [clip-string]]
             [sbsk.shared.time :refer [as-moment]]))

 (defn title []


Update `document.location.hash` when removing module

Signed-off-by: Pang Yan Han <22594c345857f664c61cd411f607c4d40a9d4af9@gmail.com>

--- src/cljs/cljs_nusmods/timetable.cljs
+++ src/cljs/cljs_nusmods/timetable.cljs
@@ -225,6 +225,18 @@
     (.log js/console (str "preToUrlHashModule = " (.stringify js/JSON (clj->js preToUrlHashModule))))
     (aset (aget js/document "location") "hash"
           (str orgUrlHash (if (empty? orgUrlHash) "" "&") moduleUrlHash))))
+
+(defn- remove-module-from-document-location-hash
+  "Removes a module from `document.location.hash`"
+  [moduleCode]
+  (let [orgUrlHash (aget (aget js/document "location") "hash")
+
+        urlHashWithoutModule
+        (clojure.string/replace
+          orgUrlHash
+          (re-pattern (str moduleCode "_[A-Z]{1,3}=[^&]+&?")) "")]
+    (aset (aget js/document "location") "hash"
+          (clojure.string/replace urlHashWithoutModule #"&$" ""))))

 (def ^{:doc "Vector of <tBody> objects representing the days of the timetable
              in the Timetable Builder page"
@@ -1125,6 +1137,8 @@
         (.log js/console "Boo ya!")
         (.log js/console (str "ModulesSelected:" (.stringify js/JSON (clj->js ModulesSelected))))

+        (remove-module-from-document-location-hash moduleCode)
+
         ; Remove from `ModulesSelectedOrder`
         (set! ModulesSelectedOrder (remove #{moduleCode} ModulesSelectedOrder))
         (.log js/console "I hear and obey!")


CMR-5695: Address review comment typo.

CMR-5695: Address review comment typo.

--- message-queue-lib/src/cmr/message_queue/queue/sqs.clj
+++ message-queue-lib/src/cmr/message_queue/queue/sqs.clj
@@ -169,7 +169,7 @@

 (defn set-aws-client-attr!
-  "Conditionally configure the AWS client instance with by calling the given
+  "Conditionally configure the AWS client instance by calling the given
   method with the given args."
   [client-obj method args]
   (when-not (nil? (first args))


fix phone component

fix phone component

--- src/cljs/phonecat_re_frame/core.cljs
+++ src/cljs/phonecat_re_frame/core.cljs
@@ -29,16 +29,16 @@
 ;; Views

 (defn phone-component
-  [name snippet]
+  [phone]
   [:li
-   [:span name]
-   [:p snippet]])
+   [:span (:name @phone)]
+   [:p (:snippet @phone)]])

 (defn phones-component
   []
   (let [phones (re-frame/subscribe [:phones])]
     (fn []
-      [:ul (for [phone in @phones] ^{:key phone} [phone-component (:name phone) (:snippet phone)] @phones)])))
+      [:ul (for [phone in @phones] ^{:key phone} [phone-component phone] @phones)])))

 (defn home-page []
   [phones-component])


Fix division to round to at least 2 decimal places

--- src/clojure/warreq/kea/calc/math.clj
+++ src/clojure/warreq/kea/calc/math.clj
@@ -21,7 +21,7 @@

 (defn floating-division [x y]
   (if (not= ^BigDecimal y BigDecimal/ZERO)
-    (.divide ^BigDecimal x ^BigDecimal y java.math.RoundingMode/HALF_UP)
+    (.divide ^BigDecimal x ^BigDecimal y 2 java.math.RoundingMode/HALF_EVEN)
     (do (u/vibrate! 500)
         (toast "Cannot divide by 0."))))


s/prepositional-phrase-adjunct/prepositional-phrase/

--- src/babel/english/grammar.cljc
+++ src/babel/english/grammar.cljc
@@ -237,18 +237,15 @@
                                              :number number-agreement}}
                               :head {:phrasal true
                                      :synsem {:propernoun propernoun}}}))
-;                   (unify-check h10
-;                                {:rule "prepositional-phrase-argument"
-;                                 :synsem {:cat :prep}})

                    (let [sem (atom :top)]
-                     (unify-check
+                     (unify-check h10
                       subcat-1-principle
                       head-first
                       {:comment "h10"
                        :schema-symbol 'h10
                        :first :head
-                       :rule "prepositional-phrase-adjunct"
+                       :rule "prepositional-phrase"
                        :synsem {:cat :prep
                                 :sem sem}
                        :head {:synsem {:sem sem}}}))


remove unneeded -reflexive rules

remove unneeded -reflexive rules

--- src/babel/italiano/grammar.clj
+++ src/babel/italiano/grammar.clj
@@ -202,15 +202,6 @@
                                            :tense :past}}})
                    (unifyc c10
                            root-is-head-root
-                           {:rule "s-future-reflexive"
-                            :head {:sem {:reflexive true}
-                                   :phrasal true}
-                            :synsem {:aux false
-                                     :infl :futuro
-                                     :cat :verb
-                                     :sem {:tense :futuro}}})
-                   (unifyc c10
-                           root-is-head-root
                            {:rule "s-future-phrasal"
                             :head {:phrasal true}
                             :synsem {:aux false
@@ -227,15 +218,6 @@
                                      :sem {:tense :futuro}}})
                    (unifyc c10
                            root-is-head-root
-                           {:rule "s-conditional-reflexive"
-                            :head {:sem {:reflexive true}
-                                   :phrasal true}
-                            :synsem {:aux false
-                                     :infl :conditional
-                                     :cat :verb
-                                     :sem {:tense :conditional}}})
-                   (unifyc c10
-                           root-is-head-root
                            {:rule "s-conditional-phrasal"
                             :head {:phrasal true}
                             :synsem {:aux false
@@ -268,16 +250,6 @@
                                      :cat :verb
                                      :sem {:aspect :progressive
                                            :tense :past}}})
-                   (unifyc c10
-                           root-is-head-root
-                           {:rule "s-present-reflexive"
-                            :head {:sem {:reflexive true}
-                                   :phrasal true}
-                            :synsem {:aux false
-                                     :infl :present
-                                     :cat :verb
-                                     :sem {:aspect :progressive
-                                           :tense :present}}})
                    (unifyc c10
                            root-is-head
                            {:rule "s-present-nonphrasal"


Remove <w:rPr> tag from the result of function wpml/p

--- src/bakyeono/litedocx/wpml.clj
+++ src/bakyeono/litedocx/wpml.clj
@@ -499,10 +499,6 @@
         :attrs {:w:val (name style)}}]}
      {:tag :w:r
       :content
-      [{:tag :w:rPr
-        :content
-        [{:tag :w:rFonts
-          :attrs {:w:hint "eastAsia"}}]}
-       {:tag :w:t
+      [{:tag :w:t
         :content [text]}]}]}))


Removed ghost dynamatch file

Removed ghost dynamatch file


Fixed :stack-types for genome_uniform_string_mutation.

--- src/clojush/instructions/genome.clj
+++ src/clojush/instructions/genome.clj
@@ -358,7 +358,7 @@

 (define-registered
   genome_uniform_string_mutation
-  ^{:stack-types [:genome :float]}
+  ^{:stack-types [:genome :float :string]}
   (fn [state]
     (if (and (not (empty? (:float state)))
              (not (empty? (:genome state))))


Added genome_alternation instruction.

Added genome_alternation instruction.

--- src/clojush/instructions/genome.clj
+++ src/clojush/instructions/genome.clj
@@ -455,4 +455,26 @@
                                         (merge @push-argmap {:uniform-addition-rate rate}))))
                         :genome)))
       state)))
+
+(define-registered
+  genome_alternation
+  ^{:stack-types [:genome :float]}
+  (fn [state]
+    (if (and (not (empty? (rest (:float state))))
+             (not (empty? (rest (:genome state)))))
+      (let [rate (mod (first (:float state)) 1.0)
+            dev (#(if (pos? %) % (- %)) (second (:float state)))
+            genome1 (first (:genome state))
+            genome2 (second (:genome state))]
+        (->> (pop-item :float state)
+             (pop-item :float)
+             (pop-item :genome)
+             (pop-item :genome)
+             (push-item (vec (:genome (alternation
+                                        {:genome genome}
+                                        (merge @push-argmap
+                                               {:alternation-rate rate
+                                                :alignment-deviation dev}))))
+                        :genome)))
+      state)))
 ;; @@


unsubbing a thread should also close it

unsubbing a thread should also close it

--- src/braid/server/db/thread.clj
+++ src/braid/server/db/thread.clj
@@ -166,4 +166,6 @@
 (defn user-unsubscribe-from-thread!
   [conn user-id thread-id]
   @(d/transact conn [[:db/retract [:user/id user-id]
-                      :user/subscribed-thread [:thread/id thread-id]]]))
+                      :user/subscribed-thread [:thread/id thread-id]
+                      [:db/retract [:user/id user-id]
+                       :user/open-thread [:thread/id thread-id]]]]))


Changed curve name detection algorithm

Changed curve name detection algorithm

Old one used KeyGenerator to generate KeyPair and then extracts curve
parameters from public key which is very inefficient (in particular it
causes KeyGenerator to use SecureRandom generator which can block while
waiting for entropy). New approach uses java.security interfaces and
providers to get initialized curve from security provider without
actually generating any keys

--- src/buddy/core/keys/jwk/ec.clj
+++ src/buddy/core/keys/jwk/ec.clj
@@ -15,12 +15,10 @@

 (ns buddy.core.keys.jwk.ec
   (:require [buddy.core.keys.jwk.proto :as proto]
-            [buddy.core.codecs.base64 :as b64]
-            [buddy.core.codecs :as codecs]
             [buddy.core.hash :as hash]
             [cheshire.core :as json])
   (:import (java.security.interfaces ECPublicKey ECPrivateKey ECKey)
-           (java.security SecureRandom KeyPairGenerator AlgorithmParameters KeyFactory)
+           (java.security AlgorithmParameters KeyFactory)
            (java.security.spec ECGenParameterSpec ECPoint ECParameterSpec ECPrivateKeySpec ECPublicKeySpec)
            (java.io StringWriter)
            (com.fasterxml.jackson.core JsonGenerator)))
@@ -81,25 +79,21 @@
   (load-public jwk "P-521"))

 (defn- get-curve [curvename]
-  (let [sr (SecureRandom/getInstance "SHA1PRNG")
-        kg (KeyPairGenerator/getInstance "EC" "BC")]
-    (.initialize kg (ECGenParameterSpec. curvename) sr)
-    (.getCurve (.getParams ^ECPublicKey (.getPublic (.generateKeyPair kg))))))
+  (let [paramspec (-> (doto (AlgorithmParameters/getInstance "EC" "BC")
+                        (.init (ECGenParameterSpec. curvename)))
+                      (.getParameterSpec ECParameterSpec))]
+    (.getCurve ^ECParameterSpec paramspec)))

 ;; the best way i've found to convert PublicKey params to EC Name
 ;; is by using equals on Curve field (it checks curve params for equality)
-(def ^:private p256curve (get-curve "P-256"))
-(def ^:private p384curve (get-curve "P-384"))
-(def ^:private p521curve (get-curve "P-521"))
-
 (defn- get-curve-name [^ECKey key]
   (let [curve (.getCurve (.getParams key))]
     (condp = curve
-      p256curve
+      (get-curve "P-256")
       "P-256"
-      p384curve
+      (get-curve "P-384")
       "P-384"
-      p521curve
+      (get-curve "P-521")
       "P-521"
       ;; default
       (throw (ex-info "Unsupported EC curve (only P-256, P-384 and P-521 supported)"


Extract async-read-call-batch for readability

--- src/com/wsscode/pathom/connect.cljc
+++ src/com/wsscode/pathom/connect.cljc
@@ -943,6 +943,27 @@
           ::p/continue))
       ::p/continue)))

+(defn- async-read-call-batch
+  [{::p/keys       [processing-sequence]
+    {::keys [sym]} ::resolver-data
+    :as            env}
+   e trace-data input]
+  (go-promise
+    (pt/tracing env (assoc trace-data ::pt/event ::call-resolver-batch)
+      (let [_              (pt/trace env (assoc trace-data ::pt/event ::call-resolver-with-cache))
+            items          (->> processing-sequence
+                                (map-async-serial #(entity-select-keys env % input)) <?
+                                (filterv #(all-values-valid? % input))
+                                (distinct))
+            _              (pt/trace env {::pt/event ::batch-items-ready
+                                          ::items    items})
+            batch-result   (<?maybe (call-resolver env items))
+            _              (pt/trace env {::pt/event    ::batch-result-ready
+                                          ::items-count (count batch-result)})
+            linked-results (zipmap items batch-result)]
+        (cache-batch env sym linked-results)
+        (get linked-results e)))))
+
 (defn- async-read-cache-read
   [{::p/keys              [processing-sequence]
     {::keys [sym batch?]} ::resolver-data
@@ -951,33 +972,19 @@
   (let [params (p/params env)]
     (p/cached-async env [sym e params]
       (fn []
-        (go-catch
+        (go-promise
           (or
             (if (and batch? processing-sequence)
-              (pt/tracing env (assoc trace-data ::pt/event ::call-resolver-batch)
-                (let [_              (pt/trace env (assoc trace-data ::pt/event ::call-resolver-with-cache))
-                      items          (->> processing-sequence
-                                          (map-async-serial #(entity-select-keys env % input)) <?
-                                          (filterv #(all-values-valid? % input))
-                                          (distinct))
-                      _              (pt/trace env {::pt/event ::batch-items-ready
-                                                    ::items    items})
-                      batch-result   (<?maybe (call-resolver env items))
-                      _              (pt/trace env {::pt/event    ::batch-result-ready
-                                                    ::items-count (count batch-result)})
-                      linked-results (zipmap items batch-result)]
-                  (cache-batch env sym linked-results)
-                  (get linked-results e)))
+              (<?maybe (async-read-call-batch env e trace-data input))
               (<?maybe (call-resolver env e)))
             {}))))))

 (defn async-reader2
   "Works in the same way `reader2`, but supports async values (core.async channels)
    on resolver return."
-  [{::keys   [indexes max-resolver-weight]
-    ::p/keys [processing-sequence]
-    :or      {max-resolver-weight 3600000}
-    :as      env}]
+  [{::keys [indexes max-resolver-weight]
+    :or    {max-resolver-weight 3600000}
+    :as    env}]
   (if-let [[plan out] (reader-compute-plan env #{})]
     (go-catch
       (let [key (-> env :ast :key)]


Throw error with explanation for default resolver dispatch on CLJS

--- src/com/wsscode/pathom/connect.cljc
+++ src/com/wsscode/pathom/connect.cljc
@@ -156,9 +156,13 @@
   :args (s/cat :env (s/keys :req [::indexes] :opt [::dependency-track])))

 (defn default-resolver-dispatch [env {::keys [sym] :as resolver} entity]
-  (if-let [f (resolve sym)]
-    (f env entity)
-    (throw (ex-info "Can't resolve symbol" {:resolver resolver}))))
+  #?(:clj
+     (if-let [f (resolve sym)]
+       (f env entity)
+       (throw (ex-info "Can't resolve symbol" {:resolver resolver})))
+
+     :cljs
+     (throw (ex-info "Default resolver-dispatch is not supported on CLJS, please implement ::p.connect/resolver-dispatch in your parser environment." {}))))

 (defn call-resolver [{::keys [resolver-dispatch]
                       :or    {resolver-dispatch default-resolver-dispatch}


stub out some API calls

stub out some API calls

--- src/clj/battlebots/handler.clj
+++ src/clj/battlebots/handler.clj
@@ -33,8 +33,23 @@
   (resources "/")
   (not-found "Not Found")

-  ;; list games
+  ;; add round - should return a URI to identify round
+  (POST "/rounds" [round])
+
+  ;; list rounds
   (GET "/rounds" [] (dao/get-rounds))
+
+  ;; add player - should return a URI to identify player
+  (POST "/rounds/:round-id/players/" [round-id player])
+
+  ;; remove player
+  (DELETE "/rounds/:round-id/players/:player-id" [round-id player-id])
+
+
+  ;; get arena
+  ;; TODO - websockets call to push all arena changes out to listeners
+
+
   )

 (def app (wrap-middleware #'routes))


Force all lazy seqs returned by protocol fns to be realized

--- src/clj/comic_reader/sites.clj
+++ src/clj/comic_reader/sites.clj
@@ -181,21 +181,24 @@
     (binding [options opt-map]
       (-> (manga-list-url)
           scrape/fetch-url
-          extract-comics-list)))
+          extract-comics-list
+          doall)))

   (get-chapter-list [this comic-id]
     (binding [options opt-map]
       (let [comic-url (comic->url comic-id)]
         (-> comic-url
             scrape/fetch-url
-            (extract-chapters-list comic-url)))))
+            (extract-chapters-list comic-url)
+            doall))))

   (get-page-list [this comic-chapter]
     (binding [options opt-map]
       (let [chapter-url (:url comic-chapter)]
         (-> chapter-url
             scrape/fetch-url
-            (extract-pages-list chapter-url)))))
+            (extract-pages-list chapter-url)
+            doall))))

   (get-image-data [this {page-url :url}]
     (binding [options opt-map]


:coffee::bomb:

:coffee::bomb:

--- src/clj/mokkameister/train.clj
+++ src/clj/mokkameister/train.clj
@@ -46,6 +46,8 @@
    (train-coffee :heart)
    (train-coffee :heart)
    (train-coffee :heart)
+   (train-coffee :heart)
+   (train-coffee :heartpulse)
    (train-coffee :syringe)
    (train-coffee :mushroom)
    (train-coffee :coffeepot)
@@ -60,6 +62,10 @@
    (train-coffee :scream)
    (train-coffee :doctor)
    (train-coffee :smoking)
+   (train-coffee :fingers_crossed)
+   (train-coffee :battery)
+   (train-coffee :bomb)
+   (train-coffee :verynice)
    (train-coffee :heavy_heart_exclamation_mark_ornament)
    (train-coffee :badger :mushroom)
    (train-coffee :coffeepot :heart)


Adding TODO

Adding TODO

--- src/clj/zetawar/events/ui.cljs
+++ src/clj/zetawar/events/ui.cljs
@@ -197,6 +197,7 @@
     (set! js/window.location.hash "")
     (app/start-new-game! handler-ctx :sterlings-aruba-multiplayer)))

+;; TODO: find a way to make player swapping nicer (maybe put in router?)
 (defmethod router/handle-event ::toggle-faction-ai
   [{:as handler-ctx :keys [ev-chan conn db players]} [_ faction]]
   (let [{:as app :keys [ai-turn-stepping]} (app/root db)


added wiki help link

added wiki help link

--- src/clj_ns_browser/browser.clj
+++ src/clj_ns_browser/browser.clj
@@ -359,6 +359,10 @@
                   (invoke-soon (browser-with-fqn *ns* fqn (new-clj-ns-browser)))
                   (invoke-soon (new-clj-ns-browser))))))))

+(add-app-action :go-github-wiki-action
+  (action :name "Clj-NS-Browser Wiki..."
+          :handler (fn [a] (future (clojure.java.browse/browse-url
+            "https://github.com/franks42/clj-ns-browser/wiki")))))
 (add-app-action :go-github-action
   (action :name "Clj-NS-Browser GitHub..."
           :handler (fn [a] (future (clojure.java.browse/browse-url
@@ -1142,7 +1146,7 @@
         (id :manual-refresh-browser-action) auto-refresh-browser-cb :separator (id :bring-all-windows-to-front-action)
         (id :cycle-through-windows-action)])

-      (config! help-menu :items [(id :go-github-action) (id :go-clojure.org-action) (id :go-clojuredocs-action) (id :go-cheatsheet-action) (id :go-stackoverflow-action) (id :go-jira-action) (id :go-about-action)])
+      (config! help-menu :items [(id :go-github-wiki-action) (id :go-github-action) (id :go-clojure.org-action) (id :go-clojuredocs-action) (id :go-cheatsheet-action) (id :go-stackoverflow-action) (id :go-jira-action) (id :go-about-action)])
       (config! docs-menu :items [update-clojuredocs :separator
                                  clojuredocs-online-rb clojuredocs-offline-rb
                                  :separator])


fix file dropper to dont close the channel

--- src/cljs/smgui/components.cljs
+++ src/cljs/smgui/components.cljs
@@ -45,7 +45,7 @@
     (render-state [_ {:keys [over view channel] :as state}]
       (let [update-over #(om/set-state! owner :over %)
             classes (class-set {"dragging" over})
-            on-files #(pipe (r/spool %) channel)]
+            on-files #(pipe (r/spool %) channel false)]
         (dom/div #js {:className   (str "flex flex-row " classes)
                       :onDragEnter (pd #(update-over true))
                       :onDragOver  (pd #(update-over true))


Make sure cljsbuild only runs for ClojureScript projects

--- src/clojure/nightcode/lein.clj
+++ src/clojure/nightcode/lein.clj
@@ -17,8 +17,6 @@
   (:import [com.hypirion.io ClosingPipe Pipe])
   (:gen-class))

-(leiningen.cljsbuild/activate)
-
 (def namespace-name (str *ns*))

 (defn get-project-clj-path
@@ -54,8 +52,8 @@
        (redirect-io in out)
        (fn [])
        Thread.
-       (reset! thread))
-  (.start @thread))
+       (reset! thread)
+       .start))

 (defmacro start-thread
   [thread in out & body]
@@ -83,7 +81,7 @@
     (start-process process
                    java-cmd
                    "-cp"
-                   (System/getProperty "java.class.path" ".")
+                   (System/getProperty "java.class.path")
                    namespace-name
                    cmd
                    path
@@ -120,36 +118,12 @@
       (->> [file-name (render file-name data)]
            (leiningen.new.templates/->files data)))))

-(defn run-project-fast
-  [process path]
-  ;We could do this:
-  ;(start-process-command process "run" path)
-  ;But instead we are calling the Leiningen code directly for speed:
-  (let [project-map (read-project-clj path)
-        _ (leiningen.core.eval/prep project-map)
-        given (:main project-map)
-        form (leiningen.run/run-form given nil)
-        main (if (namespace (symbol given))
-               (symbol given)
-               (symbol (name given) "-main"))
-        new-form `(do (set! ~'*warn-on-reflection*
-                            ~(:warn-on-reflection project-map))
-                      ~@(map (fn [[k v]]
-                               `(set! ~k ~v))
-                             (:global-vars project-map))
-                      ~@(:injections project-map)
-                      ~form)
-        cmd (leiningen.core.eval/shell-command project-map new-form)]
-    (start-process process cmd)))
-
 (defn run-project
   [process thread in out path args]
   (stop-process process)
   (stop-thread thread)
   (->> (do (println (utils/get-string :running))
-         (if (is-android-project? path)
-           (start-process-command process "run-android" path args)
-           (run-project-fast process path)))
+         (start-process-command process "run" path args))
        (start-thread thread in out)))

 (defn run-repl-project
@@ -157,8 +131,7 @@
   (stop-process process)
   (stop-thread thread)
   (->> (do (println (utils/get-string :running_with_repl))
-         (let [cmd (if (is-android-project? path) "repl-android" "repl")]
-           (start-process-command process cmd path args)))
+         (start-process-command process "repl" path args))
        (start-thread thread in out)))

 (defn build-project
@@ -166,8 +139,7 @@
   (stop-process process)
   (stop-thread thread)
   (->> (do (println (utils/get-string :building))
-         (let [cmd (if (is-android-project? path) "build-android" "build")]
-           (start-process-command process cmd path args)))
+         (start-process-command process "build" path args))
        (start-thread thread in out)))

 (defn test-project
@@ -217,15 +189,21 @@
 (defn -main
   [cmd path & args]
   (System/setProperty "jline.terminal" "dumb")
-  (let [project-map (read-project-clj path)]
+  (when-let [project-map (read-project-clj path)]
+    (when (:cljsbuild project-map)
+      (leiningen.cljsbuild/activate))
     (case cmd
-      "run" (leiningen.run/run project-map)
-      "run-android" (doseq [sub-cmd ["build" "apk" "install" "run"]]
-                      (apply leiningen.droid/droid project-map sub-cmd args))
-      "build" (leiningen.uberjar/uberjar project-map)
-      "build-android" (apply leiningen.droid/droid project-map "release" args)
-      "repl" (leiningen.repl/repl project-map)
-      "repl-android" (doseq [sub-cmd ["doall" "repl"]]
-                       (apply leiningen.droid/droid project-map sub-cmd args)
-                       (Thread/sleep 10000))
-      nil)))
+      "run" (if (is-android-project? path)
+              (doseq [sub-cmd ["build" "apk" "install" "run"]]
+                (apply leiningen.droid/droid project-map sub-cmd args))
+              (leiningen.run/run project-map))
+      "build" (if (is-android-project? path)
+                (apply leiningen.droid/droid project-map "release" args)
+                (leiningen.uberjar/uberjar project-map))
+      "repl" (if (is-android-project? path)
+               (doseq [sub-cmd ["doall" "repl"]]
+                 (apply leiningen.droid/droid project-map sub-cmd args)
+                 (Thread/sleep 10000))
+               (leiningen.repl/repl project-map))
+      nil))
+  (System/exit 0))


glitch - palette generator

glitch - palette generator

--- src/clojure2d/extra/glitch.clj
+++ src/clojure2d/extra/glitch.clj
@@ -369,23 +369,15 @@
                       :palette (m/sample (c/iq-palette-random-gradient) num)})
                0.5 {:type :colourlovers
                     :palette (rand-nth c/colourlovers-palettes)}
-               0.6 (let [preset (rand-nth c/paletton-presets-list)
-                         p (rand-nth c/colourlovers-palettes)
-                         h (map #(c/paletton-rgb-to-hue %) p)]
-                     {:type :colourlovers-paletton
-                      :conf {:hue h
-                             :preset preset
-                             :type :monochromatic
-                             :compl false}
-                      :palette (let [v (reduce #(concat %1 (c/paletton %2 preset)) p h)]
-                                 (vec v))})
+               0.6 {:type :gradient
+                    :palette (m/sample (rand-nth (vals c/gradient-presets)) 7)}
                (let [h (r/drand 360.0)
                      t (rand-nth [:monochromatic :triad :triad :triad :triad :triad :tetrad :tetrad :tetrad])
                      conf {:compl (r/brand 0.6)
                            :angle (r/drand 10.0 90.0)
                            :adj (r/brand 0.5)
                            :hue h
-                           :preset (rand-nth c/colourlovers-palettes)
+                           :preset (rand-nth c/paletton-presets-list)
                            :type t}]
                  {:type :paletton
                   :conf conf


Changed streaming route path.

Changed streaming route path.

--- src/cmr/opendap/rest/route.clj
+++ src/cmr/opendap/rest/route.clj
@@ -57,7 +57,7 @@
     :post {:handler (collection-handler/generate-urls httpd-component)
            :permissions #{:read}}
     :options core-handler/ok}]
-   ["/opendap/ous/stream/collection/:concept-id" {
+   ["/opendap/ous/streaming-collection/:concept-id" {
     :get (collection-handler/stream-urls httpd-component)}]])

 (defn admin-api


Adds insertL*

Adds insertL*

--- src/the_little_clojurian/chapter5.clj
+++ src/the_little_clojurian/chapter5.clj
@@ -72,3 +72,17 @@
   (is (= (subst* 'orange 'banana '(banana)) '(orange)))
   (is (= (subst* 'orange 'banana '((banana))) '((orange))))
   (is (= (subst* 'cup 'mug '((a mug) in the (((kitchen (mug)))))) '((a cup) in the (((kitchen (cup))))))))
+
+(with-test
+  (def insertL*
+    (fn [new old l]
+      (cond (null? l) '()
+            (atom? (car l)) (cond (eq? (car l) old) (cons new (cons old (insertL* new old (cdr l))))
+                                  :else (cons (car l) (insertL* new old (cdr l))))
+            :else (cons (insertL* new old (car l))
+                        (insertL* new old (cdr l))))))
+
+  (is (= (insertL* 'new 'old '()) '()))
+  (is (= (insertL* 'new 'old '(old)) '(new old)))
+  (is (= (insertL* 'new 'old '((old))) '((new old))))
+  (is (= (insertL* 'new 'old '((these) old ((shoes old) perfume))) '((these) new old ((shoes new old) perfume)))))


pass :jvm-opts along to tools.deps when set in config

--- src/main/shadow/cljs/npm/cli.cljs
+++ src/main/shadow/cljs/npm/cli.cljs
@@ -261,7 +261,7 @@
     (log "shadow-cljs - running: lein" (str/join " " lein-args))
     (run! project-root "lein" lein-args {})))

-(defn get-clojure-args [project-root config opts]
+(defn get-clojure-args [project-root {:keys [jvm-opts] :as config} opts]
   (let [{:keys [aliases inject]} (:deps config)

         inject?
@@ -283,9 +283,13 @@
             "-Sdeps"
             (pr-str {:aliases
                      {:shadow-cljs-inject
-                      {;; :extra-paths ["target/shadow-cljs/aot"]
-                       :extra-deps
-                       {'thheller/shadow-cljs {:mvn/version jar-version}}}}}))
+                      ;; :extra-paths ["target/shadow-cljs/aot"]
+                      (-> {:extra-deps
+                           {'thheller/shadow-cljs {:mvn/version jar-version}}}
+                          (cond->
+                            (seq jvm-opts)
+                            (assoc :jvm-opts jvm-opts))
+                          )}}))

           (seq aliases)
           (conj (str "-A" (->> aliases (map pr-str) (str/join ""))))


Made get-query-params and get-form-params return an empty map if they found nothing.

Signed-off-by: James Reeves <9dadf8ecafa226c8f7c16002bdcb090267879343@weavejester.com>

--- src/compojure/http/request.clj
+++ src/compojure/http/request.clj
@@ -42,7 +42,8 @@
   "Parse parameters from the query string."
   [request]
   (if-let [query (request :query-string)]
-    (parse-params query #"&")))
+    (parse-params query #"&")
+    {}))

 (defn get-character-encoding
   "Get the character encoding, or use the default from duck-streams."
@@ -61,7 +62,9 @@
   [request]
   (if (= (request :content-type) "application/x-www-form-urlencoded")
     (if-let [body (slurp-body request)]
-      (parse-params body #"&"))))
+      (parse-params body #"&")
+      {})
+    {}))

 (defn assoc-parameters
   "Add urlencoded parameters to a request map."


Added clear-session function

Added clear-session function

--- src/compojure/http/session.clj
+++ src/compojure/http/session.clj
@@ -213,6 +213,11 @@
   [session]
   {:session session})

+(defn clear-session
+  "Set the session to nil."
+  [session]
+  (set-session nil))
+
 (defn alter-session
   "Use a function to alter the session."
   [func & args]


absolute url for doc

absolute url for doc

--- src-cljs/frontend/components/landing.cljs
+++ src-cljs/frontend/components/landing.cljs
@@ -274,7 +274,7 @@
             [:p.content-copy
              "We designed our interface to get out of the way and let you concentrate on your ideas. "
              "It's simple enough to show on your phone and perfect for collaborating on your tablet. "]
-            [:a.feature-link {:href "/document/17592197661694"}
+            [:a.feature-link {:href "https://precursorapp.com/document/17592197661694"}
              "Try on iPhone."]]
            [:div.feature-media artwork-mobile]]
           [:div.feature-divider]


remove unused copy iterations

remove unused copy iterations

--- src-cljs/frontend/components/landing.cljs
+++ src-cljs/frontend/components/landing.cljs
@@ -233,15 +233,7 @@
                [:span.philosphy-excess " workflow"]
                [:span.philosphy-needed "."]]
               [:p.philosphy-subtext
-               ; [:span.philosphy-needed "No nonsense—just what you need"]
-               ; ; [:span.philosphy-excess ", when your team needs it"]
-               ; [:span.philosphy-excess ", only when you need it"]
-               ; [:span.philosphy-needed "."]
-               ; [:span.philosphy-needed "No nonsense—the features you need, easily accessible when you need it."]
-               ; [:span.philosphy-needed "No nonsense—exactly what you need, easily accessible when you need it."]
-               ; [:span.philosphy-needed "No nonsense, just the tools you need when you need them."]
-               [:span.philosphy-needed "No nonsense, just the tools you need when you need them."]
-               ]
+               [:span.philosphy-needed "No nonsense, just the tools you need when you need them."]]
               [:div.calls-to-action
                (om/build make-button (select-keys app [:document/id]))]]]]
            [:div.our-proof
@@ -267,11 +259,7 @@
            {:class (when (contains? past-center-features "1") "art-visible") :ref "1"}
            [:div.feature-story
             [:h2.feature-headline
-             ; [:span "Access your ideas on any device right in the browser."]
-             ; [:span "Make all of your ideas accessible in any browser."]
-             ; [:span "Keep your ideas within reach, by using any device."]
-             [:span "Make your ideas accessible anywhere, using any device."]
-             ]
+             [:span "Make your ideas accessible anywhere, using any device."]]
             [:p.feature-copy
              [:span.content-copy
               "With Precursor all of your ideas are easily accessible right from the browser, whether you're on your desktop, tablet, or phone."]]]
@@ -281,12 +269,7 @@
            {:class (when (contains? past-center-features "2") "art-visible") :ref "2"}
            [:div.feature-story
             [:h2.feature-headline
-             ; [:span "Interact with your ideas way before development."]
-             ; [:span "By letting you interact with your ideas before development ..."]
-             ; [:span "Make your ideas interactive before writing code."]
-             ; [:span "Make your ideas interactive early on & prevent bugs."]
-             [:span "Make prototypes interactive & refine your user experience."]
-             ]
+             [:span "Make prototypes interactive & refine your user experience."]]
             [:p.feature-copy
              [:span.content-copy
               "Make working demos in just minutes using our simple target linking."]]
@@ -299,11 +282,7 @@
            {:class (when (contains? past-center-features "3") "art-visible") :ref "3"}
            [:div.feature-story
             [:h2.feature-headline
-             ; [:span "Collaborate with your whole team in real time."]
-             ; [:span "Make team collaboration productive & more engaging."]
-             [:span "Make team collaboration more productive & engaging."]
-             ; [:span "Make collaborating with your team more productive & engaging."]
-             ]
+             [:span "Make team collaboration more productive & engaging."]]
             [:p.feature-copy
              [:span.content-copy
               "Our new team features are optimized for efficient collaboration.
@@ -325,26 +304,11 @@
              [:div.our-philosphy-wrap
               [:div.our-philosphy.content
                [:h1.philosphy-headline
-                ; [:span "It's purely productive prototyping."]
-                [:span "Precursor is pure prototyping."]
-                ]
-               ; [:h1 "What you need when you need it."]
+                [:span "Precursor is pure prototyping."]]
                [:p.philosphy-subtext
-                ; [:span.content-copy "Precursor is the easiest way to share ideas with your teammates, fast."]
-                ; [:span.philosphy-subtext "Collaborating on ideas with your whole team is simple."]
-                ; [:span.philosphy-subtext "Real time, team collaboration that's fast & simple."]
-                ; [:span.philosphy-subtext "It's real time, team collaboration that lets you focus on your ideas."]
-                ; [:span.philosphy-subtext "It's real time collaboration that's simple enough to let you focus on your idea."]
-                ; [:span.philosphy-subtext "It's real time collaboration that makes it simple to focus on your ideas."]
-                ; [:span.philosphy-subtext "It's real-time collaboration that makes it simple to focus on your inspiration."]
-                ; [:span.philosphy-subtext "It's real-time collaboration that makes focusing on your ideas simple."]
-                ; [:span.philosphy-subtext "It's real-time collaboration that makes it easy to focus on what's important."]
                 [:span.philosphy-needed "Real-time collaboration"]
                 [:span.philosphy-excess " that makes it easy "]
-                [:span.philosphy-needed " to focus on what's important."]
-                ; [:span.philosphy-subtext "Sharing ideas should be simple."]
-                ; [:p "Prototype anywhere on any device. No nonsense, just what you need when you need it."]
-                ]
+                [:span.philosphy-needed " to focus on what's important."]]
                [:div.calls-to-action
                 (common/google-login)
                 (om/build make-button (select-keys app [:document/id]))]]]


Small cosmetics when printing known implications

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

--- src/conexp/fca/exploration/repl.clj
+++ src/conexp/fca/exploration/repl.clj
@@ -194,7 +194,8 @@

 (define-repl-fn knowledge
   "Prints the currently known implications (including background knowledge)."
-  (println knowledge)
+  (doseq [impl (:knowledge state)]
+    (println impl))
   state)

 (define-repl-fn implication


Add tests for repo= inequaltiy

Add tests for repo= inequaltiy

--- test/grafter/rdf/repository_test.clj
+++ test/grafter/rdf/repository_test.clj
@@ -20,10 +20,15 @@

 (deftest repo=test
   (testing "repo-like things coerce for equality checks"
-    (repo= (repo "./test/grafter/rdf-types.trig")
-           (grafter.rdf/statements "./test/grafter/rdf-types.trig")
-           "./test/grafter/rdf-types.trig"
-           (file "./test/grafter/rdf-types.trig")))
+    (is (repo= (repo "./test/grafter/rdf-types.trig")
+               (grafter.rdf/statements "./test/grafter/rdf-types.trig")
+               "./test/grafter/rdf-types.trig"
+               (file "./test/grafter/rdf-types.trig"))))
+
+  (testing "Inequality"
+    (is (not (repo= "./test/grafter/rdf-types.trig"
+                    "./test/grafter/rdf-types.ttl"))
+        "Should not be equal because the trig file are quads and the ttl file are triples."))

   (testing "An empty repo is equal to an empty repo"
     (is (repo= (repo (MemoryStore.))


refactoring accumulate-db-cha

refactoring accumulate-db-cha

--- libs/cloudlog-events/src/cloudlog_events/core.clj
+++ libs/cloudlog-events/src/cloudlog_events/core.clj
@@ -98,6 +98,9 @@
          (assoc ev :change ch))
        (filter #(> (:change %) 0))))

+(defn mapchan [f chan]
+  (async/map f [chan]))
+
 (defn accumulate-db-chan [db-chan]
   (let [my-chan (async/chan)]
     (async/go
@@ -105,14 +108,11 @@
         (let [my-resp-chan (async/chan)
               [req resp-chan] (async/<! my-chan)]
           (async/>! db-chan [req my-resp-chan])
-          (let [accum (async/reduce accumulate (accumulate) my-resp-chan)
-                accum (async/map accumulated-events [accum])
-                accum (async/<! accum)]
-            (loop [accum accum]
-              (when-not (empty? accum)
-                (async/>! resp-chan (first accum))
-                (recur (rest accum))))
-            (async/close! resp-chan)))
+          (let [accum (->> (async/reduce accumulate (accumulate) my-resp-chan)
+                           (mapchan accumulated-events)
+                           async/<!
+                           async/to-chan)]
+            (async/pipe accum resp-chan)))
         (recur)))
     my-chan))


Store repo URL and selected branch into job results table

--- src/emender_service/db_interface.clj
+++ src/emender_service/db_interface.clj
@@ -35,10 +35,10 @@
             (println e))))

 (defn record-job-results
-    [job-name datetime results]
+    [job-name repo-url branch datetime results]
     (try
         (jdbc/insert! db-spec/emender-service-db
-                      :results {:job job-name :datetime datetime :results results})
+                      :results {:job job-name :datetime datetime :url repo-url :branch branch :results results})
         (catch Exception e
             (println e))))

@@ -69,8 +69,9 @@

 (defn log-job-results
     ([job-name repo-url branch results]
-     (record-job-event job-name (format-date/format-current-date) "results")
-     (record-job-results job-name (format-date/format-current-date) results))
+     (let [formatted-date (format-date/format-current-date)]
+         (record-job-event job-name formatted-date "results")
+         (record-job-results job-name repo-url branch formatted-date results)))
     ([job-name results]
      (log-job-results job-name nil nil results)))


Return top 3 athletes when all are skipped

This is helpful for focusing on a certain position. Normally if you want a QB before round 3, they will all be passed over because their adp is still too high. This returns the top 3 in that case.

--- src/dynasty_league/calculations.clj
+++ src/dynasty_league/calculations.clj
@@ -111,16 +111,17 @@
 (defn adp-vs-spot
   "Calculates whether or not to take the best athlete available. If he will likely
   still be around for my next pick, I want to wait to take him and instead get the
-  second best athlete available." [athletes]
-  (let [top-athlete (first athletes)
-        moves (count moves-made)]
-    (if (pos? (- (:adp top-athlete) moves))
-      ;; If positive, then we can possibly wait to draft based on how many moves
-      ;; until our next pick.
-      (if (<= (util/gen-next-draft-spot) (:adp top-athlete))
-        ;; We can wait, so look for next best athlete (unless it is last athlete).
-        (if (= (count athletes) 1) top-athlete (recur (rest athletes)))
-        ;; We can't wait, so return the top 3 athletes.
-        (take 3 athletes))
-      ;; If negative, then this player should have been drafted already. TAKE HIM!!
-      (take 3 athletes))))
+  second best athlete available." [aths]
+  (loop [athletes aths]
+    (let [top-athlete (first athletes)
+          moves (count moves-made)]
+      (if (pos? (- (:adp top-athlete) moves))
+        ;; If positive, then we can possibly wait to draft based on how many moves
+        ;; until our next pick.
+        (if (<= (util/gen-next-draft-spot) (:adp top-athlete))
+          ;; We can wait, so look for next best athlete (unless it is last athlete).
+          (if (= (count athletes) 1) (take 3 aths) (recur (rest athletes)))
+          ;; We can't wait, so return the top 3 athletes.
+          (take 3 athletes))
+        ;; If negative, then this player should have been drafted already. TAKE HIM!!
+        (take 3 athletes)))))


Move the header out of the main grid

Move the header out of the main grid

--- src/cljs/onyx_dashboard/components/main.cljs
+++ src/cljs/onyx_dashboard/components/main.cljs
@@ -23,52 +23,52 @@
   (render-state [_ {:keys [api-chan]}]
                 (let [{:keys [selected-job jobs]} deployment
                       job (and selected-job jobs (jobs selected-job))]
-                  (g/grid {}
-                          (g/row {}
-                                 (r/page-header {:class "page-header, main-header"}
-                                                (g/grid {}
-                                                        (g/col {:xs 4}
-                                                               (dom/a {:href "https://github.com/MichaelDrogalis/onyx"}
-                                                                      (dom/img {:class "logo"
-                                                                                :src "/img/high-res.png"
-                                                                                :height 60})))
-                                                        (g/col {:xs 8}
-                                                               (dom/div {:style {:font-size "42px"
-                                                                                :margin-top "10px"}}
-                                                                        "Onyx Dashboard")))))
-                          (g/row {}
-                                 (g/col {:xs 6 :md 4}
-                                        (dom/div {:class "left-nav-deployment"}
-                                                 (om/build select-deployment app {}))
+                  (dom/div
+                    (r/page-header {:class "page-header, main-header"}
+                                   (g/grid {}
+                                           (g/col {:xs 6 :md 4}
+                                                  (dom/a {:href "https://github.com/MichaelDrogalis/onyx"}
+                                                         (dom/img {:class "logo"
+                                                                   :src "/img/high-res.png"
+                                                                   :height 60})))
+                                           (g/col {:xs 12 :md 8}
+                                                  (dom/div {:style {:font-size "42px"
+                                                                    :margin-top "10px"}}
+                                                           "Onyx Dashboard"))))
+                    (g/grid {}
+                            (g/row {}
+                                   (g/col {:xs 6 :md 4}
+                                          (dom/div {:class "left-nav-deployment"}
+                                                   (om/build select-deployment app {}))

-                                        (if (:id deployment)
-                                          (dom/div {}
-                                                   (om/build deployment-indicator
-                                                             {:deployment deployment
-                                                              :last-entry ((:entries deployment) (:message-id-max deployment))}
-                                                             {})))
+                                          (if (:id deployment)
+                                            (dom/div {}
+                                                     (om/build deployment-indicator
+                                                               {:deployment deployment
+                                                                :last-entry ((:entries deployment) (:message-id-max deployment))}
+                                                               {})))

-                                        (if (:id deployment)
-                                          (dom/div {}
-                                                   (om/build job-selector deployment {})))
+                                          (if (:id deployment)
+                                            (dom/div {}
+                                                     (om/build job-selector deployment {})))

-                                        (if (:id deployment)
-                                          (dom/div {}
-                                                   (om/build deployment-peers deployment {})))
+                                          (if (:id deployment)
+                                            (dom/div {}
+                                                     (om/build deployment-peers deployment {})))

-                                        (dom/div {}
-                                                 (if job
-                                                   (om/build job-management
-                                                             job
-                                                             {:react-key (str "management-" (:id job))}))))
-                                 (g/col {:xs 12 :md 8}
-                                        (dom/div
-                                          (if job
-                                            (om/build job-info
-                                                      (if (:up? deployment) job (dissoc job :tasks :peers))
-                                                      {:react-key (str "job-info-" (:id job))}))
+                                          (dom/div {}
+                                                   (if job
+                                                     (om/build job-management
+                                                               job
+                                                               {:react-key (str "management-" (:id job))}))))
+                                   (g/col {:xs 11 :md 8}
+                                          (dom/div
+                                            (if job
+                                              (om/build job-info
+                                                        (if (:up? deployment) job (dissoc job :tasks :peers))
+                                                        {:react-key (str "job-info-" (:id job))}))

-                                          (om/build log-entries-pager
-                                                    {:entries (:entries deployment)
-                                                     :job-filter (:id job)}
-                                                    {:react-key (str "log-" (:id deployment) "-filter-" (:id job))}))))))))
+                                            (om/build log-entries-pager
+                                                      {:entries (:entries deployment)
+                                                       :job-filter (:id job)}
+                                                      {:react-key (str "log-" (:id deployment) "-filter-" (:id job))})))))))))


Fix regular expression for date parse from iso format

--- src/cljs/re_form/inputs/date_input_impl.cljs
+++ src/cljs/re_form/inputs/date_input_impl.cljs
@@ -69,7 +69,7 @@
                  :delimiter "/"
                  :placeholder "mm/dd/yyyy"
                  :groups [:m :d :y]}
-   "iso"        {:regex #"^(\d\d\d\d)-(\d\d)-(\d\d)$"
+   "iso"        {:regex #"^(\d\d\d\d)-(\d\d)-(\d\d).*$"
                  :delimiter "-"
                  :placeholder "yyyy-mm-dd"
                  :groups [:y :m :d]}


Always blink tap tempo button on new beat.

Similar to change just made to Ableton Push controller: Flash the tempo
button if we have reached a new beat even if the tempo is so fast that
we are far enough into the beat by the time the screen refresh occurs
that the button would already be darkened.

--- src/afterglow/web/routes/show_control.clj
+++ src/afterglow/web/routes/show_control.clj
@@ -251,15 +251,17 @@

 (defn metronome-states
   "Gather details about the current state of the main show metronome."
-  [show]
+  [show last-states]
   (with-show show
-    (let [snap (rhythm/metro-snapshot (:metronome show))]
-      {:bpm (format "%.1f" (float (:bpm snap)))
-       :phrase (:phrase snap)
-       :bar (rhythm/snapshot-bar-within-phrase snap)
-       :beat (rhythm/snapshot-beat-within-bar snap)
-       :blink (< (rhythm/snapshot-beat-phase snap) 0.15)
-       :sync (dissoc (show/sync-status) :status :source)})))
+    (let [snap (rhythm/metro-snapshot (:metronome show))
+          position {:phrase (:phrase snap)
+                    :bar (rhythm/snapshot-bar-within-phrase snap)
+                    :beat (rhythm/snapshot-beat-within-bar snap)}]
+      (merge {:bpm (format "%.1f" (float (:bpm snap)))
+              :blink (or (not= position (select-keys last-states [:phrase :bar :beat]))
+                         (< (rhythm/snapshot-beat-phase snap) 0.2))
+              :sync (dissoc (show/sync-status) :status :source)}
+             position))))

 (defn metronome-changes
   "Return the list of changes that should be applied to the show
@@ -267,7 +269,7 @@
   [page-id]
   (let [last-info (get @clients page-id)
         last-states (:metronome last-info)
-        next-states (metronome-states (:show last-info))
+        next-states (metronome-states (:show last-info) last-states)
         changes (filter identity (for [[key val] next-states]
                                    (when (not= (key last-states) (key next-states))
                                      {:id (name key) :val val})))]


it clones via ssh when credentials are given

--- main/src/dda/pallet/dda_managed_vm/domain/git.clj
+++ main/src/dda/pallet/dda_managed_vm/domain/git.clj
@@ -40,7 +40,11 @@
  [domain-config]
  (let [{:keys [user usage-type]} domain-config
        {:keys [name email git-credentials desktop-wiki credentials]
-        :or {email (str name "@mydomain")}} user]
+        :or {email (str name "@mydomain")}} user
+       github-ssh (for [x git-credentials] (and (= (:host x) "github.com") (= (:protocol x) :ssh)))
+       protocol-type (if (and (contains? user :git-credentials)
+                              (some true? github-ssh))
+                        :ssh :https)]
    {(keyword name)
     (merge
       {:user-email email}
@@ -50,12 +54,12 @@
               [{:host "github.com"
                 :orga-path "DomainDrivenArchitecture"
                 :repo-name "ddaArchitecture"
-                :protocol (if (contains? user :ssh) :ssh :https)
+                :protocol protocol-type
                 :server-type :github}]}}
       {:synced-repo  {:password-store
                       [{:host "github.com"
                         :orga-path "DomainDrivenArchitecture"
                         :repo-name "password-store-for-teams"
-                        :protocol (if (contains? user :ssh) :ssh :https)
+                        :protocol protocol-type
                         :server-type :github}]}}
       {})}))


License text into server module

License text into server module

--- src/emender_service/server.clj
+++ src/emender_service/server.clj
@@ -1,8 +1,21 @@
+;
+;  (C) Copyright 2016  Pavel Tisnovsky
+;
+;  All rights reserved. This program and the accompanying materials
+;  are made available under the terms of the Eclipse Public License v1.0
+;  which accompanies this distribution, and is available at
+;  http://www.eclipse.org/legal/epl-v10.html
+;
+;  Contributors:
+;      Pavel Tisnovsky
+;
+
 (ns emender-service.server)

 (require '[ring.util.response     :as http-response])

 (require '[emender-service.html-renderer :as html-renderer])
+(require '[emender-service.results       :as results])

 (defn render-front-page
     "Create front page."
@@ -57,7 +70,8 @@
 (defn handler
     "Handler that is called by Ring for all requests received from user(s)."
     [request]
-    (println "request URI: " (request :uri))
+    (println "request URI: " (:uri request))
+    (println (:configuration request))
     (let [uri    (:uri request)
           method (:request-method request)]
          (if (.startsWith uri "/v1")