Make sformat more robust to %% and %n specifiers

The previous version of sformat had a number of minor bugs relating to
the use of the %% and %n specifiers (to create literal percent signs and
platform-independent newlines). This commit restructures the way in
which these specifiers are handled, viz. they are treated as normal
specifiers, but when sformat calls through to format the corresponding
argument is simply ignored. Also, an additional check is added to make
sure that %% and %n do not cause an argument to be skipped for the next
format specifier.

--- cortex/src/cortex/util.cljc
+++ cortex/src/cortex/util.cljc
@@ -553,14 +553,19 @@
   https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html
   for details. Groups match the argument number (if given) and the
   remainder of the format specifier, respectively."
-  #"%(?:([1-9][0-9]*)\$)?([-#+ 0,(]*(?:[1-9][0-9]*)?(?:\.[0-9]+)?(?:[bBhHsScCdoxXeEfgGaA]|[tT][HIklMSLNpzZsQBbhAaCYyjmdeRTrDFc]))")
+  #"%(?:([1-9][0-9]*)\$)?([-#+ 0,(]*(?:[1-9][0-9]*)?(?:\.[0-9]+)?(?:[bBhHsScCdoxXeEfgGaA%n]|[tT][HIklMSLNpzZsQBbhAaCYyjmdeRTrDFc]))")

 (defn sformat
   "Like format, but smarter. If one of the args is a collection,
   the format specifier is mapped over each element of the collection,
   and the results are placed in the formatted string as a vector.
-  Also works on nested collections. If the conversion is 'f', will
-  try to cast the argument to a double before passing it to format."
+  Also works on nested collections. For some format types, will
+  attempt to cast the object before formatting. That is,
+  (sformat \"%.1f\" 42) will return \"42.0\" rather than throwing an
+  IllegalFormatConversionException.
+
+  Will not necessarily handle malformed format specifiers gracefully,
+  but anything legal according to the Javadoc is fair game."
   [fmt & args]
   (let [fmt-strings
         (for [[fmt-string ^long arg-index fmt-specifier]
@@ -569,34 +574,33 @@
                      arg-index 1]
                 (if (seq unprocessed)
                   (let [match (first unprocessed)
-                        positional? (nth match 1)]
+                        positional? (nth match 1)
+                        argless? (#{\% \n} (last (nth match 2)))]
                     (recur (rest unprocessed)
                            (conj processed (update match 1 (if positional?
                                                              parse-long
                                                              (constantly arg-index))))
-                           (if positional?
+                           (if (or positional? argless?)
                              arg-index
                              (inc arg-index))))
                   processed))]
           (let [arg-index (dec arg-index)
-                arg (nth args arg-index)]
-            (str/replace
-              (if (seq-like? arg)
-                (str "["
-                     (str/join " "
-                               (map (fn [item]
-                                      (sformat (str "%" fmt-specifier)
-                                               item))
-                                    arg))
-                     "]")
-                (format (str "%" fmt-specifier)
-                        (case (last fmt-specifier)
-                          (\e \E \f \g \G \a \A) (double arg)
-                          (\d \o \x \X) (long arg)
-                          arg)))
-              "%" "%%")))
+                arg (nth args arg-index nil)]
+            (if (seq-like? arg)
+              (str "["
+                   (str/join " "
+                             (map (fn [item]
+                                    (sformat (str "%" fmt-specifier)
+                                             item))
+                                  arg))
+                   "]")
+              (format (str "%" fmt-specifier)
+                      (case (last fmt-specifier)
+                        (\e \E \f \g \G \a \A) (double arg)
+                        (\d \o \x \X) (long arg)
+                        arg)))))
         splits (str/split fmt fmt-string-regex)]
-    (format (apply str (interleave-all splits fmt-strings)))))
+    (apply str (interleave-all splits fmt-strings))))

 (defn sprintf
   "Like printf, but uses sformat instead of format."


Actually I mean optional-key

Actually I mean optional-key

--- src/icecap/handlers/core.clj
+++ src/icecap/handlers/core.clj
@@ -58,5 +58,5 @@
          ~@forms))))

 (defstep :succeed
-  {(s/optional :name) s/Str}
+  {(s/optional-key :name) s/Str}
   (async/to-chan [step]))


fix execution for interface-definition

fix execution for interface-definition

--- src/graphql_clj/executor.clj
+++ src/graphql_clj/executor.clj
@@ -55,7 +55,7 @@
       (cond
         (#{:scalar-definition :union-definition :enum-definition} tag) result
         (#{:type-definition} tag) (execute-fields selection-set state type-name result)
-        ;; (#{:interface-definition} tag) (execute-fields selection-set state type-name result)
+        (#{:interface-definition} tag) (execute-fields selection-set state type-name result)
         (#{:basic-type} tag) (let [unwrapped-type (get-in schema [:type-map type-name])]
                                (complete-value (assoc field-entry :type unwrapped-type) state result))
         (#{:list-type} tag) (do


Add an assertion that the source for read-content exists.

--- src/io/aviso/twixt/utils.clj
+++ src/io/aviso/twixt/utils.clj
@@ -56,6 +56,7 @@
 (defn read-content
   "Reads the content of a provided source (compatible with clojure.java.io/input-stream) as a byte array."
   [source]
+  (assert source "Unable to read content from nil.")
   (with-open [bos (ByteArrayOutputStream.)
               in (io/input-stream source)]
     (io/copy in bos)


removing scanning ns

removing scanning ns

--- src/hypervisors/scanning.clj
+++ src/hypervisors/scanning.clj
@@ -1,34 +0,0 @@
-(ns hypervisors.scanning
-  "Scanning hosts"
-  (:require
-    [hypervisors.networking :refer (list-used-ips)]
-    [clojure.data :refer [diff]]
-    [clojure.java.data :refer [from-java]])
-  (:import
-    org.nmap4j.Nmap4j
-    org.nmap4j.parser.OnePassParser))
-
-(defn ports-open? [host]
-  (not (nil? (first (filter #(= % "open") (map #(get-in % [:state :state]) (get-in host [:ports :ports])))))))
-
-(defn raw-scan
-  "runs raw scan, require nmap bin to be symlinked to /usr/local"
-  [ip]
-  (let [nmap (Nmap4j. "/usr/local")]
-    (doto nmap
-      (.includeHosts ip)
-      (.addFlags "-n -T5 -p U:1194,T:21,22,25,53,80,110,111")
-      (.execute)
-      (.getResult))))
-
-(defn hosts-scan
-  "Uses nmap so scan a list of hosts (192.168.10.1-50)"
-  [hosts]
-  (map :addresses
-       (filter ports-open?  (get-in (from-java (raw-scan hosts)) [:result :hosts]))))
-
-(defn correlate
-  "compares stored ips to scan result"
-  [k]
-  (let [scanned (map (fn [[{:keys [addr]}]] addr) (hosts-scan "192.168.20.170-254"))]
-    (zipmap [:scanned :listed :common] (diff (into #{} scanned) (into #{} (list-used-ips k))))))


Enabling PUT functionality for group.

Enabling PUT functionality for group.

--Tom

--- src/kilo/resources/group.clj
+++ src/kilo/resources/group.clj
@@ -13,6 +13,7 @@
     :example "curl --header 'Accept:application/edn' http://localhost:4001/kilo/user/36590"}

   get-group [id]
+
   :allowed-methods [:get]
   :available-media-types ["application/json" "application/edn"]
   :exists? (fn [ctx]
@@ -26,8 +27,9 @@
   :allowed-methods [:put]
   :available-media-types ["application/json" "application/edn"]
   :put! (fn [ctx]
-          ;;(k-usersql/set-user-data id (json/read-str  (slurp (get-in
-          ;ctx [:request :body])) :key-fn keyword) )
+          (k-group/set-group-data id
+                                   (json/read-str  (slurp
+                                                       (get-in ctx [:request :body])) :key-fn keyword) )
           )
   :new? false
   :respond-with-entity? true


Minor normalization

Minor normalization


some useful msg when tests are failed

some useful msg when tests are failed

--- src/leiningen/namespaces.clj
+++ src/leiningen/namespaces.clj
@@ -173,18 +173,18 @@
       {:result :failed :cmd (str/join " " cmd)})))

 (defn lein-test [project]
-  (m/info "\n... Executing tests of" project "on" (u/output-of (sh/sh "pwd")) "\n")
+  (m/info "\n... Executing tests of" project "on" (u/output-of (sh/sh "pwd")))
   (let [failed-cmd (->> project
                         (test-cmd)
                         (map run-cmd)
-                        (filter #(= (:result %) :failed))
-                        (first))]
+                        (filter #(= (:result %) :failed)))]
     (if (empty? failed-cmd)
       (do
         (m/info "===> All tests of" project "are passed\n")
         {:project project :result :passed})
       (do
-        (m/info "===> Some tests when running" (:cmd failed-cmd) project "are FAILED!!!\n")
+        (m/info "===> On" project "some tests are FAILED when executing"
+                (str/join " and " (map :cmd failed-cmd)) "\n")
         {:project project :result :failed}))))

 (defn reset-project! [project]


pred cambiare to change

pred cambiare to change

--- src/babel/espanol/lexicon.clj
+++ src/babel/espanol/lexicon.clj
@@ -61,7 +61,7 @@
                      :sem {:pred :lower}}}

    "cambiar" {:synsem {:cat :verb
-                       :sem {:pred :cambiare}}}
+                       :sem {:pred :change}}}

    "cerrar" {:espanol {:boot-stem "cierr"}
              :synsem {:cat :verb


Make Exception types printable

Make Exception types printable

--- src/cats/monad/exception.cljc
+++ src/cats/monad/exception.cljc
@@ -107,6 +107,21 @@
            (= v (.-v other))
            false))]))

+(defn success->str
+  [mv]
+  (str "#<Success " (pr-str (.-v mv)) ">"))
+
+#?(:clj
+   (defmethod print-method Success
+     [mv writer]
+     (.write writer (success->str mv))))
+
+#?(:cljs
+   (extend-type Success
+     IPrintWithWriter
+     (-pr-writer [mv writer _]
+       (-write writer (success->str mv)))))
+
 (deftype Failure [e]
   p/Contextual
   (-get-context [_] context)
@@ -136,6 +151,21 @@
          (if (instance? Failure other)
            (= e (.-e other))
            false))]))
+
+(defn failure->str
+  [mv]
+  (str "#<Failure " (pr-str (.-e mv)) ">"))
+
+#?(:clj
+   (defmethod print-method Failure
+     [mv writer]
+     (.write writer (failure->str mv))))
+
+#?(:cljs
+   (extend-type Failure
+     IPrintWithWriter
+     (-pr-writer [mv writer _]
+       (-write writer (failure->str mv)))))

 (alter-meta! #'->Success assoc :private true)
 (alter-meta! #'->Failure assoc :private true)


using carmine hgetall*

using carmine hgetall*

--- src/celestial/persistency.clj
+++ src/celestial/persistency.clj
@@ -28,13 +28,9 @@
     (doseq [[k v] props]
       (car/hset (hk (machine :hostname)) k v))))

-(defn hgetall [h]
-  "require since expect fails to mock otherwise"
-  (wcar (car/hgetall (hk h))))
-
 (defn host [h]
-  (if-let [data (hgetall h)]
-    (apply merge (map (partial apply hash-map) (partition 2 data)))
+   (if-let [data (wcar (car/hgetall* (hk h)))]
+     data
     (throw+ {:type ::missing-host :host h})))

 (defn fuzzy-host [h]


Add news entry

Add news entry

--- demo/reagentdemo/news.cljs
+++ demo/reagentdemo/news.cljs
@@ -13,6 +13,9 @@

 (defn main []
   [:div
+   [:div.reagent-demo
+    [:h1 [:a {:href "https://github.com/reagent-project/reagent/blob/master/CHANGELOG.md#081-2018-05-15"} "Reagent 0.8.1"]]
+    [:span "2018-05-15"]]
    [:div.reagent-demo
     [:h1 [:a {:href "https://github.com/reagent-project/reagent/blob/master/CHANGELOG.md#080-2018-04-19"} "Reagent 0.8.0"]]
     [:span "2018-04-19"]]


do not nil here, not nil area here

do not nil here, not nil area here

--- src/clj/runbld/facts/oshi.clj
+++ src/clj/runbld/facts/oshi.clj
@@ -46,10 +46,10 @@
     (get-in x [:operatingSystem :networkParams :hostName]))

   (ip4 [{x :facts}]
-    (seq (mapcat :ipv4 (get-in facts [:hardware :networks]))))
+    (seq (remove nil? (mapcat :ipv4 (get-in facts [:hardware :networks])))))

   (ip6 [{x :facts}]
-    (seq (mapcat :ipv6 (get-in facts [:hardware :networks]))))
+    (seq (remove nil? (mapcat :ipv6 (get-in facts [:hardware :networks])))))

   (kernel-name [{x :facts}]
     (get-in x [:uname :name]))


Fix user fullname search in gallery views

--- src/clj/salava/gallery/db.clj
+++ src/clj/salava/gallery/db.clj
@@ -32,7 +32,7 @@
                          [(str where " AND ic.name LIKE ?") (conj params (str "%" issuer-name "%"))]
                          [where params])
         [where params] (if-not (empty? recipient-name)
-                         [(str where " AND (u.first_name LIKE ? OR u.last_name LIKE ?)") (conj params (str recipient-name "%") (str recipient-name "%"))]
+                         [(str where " AND CONCAT(u.first_name,' ',u.last_name) LIKE ?") (conj params (str "%" recipient-name "%"))]
                          [where params])
         [where params] (if (and (not (empty? issuer-name)) (empty? recipient-name)) ;if issuer name is present but recipient name is not, search also private badges
                          [where params]
@@ -117,7 +117,7 @@
                          [(str where " AND u.country = ?") (conj params country)]
                          [where params])
         [where params] (if-not (empty? owner)
-                         [(str where " AND (u.first_name LIKE ? OR u.last_name LIKE ?)") (conj params (str owner "%") (str owner "%"))]
+                         [(str where " AND CONCAT(u.first_name,' ',u.last_name) LIKE ?") (conj params (str "%" owner "%"))]
                          [where params])
         query (str "SELECT p.id, p.ctime, p.mtime, user_id, name, description, u.first_name, u.last_name, u.profile_picture, GROUP_CONCAT(pb.badge_id) AS badges FROM page AS p
                     JOIN user AS u ON p.user_id = u.id
@@ -147,7 +147,7 @@
                          [(str where " AND country = ?") (conj params country)]
                          [where params])
         [where params] (if-not (empty? name)
-                         [(str where " AND (first_name LIKE ? OR last_name LIKE ?)") (conj params (str name "%") (str name "%"))]
+                         [(str where " AND CONCAT(first_name,' ',last_name) LIKE ?") (conj params (str "%" name "%"))]
                          [where params])
         having (if common_badges " HAVING common_badge_count > 0")
         query (str "SELECT id AS uid, first_name, last_name, country, profile_picture, ctime, (SELECT COUNT(DISTINCT badge_content_id) FROM badge WHERE user_id = uid AND status = 'accepted' AND deleted = 0 AND (expires_on IS NULL OR expires_on > UNIX_TIMESTAMP()) AND badge_content_id IN (SELECT DISTINCT badge_content_id FROM badge WHERE user_id = ? AND status = 'accepted' AND deleted = 0 AND (expires_on IS NULL OR expires_on > UNIX_TIMESTAMP()))) AS common_badge_count


full path library abstraction

full path library abstraction

--- src/cljs/filesystem/path.cljs
+++ src/cljs/filesystem/path.cljs
@@ -6,6 +6,17 @@
 (def pathlib (nodejs/require "path"))

-(defn get-extension [path] (.extname pathlib path))
-
-(defn join [& parts] (apply (.-join pathlib) parts))
+(defonce basename (.-basename pathlib))
+(defonce delimiter (.-delimiter pathlib))
+(defonce dirname (.-dirname pathlib))
+(defonce get-extension (.-extname pathlib))
+(defonce format (.-format pathlib))
+(defonce is-absolute (.-isAbsolute pathlib))
+(defonce normalize (.-normalize pathlib))
+(defonce parse (.-parse pathlib))
+(defonce posix (.-posix pathlib))
+(defonce relative (.-relative pathlib))
+(defonce resolve (.-resolve pathlib))
+(defonce sep (.-sep pathlib))
+(defonce win32 (.-win32 pathlib))
+(defonce join (.-join pathlib))


Add `fexecute` function to job graph API.

--- src/clojure/parkour/graph.clj
+++ src/clojure/parkour/graph.clj
@@ -430,3 +430,14 @@
                    (into {}))
         runner (if (mr/local-runner? conf) graph-delay graph-future)]
     (run-graph runner graph tails)))
+
+(defn fexecute
+  "As per `execute`, but require and return only a single result desq;
+almost `(comp first execute)`."
+  [graph conf jname]
+  (let [[result :as results] (execute graph conf jname)
+        nresults (count results)]
+    (if (= 1 nresults)
+      result
+      (throw (ex-info "Multiple outputs from `fexecute`d graph."
+                      {:nresults nresults})))))


Queries for CCS-made description(s)

Queries for CCS-made description(s)

--- src/clouseau/db_interface.clj
+++ src/clouseau/db_interface.clj
@@ -62,6 +62,18 @@
     [package]
     (jdbc/query db-spec/ccs-db (str "select description from packages where lower(name)='" (clojure.string/lower-case package) "';")))

+(defn read-ccs-description-count
+    []
+    (-> (jdbc/query db-spec/ccs-db (str "select count(description) as cnt from packages"))
+        first
+        :cnt))
+
+(defn read-first-ccs-description
+    [package]
+    (-> (jdbc/query db-spec/ccs-db (str "select description from packages where lower(name)='" (clojure.string/lower-case package) "';"))
+        first
+        :description))
+
 (defn read-all-descriptions
     []
     ; we need to use trim() here because some package names starts with one space or even with more spaces


Adding error checking in the spatial library.

--- src/cmr/spatial/serialize.clj
+++ src/cmr/spatial/serialize.clj
@@ -232,6 +232,10 @@
       shapes
       (let [[int-type size] (first ords-info-pairs)
             type (integer->shape-type int-type)
+            _ (when-not type
+                (errors/internal-error!
+                  (format "Could not get a shape type from integer [%s]. Ords info: %s"
+                          int-type (pr-str ords-info))))
             shape-ords (take size ords)
             shape (stored-ords->shape type shape-ords)
             ;; If shape is a hole add it to the last shape


rm println

rm println

--- src/com/kaicode/infamous.cljs
+++ src/com/kaicode/infamous.cljs
@@ -98,7 +98,6 @@
 (defn mount-component [reagent-component get-mount-element]

       (.. FamousEngine (requestUpdate (clj->js {:onUpdate (fn [time]
-                                                              (println "mounting " (get-mount-element))
                                                               (let [element (get-mount-element)]
                                                                    (if element
                                                                      (reagent/render [reagent-component] element)


Add proof-of-concept

Add proof-of-concept


up version

up version

--- kafka-clj/project.clj
+++ kafka-clj/project.clj
@@ -1,4 +1,4 @@
-(defproject kafka-clj "3.5.6"
+(defproject kafka-clj "3.5.6-SNAPSHOT"
   :description "fast kafka library implemented in clojure"
   :url "https://github.com/gerritjvv/kafka-fast"
   :license {:name "Eclipse Public License"


Fixed a problem with resource paths containing spaces.

--- src/appengine_magic/core_local.clj
+++ src/appengine_magic/core_local.clj
@@ -18,7 +18,10 @@
                              {:keys [war-root] :or {war-root "war"}}]
   `(def ~app-var-name
         (let [handler# ~handler
-              war-root# (-> (clojure.lang.RT/baseLoader) (.getResource ~war-root) .getFile)]
+              war-root# (-> (clojure.lang.RT/baseLoader)
+                            (.getResource ~war-root)
+                            .getFile
+                            java.net.URLDecoder/decode)]
           {:handler (wrap-war-static
                      (environment-decorator handler#)
                      war-root#)


working on pattern-to-structure

working on pattern-to-structure

--- src/babel/francais/morphology.cljc
+++ src/babel/francais/morphology.cljc
@@ -535,14 +535,23 @@
                   :structure {:synsem {:infl :past-p
                                        :subcat {:1 {:agr {:number :sing
                                                           :gender :fem}}}}}}]
-   #"^(\S+)ées$" [{:replace-with "er" ;; allées -> aller
+   #"^([^aeéiou]\S+)ées$" [{:replace-with "er" ;; allées -> aller
                    :structure {:synsem {:infl :past-p
                                         :subcat {:1 {:agr {:number :plur
                                                            :gender :fem}}}}}}]
+   #"^([aeéiou]\S+)é$" [{:replace-with "er" ;; amusé -> s'amuser
+                         :structure {:synsem {:infl :past-p
+                                              :subcat {:1 {:agr {:number :sing
+                                                                 :gender :masc}}}}}}]
    #"^(\S+)é$" [{:replace-with "er" ;; allé -> aller
                  :structure {:synsem {:infl :past-p
                                       :subcat {:1 {:agr {:number :sing
                                                          :gender :masc}}}}}}]
+   #"^([aeéiou]\S+)és$" [{:replace-with "er" ;; amusés -> s'amuser
+                          :replace-pattern "se $1"
+                          :structure {:synsem {:infl :past-p
+                                               :subcat {:1 {:agr {:number :plur
+                                                                  :gender :masc}}}}}}]
    #"^(\S+)és$" [{:replace-with "er" ;; allés -> aller
                   :structure {:synsem {:infl :past-p
                                        :subcat {:1 {:agr {:number :plur


less logging

less logging

--- src/babel/italiano/morphology.cljc
+++ src/babel/italiano/morphology.cljc
@@ -200,8 +200,8 @@
     (map (string/join " " #(get-string-1 %))
          word)
   (let [person (get-in word '(:agr :person))
-        number (get-in word '(:agr :number))
-        info (log/debug "get-string-1: input word: " word)]
+        number (get-in word '(:agr :number))]
+    (log/trace "get-string-1: input word: " word)]

     (log/debug (str "word's a is a string? " (get-in word '(:a)) " => " (string? (get-in word '(:a)))))
     (log/debug (str "word's b is a map? " (get-in word '(:b)) " => " (map? (get-in word '(:b)))))


Cleaning up dead code.

Cleaning up dead code.

--- src-cljs/frontend/components/build_steps.cljs
+++ src-cljs/frontend/components/build_steps.cljs
@@ -108,8 +108,7 @@
                    [:div.action-log-messages
                     (common/messages (:messages action))
                     [:i.click-to-scroll.fa.fa-arrow-circle-o-down.pull-right
-                     {:on-click #(let [node (om/get-node owner)
-                                       target (.-parentNode (.-currentTarget %))]
+                     {:on-click #(let [target (.-parentNode (.-currentTarget %))]
                                    (.scrollIntoView target false))}]

                     (when (:bash_command action)


Activate aside meny for account page

Activate aside meny for account page

--- src-cljs/frontend/controllers/navigation.cljs
+++ src-cljs/frontend/controllers/navigation.cljs
@@ -514,7 +514,7 @@
        (-> state
            state-utils/clear-page-state
            (assoc state/current-view navigation-point
-                  state/navigation-data (assoc args :show-aside-menu? false))
+                  state/navigation-data (assoc args :show-aside-menu? true))
            (assoc-in state/crumbs-path [{:type :account}]))
        (do
          (routes/open-to-outer! nav-ch :error {:status 401})


Fix hash benchmark to clear cached hash

Fix hash benchmark to clear cached hash

--- src/bench/cljs/lean_map/bench.cljs
+++ src/bench/cljs/lean_map/bench.cljs
@@ -64,7 +64,7 @@
   (let [maps [small-map medium-map large-map]
         samples [small-map-sample medium-map-sample large-map-sample]]
     (doseq [[m sample] (partition 2 (interleave maps samples))]
-      (simple-benchmark [] (hash-unordered-coll m) sample))))
+      (simple-benchmark [] (hash (clone m)) sample))))

 (defmethod map-bench :equals [_ _ {:keys [small-map medium-map large-map]}]
   (println "Equals")


Make sixteen nuls private

Make sixteen nuls private

--- src/caesium/crypto/generichash.clj
+++ src/caesium/crypto/generichash.clj
@@ -1,7 +1,7 @@
 (ns caesium.crypto.generichash
   (:import (org.abstractj.kalium.crypto Hash)))

-(def sixteen-nuls (repeat 16 (byte 0)))
+(def ^:private sixteen-nuls (repeat 16 (byte 0)))

 (defn blake2b
   "Computes the BLAKE2b digest of the given message, with optional


add scroll-to-bottom on-mount as well

add scroll-to-bottom on-mount as well

--- src/chat/client/views/threads.cljs
+++ src/chat/client/views/threads.cljs
@@ -57,34 +57,40 @@
                    (om/build tag-view tag)) tags)))))))

 (defn thread-view [thread owner {:keys [searched?] :as opts}]
-  (reify
-    om/IDidUpdate
-    (did-update [_ _ _]
-      (when-not (thread :new?) ; need this here b/c get-node breaks if no refs???
-        (when-let [messages (om/get-node owner "messages")]
-          ; scroll to bottom of messages
-          (set! (.-scrollTop messages) (.-scrollHeight messages)))))
-    om/IRender
-    (render [_]
-      (dom/div #js {:className "thread"}
-        (dom/div #js {:className "card"}
-          (dom/div #js {:className "head"}
-            (when-not (or (thread :new?) searched?)
-              (dom/div #js {:className "close"
-                            :onClick (fn [_]
-                                       (dispatch! :hide-thread {:thread-id (thread :id)}))} "×"))
-            (om/build thread-tags-view thread))
-          (when-not (thread :new?)
-            (apply dom/div #js {:className "messages"
-                                :ref "messages"}
-              (om/build-all message-view (->> (thread :messages)
-                                              (sort-by :created-at))
-                            {:key :id})))
-          (om/build new-message-view {:thread-id (thread :id)
-                                      :placeholder (if (thread :new?)
-                                                     "Start a conversation..."
-                                                     "Reply...")}
-                    {:react-key "message"}))))))
+  (let [scroll-to-bottom
+        (fn []
+          (when-not (thread :new?) ; need this here b/c get-node breaks if no refs???
+            (when-let [messages (om/get-node owner "messages")]
+              ; scroll to bottom of messages
+              (set! (.-scrollTop messages) (.-scrollHeight messages)))))]
+    (reify
+      om/IDidMount
+      (did-mount [_]
+        (scroll-to-bottom))
+      om/IDidUpdate
+      (did-update [_ _ _]
+        (scroll-to-bottom))
+      om/IRender
+      (render [_]
+        (dom/div #js {:className "thread"}
+          (dom/div #js {:className "card"}
+            (dom/div #js {:className "head"}
+              (when-not (or (thread :new?) searched?)
+                (dom/div #js {:className "close"
+                              :onClick (fn [_]
+                                         (dispatch! :hide-thread {:thread-id (thread :id)}))} "×"))
+              (om/build thread-tags-view thread))
+            (when-not (thread :new?)
+              (apply dom/div #js {:className "messages"
+                                  :ref "messages"}
+                (om/build-all message-view (->> (thread :messages)
+                                                (sort-by :created-at))
+                              {:key :id})))
+            (om/build new-message-view {:thread-id (thread :id)
+                                        :placeholder (if (thread :new?)
+                                                       "Start a conversation..."
+                                                       "Reply...")}
+                      {:react-key "message"})))))))

 (defn debounce
   "Given the input channel source and a debouncing time of msecs, return a new


Let anti-forgery protection handle keywordized requests graciously

--- src/cider_ci/auth/anti_forgery.clj
+++ src/cider_ci/auth/anti_forgery.clj
@@ -36,7 +36,8 @@
 (defn- valid-forgery-protection? [token request]
   (boolean
     (when token
-      (when-let [x-csrf-header-token (-> request :headers (get "x-csrf-token"))]
+      (when-let [x-csrf-header-token (or (-> request :headers :x-csrf-token)
+                                         (-> request :headers (get "x-csrf-token")))]
         (= x-csrf-header-token token)))))

 (def response-401
@@ -50,6 +51,7 @@

 (defn process [request handler]
   (let [token (or (-> request :cookies (get cookie-name nil) :value)
+                  (-> request :cookies (get (keyword cookie-name) nil) :value)
                   (crypto.random/url-part 32))
         resp (if (and (not (safe-request? request))
                       (not (valid-forgery-protection? token request))


Update sync.clj

Update sync.clj

--- src/metabase/driver/sync.clj
+++ src/metabase/driver/sync.clj
@@ -162,7 +162,7 @@
   (let [active-field-ids         #(set (sel :many :field [Field :id], :table_id (:id table), :active true, :parent_id nil))
         table-def                (driver/describe-table driver table)
         current-active-field-ids (active-field-ids)]
-    (schema/validate driver/describe-table-schema table-def)
+    (schema/validate driver/DescribeTable table-def)

     ;; Run basic schema syncing to create all the Fields / PKs
     (u/try-apply sync-table-active-fields-and-pks! table table-def)
@@ -175,7 +175,7 @@
     (when analyze?
       (let [new-field-ids (set/difference (active-field-ids) current-active-field-ids)]
         (when-let [table-stats (driver/analyze-table driver table new-field-ids)]
-          (schema/validate driver/analyze-table-schema table-stats)
+          (schema/validate driver/AnalyzeTable table-stats)

           ;; update table row count
           (when (:row_count table-stats)
@@ -252,7 +252,7 @@
     (events/publish-event :database-sync-begin {:database_id (:id database) :custom_id tracking-hash})

     (let [database-schema (driver/describe-database driver database)]
-      (schema/validate driver/describe-database-schema database-schema)
+      (schema/validate driver/DescribeDatabase database-schema)

       ;; now persist the list of tables, creating new ones as needed and inactivating old ones
       (save-database-tables-list! database (:tables database-schema))
@@ -464,7 +464,7 @@
 (defn- sync-table-fks! [driver table]
   (when (contains? (driver/features driver) :foreign-keys)
     (let [fks (driver/describe-table-fks driver table)]
-      (schema/validate driver/describe-table-fks-schema fks)
+      (schema/validate driver/DescribeTableFKs fks)
       (when (seq fks)
         (let [fk-name->id (sel :many :field->id [Field :name], :table_id (:id table), :name [in (map :fk-column-name fks)], :parent_id nil)]
           (doseq [{:keys [fk-column-name dest-column-name dest-table]} fks]


Remove unnecessary return values from parser args

--- src/clj/reply/eval_modes/nrepl.clj
+++ src/clj/reply/eval_modes/nrepl.clj
@@ -59,7 +59,7 @@
     (reset! current-command-id nil)
     @current-ns))

-(defn repl-parse [request-prompt request-exit read-error execute]
+(defn repl-parse [request-exit execute]
   (loop [text-so-far nil]
     (if-let [next-text (.readLine *in*)]
       (let [concatted-text (if text-so-far
@@ -89,24 +89,22 @@
         (prompt ns)
         (flush)
         (let [eof (Object.)
-              request-prompt (Object.)
               read-error (Object.)
+              execute (partial execute-with-client connection
+                               (assoc options :interactive true))
               [raw-input read-result]
                 (try
                   (binding [*ns* (eval-state/get-ns)]
-                    (repl-parse request-prompt eof read-error
-                                (partial execute-with-client connection
-                                         (assoc options :interactive true))))
+                    (repl-parse eof execute))
                   (catch Exception e
                     [e read-error]))]
           (cond (reply.exit/done? eof read-result)
                   nil
-                (= request-prompt read-result)
-                  (recur ns)
                 (= read-error read-result)
                   (do (println raw-input) ; where we stash any read exceptions
                       (recur ns))
                 :else
+                  ; TODO: expect result as seq of forms to consume and eval on this side
                   (recur (:ns read-result))))))))

 ;; TODO: this could be less convoluted if we could break backwards-compat


document the rationale behind `clojure.browser.repl/bootstrap` implementation

--- src/cljs/clojure/browser/repl.cljs
+++ src/cljs/clojure/browser/repl.cljs
@@ -122,6 +122,10 @@
     (set! (.-isProvided_ js/goog) (fn [name] false))
     (set! (.-writeScriptTag__ js/goog)
       (fn [src opt_sourceText]
+        ;; the page is already loaded, we can no longer leverage document.write
+        ;; instead construct script tag elements and append them to the body
+        ;; of the page, to avoid parallel script loading enforce sequential
+        ;; load with a simple load queue
         (let [loaded (atom false)
               onload (fn []
                        (when (and load-queue (false? @loaded))
@@ -130,14 +134,15 @@
                            (set! load-queue nil)
                            (.apply js/goog.writeScriptTag__ nil (.shift load-queue)))))]
           (.appendChild js/document.body
-           (as-> (.createElement js/document "script") script
-             (doto script
-               (aset "type" "text/javascript")
-               (aset "onload" onload)
-               (aset "onreadystatechange" onload))
-             (if (nil? opt_sourceText)
-               (doto script (aset "src" src))
-               (doto script (gdom/setTextContext opt_sourceText))))))))
+            (as-> (.createElement js/document "script") script
+              (doto script
+                (aset "type" "text/javascript")
+                (aset "onload" onload)
+                (aset "onreadystatechange" onload)) ;; IE
+              (if (nil? opt_sourceText)
+                (doto script (aset "src" src))
+                (doto script (gdom/setTextContext opt_sourceText))))))))
+    ;; queue or load
     (set! (.-writeScriptTag_ js/goog)
       (fn [src opt_sourceText]
         (if load-queue
@@ -145,6 +150,8 @@
           (do
             (set! load-queue #js [])
             (js/goog.writeScriptTag__ src opt_sourceText)))))
+    ;; we must reuse Closure library dev time dependency management, under namespace
+    ;; reload scenarios we simply delete entries from the correct private locations
     (set! (.-require js/goog)
       (fn [src reload]
         (when (= reload "reload-all")


Refactor examples frontend

Refactor examples frontend

--- src/cljs/clojuredocs/examples.cljs
+++ src/cljs/clojuredocs/examples.cljs
@@ -8,88 +8,198 @@
             [clojure.string :as str]
             [cljs.reader :as reader]
             [sablono.core :as sab :refer-macros [html]]
-            [clojuredocs.util :as util])
+            [clojuredocs.util :as util]
+            [clojuredocs.schemas :as schemas]
+            [clojure.data :refer [diff]])
   (:require-macros [dommy.macros :refer [node sel1]]))

-(defn validate-and-submit [owner {:keys [text var]}]
+(defn client-call [comp context payload success error]
+  (let [{:keys [api-root]} comp
+        {:keys [http-method]} (-> comp :contexts context)]
+    (ajax
+      {:path (str "/api" api-root)
+       :method http-method
+       :data-type :edn
+       :data payload
+       :success success
+       :error error})))
+
+(defn validate-and-submit [app owner payload]
   (om/set-state! owner :loading? true)
   (om/set-state! owner :error-message nil)
-  (ajax
-    {:path "/api/examples"
-     :method :post
-     :data-type :edn
-     :data {:body text
-            :var var}
-     :success (fn []
-                (.reload js/location))
-     :error (fn [{:keys [status body]}]
-              (om/set-state! owner :loading? false)
-              (cond
-                (= 422 status)
-                (om/set-state! owner :error-message (:error-message body))
-
-                :else
-                (om/set-state! owner :error-message "There was a problem contacting the server.")))})
-  false)
-
-(defn set-expanded [owner expanded?]
-  (om/set-state! owner :expanded? expanded?)
-  (om/set-state! owner :should-focus? true)
-  false)
-
-(defn update-text [e owner]
-  (om/set-state! owner :text (.. e -target -value))
-  false)
-
-(defn cancel-clicked [e owner]
-  (set-expanded owner (not (om/get-state owner :expanded?)))
-  (om/set-state! owner :text nil)
-  false)
-
-(defn $toggle-controls [owner {:keys [expanded?]}]
+  (client-call schemas/ExampleComp :create
+    (-> payload
+        (update-in [:var] #(select-keys % [:ns :name :library-url]))
+        (assoc :history []))
+    (fn [data]
+      (om/transact! app (fn [app]
+                          (update-in app [:examples] (fn [es] (vec
+                                                                (concat
+                                                                  es
+                                                                  [(assoc (:body data)
+                                                                     :new? true)]))))))
+      (om/set-state! owner :loading? false)
+      (om/set-state! owner :text nil)
+      (om/set-state! owner :expanded? false))
+    (fn [{:keys [status body]}]
+      (om/set-state! owner :loading? false)
+      (cond
+        (= 422 status)
+        (om/update-state! owner #(merge % body))
+
+        :else
+        (om/set-state! owner :error-message "There was a problem contacting the server."))))
+  false)
+
+(defn update-example [{:keys [_id var]} owner text]
+  (om/set-state! owner :loading? true)
+  (om/set-state! owner :error-message nil)
+  (client-call schemas/ExampleComp :update
+    {:var (select-keys var [:ns :name :library-url])
+     :example-id _id
+     :body text}
+    (fn [data]
+      (om/transact! app (fn [app]
+                          (update-in app [:examples] (fn [es] (concat es [(assoc (:body data)
+                                                                            :new? true)])))))
+      (om/set-state! owner :loading? false)
+      (om/set-state! owner :text nil)
+      (om/set-state! owner :expanded? false))
+    (fn [{:keys [status body]}]
+      (om/set-state! owner :loading? false)
+      (cond
+        (= 422 status)
+        (om/update-state! owner #(merge % body))
+
+        :else
+        (om/set-state! owner :error-message "There was a problem contacting the server."))))
+  false)
+
+(defn update-text [e owner on-text]
+  (let [new-text (.. e -target -value)]
+    (om/set-state! owner :text new-text)
+    (when on-text (on-text new-text)))
+  false)
+
+(defn cancel-clicked [e example]
+  (om/update! example [:editing?] false)
+  false)
+
+(defn $toggle-controls [{:keys [editing?] :as example}]
   [:div.toggle-controls
-   [:a.toggle-link {:href "#" :on-click #(set-expanded owner (not expanded?))}
-    (if-not expanded? "Add an Example" "Collapse")]])
-
-(defn $editor [{:keys [var]} owner {:keys [expanded? text loading? error-message] :as state}]
-  [:div {:class (str "add-example-content" (when-not expanded? " hidden"))}
-   [:h5 "New Example"]
-   [:div.add-example-preview
-    [:div.live-preview {:ref "live-preview"}]]
-   [:form
-    {:on-submit #(validate-and-submit
-                   owner
-                   {:body text
-                    :var var})}
-    [:textarea
-     {:class "form-control"
-      :cols 80 :on-input #(update-text % owner)
-      :ref "textarea"
-      :disabled (when loading? "disabled")}]
-    [:p.instructions
-     "See our "
-     [:a {:href "/examples-styleguide"} "examples style guide"]
-     " for content and formatting guidelines. "
-     "Examples submitted to ClojureDocs are licensed under the "
-     [:a {:href "https://creativecommons.org/publicdomain/zero/1.0/"}
-      "Creative Commons CC0 license"]
-     "."]
-    (when error-message
-      [:div.form-group
-       [:div.error-message.text-danger
-        [:i.fa.fa-exclamation-circle]
-        error-message]])
-    [:div.add-example-controls.form-group.clearfix
-     [:button.btn.btn-default
-      {:disabled (when loading? "disabled")
-       :on-click #(cancel-clicked % owner)}
-      "Cancel"]
-     [:button.btn.btn-success.pull-right
-      {:disabled (when loading? "disabled")}
-      "Add Example"]
-     [:img.loading.pull-right
-      {:class (when-not loading? " hidden")
-       :src "/img/loading.gif"}]]]])
+   [:a.toggle-link {:href "#"
+                    :on-click (fn []
+                                (om/transact!
+                                  example
+                                  #(assoc %
+                                     :editing? (not editing?)
+                                     :should-focus? true))
+                                false)}
+    (if-not editing? "Add an Example" "Collapse")]])
+
+(defn $editor [{:keys [var body loading?] :as app} owner]
+  (reify
+    om/IInitState
+    (init-state [_]
+      {:text body})
+    om/IDidMount
+    (did-mount [_]
+      (dommy/append!
+        (om/get-node owner "live-preview")
+        (node [:div.empty-live-preview "Live Preview"]))
+      (update-preview owner)
+      (dommy/set-value!
+        (om/get-node owner "textarea")
+        (om/get-state owner :text)))
+
+    om/IDidUpdate
+    (did-update [this prev-props prev-state]
+      (let [{:keys [should-focus? expanded? text]} (om/get-state owner)]
+        (when (and should-focus? expanded?)
+          (om/set-state! owner :should-focus? false)
+          (.focus (om/get-node owner "textarea"))))
+      (update-preview owner))
+
+    om/IRenderState
+    (render-state [_ {:keys [text on-text]}]
+      (html
+        [:div.example-editor
+         [:div.live-preview {:ref "live-preview"}]
+         [:textarea
+          {:class "form-control"
+           :cols 80 :on-input #(update-text % owner on-text)
+           :ref "textarea"
+           :disabled (when loading? "disabled")}]
+         [:p.instructions
+          "See our "
+          [:a {:href "/examples-styleguide"} "examples style guide"]
+          " for content and formatting guidelines. "
+          "Examples submitted to ClojureDocs are licensed under the "
+          [:a {:href "https://creativecommons.org/publicdomain/zero/1.0/"}
+           "Creative Commons CC0 license"]
+          "."]]))))
+
+(defn $add-example-editor [{:keys [var loading? body] :as example} owner]
+  (reify
+    om/IRenderState
+    (render-state [_ {:keys [error-message] :as state}]
+      (html
+        [:div.add-example-content
+         [:h5 "New Example"]
+         [:form
+          {:on-submit #(validate-and-submit
+                         example
+                         owner
+                         {:body body
+                          :var @var})}
+          (om/build $editor example {:init-state {:on-text #(om/update! example [:body] %)} :state state})
+          (when error-message
+            [:div.form-group
+             [:div.error-message.text-danger
+              [:i.fa.fa-exclamation-circle]
+              error-message]])
+          [:div.add-example-controls.form-group.clearfix
+           [:button.btn.btn-default
+            {:disabled (when loading? "disabled")
+             :on-click #(cancel-clicked % example)}
+            "Cancel"]
+           [:button.btn.btn-success.pull-right
+            {:disabled (when loading? "disabled")}
+            "Add Example"]
+           [:img.loading.pull-right
+            {:class (when-not loading? " hidden")
+             :src "/img/loading.gif"}]]]]))))
+
+(defn $update-example-editor [{:keys [var loading? body] :as example} owner]
+  (reify
+    om/IRenderState
+    (render-state [_ {:keys [error-message text] :as state}]
+      (html
+        [:div.add-example-content
+         [:h5 "Edit Example"]
+         [:form
+          {:on-submit #(validate-and-submit
+                         example
+                         owner
+                         {:body body
+                          :var @var})}
+          (om/build $editor example {:init-state {:on-text #(om/set-state! owner text %)} :state state})
+          (when error-message
+            [:div.form-group
+             [:div.error-message.text-danger
+              [:i.fa.fa-exclamation-circle]
+              error-message]])
+          [:div.add-example-controls.form-group.clearfix
+           [:button.btn.btn-default
+            {:disabled (when loading? "disabled")
+             :on-click #(cancel-clicked % example)}
+            "Cancel"]
+           [:button.btn.btn-success.pull-right
+            {:disabled (when loading? "disabled")}
+            "Update Example"]
+           [:img.loading.pull-right
+            {:class (when-not loading? " hidden")
+             :src "/img/loading.gif"}]]]]))))

 (defn update-preview [owner]
   (let [text (om/get-state owner :text)
@@ -106,81 +216,156 @@
           (catch js/Error e (prn "Error highlighting example"))))
       (dommy/append! preview (node [:div.empty-live-preview "Live Preview"])))))

-(defn $add [app owner]
+(defn $add [{:keys [editing? should-focus?] :as example} owner]
+  (reify
+    om/IDidUpdate
+    (did-update [this prev-props prev-state]
+      (when (and should-focus? editing?)
+        (om/transact! example #(assoc % :should-focus? false))
+        (anim/scroll-to (om/get-node owner "wrapper") {:pad 10})))
+    om/IRenderState
+    (render-state [this {:keys [text loading?] :as state}]
+      (sab/html
+        [:div.add-example {:ref "wrapper"}
+         ($toggle-controls example)
+         [:div.add-example-content {:class (when-not editing? " hidden")}
+          (om/build $add-example-editor example {:state state})]]))))
+
+(defn user-can-delete? [user {:keys [author]}]
+  (= (select-keys user [:login :account-source])
+     (select-keys author [:login :account-source])))
+
+(defn update-example-body [owner {:keys [body]}]
+  (let [el (om/get-node owner "example-body")
+        pre (node [:pre.raw-example {:class "brush: clojure"}
+                   body])]
+    (dommy/clear! el)
+    (dommy/append! el pre)
+    (try
+      (.highlight js/SyntaxHighlighter pre)
+      ;; Not handling this error prevents subsequent
+      ;; highlights from succeeding
+      (catch js/Error e (prn "Error highlighting example")))))
+
+(defn delete-example [owner ex del-fn]
+  (om/set-state! owner :delete-state :loading)
+  (ajax
+    {:path (str "/api/examples")
+     :method :delete
+     :data-type :edn
+     :data @ex
+     :success (fn [data]
+                (om/set-state! owner :delete-state :none)
+                (del-fn @ex))
+     :error (fn [resp]
+              (om/set-state! owner :delete-state :error))})
+  false)
+
+(defn $example-meta [{:keys [editing? author editors can-delete?] :as ex} owner]
+  (reify
+    om/IRenderState
+    (render-state [_ {:keys [delete-ex delete-state]}]
+      (let [authors (distinct
+                      (concat
+                        [author]
+                        editors))
+            num-to-show 7]
+        (html
+          [:div.example-meta
+           [:div.contributors
+            (->> authors
+                 (take num-to-show)
+                 (map util/$avatar))
+            (when (> (count authors) num-to-show)
+              [:div.contributors
+               "+ "
+               (- (count authors) num-to-show)
+               " more"])]
+           [:div.links
+            [:a {:href (str "#example_" _id)}
+             "permalink"]
+            " / "
+            [:a {:href (str "/ex/" _id)}
+             "history"]
+            " / "
+            (if editing?
+              [:a {:href "#"
+                   :on-click #(do
+                                (om/update! ex [:editing?] false)
+                                false)}
+               "cancel edit"]
+              [:a {:href "#"
+                   :on-click #(do
+                                (om/update! ex [:editing?] true)
+                                false)}
+               "edit"])
+            (when (and can-delete? (not editing?))
+              [:span
+               " / "
+               (if (get #{:confirm :loading} delete-state)
+                 (if (= :loading delete-state)
+                   [:img.loading {:src "/img/loading.gif"}]
+                   [:span
+                    [:a {:href "#"
+                         :on-click #(do
+                                      (om/set-state! owner :delete-state :none)
+                                      false)}
+                     "cancel"]
+                    " | "
+                    [:a {:href "#"
+                         :on-click #(delete-example owner ex delete-ex)}
+                     "confirm delete?"]
+                    ])
+                 [:span
+                  {:class (when (= :error delete-state) "error-deleting bg-danger")}
+                  [:a {:href "#"
+                       :on-click #(do
+                                    (om/set-state! owner :delete-state :confirm)
+                                    false)}
+                   "delete"]])])
+            [:span.edit-example-widget]]])))))
+
+(defn $example-body [ex owner]
   (reify
     om/IDidMount
     (did-mount [_]
-      (dommy/append!
-        (om/get-node owner "live-preview")
-        (node [:div.empty-live-preview "Live Preview"]))
-      (update-preview owner)
-      (dommy/set-value!
-        (om/get-node owner "textarea")
-        (om/get-state owner :text)))
-
+      (update-example-body owner ex))
     om/IDidUpdate
-    (did-update [this prev-props prev-state]
-      (let [{:keys [should-focus? expanded? text]} (om/get-state owner)]
-        (when (and should-focus? expanded?)
-          (om/set-state! owner :should-focus? false)
-          (.focus (om/get-node owner "textarea"))
-          (anim/scroll-to (om/get-node owner "wrapper") {:pad 10})))
-      (update-preview owner))
-
-    om/IRenderState
-    (render-state [this {:keys [expanded? text loading?] :as state}]
-      (sab/html
-        [:div.add-example {:ref "wrapper"}
-         ($toggle-controls owner state)
-         ($editor app owner state)]))))
-
-(defn $example-body [{:keys [body]}]
-  [:div.example-body
-   [:pre.raw-example {:class "brush: clojure"} body]])
-
-(defn $example [{:keys [body _id user history created-at updated-at] :as ex}]
-  [:div.var-example
-   [:div
-    (let [users (distinct
-                  (concat
-                    [user]
-                    (->> history
-                         (map :user)
-                         reverse)))
-          num-to-show 7]
-      [:div.example-meta
-       [:div.contributors
-        (->> users
-             (take num-to-show)
-             (map util/$avatar))
-        (when (> (count users) 10)
-          [:div.contributors
-           "+ "
-           (- (count users) num-to-show)
-           " more"])]
-
-       [:div.links
-        [:a {:href (str "#example_" _id)}
-         "permalink"]
-        " / "
-        [:a {:href (str "/ex/" _id)}
-         "history"]
-        [:span.edit-example-widget]]])]
-   [:div
-    [:a {:id (str "example_" _id)}]
-    ($example-body ex)]])
-
-(defn $examples [{:keys [examples var user] :as app} owner]
-  (reify
+    (did-update [_ _ _]
+      (update-example-body owner ex))
     om/IRender
     (render [_]
-      (sab/html
+      (html
+        [:div.example-body {:ref "example-body" :class (when new? "just-created")}]))))
+
+(defn $example [{:keys [editing? body _id author history created-at updated-at new? can-delete?] :as ex} owner]
+  (reify
+    om/IRenderState
+    (render-state [_ {:keys [delete-ex]}]
+      (html
+        [:div.var-example
+         [:a {:id (str "example_" _id)}]
+         [:div
+          (om/build $example-meta ex {:init-state {:delete-ex delete-ex}})]
+         (if editing?
+           (om/build $update-example-editor ex)
+           (om/build $example-body ex))]))))
+
+(defn $examples [{:keys [examples var user] :as app} owner]
+  (reify
+    om/IRenderState
+    (render-state [_ {:keys [delete-ex]}]
+      (html
         [:div.var-examples
          [:h5 (util/pluralize (count examples) "Example" "Examples")]
          (if (empty? examples)
            [:div.null-state
             "No examples for " (:ns var) "/" (:name var) "."]
-           (map $example examples))
+           (om/build-all
+             $example
+             (->> (:examples app)
+                  (map #(assoc % :can-delete? (user-can-delete? user %))))
+             {:init-state {:delete-ex delete-ex}}))
          (if user
            (om/build $add app)
            [:div.login-required-message


Update to new log rotor

Update to new log rotor

--- src/com/frereth/server/logging.clj
+++ src/com/frereth/server/logging.clj
@@ -1,8 +1,8 @@
 (ns com.frereth.server.logging
-  (require [com.postspectacular.rotor :as rotor]
-           [com.stuartsierra.component :as component]
+  (require [com.stuartsierra.component :as component]
            [taoensso.timbre :as log
-            :refer (trace debug info warn error fatal spy with-log-level)]))
+            :refer (trace debug info warn error fatal spy with-log-level)]
+           [taoensso.timbre.appenders.3rd-party.rotor :as rotor]))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Schema
@@ -12,17 +12,10 @@

   (start
     [this]
-    (log/set-config!
-     [:appenders :rotor]
-     {:doc "Writes to (:path (:rotor :shared-appender-config)) file and creates optional backups"
-      :min-level :trace
-      :enabled? true
-      :async? false
-      :max-message-per-msecs nil
-      :fn rotor/append})
-    (log/set-config!
-     [:shared-appender-config :rotor]
-     {:path "logs/app.log" :max-size (* 512 1024) :backlog 5})
+    (log/merge-config!
+     {:appenders {:rotor (rotor/rotor-appender {:path "logs/app.log"
+                                                :max-size (* 512 1024)
+                                                :backlog 5})}})
     (log/warn "FIXME: Log to a database instead")
     this)


Ignore abstract classes in item 10 checks

--- src/app/itemsOnLifecycle.clj
+++ src/app/itemsOnLifecycle.clj
@@ -212,7 +212,8 @@

 (defn does-not-override-toString-but-should? [classes class]
   (and (not (hierarchy-overrides-toString? classes class))
-       (not (isUtilClass? class))))
+       (not (isUtilClass? class))
+       (not (isAbstract? class))))

 (defn classes-that-do-not-override-toString-but-should
   "Item 10 of Effective Java recommends that all classes should override


Define deftest-db to do async testing with an open DB.

--- src/datomish/test_macros.cljc
+++ src/datomish/test_macros.cljc
@@ -4,7 +4,9 @@

 (ns datomish.test-macros
   #?(:cljs
-     (:require-macros [datomish.test-macros]))
+     (:require-macros
+        [datomish.test-macros]
+        [datomish.node-tempfile-macros]))
   (:require
    [datomish.pair-chan]))

@@ -38,3 +40,20 @@
        (let [[v# e#] (clojure.core.async/<!! (datomish.pair-chan/go-pair ~@body))]
          (when e# (throw e#)) ;; Assert nil just to be safe, even though we should always throw first.
          (clojure.test/is (= e# nil))))))
+
+(defmacro deftest-db
+  [n conn-var & body]
+  `(deftest-async ~n
+    (if-cljs
+      (datomish.node-tempfile-macros/with-tempfile [t# (datomish.node-tempfile/tempfile)]
+         (let [~conn-var (datomish.pair-chan/<? (datomish.api/<connect t#))]
+           (try
+             ~@body
+             (finally
+               (datomish.pair-chan/<? (datomish.api/<close ~conn-var))))))
+      (tempfile.core/with-tempfile [t# (tempfile.core/tempfile)]
+       (let [~conn-var (datomish.pair-chan/<? (datomish.api/<connect t#))]
+         (try
+           ~@body
+           (finally
+             (datomish.pair-chan/<? (datomish.api/<close ~conn-var)))))))))


Fix parsing notabenoid

Fix parsing notabenoid

--- src/clj/subman/sources/notabenoid.clj
+++ src/clj/subman/sources/notabenoid.clj
@@ -110,4 +110,5 @@
         (html/select <> [:ul.search-results :li :p :a])
         (map (helpers/make-safe book-from-line nil))
         (remove nil?)
+        (map episodes-from-book)
         flatten))


Rename draw-selection to draw-selection-outline

--- src/cljs/goya/components/drawing.cljs
+++ src/cljs/goya/components/drawing.cljs
@@ -246,7 +246,7 @@
     (om/set-state! owner :selection-image (clip-sub-image main-image selection-rect doc-width))))

-(defn draw-selection [app owner]
+(defn draw-selection-outline [app owner]
    (let [preview-context (.getContext preview-canvas-elem "2d")
          [x1 y1 x2 y2] (om/get-state owner :selection)
          zoom-factor (get-in app [:zoom-factor])]
@@ -464,7 +464,7 @@
       (did-update [_ _ _]
           (clear-preview-canvas)
           (when (= (get-in app [:tools :paint-tool]) :selection)
-            (draw-selection app owner)))
+            (draw-selection-outline app owner)))

     om/IWillMount
     (will-mount [_]


Trying to get systems working again.

Trying to get systems working again.

--- src/numerics/runge_kutta.clj
+++ src/numerics/runge_kutta.clj
@@ -49,27 +49,17 @@

 (defn f [[x y]] (- (* 4.0 (Math/exp (* 0.8 x))) (* 0.5 y)))
-;;This is wrong and needs fixing.
-(prn (ks [f] [0 2] 2.0 tableaus/cash-karp))
-
-(def c (tableaus/cash-karp :c))
-(def a (tableaus/cash-karp :a))
-
-(def tn 0.0)
-(def yn 2.0)
-(def dt 2.0)
-;(def ks (or (peek k) (repeat 0)))
-;(def y (vec (map + yn (map (fn [k] (* dt (reduce + (map #(* % k) (first ai))))) ks))))

 ;; http://en.wikipedia.org/wiki/List_of_Runge–Kutta_methods
 (prn "YYYYYYYYY")
-(defn ki [f [tn yn] dt a c K]
-  (let [ys (+ yn (* dt (reduce + (map * a K))))]
+(defn ki [f [tn yn] dt a c k]
+  (let [ys (+ yn (* dt (reduce + (map * a k))))]
     (f (into [(+ tn (* dt c))] [ys]))))

-(def kk (loop [ks [] ai a ci c]
-  (if-not (first ci)
-    ks
-    (recur (conj ks (ki f [tn yn] dt (first ai) (first ci) ks)) (rest ai) (rest ci)))))
+(defn ks1 [f [tn yn] dt { :keys [a c] }]
+  (loop [ks [] ai a ci c]
+    (if-not (first ci)
+      ks
+      (recur (conj ks (ki f [tn yn] dt (first ai) (first ci) ks)) (rest ai) (rest ci)))))

-(prn kk)+(prn (ks1 f [0 2] 2 tableaus/cash-karp))


badge name in quotes

badge name in quotes

--- src/cljs/salava/social/ui/stream.cljs
+++ src/cljs/salava/social/ui/stream.cljs
@@ -96,7 +96,7 @@
   (if (:badge-alert @state)
     [:div {:class "alert alert-success"}
      (case (:badge-alert @state)
-       "accepted"  [:div (str (t :badge/Youhaveaccepted) " " (:badge-name @state)". ") (t :badge/Youcanfind)]
+       "accepted"  [:div (str (t :badge/Youhaveaccepted) " \"" (:badge-name @state) "\". ") (t :badge/Youcanfind)]
        "declined" (t :badge/Badgedeclined)
        "")]))


Minify fns

Minify fns

--- src/discuss/utils/common.cljs
+++ src/discuss/utils/common.cljs
@@ -163,10 +163,8 @@

 (defn loading?
   "Return boolean if app is currently loading content. Provide a boolean to change the app-state."
-  ([]
-   (get-in @app-state [:layout :loading?]))
-  ([bool]
-   (update-state-item! :layout :loading? (fn [_] bool))))
+  ([] (get-in @app-state [:layout :loading?]))
+  ([bool] (update-state-item! :layout :loading? (fn [_] bool))))

 (defn update-all-states!
   "Update item list with the data provided by the API.
@@ -187,10 +185,8 @@
 ;; Show error messages
 (defn error?
   "Return boolean indicating if there are errors or not. Provide a boolean to change the app-state."
-  ([]
-   (get-in @app-state [:layout :error?]))
-  ([bool]
-   (update-state-item! :layout :error? (fn [_] bool))))
+  ([] (get-in @app-state [:layout :error?]))
+  ([bool] (update-state-item! :layout :error? (fn [_] bool))))

 (defn error-msg!
   "Set error message."


Fixing a failing test.

Fixing a failing test.

--- src/cmr/search/api/search_results.clj
+++ src/cmr/search/api/search_results.clj
@@ -32,7 +32,7 @@
   [mime-type]
   (when-not (mime-type->format mime-type)
     (errors/throw-service-error
-      :bad-request "The mime type [%s] is not supported for search results." mime-type)))
+      :bad-request (format "The mime type [%s] is not supported for search results." mime-type))))

 (defmulti search-results->response
   (fn [results result-type]


beef up nth-diatonic docstring

beef up nth-diatonic docstring

--- src/overtone/music/pitch.clj
+++ src/overtone/music/pitch.clj
@@ -121,9 +121,20 @@
      :lochrian   (rotate-ionian 6)}))

 (defn nth-diatonic
-  "Return the count of semitones for the nth interval from the start of the diatonic scale in the specifiec mode (or ionian/major by default).
+  "Return the count of semitones for the nth degree from the start of the diatonic scale in the specifiec mode (or ionian/major by default).
      i.e. the ionian/major scale has an interval sequence of 2 2 1 2 2 2 1
-          therefore the 4th interval is (+ 2 2 1 2) semitones from the start of the scale."
+          therefore the 4th degree is (+ 2 2 1 2) semitones from the start of the scale.
+
+  You may be interested to know that each of the seven degrees of the diatonic scale has its own name:
+
+  1 (do)  tonic
+  2 (re)  supertonic
+  3 (mi)  mediant
+  4 (fa)  subdominant
+  5 (sol) dominant
+  6 (la)  submediant/superdominant
+  7 (ti)  subtonic"
+
   ([n] (nth-diatonic n :ionian))
   ([n mode]
      (reduce + (take n (cycle (mode DIATONIC-MODES))))))


add our name and Logo icon to the webhook

--- src/pc/http/integrations.clj
+++ src/pc/http/integrations.clj
@@ -10,7 +10,9 @@
                 (str "Precursor document " (:db/id doc))
                 (:document/name doc))]
     (slack/queue-slack-webhook slack-hook
-                               {:attachments [(merge {:fallback title
+                               {:username "Precursor"
+                                :icon_url "https://dtwdl3ecuoduc.cloudfront.net/img/precursor-logo.png"
+                                :attachments [(merge {:fallback title
                                                       :title title
                                                       :title_link (urls/from-doc doc)
                                                       :image_url (urls/svg-from-doc doc


Extend cookies max-age from 7 days to 365 days

--- src/braid/server/handler.clj
+++ src/braid/server/handler.clj
@@ -25,6 +25,8 @@
             ; requiring so mount sees state
             [braid.server.email-digest :refer [email-jobs]]))

+(def session-max-age (* 60 60 24 365))
+
 ; NOT using config here, b/c it won't have started when this runs
 (if (= (env :environment) "prod")
   (do
@@ -34,7 +36,7 @@
                                         :port 6379}})
     (let [carmine-store (ns-resolve 'taoensso.carmine.ring 'carmine-store)]
       (def session-store
-        (carmine-store '*redis-conf* {:expiration-secs (* 60 60 24 7)
+        (carmine-store '*redis-conf* {:expiration-secs session-max-age
                                       :key-prefix "braid"}))))
   (do
     (require 'ring.middleware.session.memory)
@@ -45,7 +47,7 @@
   (-> defaults
       (assoc-in [:session :cookie-name] "braid")
       (assoc-in [:session :cookie-attrs :secure] false #_(= (env :environment) "prod"))
-      (assoc-in [:session :cookie-attrs :max-age] (* 60 60 24 7))
+      (assoc-in [:session :cookie-attrs :max-age] session-max-age)
       (assoc-in [:session :store] session-store)))

 (defn assoc-csrf-conf [defaults]


Removed superflous debug println from jobs.clj

--- src/engulf/web_views/jobs.clj
+++ src/engulf/web_views/jobs.clj
@@ -37,7 +37,6 @@
 (na/defpage-async [:post "/jobs/current"] {} conn
   (try
     (let [params (walk/keywordize-keys (json/parse-string (na/request-body-str conn)))
-          _ (println "GOT PARAMS" params)
           {:keys [results-ch job]} (ctrl/start-job params)]
       (if (= (:_stream params) "true")
         (async-stream conn results-ch)


Add feature to complete a project

Add feature to complete a project

--- src/front/ui/viewport/project.cljs
+++ src/front/ui/viewport/project.cljs
@@ -30,6 +30,11 @@
   (state/update-project! project
                          :description description))

+(defn- project-done
+  [project]
+  (state/update-project! project
+                         :done true))
+
 (defn- render-empty-project
   []
   [:div.empty-project
@@ -46,7 +51,8 @@
        {:class (if (:today project)
                  "name today"
                  "name")}
-       [:div.input]
+       [:div.input.check-box
+        {:on-click #(project-done project)}]
        [:div.project-name
         (:name project)]]
       [:div.tags


Refactor a bit

Refactor a bit

--- src/fp_contest_solution_tree/core.clj
+++ src/fp_contest_solution_tree/core.clj
@@ -60,22 +60,20 @@
   (let [feature (first (first answers))]
     (println "What is the value of feature: " feature "?")
     (let [indexed-answers (print-answers answers)]
-      #_(println "Indexed-answers" indexed-answers)
       (println "0. Nothing of the kind" )
       (print "Answer (number of the option): ")
       (flush)
       (let [cr (ConsoleReader.)
-            users-choise (.readLine cr)]
+            user-choise (.readLine cr)]
         (try
-          (let [answer-number (Integer/parseInt users-choise)]
+          (let [answer-number (Integer/parseInt user-choise)]
             (if-let [answer (indexed-answers answer-number)]
               answer
               (throw (IllegalStateException. (str "Subject don't corresponds any of options for feature: " feature)))))
           (catch NumberFormatException e
             (do (println "Please, choose right option from answers. Try one more time")
                 (ask-question answers))))
-        )))
-  )
+        ))))

 (defn answers [tree]
   (into #{}


fix insert query so you can enter mounts

--- src/clj/apollo/db/schema.clj
+++ src/clj/apollo/db/schema.clj
@@ -126,9 +126,11 @@
       {:id (insert-track! cn track-info scan-date) :action :insert})))

 (defn insert-mount! [cn p]
-  (jdbc/execute! cn (-> (h/insert-into :mounts)
-                     (h/values {:path p})
-                     (sql/format))))
+  (let [q (-> (h/insert-into :mounts)
+              (h/columns :path)
+              (h/values [[p]])
+              (sql/format))]
+    (jdbc/execute! cn q)))

 (defn delete-mount!
   "returns rows effected which should be > 1 if successful"


reimplement stay-then-continue and continue-then-stay in terms of multi-path

--- src/clj/com/rpl/specter.cljx
+++ src/clj/com/rpl/specter.cljx
@@ -240,31 +240,6 @@
                 ancestry))
       )))

-(defn stay-then-continue
-  "Navigates to the current element and then navigates via the provided path.
-   This can be used to implement pre-order traversal."
-  [& path]
-  (fixed-pathed-path [late path]
-    (select* [this structure next-fn]
-      (concat (next-fn structure)
-              (doall (mapcat next-fn (compiled-select late structure)))))
-    (transform* [this structure next-fn]
-      (compiled-transform late next-fn (next-fn structure))
-      )))
-
-(defn continue-then-stay
-  "Navigates to the provided path and then to the current element. This can be used
-   to implement post-order traversal."
-  [& path]
-  (fixed-pathed-path [late path]
-    (select* [this structure next-fn]
-      (concat (doall (mapcat next-fn (compiled-select late structure)))
-              (next-fn structure)))
-    (transform* [this structure next-fn]
-      (next-fn (compiled-transform late next-fn structure))
-      )))
-
-
 (defpath keypath [key]
   (select* [this structure next-fn]
     (next-fn (get structure key)))
@@ -445,3 +420,15 @@
         structure
         compiled-paths
         ))))
+
+(defn stay-then-continue
+  "Navigates to the current element and then navigates via the provided path.
+   This can be used to implement pre-order traversal."
+  [& path]
+  (multi-path STAY path))
+
+(defn continue-then-stay
+  "Navigates to the provided path and then to the current element. This can be used
+   to implement post-order traversal."
+  [& path]
+  (multi-path path STAY))


add evidences to pdf

add evidences to pdf

--- src/clj/salava/badge/pdf.clj
+++ src/clj/salava/badge/pdf.clj
@@ -110,6 +110,8 @@
                                                                 (when-not (empty? $tags)
                                                                   [:paragraph.generic
                                                                    [:chunk.chunk (str (t :badge/Tags ul)": ")] (into [:phrase ] (for [t $tags] (str t " ")))])
+
+
                                                                 [:paragraph
                                                                  (let [alignments (replace-nils (select-alignment-content {:badge_content_id (:badge_content_id %)} (u/get-db ctx)))]
                                                                    (when-not (empty? alignments)
@@ -127,6 +129,20 @@

                                                                  [:spacer 0]
                                                                  (process-markdown (:criteria_content %) $id "Criteria")]]
+
+                                                               (when-not (empty? $evidences)
+                                                                 [:paragraph.generic
+                                                                  [:spacer 0]
+                                                                  [:phrase {:size 12 :style :bold} (if (= 1 (count $evidences)) (t :badge/Evidence ul) (t :badge/Evidences ul))]
+                                                                  [:spacer]
+                                                                  (reduce (fn [r evidence]
+                                                                            (conj r [:phrase
+                                                                                (when (and (not (blank? (:name evidence))) (not= "-" (:name evidence))) [:phrase [:chunk (:name evidence)]"\n"])
+                                                                                (when (and (not (blank? (:narrative evidence))) (not= "-" (:narrative evidence)))  [:phrase [:chunk (:narrative evidence)] "\n"])
+                                                                                (when (and (not (blank? (:description evidence))) (not= "-" (:description evidence))) [:phrase [:chunk (:description evidence)]"\n"])
+                                                                                [:anchor {:target (:url evidence)} [:chunk.link (str (t :badge/Openevidencepage ul) "...")]]
+                                                                                [:spacer 2]])
+                                                                            ) [:list {:numbered true :indent 0}] $evidences)])

                                                                (when-not (empty? $endorsements)
                                                                  [:paragraph.generic


Run migrations with uberjar build

Run migrations with uberjar build

--- src/clj/salava/core/main.clj
+++ src/clj/salava/core/main.clj
@@ -1,6 +1,9 @@
 (ns salava.core.main
   (:gen-class)
-  (:require [salava.core.system]))
+  (:require [salava.core.system]
+            [salava.core.migrator :refer [migrate]]))

 (defn -main [& args]
-  (salava.core.system/start-base-system))
+  (if (= "migrate" (first args))
+    (migrate false)
+    (salava.core.system/start-base-system)))


return id for created docker user

return id for created docker user

--- src/clj/swarmpit/handler.clj
+++ src/clj/swarmpit/handler.clj
@@ -327,7 +327,7 @@
       (api/dockeruser-login payload)
       (let [response (api/create-dockeruser payload user-info)]
         (if (some? response)
-          (resp-created)
+          (resp-created (select-keys response [:id]))
           (resp-error 400 "Docker user already exist"))))))

 (defmethod dispatch :dockerhub-user-delete [_]


fix link on the front page

fix link on the front page

--- src/clj/yambox/templates.clj
+++ src/clj/yambox/templates.clj
@@ -64,7 +64,7 @@
                "Собираете деньги на добрые дела? Добро должно быть открытым."
                [:p
                 [:a.btn.btn-default
-                 {:href "/management/create-campaign"}
+                 {:href "/management/"}
                  "Я тоже так считаю"]]]
               [:div.copyright
                "Image by "
@@ -132,7 +132,7 @@
                           :scrolling "no"}]
                 [:p
                  [:a.btn.btn-default
-                  {:href "/management/create-campaign"}
+                  {:href "/management/"}
                   "Хочу себе такой виджет"]]]
                [:div.col-sm-2]]]
              (wrap-footer)]}))


change layout function to a macro

change layout function to a macro

--- src/clj_money/web/shared.clj
+++ src/clj_money/web/shared.clj
@@ -153,7 +153,7 @@
            [:div {:class (str "alert alert-" (name css-class))} message]))
        alerts))

-(defn- head
+(defn head
   [page-title options]
   [:head
    [:meta  {:charset "utf-8"}]
@@ -183,25 +183,25 @@
    [:link {:rel "stylesheet" :href "/css/clj-money.css"}]
    ])

-(defn layout
+(defmacro layout
   "Renders content inside a standard page template"
   [page-title options & content]
-  (html5
+  `(html5
     [:html {:lang "en"}
-     (head page-title options)
+     (head ~page-title ~options)
      [:body
-      (primary-nav (:entity options))
+      (primary-nav (:entity ~options))
       [:div.container {:style "margin-top: 2em;"}
        (html
-         (let [side-bar (:side-bar options)]
+         (let [side-bar# (:side-bar ~options)]
            [:div.row
-            [:div {:class (format "col-md-%s" (if side-bar 8 12))}
-             [:h1#page-title page-title]
-             (if-let [alerts (:alerts options)]
-               (render-alerts alerts))
-             content]
-            (if side-bar
-              [:div.col-md-4 side-bar])]))]]]))
+            [:div {:class (format "col-md-%s" (if side-bar# 8 12))}
+             [:h1#page-title ~page-title]
+             (if-let [alerts# (:alerts ~options)]
+               (render-alerts alerts#))
+             ~@content]
+            (if side-bar#
+              [:div.col-md-4 side-bar#])]))]]]))

 (defn- input-element
   [name value options]


:space_invader:

--- src/cljs/openslack/core.cljs
+++ src/cljs/openslack/core.cljs
@@ -26,7 +26,7 @@
   (let [mv (<! (mlet-with async/either-pipeline-monad
                  [jid (xmpp/start-session client)
                   roster (xmpp/get-roster client)]
-                 (m/return {:jid jid,:roster roster})))]
+                 (m/return {:jid jid, :roster roster})))]
       (if (either/right? mv)
         (print "JID: " (:jid (either/from-either mv))))
         (print "Roster: " (:roster (either/from-either mv)))))


ideas

ideas

--- src/cljs/triboard/ai/ai.cljs
+++ src/cljs/triboard/ai/ai.cljs
@@ -53,7 +53,7 @@
 ;; -----------------------------------------

 ;; TODO - How to add the custom scoring? How to keep the game? (use keys)
-;; TODO - Sort by score and use alpha-beta min/max functions instead of standard min/max
+;; TODO - Use mapmin from http://worrydream.com/refs/Hughes-WhyFunctionalProgrammingMatters.pdf
 (defn leaf-score
   [ai game]
   (:scores (game/current-turn game)))


Report assertion failures correctly to the client

--- src/glory_of_empires/main.clj
+++ src/glory_of_empires/main.clj
@@ -25,7 +25,7 @@
   (println "------------ request received -----------")
   (let [ message (slurp (:body request)) ]
     (println message)
-    (reply (try (eval-input message) (catch Exception e (handle-exception e))))))
+    (reply (try (eval-input message) (catch Throwable e (handle-exception e))))))

 (defn -main [& args]
   (game-state/load-game)


Add full orchestra.

Add full orchestra.

--- src/african_polyphony_and_polyrhythm/talk.clj
+++ src/african_polyphony_and_polyrhythm/talk.clj
@@ -79,20 +79,33 @@

 (def tulule
   (part
-    (phrase [2 2] (repeat 2))))
+    (phrase [2 2] (repeat 3))
+    (comp (split 2 1/2) (split 0 1/2))))

 (def bongo
   (part
-    (phrase [3/2 3/4 7/4] (cons nil (repeat 2)))))
+    (phrase [3/2 3/4 7/4] (cons nil (repeat 4)))
+    (split 2 5/7)
+    (comp (split 1 1/3) (split 2 5/7))
+    (comp (split 4 1/2) (split 1 1/3) (split 2 5/7))))
+
+(defn up [notes]
+  (->> notes
+       (map (partial where :pitch #(+ % 5)))))

 (def balendorc
-  (->> [tete ta ha tulule bongo]
+  (->> [tete ta ha tulule bongo
+        (up tete) (up ta) (up ha) (up tulule) (up bongo)
+        (up (up tete)) (up (up ta)) (up (up ha)) (up (up tulule)) (up (up bongo))
+        (up (up (up tete))) (up (up (up ta))) (up (up (up ha)))]
        (map rand-variations)
        (reduce with)))

-(def inverse-pentatonic (comp (partial + 24) pentatonic -))
+(def inverse-pentatonic (comp (partial + 12) pentatonic -))

 (comment
+  (fx-reverb)
+  (map fx-distortion [0 1])
   (->>
     balendorc
     (where :pitch (comp temperament/equal A inverse-pentatonic))


Use thing->url not thing->path in the web driver

--- src/grimoire/api/web/read.clj
+++ src/grimoire/api/web/read.clj
@@ -52,7 +52,7 @@
          (string? op)]}
   (str (:host config)
        baseurl
-       (when thing (t/thing->path thing))
+       (when thing (t/thing->url thing))
        "?op=" op "&type=edn"))

 (defn do-data-req


Added scrollbar to buttons in lattice editor

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

--- src/conexp/graphics/draw.clj
+++ src/conexp/graphics/draw.clj
@@ -36,7 +36,7 @@
 	clojure.contrib.swing-utils)
   (:import [javax.swing JFrame JPanel JButton JTextField JLabel
 	                JOptionPane JSeparator SwingConstants
-	                BoxLayout Box JScrollBar JComboBox]
+	                BoxLayout Box JScrollBar JComboBox JScrollPane]
 	   [java.awt Canvas Color Dimension BorderLayout GridLayout Component Graphics]
 	   [java.awt.event ActionListener]
 	   [no.geosoft.cc.graphics GScene]))
@@ -168,16 +168,14 @@
 (defn- export-as-file
   "Installs a file exporter."
   [frame scn buttons]
-  (let [#^JButton gif-exporter (make-button buttons "to GIF"),
-	#^JButton png-exporter (make-button buttons "to PNG"),
-	#^JButton jpg-exporter (make-button buttons "to JPG")]
+  (let [#^JButton save-button (make-button buttons "Save")]
     ;; TODO: add handlers to save to file
     nil))

-;; safe changes
+;; save changes

 (defn- snapshot-saver
-  "Installs a snapshot safer, which, whenever a node has been moved,
+  "Installs a snapshot saver, which, whenever a node has been moved,
   saves the image."
   [frame scn buttons]
   (let [saved-layouts (atom {}),
@@ -206,7 +204,7 @@
 (defvar- *item-height* 25
   "Heights of items on toolbar.")

-(defvar- *toolbar-width* (+ 10 *item-width*)
+(defvar- *toolbar-width* (+ 20 *item-width*)
   "Width of toolbar containing buttons, labels and so on.")

 (defn- make-padding
@@ -300,7 +298,7 @@
 	#^JPanel buttons (JPanel.),
 	box-layout (BoxLayout. buttons BoxLayout/Y_AXIS)]
     (.setLayout buttons box-layout)
-    (.setPreferredSize buttons (Dimension. *toolbar-width* 0))
+    (.setPreferredSize buttons (Dimension. *toolbar-width* 600))
     (install-changers frame scn buttons
       toggle-zoom-move
       change-parameters
@@ -314,7 +312,9 @@
     (.installScrollHandler scn hscrollbar vscrollbar)
     (doto main-panel
       (.add canvas-panel BorderLayout/CENTER)
-      (.add buttons BorderLayout/WEST))
+      (.add (JScrollPane. buttons JScrollPane/VERTICAL_SCROLLBAR_ALWAYS
+			          JScrollPane/HORIZONTAL_SCROLLBAR_NEVER)
+	    BorderLayout/WEST))
     main-panel))


threading - make dispatch between a Router/Splitter and its Views asynchronous

--- src/main/clojure/org/dada/core.clj
+++ src/main/clojure/org/dada/core.clj
@@ -19,6 +19,7 @@
 	      Model
 	      Router
 	      Router$Strategy
+	      ServiceFactory
 	      SparseOpenLazyViewTable
 	      Transformer
 	      Transformer$Transform
@@ -43,7 +44,9 @@
 (defn start-server [#^String name]
   (System/setProperty "server.name" name)
   (let [context (ClassPathXmlApplicationContext. "application-context.xml")]
-    (def *spring-context* context)
+    (def #^ClassPathXmlApplicationContext *spring-context* context)
+    (def #^ServiceFactory *internal-view-service-factory*
+	 (.getBean *spring-context* "internalViewServiceFactory"))
     (.getBean context "metaModel")))

 (defn start-client [#^String name]
@@ -279,7 +282,7 @@
   (let [map (new ConcurrentHashMap)
 	prefix (str (.getName src-model) "." (name key) "=")
 	metadata (.getMetadata src-model)
-	view-factory (proxy [Factory] [] (create [key] (view-hook (model (str prefix (route-to-value key)) metadata))))
+	view-factory (proxy [Factory] [] (create [key] (.decouple *internal-view-service-factory* (view-hook (model (str prefix (route-to-value key)) metadata)))))
 	lazy-factory (proxy [Factory] [] (create [key] (new LazyView map key view-factory)))
 	table (new SparseOpenLazyViewTable map lazy-factory)
 	getter (.getAttributeGetter metadata (name key))]


remove excess whitespace

remove excess whitespace

--- src/metabase/driver/sync.clj
+++ src/metabase/driver/sync.clj
@@ -398,7 +398,7 @@
   (field-avg-length [this field]
     (let [field-values (->> (field-values-lazy-seq this field)
                             (filter identity)
-                            (take max-sync-lazy-seq-results))                      ; as with field-percent-urls it's probably fine to consider the first 10,000 values rather than potentially millions
+                            (take max-sync-lazy-seq-results)) ; as with field-percent-urls it's probably fine to consider the first 10,000 values rather than potentially millions
           field-values-count (count field-values)]
       (if (= field-values-count 0) 0
           (int (math/round (/ (->> field-values


Tune pooling options

Tune pooling options

--- src/cyanite_fetcher/core.clj
+++ src/cyanite_fetcher/core.clj
@@ -182,7 +182,9 @@
   "Get data from C*."
   [f-par-fetch n-par-fetch host paths tenant rollup period from to]
   (println "Connecting to Cassandra...")
-  (let [cluster (alia/cluster {:contact-points [host]})
+  (let [cluster (alia/cluster {:contact-points [host]
+                               :pooling-options {:max-connections-per-host {:local 8192
+                                                                            :remote 8192}}})
         session (alia/connect cluster keyspace)
         fetch! (fetchq session)]
     (println (format "Getting data form Cassandra using %s..." n-par-fetch))


Fix indentation

Fix indentation

--- src/main/clj/lemur/core.clj
+++ src/main/clj/lemur/core.clj
@@ -833,7 +833,7 @@
                       opt-key (get-opt-key arg-key orig-val)]
                   ; test if this arg is explicit (i.e. appears in catch-args)
                   (if (->> (context-get :command-spec) (map first) (filter #(= opt-key %)) seq)
-                      sm
+                    sm
                     ; if not explicit, create implicit command line arg
                     (let [opt-name (name opt-key)]
                       (catch-args [opt-key


NO_DURATION feature

NO_DURATION feature

--- org-mode/src/com/gfredericks/org_agenda.clj
+++ org-mode/src/com/gfredericks/org_agenda.clj
@@ -327,6 +327,7 @@
   [events]
   (let [durations (for [event events
                         :when (not (all-day? event))
+                        :when (not (= "t" (get (:properties event) "NO_DURATION")))
                         :let [[t1 t2] (timetable-slot event)]]
                     (if t2
                       (Duration/ofSeconds (- (.toSecondOfDay (.toLocalTime t2))
@@ -392,7 +393,8 @@
                                       (let [past? (compare/< (.atZone (or t2 t1) CHICAGO) now)
                                             t1 (.toLocalTime t1)
                                             t2 (some-> t2 .toLocalTime)]
-                                        (printf "       %s%s: %s\n"
+                                        (printf "      %s%s%s: %s %s\n"
+                                                (if (= "t" (get (:properties item) "NO_DURATION")) "*" " ")
                                                 (if past? "# " "")
                                                 (if t2
                                                   (if (all-day? item)


Whitespace and replace an (if foo bar nil) with when

--- src/mavlink/mavlink_xml.clj
+++ src/mavlink/mavlink_xml.clj
@@ -147,8 +147,8 @@
                             []
                             (range length))]
             (assoc! message  name-key (if (= type-key :char)
-                         (.trim (new String ^"[B" (into-array Byte/TYPE new-array)))
-                         new-array) )))
+                                        (.trim (new String ^"[B" (into-array Byte/TYPE new-array)))
+                                        new-array))))
         (fn decode-it [buffer message]
           (assoc! message name-key (let [v (read-fn buffer)]
                                      (get enum-group v v))))))))
@@ -190,12 +190,11 @@
        enums-by-group
         (apply merge (zip-xml/xml-> zipper :mavlink :enums :enum
                       (fn [e]
-                        { (keywordize (zip-xml/attr e :name))
-                              (apply merge
-                                     (zip-xml/xml-> e :entry
-                                       #(let [enum-key (keywordize (zip-xml/attr % :name))]
-                                          {(enum-key enum-to-value) enum-key})))
-                             } )))
+                        {(keywordize (zip-xml/attr e :name))
+                         (apply merge
+                                (zip-xml/xml-> e :entry
+                                               #(let [enum-key (keywordize (zip-xml/attr % :name))]
+                                                  {(enum-key enum-to-value) enum-key})))})))
        messages-by-keyword
           (apply
             merge
@@ -225,7 +224,7 @@
                                                    (map #(let [{:keys [fld-name type-key length]} %]
                                                            (str (if (= type-key :uint8_t_mavlink_version)
                                                                   "uint8_t"
-                                                                  (name type-key))  " "
+                                                                  (name type-key)) " "
                                                                 fld-name " "
                                                                 (when length
                                                                   (char length))))
@@ -238,22 +237,22 @@
                       ext-encode-fns (mapv gen-encode-fn ext-fields)
                       ext-decode-fns (mapv #(gen-decode-fn % enums-by-group) ext-fields)
                       ]
-                  { (keywordize msg-name)
-                    {:msg-id msg-id
-                     :msg-key (keywordize msg-name)
-                     :payload-size payload-size
-                     :extension-payload-size (+ payload-size payload-size-ext)
-                     :fields fields
-                     :encode-fns encode-fns
-                     :decode-fns decode-fns
-                     :extension-fields ext-fields
-                     :extension-encode-fns ext-encode-fns
-                     :extension-decode-fns ext-decode-fns
-                     :crc-seed crc-seed
+                  {(keywordize msg-name)
+                   {:msg-id msg-id
+                    :msg-key (keywordize msg-name)
+                    :payload-size payload-size
+                    :extension-payload-size (+ payload-size payload-size-ext)
+                    :fields fields
+                    :encode-fns encode-fns
+                    :decode-fns decode-fns
+                    :extension-fields ext-fields
+                    :extension-encode-fns ext-encode-fns
+                    :extension-decode-fns ext-decode-fns
+                    :crc-seed crc-seed
                     }
                   }))))
        all-descriptions
-         (if descriptions
+         (when descriptions
            (apply
              merge
              (concat
@@ -271,8 +270,7 @@
                             (fn[m]
                               { (keywordize (zip-xml/attr m :name))
                                 (zip-xml/xml1-> m :description zip-xml/text)
-                              }))))
-           nil)]
+                              })))))]
    {:descriptions all-descriptions
     :enum-to-value enum-to-value
     :enums-by-group enums-by-group


Fix follow data usage to filter out unfollowed boards and in followed publishers.

--- src/oc/storage/db/common.clj
+++ src/oc/storage/db/common.clj
@@ -47,8 +47,8 @@
                        (r/or (not (sequential? allowed-boards))
                              (r/contains allowed-boards (r/get-field post-row :board-uuid)))
                        (r/or (not (map? follow-data))
-                             (r/contains (vec (:publisher-uuids follow-data)) (r/get-field post-row [:publisher :user-id]))
-                             (r/not (r/contains (vec (:board-uuids follow-data)) (r/get-field post-row :board-uuid)))))))
+                             (r/contains (vec (:follow-publisher-uuids follow-data)) (r/get-field post-row [:publisher :user-id]))
+                             (r/not (r/contains (vec (:unfollow-board-uuids follow-data)) (r/get-field post-row :board-uuid)))))))
               query)
             ;; Merge in a last-activity-at date for each post, which is the
             ;; last comment created-at, with fallback to published-at or created-at for published entries
@@ -136,8 +136,8 @@
                      (r/not (r/default (r/get-field post-row [:user-visibility user-id :unfollow]) false))
                      ;; Filter on followed boards and authors
                      (r/or (not (map? follow-data))
-                           (r/contains (vec (:publisher-uuids follow-data)) (r/get-field post-row [:publisher :user-id]))
-                           (r/not (r/contains (vec (:board-uuids follow-data)) (r/get-field post-row :board-uuid)))))))
+                           (r/contains (vec (:follow-publisher-uuids follow-data)) (r/get-field post-row [:publisher :user-id]))
+                           (r/not (r/contains (vec (:unfollow-board-uuids follow-data)) (r/get-field post-row :board-uuid)))))))
             ;; Merge in a last-activity-at date for each post (last comment created-at, fallback to published-at)
             (r/merge query (r/fn [post-row]
               {:last-activity-at (-> (r/table relation-table-name)


beginning to remove redundant arguments.

--- src/midje/util/checkers.clj
+++ src/midje/util/checkers.clj
@@ -314,8 +314,8 @@
 ;;-

 (defmulti compare-results
-  (fn [midje-classification actual expected looseness]
-    (if (= ::map midje-classification)
+  (fn [actual expected looseness]
+    (if (= ::map (midje-classification actual))
       midje-classification
       [::not-map (or (some #{:in-any-order} looseness) :strict-order)])))

@@ -396,27 +396,27 @@
           (recur (rest expected-permutations)
                  (better-of comparison best-so-far)))))))

-(defmethod compare-results ::map [midje-classification actual expected looseness]
+(defmethod compare-results ::map [actual expected looseness]
   (order-free-compare-results expected
                               (feasible-permutations (keys expected))
                               (fn [permutation]
-                                (compare-one-map-permutation midje-classification
+                                (compare-one-map-permutation (midje-classification actual)
                                                              actual
                                                              expected
                                                              permutation))))

 (defmethod compare-results [::not-map :in-any-order]
-  [midje-classification actual expected looseness]
+  [actual expected looseness]
   (order-free-compare-results expected
                               (feasible-permutations expected)
                               (fn [permutation]
-                                (compare-one-seq-permutation midje-classification
+                                (compare-one-seq-permutation (midje-classification actual)
                                                              actual
                                                              permutation
                                                              looseness))))

 (defmethod compare-results [::not-map :strict-order]
-  [midje-classification actual expected looseness]
+  [actual expected looseness]
   (let [starting-candidate (base-starting-candidate expected)
         gaps-ok? (some #{:gaps-ok} looseness)]

@@ -524,7 +524,7 @@

 (defn match? [actual expected looseness]
-  (let [comparison (compare-results (midje-classification actual) actual expected looseness)]
+  (let [comparison (compare-results  actual expected looseness)]
     (or (total-match? comparison)
         (apply noted-falsehood
                (cons (best-actual-match (midje-classification actual) comparison)


Minor code cleanup on db.init.

Minor code cleanup on db.init.

--- src/open_company/db/init.clj
+++ src/open_company/db/init.clj
@@ -34,7 +34,7 @@
   [conn table-name index-name]
   (when (not-any? #(= index-name %) (index-list conn table-name))
     (-> (r/table table-name)
-      (r/index-create index-name
+      (r/index-create index-name
         (r/fn [row]
           (r/get-field row (keyword index-name))))
       (r/run conn))
@@ -42,17 +42,21 @@
       (r/index-wait index-name)
       (r/run conn))))

-(defn init []
+(defn init
+  "Create any missing tables and indexes in RethinkDB."
+  []
   (let [db-name c/db-name]
     (println (str "\nOpen Company: Initializing database - " db-name))
     (with-open [conn (apply r/connect c/db-options)]
-      (when (create-database conn db-name)
-        (do
+      (when (create-database conn db-name)
+        (do
           (print ".")
           (create-table conn db-name "companies" "symbol") (print ".")
           (create-table conn db-name "reports" "symbol-year-period") (print ".")
           (create-index conn "reports" "symbol") (print ".")
           (println "\nOpen Company: Database initialization complete - " db-name "\n"))))))

-(defn -main []
+(defn -main
+  "Initialize the RethinkDB instance."
+  []
   (init))


db/docids.clj: fix errors in get-docid and set-docid

--- src/org/altlaw/db/docids.clj
+++ src/org/altlaw/db/docids.clj
@@ -13,12 +13,12 @@
   (data/save-data (str "docids/" collection)))

 (defn get-docid [collection key]
-  (get @(get-docids collection key)))
+  (get @(get-docids collection) key))

 (defn set-docid [collection keys docid]
   (assert (coll? keys))
   (assert (every? string? keys))
   (assert (integer? docid))
   (dosync (apply alter (get-docids collection)
-                 assoc (zipmap keys (repeat docid)))))
+                 assoc (mapcat list keys (repeat docid)))))