detect when query changed

detect when query changed

find the right query now

--- src/webapp/framework/server/systemfns.clj
+++ src/webapp/framework/server/systemfns.clj
@@ -645,8 +645,10 @@
    (println (str "Count: " (-> @cached-queries keys count str)))
    (let [queries (keys @cached-queries)]
    (doall (for [query queries]
-     (println (str "   " query)))
-   ))))
+            (do
+              (if (= (get query :db-table) (get realtime-log-entry :record_table_name))
+                (println (str "   " query))))
+   )))))


Restore spaces in join; fix devth/yetibot#359

--- src/yetibot/core/commands/collections.clj
+++ src/yetibot/core/commands/collections.clj
@@ -112,7 +112,7 @@
 (defn join
   "join <list> # joins list with a single space or whatever character is given"
   [{match :match items :opts}]
-  (let [join-char (if (= match :empty) " " match)]
+  (let [join-char (if (empty? match) " " match)]
     (s/join join-char (ensure-items-collection items))))

 (cmd-hook #"join"


Add to test.

Add to test.

--- test-cljs/frontend/models/test_build.cljs
+++ test-cljs/frontend/models/test_build.cljs
@@ -18,7 +18,8 @@
          "success"              "pass"
          "running"              "busy"
          "queued"               "queued"
-         "not_running"          "queued")))
+         "not_running"          "queued"
+         "scheduled"            "queued")))

 (deftest status-badge-icons
   (testing "correct icons are mapped to build states"
@@ -35,4 +36,5 @@
          "success"              "Status-Passed"
          "running"              "Status-Running"
          "queued"               "Status-Queued"
-         "not_running"          "Status-Queued")))
+         "not_running"          "Status-Queued"
+         "scheduled"            "Status-Queued")))


Tests around document/index watching are a bit brittle, moving the database to the cloud means we need to sleep a little longer.

--- test/clj_ravendb/client_watching_test.clj
+++ test/clj_ravendb/client_watching_test.clj
@@ -13,8 +13,9 @@
             document {:test 2 :name "WatchedDocument"}
             ch (chan)
             watcher (watch-documents client ["TestDocToWatch"] ch {:wait 0})
-            _ (Thread/sleep 1000)
+            _ (Thread/sleep 2000)
             _ (put-document! client id document)
+            _ (Thread/sleep 2000)
             actual (first (:results (<!! ch)))
             actual (dissoc actual :last-modified-date)
             actual (dissoc actual :etag)]
@@ -22,13 +23,14 @@
         (is (= actual {:id id :document document})))))

   (deftest test-watching-index-puts-to-channel-on-index-change
-    (testing "Watching a index puts to a channel on index change"
+    (testing "Watching an index puts to a channel on index change"
       (let [id "TestDocToWatch"
             document {:test 2 :name "WatchedDocument"}
             ch (chan)
             watcher (watch-index client {:index "WatchedDocuments"} ch {:wait 0})
-            _ (Thread/sleep 1000)
+            _ (Thread/sleep 2000)
             _ (put-document! client id document)
+            _ (Thread/sleep 2000)
             actual (first (:results (<!! ch)))]
         ((:stop watcher))
         (is (= actual document)))))


Added explict require for the instance.bind fn referred to in job catalog

--- test/onyx_java/test/single_javafn/job.clj
+++ test/onyx_java/test/single_javafn/job.clj
@@ -1,7 +1,9 @@
 (ns onyx-java.test.single-javafn.job
   (:require [clojure.test :refer [deftest is]]
             [onyx-java.test.job :as j]
-            [onyx-java.test.single-javafn.catalog :as cat]))
+            [onyx-java.test.single-javafn.catalog :as cat]
+
+            [onyx-java.instance.bind]))

 (deftest java-pass-through
   (let [catalog (cat/build-catalog)


Add macro for running a block of code w/o jvm shutdown hooks

--- test/puppetlabs/kitchensink/testutils.clj
+++ test/puppetlabs/kitchensink/testutils.clj
@@ -1,5 +1,6 @@
 (ns puppetlabs.kitchensink.testutils
-  (:require [fs.core :as fs]))
+  (:require [fs.core :as fs]
+            [puppetlabs.kitchensink.core :as ks]))

 (defn call-counter
   "Returns a method that just tracks how many times it's called, and
@@ -36,3 +37,8 @@
 (def ^{:doc "Creates a temporary directory that will be deleted on JVM shutdown."}
   temp-dir
   (comp delete-on-exit fs/temp-dir))
+
+(defmacro with-no-jvm-shutdown-hooks
+  [& body]
+  `(with-redefs [ks/add-shutdown-hook! (fn [_#] nil)]
+    ~@body))


+:grammar-map

+:grammar-map

--- src/babel/italiano/grammar.cljc
+++ src/babel/italiano/grammar.cljc
@@ -586,6 +586,9 @@
      :enrich enrich
      :generate {:lexicon lexicon}
      :grammar grammar
+     :grammar-map (zipmap
+                   (map #(keyword (get-in % [:rule])) grammar)
+                   grammar)
      :lexicon lexicon
      :lexical-cache (atom (cache/fifo-cache-factory {} :threshold 1024))
      :index (create-index grammar (flatten (vals lexicon)) head-principle)}))


more liberal inclusion of lexical items (e.g. "_" => {})

--- src/babel/italiano/grammar.cljc
+++ src/babel/italiano/grammar.cljc
@@ -477,9 +477,9 @@
         (into {}
               (for [[k v] lexicon]
                 (let [filtered-v
-                      (filter #(or (= (get-in % [:synsem :cat]) :adjective)
-                                   (= (get-in % [:synsem :cat]) :det)
-                                   (and (= (get-in % [:synsem :cat]) :noun)
+                      (filter #(or (= (get-in % [:synsem :cat] :adjective) :adjective)
+                                   (= (get-in % [:synsem :cat] :det) :det)
+                                   (and (= (get-in % [:synsem :cat] :noun) :noun)
                                         (not (= (get-in % [:synsem :propernoun] false) true))
                                         (not (= (get-in % [:synsem :pronoun] false) true))))
                               v)


caffè: singular+plural

caffè: singular+plural

--- src/babel/italiano/lexicon.cljc
+++ src/babel/italiano/lexicon.cljc
@@ -528,9 +528,14 @@
                    :speakable false}
              :subcat {:1 {:def :def}}}}

-   "caffè" {:synsem {:agr {:gender :masc}
-                     :cat :noun
-                     :sem {:pred :lesson}}}
+   "caffè" [{:synsem {:agr {:gender :masc
+                            :number :sing}
+                      :cat :noun
+                      :sem {:pred :coffee}}}
+            {:synsem {:agr {:gender :masc
+                            :number :plur}
+                      :cat :noun
+                      :sem {:pred :coffee}}}]
    "calzoni"
    ;; inherently plural
    {:synsem {:cat :noun


Give compose text a bit more breathing room from border and align it with message text

--- src/braid/ui/styles/thread.cljs
+++ src/braid/ui/styles/thread.cljs
@@ -142,6 +142,7 @@
       :resize "none"
       :border "none"
       :box-sizing "border-box"
+      :padding (rem 0.5)
       :min-height (em 3.5)
       :box-shadow "0 0 1px 1px #ccc"
       :border-radius vars/border-radius}


Made Jetty server interface more idiomatic

--- modules/jetty/server.clj
+++ modules/jetty/server.clj
@@ -11,32 +11,44 @@
   (ref {}))

 (defn get-continuation
+  "Get the current Jetty continuation object for the request."
   [request]
   (. ContinuationSupport (getContinuation request request)))

 (defn suspend-request
+  "Use Jetty's pseudo-continuation support to suspend handling a HTTP request.
+  When called, the current servlet ends and is re-called when the request is
+  resumed. When resumed, suspend-request exits immediatedly.
+    Requests are stored in a hash with a user defined key, so you can resume
+  a group of requests at once (e.g. all the requests in one chat room)."
   ([request key]
     (suspend-request request key *default-timeout*))
   ([request key timeout]
     (let [cc (get-continuation request)]
       (dosync
-        (let [cset (*continuations* key)]
-          (alter *continuations*
-            #(assoc % key (set (conj cset cc))))))
+        (let [cset    (*continuations* key)
+              cset+cc (conj (set cset) cc)]
+          (alter *continuations* assoc key cset+cc)))
       (. cc (suspend timeout)))))

-(defn resume-request
+(defn resume-requests
+  "Resumes a group of suspended requests by key. See: suspend-request."
   [key]
-  (doseq continuation
-    (dosync (return (*continuations* key)
-              (alter *continuations* #(dissoc % key))))
-    (. continuation (resume))))
+  (let [cset (dosync (return (*continuations* key)
+                       (alter *continuations* dissoc key)))]
+    (doseq cc cset
+      (. cc (resume)))))

+(def resume-request resume-requests) ; An alias for resume-requests
+
+; Bind suspend-request to all resource calls, so you don't have to manually
+; specify the request object each time.
 (add-resource-binding
   'suspend-request
   `(partial suspend-request ~'request))

 (defn http-server
+  "Create a new Jetty HTTP server with the supplied servlet."
   [servlet & options]
   (let [options (apply hash-map options)
         port    (or (options :port) 8080)


Remove continuation monad from labs.

Remove continuation monad from labs.

--- src/cats/labs/continuation.cljc
+++ src/cats/labs/continuation.cljc
@@ -1,98 +0,0 @@
-;; Copyright (c) 2014-2015 Andrey Antukh <niwi@niwi.nz>
-;; Copyright (c) 2014-2015 Alejandro Gómez <alejandro@dialelo.com>
-;; All rights reserved.
-;;
-;; Redistribution and use in source and binary forms, with or without
-;; modification, are permitted provided that the following conditions
-;; are met:
-;;
-;; 1. Redistributions of source code must retain the above copyright
-;;    notice, this list of conditions and the following disclaimer.
-;; 2. Redistributions in binary form must reproduce the above copyright
-;;    notice, this list of conditions and the following disclaimer in the
-;;    documentation and/or other materials provided with the distribution.
-;;
-;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-(ns cats.labs.continuation
-  "The Continuation Monad."
-  #?(:clj  (:require [cats.protocols :as p]
-                     [cats.context :as ctx]
-                     [cats.util :as util])
-     :cljs (:require [cats.protocols :as p]
-                     [cats.context :as ctx :include-macros true]
-                     [cats.util :as util])))
-
-(declare context)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Type constructors and functions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(deftype Continuation [mfn]
-  p/Contextual
-  (-get-context [_] context)
-
-  #?(:clj  clojure.lang.IFn
-     :cljs cljs.core/IFn)
-  (#?(:clj invoke :cljs -invoke) [self seed]
-    (mfn seed)))
-
-(alter-meta! #'->Continuation assoc :private true)
-
-(defn continuation
-  "Default constructor for continuation."
-  [mfn]
-  (Continuation. mfn))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Monad definition
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(def context
-  (reify
-    p/Context
-    (-get-level [_] ctx/+level-default+)
-
-    p/Monad
-    (-mreturn [_ v]
-      (Continuation. (fn [c] (c v))))
-
-    (-mbind [_ self mf]
-      (Continuation. (fn [c]
-                       (self (fn [v]
-                               ((mf v) c))))))
-
-    p/Printable
-    (-repr [_]
-      "#<Continuation>")))
-
-(util/make-printable (type context))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Continuation monad functions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defn run-cont
-  "Given a Continuation instance, execute the
-  wrapped computation and return its value."
-  [cont]
-  (ctx/with-monad context
-    (cont identity)))
-
-(defn call-cc
-  [f]
-  (continuation
-    (fn [cc]
-      (let [k (fn [a]
-                (continuation (fn [_] (cc a))))]
-        ((f k) cc)))))


adjusted indentation in filter.

adjusted indentation in filter.

--- src/clj/forma/trends/filter.clj
+++ src/clj/forma/trends/filter.clj
@@ -18,6 +18,8 @@

 ;; De-seasonalize time-series

+;; TODO: What's a monthly dummy vector? Can you describe why we need
+;; these?
 (defn seasonal-rows [n]
   "lazy sequence of monthly dummy vectors."
   (->> (cycle (cons 1 (repeat 11 0)))
@@ -145,10 +147,9 @@
   [bad-set reli-coll val-coll]
   (let [avg (act-on-good average
                          (mask bad-set reli-coll val-coll))]
-    (replace-index-set
-     (bad-ends bad-set reli-coll)
-     avg
-     val-coll)))
+    (replace-index-set (bad-ends bad-set reli-coll)
+                       avg
+                       val-coll)))

 ;; TODO: This function works, but it's ugly.  Clean up. And put in
 ;; pre- and post-conditions.
@@ -162,22 +163,16 @@
   is not true, then an adjustment will have to be made to this function."
   [bad-set good-set quality-coll value-coll]
   (if (empty? (filter bad-set quality-coll)) nil
-      (let [bad-end-set (bad-ends
-                         bad-set
-                         quality-coll)
-            new-qual (replace-index-set
-                      bad-end-set
-                      (first good-set)
-                      quality-coll)
-            new-vals (neutralize-ends
-                      bad-set
-                      quality-coll
-                      value-coll)
-            good-seq (positions
-                      (complement bad-set)
-                      new-qual)]
+      (let [bad-end-set (bad-ends bad-set quality-coll)
+            new-qual (replace-index-set bad-end-set
+                                        (first good-set)
+                                        quality-coll)
+            new-vals (neutralize-ends bad-set
+                                      quality-coll
+                                      value-coll)
+            good-seq (positions (complement bad-set)
+                                new-qual)]
         (vec (flatten
               (vector (map (partial stretch-ts new-vals)
                            (partition 2 1 good-seq))
                       (nth new-vals (last good-seq))))))))
-


replay

replay

--- src/com/billpiel/sayid/core.clj
+++ src/com/billpiel/sayid/core.clj
@@ -186,6 +186,16 @@
               force)
   true)
 (util/defalias w-l! ws-load!)
+
+(defn ws-replay!
+  "Replays the function call recorded in the active workspace with an id
+  of `id`."
+  [id]
+  (let [t (-> (w-q [:id id]) first)
+        f (-> t :name resolve)
+        a (:args t)]
+    (apply f a)))
+(util/defalias w-rp! ws-replay!)

 ;; === END Workspace functions


Don't transform collection items directly

--- src/com/wsscode/pathom/gen.cljc
+++ src/com/wsscode/pathom/gen.cljc
@@ -183,7 +183,7 @@
         (if-let [r (or (::coll s)
                        (if (coll-spec? k) [0 5]))]
           (let [[min max] (normalize-range r)]
-            (cond->> (gen/vector sub-gen min max)
+            (cond->> (gen/vector (map->gen (p/join env)) min max)
               distinct (gen/fmap #(distinct-by distinct %))))
           sub-gen))
       (try


hiccup.page-helpers is now hiccup.page.

hiccup.page-helpers is now hiccup.page.

--- integration-tests/apps/ring/noir-app/src/noir_app/views/common.clj
+++ integration-tests/apps/ring/noir-app/src/noir_app/views/common.clj
@@ -1,6 +1,6 @@
 (ns noir-app.views.common
   (:use [noir.core :only [defpartial]]
-        [hiccup.page-helpers :only [include-css html5]]))
+        [hiccup.page :only [include-css html5]]))

 (defpartial layout [& content]
             (html5


Simplify implementation of where clauses with pattern matches

--- src/clojure/clojurewerkz/cassaforte/new_query_api.clj
+++ src/clojure/clojurewerkz/cassaforte/new_query_api.clj
@@ -11,8 +11,9 @@
             CreateKeyspace DropKeyspace
             SchemaBuilder$Caching SchemaBuilder$KeyCaching])
   (:require [clojurewerkz.cassaforte.aliases :as alias]
-            clojurewerkz.cassaforte.query.query-builder
-            clojurewerkz.cassaforte.query.types))
+            [clojure.core.match              :refer [match]]
+            [clojurewerkz.cassaforte.query.query-builder]
+            [clojurewerkz.cassaforte.query.types]))

 (set! *warn-on-reflection* false)

@@ -44,7 +45,7 @@
       gte (fn [^String column ^Object value]
             (QueryBuilder/gte column value))]

-  (def ^:private query-type-map
+  (def ^:private query-type-mappings
     {:in in
      :=  eq
      =   eq
@@ -64,10 +65,12 @@
     clojure.lang.IPersistentVector
     (to-clauses [construct]
       (reduce
-       (fn [acc [query-type column value]]
-         (if-let [eq-type (query-type-map query-type)]
-           (conj acc ((query-type-map query-type) (name column) value))
-           (throw (IllegalArgumentException. (str query-type " is not a valid Clause")))))
+       (fn [acc v]
+         (conj acc
+               (match v
+                      [column value]     (eq (name column) value)
+                      [op column value]  ((get query-type-mappings op) (name column) value)
+                      :else (throw (IllegalArgumentException. (str v " is not a valid Clause"))))))
        []
        construct))
     clojure.lang.IPersistentMap


Fixed whitespace tabs in decoder.clj

Fixed whitespace tabs in decoder.clj

--- src/ais/decoder.clj
+++ src/ais/decoder.clj
@@ -95,13 +95,13 @@
                 (if (and (types msg-type) (= frag-num 1))
 	          (condp = frag-count
 	            1 (async/>!! out-ch line)
-		    ;; We assume group values stream in sequential order hence sequential
-		    ;; reads from the input channel
-	    	    2 (async/>!! out-ch (parse-group line (async/<!! in-ch)))
+	            ;; We assume group values stream in sequential order hence sequential
+	            ;; reads from the input channel
+	            2 (async/>!! out-ch (parse-group line (async/<!! in-ch)))
 	     	    (.println *err* (str "Unexpected fragment count: " frag-count ". " line)))
-		  (.println *err* (str "Dropping [type=" msg-type "] " line)))))
-             (recur))
-           (async/close! out-ch))))
+	          (.println *err* (str "Dropping [type=" msg-type "] " line)))))
+            (recur))
+          (async/close! out-ch))))
     out-ch))

 (defn- process [format n in-ch]


whitespace

whitespace

--- src/babel/korma.clj
+++ src/babel/korma.clj
@@ -80,20 +80,21 @@
     (https://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html)
    will be used to do the actual conversion."

-  (->> (-> sql-array ;; (type = implementation of SqlArray (e.g. org.postgresql.jdbc.PgArray)
-           .getArray ;; java array: (type %) = #object["Ljava.lang.String;" .."
-           vec) ;; clojure.lang.PersistentVector
-
-       (map #(try
-               ;; if input elements are parseable as JSON, read them, each of which will be a Clojure map.
+  (if (not (nil? sql-array))
+    (->> (-> sql-array ;; (type = implementation of SqlArray (e.g. org.postgresql.jdbc.PgArray)
+             .getArray ;; java array: (type %) = #object["Ljava.lang.String;" .."
+             vec) ;; clojure.lang.PersistentVector
+
+         (map #(try
+                 ;; if input elements are parseable as JSON, read them, each of which will be a Clojure map.
                  ;; otherwise, return the input elements unmodified.
-               (json/read-str % :value-fn value-fn) ;; rely on json/read-str to throw an error if input is not JSON
+                 (json/read-str % :value-fn value-fn) ;; rely on json/read-str to throw an error if input is not JSON
                  (catch Exception e %))) ;; % is not JSON-parseable: just return it as-is.

-       ;; Input is now a sequence of Clojure-native elements such as maps, but, if an
-       ;; element is a map, then its keys are strings.
-       ;; Final step, convert the keys from strings e.g. convert "foo" to :foo.
-       (map convert-keys-from-string-to-keyword)))
+         ;; Input is now a sequence of Clojure-native elements such as maps, but, if an
+         ;; element is a map, then its keys are strings.
+         ;; Final step, convert the keys from strings e.g. convert "foo" to :foo.
+         (map convert-keys-from-string-to-keyword))))

 (defn init-db []
   (defdb korma-db


trying to use a destructuring (let)

trying to use a destructuring (let)

--- src/babel/over.cljc
+++ src/babel/over.cljc
@@ -432,8 +432,16 @@
             (throw (exception (str "no schema symbol for parent: " (:rule parent))))

             true
-            (do
-              (log/debug (str "over: parent: " (get-in parent [:rule]) " with schema symbol: " (get-in parent [:schema-symbol])))
+            (let [[head comp] (if (= (:first parent) :head)
+                                [child1 child2]
+                                [child2 child1])]
+              (log/debug (str "over: parent: " (get-in parent [:rule]) " (" (get-in parent [:schema-symbol]) "); heads:["
+                              (string/join ","
+                                           (map (fn [h]
+                                                  (get-in h [:rule]
+                                                          (str (get-in h [:synsem :sem :pred]))))
+                                                head))
+                              "]"))
               (if (= (:first parent) :head)
                 ;; else, head is left child.
                 (do (log/trace "over: left child (head):" (strip-refs child1))


Also remove hidden commands for completion.

--- src/cli4clj/cli.clj
+++ src/cli4clj/cli.clj
@@ -135,7 +135,7 @@
         err-fn (opts :print-err)
         prompt-string (opts :prompt-string)
         in-rdr (doto (ConsoleReader. nil *jline-input-stream* *jline-output-stream* nil)
-                 (.addCompleter (StringsCompleter. (map name (keys cmds))))
+                 (.addCompleter (StringsCompleter. (remove #(.startsWith % "_") (map name (keys cmds)))))
                  (.setPrompt prompt-string))
         arg-hint-completers (create-arg-hint-completers cmds)
         _ (doseq [compl arg-hint-completers]


Refactor argument completer creation.

Refactor argument completer creation.

--- src/cli4clj/cli.clj
+++ src/cli4clj/cli.clj
@@ -63,37 +63,37 @@
     cmds))

 (defn create-arg-hint-completers
-  [cmds cmd-aliases]
-  (reduce
-    (fn [v k]
-      (let [fn-args (get-in cmds [k :fn-args])
-            completion-hint (get-in cmds [k :completion-hint])]
-        (if (or (not (nil? fn-args))
-                (not (nil? completion-hint)))
-          (conj v
-                (ArgumentCompleter.
-                  [(StringsCompleter. (conj (vec (map name (cmd-aliases k))) (name k)))
-                   (proxy [Completer] []
-                     (complete [buffer cursor candidates]
-                       (if (not (nil? fn-args))
-                         (.add candidates (str "Arguments: " fn-args)))
-                       (if (not (nil? completion-hint))
-                         (.add candidates (str completion-hint)))
-                       (if (or (not (nil? fn-args))
-                               (not (nil? completion-hint)))
-                         (.add candidates ""))
-                       0))]))
-          v)))
-    []
-    (keys cmds)))
+  [cmds]
+  (let [cmd-aliases (get-cmd-aliases cmds)]
+    (reduce
+      (fn [v k]
+        (let [fn-args (get-in cmds [k :fn-args])
+              completion-hint (get-in cmds [k :completion-hint])]
+          (if (or (not (nil? fn-args))
+                  (not (nil? completion-hint)))
+            (conj v
+                  (ArgumentCompleter.
+                    [(StringsCompleter. (conj (vec (map name (cmd-aliases k))) (name k)))
+                     (proxy [Completer] []
+                       (complete [buffer cursor candidates]
+                         (if (not (nil? fn-args))
+                           (.add candidates (str "Arguments: " fn-args)))
+                         (if (not (nil? completion-hint))
+                           (.add candidates (str completion-hint)))
+                         (if (or (not (nil? fn-args))
+                                 (not (nil? completion-hint)))
+                           (.add candidates ""))
+                         0))]))
+            v)))
+      []
+      (keys cmds))))

 (defn create-jline-read-fn
   [cmds prompt-string]
-  (let [cmd-aliases (get-cmd-aliases cmds)
-        in-rdr (doto (ConsoleReader.)
+  (let [in-rdr (doto (ConsoleReader.)
                  (.addCompleter (StringsCompleter. (map name (keys cmds))))
                  (.setPrompt prompt-string))
-        arg-hint-completers (create-arg-hint-completers cmds cmd-aliases)
+        arg-hint-completers (create-arg-hint-completers cmds)
         _ (doseq [compl arg-hint-completers]
             (.addCompleter in-rdr compl))
         rdr-fn (create-repl-read-fn cmds)]


Fix escaping of 404 page

Fix escaping of 404 page

--- src/clojars/web.clj
+++ src/clojars/web.clj
@@ -30,10 +30,6 @@
             [cemerick.friend.credentials :as creds]
             [cemerick.friend.workflows :as workflows]))

-(defn not-found-doc []
-  (html [:h1 "Page not found"]
-        [:p "Thundering typhoons!  I think we lost it.  Sorry!"]))
-
 (defroutes main-routes
   (GET "/search" {session :session params :params}
        (try-account
@@ -56,9 +52,9 @@
   (GET "/forgot-password" {params :params}
        (forgot-password-form))
   (friend/logout (ANY "/logout" request
-                      ; Work around friend#20 and ring-anti-forgery#10
+                                        ; Work around friend#20 and ring-anti-forgery#10
                       (-> (ring.util.response/redirect "/")
-                           (assoc :session (:session request)))))
+                          (assoc :session (:session request)))))

   (GET "/" {session :session params :params}
        (try-account
@@ -157,7 +153,8 @@
   (ANY "*" {session :session}
        (not-found (html-doc (session :account)
                             "Page not found"
-                            (not-found-doc)))))
+                            [:h1 "Page not found"]
+                            [:p "Thundering typhoons!  I think we lost it.  Sorry!"]))))

 (defroutes clojars-app
   (context "/repo" _


Using dopar in parallel-closures

Using dopar in parallel-closures

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

--- src/conexp/base.clj
+++ src/conexp/base.clj
@@ -869,15 +869,11 @@
     (if (< (count base) n)
       closures
       (let [next-current (atom current)]
-        (apply await
-               (for [C current]
-                 (let [a (agent nil)]
-                   (send a
-                         (fn [_]
-                           (when (not= (count C) n)
-                             (swap! next-current #(disj % C))
-                             (doseq [x base :when (not (contains? C x))]
-                               (swap! next-current #(conj % (clop (conj C x)))))))))))
+        (dopar [C current]
+          (when (not= (count C) n)
+            (swap! next-current #(disj % C))
+            (doseq [x base :when (not (contains? C x))]
+              (swap! next-current #(conj % (clop (conj C x)))))))
         (recur (inc n) (into closures @next-current) @next-current)))))


added test coverage for union reads

added test coverage for union reads

--- spec/untangled/client/impl/om_plumbing_spec.cljs
+++ spec/untangled/client/impl/om_plumbing_spec.cljs
@@ -9,11 +9,15 @@
     [untangled-spec.core :refer [specification behavior assertions provided component when-mocking]]))

 (specification "Local read can"
-  (let [state (atom {:top-level  :top-level-value
-                     :join       {:sub-key-1 [:item/by-id 1]
-                                  :sub-key-2 :sub-value-2}
-                     :item/by-id {1 {:survey/title "Howdy!" :survey/description "More stuff"}}
-                     :settings   {:tags nil}})
+  (let [state (atom {:top-level    :top-level-value
+                     :union-join   [:panel :a]
+                     :union-join-2 [:dashboard :b]
+                     :join         {:sub-key-1 [:item/by-id 1]
+                                    :sub-key-2 :sub-value-2}
+                     :item/by-id   {1 {:survey/title "Howdy!" :survey/description "More stuff"}}
+                     :settings     {:tags nil}
+                     :dashboard    {:b {:x 2 :y 1}}
+                     :panel        {:a {:x 1 :n 4}}})
         parser (partial (om/parser {:read impl/read-local}) {:state state})]

     (reset! i18n/*current-locale* "en-US")
@@ -22,11 +26,15 @@
       "read the app locale"
       (parser [:app/locale]) => {:app/locale "en-US"}

-      "read top-level queries"
-      {:top-level :top-level-value} => (parser [:top-level])
+      "read top-level properties"
+      (parser [:top-level]) => {:top-level :top-level-value}

       "read nested queries"
-      {:join {:sub-key-2 :sub-value-2}} => (parser [{:join [:sub-key-2]}])
+      (parser [{:join [:sub-key-2]}]) => {:join {:sub-key-2 :sub-value-2}}
+
+      "read union queries"
+      (parser [{:union-join {:panel [:x :n] :dashboard [:x :y]}}]) => {:union-join {:x 1 :n 4}}
+      (parser [{:union-join-2 {:panel [:x :n] :dashboard [:x :y]}}]) => {:union-join-2 {:x 2 :y 1}}

       "read queries with references"
       (parser [{:join [{:sub-key-1 [:survey/title :survey/description]}]}]) =>


Add icon component

Add icon component

--- src-cljs/frontend/components/pages/workflow.cljs
+++ src-cljs/frontend/components/pages/workflow.cljs
@@ -1,6 +1,7 @@
 (ns frontend.components.pages.workflow
   (:require [frontend.components.common :as common]
             [frontend.components.pieces.card :as card]
+            [frontend.components.pieces.icon :as icon]
             [frontend.components.pieces.status :as status]
             [frontend.components.templates.main :as main-template]
             [frontend.datetime :as datetime]


delete stray log line

delete stray log line

--- src-cljs/frontend/components/pages/workflow.cljs
+++ src-cljs/frontend/components/pages/workflow.cljs
@@ -30,7 +30,6 @@
     (component
       (let [{:keys [connection/total-count connection/offset connection/edges]} (om-next/props this)
             {:keys [empty-state prev-page-href next-page-href]} (om-next/get-computed this)]
-        (js/console.log (contains? (om-next/props this) :connection/total-count))
         (cond
           (not (contains? (om-next/props this) :connection/total-count))
           (html


Show synthetic sensors and devices

Show synthetic sensors and devices

Allow for marking them for colculation but don't allow for editing
details of device/sensor, e.g. period, unit, name, location etc.

--- src-cljs/kixi/hecuba/tabs/hierarchy/devices.cljs
+++ src-cljs/kixi/hecuba/tabs/hierarchy/devices.cljs
@@ -3,7 +3,7 @@
   (:require [cljs.core.async :refer [<! >! chan put!]]
             [om.core :as om :include-macros true]
             [sablono.core :as html :refer-macros [html]]
-            [kixi.hecuba.bootstrap :refer (static-text) :as bs]
+            [kixi.hecuba.bootstrap :as bs]
             [kixi.hecuba.tabs.hierarchy.data :refer (fetch-property fetch-devices fetch-sensors)]
             [clojure.string :as string]
             [kixi.hecuba.common :refer (log delete-resource) :as common]
@@ -27,6 +27,11 @@
              :on-change #(om/set-state! owner (conj path key) (.-value (.-target %1)))
              :class "form-control"
              :type "text"}]]])
+
+(defn static-text [data keys label]
+  [:div.form-group {:style {:padding-left "15px"}}
+   [:label {:for label} label]
+   [:p {:class "form-control-static"} (get-in data keys "")]])

 (defn checkbox [cursor owner path key label]
   [:div.checkbox {:style {:padding-left "15px"}}
@@ -211,6 +216,15 @@
      (text-input-control cursor owner [:sensors sensor_id] :resolution "Resolution")
      (checkbox cursor owner [:sensors sensor_id] :actual_annual "Calculated Field")]))

+(defn synthetic-sensor-edit-div [cursor owner]
+  (let [sensor_id   (:sensor_id cursor)]
+    [:div
+     [:li.list-group-item
+      (static-text cursor [:type] "Type")
+      (static-text cursor [:unit] "Unit")
+      (static-text cursor [:period] "Period")
+      (checkbox cursor owner [:sensors sensor_id] :actual_annual "Calculated Field")]]))
+
 (defn privacy-checkbox [cursor owner keys label]
   [:div.checkbox
    [:label
@@ -231,7 +245,8 @@
             device_id    (-> cursor :device :device_id)
             refresh-chan (om/get-shared owner :refresh)
             event-chan   (om/get-state owner :event-chan)
-            {:keys [status text]} state]
+            {:keys [status text]} state
+            synthetic?   (-> cursor :device :synthetic)]
         (html
          [:div
           (alert "alert alert-danger" [:p text] status "edit-device-form-alert" owner)
@@ -250,23 +265,30 @@
                         :class (str "btn btn-danger")
                         :onClick (fn [_]
                                    (put! event-chan {:event :editing :value false}))} "Cancel"]
-              [:button {:type "button"
-                        :class "btn btn-danger pull-right"
-                        :onClick (fn [_]
-                                   (delete-device property_id device_id event-chan refresh-chan))}
-               "Delete Device"]]]
+              (when-not synthetic?
+                [:button {:type "button"
+                          :class "btn btn-danger pull-right"
+                          :onClick (fn [_]
+                                     (delete-device property_id device_id event-chan refresh-chan))}
+                 "Delete Device"])]]
             [:h3 "Device"]
             (bs/static-text cursor [:device :device_id] "Device ID")
-            (bs/text-input-control cursor owner [:device :description] "Unique Description")
-            (bs/text-input-control cursor owner [:device :name] "Further Description")
-            (location-input cursor owner)
-            (privacy-checkbox cursor owner [:device :privacy] "Private")
+            (if-not synthetic?
+              [:div
+               (bs/text-input-control cursor owner [:device :description] "Unique Description")
+               (bs/text-input-control cursor owner [:device :name] "Further Description")
+               (location-input cursor owner)
+               (privacy-checkbox cursor owner [:device :privacy] "Private")]
+              [:div
+               (bs/static-text cursor [:device :description] "Unique Description")])
             [:h3 "Sensors"]
-            (let [sensors (into [] (remove #(:synthetic %) (:readings (:device cursor))))]
+            (let [sensors (into [] (:readings (:device cursor)))]
               (if (seq sensors)
                 [:ul.list-group
                  (for [sensor  sensors]
-                   (sensor-edit-div property_id sensor owner event-chan refresh-chan))]
+                   (if (:synthetic sensor)
+                     (synthetic-sensor-edit-div sensor owner)
+                     (sensor-edit-div property_id sensor owner event-chan refresh-chan)))]
                 [:p "No sensors found."]))]]])))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -388,13 +410,14 @@
              [:h3 "Sensors"]
              [:table.table.borderless
               [:thead
-               [:tr [:th "Type"] [:th "Header Rows"] [:th "Unit"] [:th "Period"]
+               [:tr [:th "Type"] [:th "Synthetic?"] [:th "Header Rows"] [:th "Unit"] [:th "Period"]
                 [:th "Resolution"] [:th "Calculated Field"]]]
               [:tbody
-               (for [sensor (remove :synthetic (:readings device))]
+               (for [sensor (:readings device)]
                  (let [{:keys [alias actual_annual]} sensor]
                    [:tr
                     [:td (:type sensor)]
+                    [:td (if (:synthetic sensor) "Yes" "No")]
                     [:td alias]
                     [:td (:unit sensor)]
                     [:td (:period sensor)]
@@ -421,7 +444,7 @@
             [:td (common/location-col location)]
             [:td (privacy-label privacy)]
             [:td (count (filter #(not (:synthetic %)) (:readings cursor)))]
-            [:td (string/join ", " (mapv :type (filter #(not (:synthetic %)) (:readings cursor))))]
+            [:td (string/join ", " (mapv :type (:readings cursor)))]
             [:td device_id]]))))))

@@ -452,8 +475,7 @@
         (let [sort-spec                   (:sort-spec cursor)
               {:keys [sort-key sort-asc]} sort-spec
               th-chan                     (om/get-state owner :th-chan)
-              ;; Don't show synthethic devices as they can't be edited by the user
-              devices                     (into [] (remove #(:synthetic %) (fetch-devices (-> properties :selected) properties)))
+              devices                     (into [] (fetch-devices (-> properties :selected) properties))
               table-id                    "sensors-table"]
           (html
            [:div.col-md-12 {:style {:overflow "auto"}}


Clean up code

Clean up code

--- src/main/clojure/conexp/fca/applications/wikidata.clj
+++ src/main/clojure/conexp/fca/applications/wikidata.clj
@@ -1,28 +1,36 @@
 (ns conexp.fca.applications.wikidata
-  (:require [conexp.fca.contexts :refer [attributes objects make-context incidence-relation]]
-            [conexp.fca.implications :refer [make-implication premise conclusion]]
+  (:require [conexp.fca.contexts :refer [attributes objects
+                                         make-context incidence-relation]]
+            [conexp.fca.implications :refer [make-implication premise
+                                             conclusion]]
             [conexp.fca.fast :refer :all]
             [conexp.io.contexts :refer :all]
             [clojure.java.io :as io]
+            [clojure.string :as str]
             [clojure.set :refer :all]
             [clj-http.client :as client]
             [clojure.data.json :as json])
   (:import org.apache.http.impl.client.HttpClientBuilder))

 (def ^:dynamic *sparql-endpoint*
+  "Wikidata SPARQL query endpoint URI"
   "https://query.wikidata.org/bigdata/namespace/wdq/sparql")

 (def ^:dynamic *tool-banner*
+  "tool banner to send with SPARQL queries"
   "#TOOL:conexp-clj, https://github.com/exot/conexp-clj")

 (def ^:dynamic *max-entities-per-query*
-  500)
+  "maximum number of entities requested in a single query (entities
+  will be split over multiple queries if above this threshold)" 500)

 (def ^:dynamic *query-delay*
+  "delay between two queries, in milliseconds"
   500)

 (defn- disable-cookies [^HttpClientBuilder builder
                         request]
+  "helper to disable cookie management in HTTP requests"
   (.disableCookieManagement builder))

 (defn sparql-query
@@ -56,14 +64,14 @@
 (defn- entity-id-from-uri
   "retrieve an entity id from a Wikidata entity URI"
   [uri]
-  (let [slash (clojure.string/last-index-of uri "/")]
+  (let [slash (str/last-index-of uri "/")]
     (subs uri (+ 1 slash))))

 (defn- label-query-for-entities
-  ""
+  "construct a query that retrieves labels for a list of entities, in a given language (default english)"
   [entities & {:keys [lang] :or {lang "en"}}]
   (str "SELECT ?entity ?label WHERE { VALUES ?entity {"
-       (clojure.string/join " "
+       (str/join " "
                             (map entity-add-sparql-prefix entities))
        "} ?entity rdfs:label ?label FILTER(LANG(?label)=\""
        lang
@@ -124,8 +132,8 @@
   [label]
   (subs label
         (+ 1
-           (clojure.string/last-index-of label "("))
-        (clojure.string/last-index-of label ")")))
+           (str/last-index-of label "("))
+        (str/last-index-of label ")")))

 (defn- unlabel-implication
   "turn an implication on labels into an implication on ids"
@@ -133,7 +141,6 @@
   (make-implication
    (map id-from-label (premise implication))
    (map id-from-label (conclusion implication))))
-

 (defn- pattern-for-premise
   "generate a graph pattern matching a premise"
@@ -143,7 +150,7 @@
                          property
                          " []"))]
     (str "?entity "
-         (clojure.string/join
+         (str/join
           ";\n    "
           (map to-clause premise))
          " .")))
@@ -173,7 +180,7 @@
      " WHERE {\n  "
      (pattern-for-premise body)
      "\n  "
-     (clojure.string/join
+     (str/join
       " UNION\n  "
       (map pattern-for-conclusion
            head))


Refactoring: get-job-results should call read-job-results and then rearange data into the tree structure

--- src/emender_jenkins/results.clj
+++ src/emender_jenkins/results.clj
@@ -134,6 +134,7 @@
                                                        preview-jobs-suffix stage-jobs-suffix prod-jobs-suffix)
           job-results (read-update-job-info job-list   preview-jobs-suffix stage-jobs-suffix prod-jobs-suffix)]
           (clojure.pprint/pprint job-results)
+          ;(spit "test.edn" (with-out-str (clojure.pprint/pprint job-results)))
           ;job-results (read-all-test-results configuration job-list)]
           (reset! results job-results)
           ;job-results))
@@ -144,12 +145,21 @@
     (into []
         (filter pred results)))

-(defn get-job-results
+(defn read-job-results
     [product version]
     (cond
         (and product version) (select-jobs @results #(and (= product (:product %)) (= version (:version %))))
         product               (select-jobs @results #(= product (:product %)))
         :else                 (into [] @results)))
+
+
+(defn get-job-results
+    [product version]
+    (let [results  (read-job-results product version)
+          products (all-products results)] ; set of all products read from test results
+          (into {}
+                (for [product products]
+                     [product (select-results-for-product product results)]))))

 (defn find-job-with-name
     [job-name]
@@ -160,3 +170,6 @@
     (if job-name
         (some #(= job-name (:job-name %)) @results)))

+; REPL testing
+;(def results (atom (clojure.edn/read-string (slurp "x.edn"))))
+


oops, fix misaligned icons and improve naming

--- frontend/components/aside.cljs
+++ frontend/components/aside.cljs
@@ -60,7 +60,7 @@
            [:a {:href (routes/v1-dashboard-path {:org org :repo repo :branch (name name-kw)})
                 :title (utils/display-branch name-kw)}
             (-> name-kw utils/display-branch (utils/trim-middle 23))]]
-          [:div.status {:role "button"}
+          [:div.statuses {:role "button"}
            (for [build display-builds]
              (sidebar-build build {:org org :repo repo :branch (name name-kw)}))]])))))


another bootstrap compatibility change (from @mfikes)

--- src/clj/com/rpl/specter/impl.cljx
+++ src/clj/com/rpl/specter/impl.cljx
@@ -12,7 +12,6 @@
             [clojure.string :as s]
             #+clj [com.rpl.specter.defhelpers :as dh]
             #+clj [riddley.walk :as riddley]
-;;            #+cljs [cljs.js :as cljs]
             )
   #+clj
   (:import [com.rpl.specter Util])
@@ -50,8 +49,8 @@
 #+cljs
 (defn macroexpand'
   [form]
-  (binding [cljs/*eval-fn* cljs/js-eval]
-    (cljs/eval (cljs/empty-state)
+  (binding [cljs.js/*eval-fn* cljs.js/js-eval]
+    (cljs.js/eval (cljs.js/empty-state)
       `(macroexpand (quote ~form))
       identity)))


Workaround for #515 suggested by @nealterrell. Fisk can be used by clicking on his identity card when the successful-run button becomes available.

--- src/clj/game/cards-identities.clj
+++ src/clj/game/cards-identities.clj
@@ -170,14 +170,15 @@
                           :msg "gain 1 [Credits]" :effect (effect (gain :credit 1))}}}

    "Laramy Fisk: Savvy Investor"
-   {:events {:successful-run {:req (req (and (#{:hq :rd :archives} target)
-                                             (empty? (let [successes (map first (turn-events state side :successful-run))]
-                                                       (do
-                                                         (prn successes)
-                                                         (filter #(not (= % :remote)) successes))))))
-                              :optional {:prompt "Force the Corp to draw 1 card?"
-                                         :yes-ability {:msg "force the Corp to draw 1 card"
-                                                       :effect (effect (draw :corp))}}}}}
+   {:abilities [{:msg "force the Corp to draw 1 card"
+                 :req (req (and run
+                                (some #{:hq :rd :archives} (:server run))
+                                (:no-action run)
+                                (not current-ice)
+                                (not (get-in @state [:per-turn (:cid card)]))
+                                (empty? (let [successes (map first (turn-events state side :successful-run))]
+                                          (filter #(not (= % :remote)) successes)))))
+                 :effect (req (effect (draw :corp)) (swap! state assoc-in [:per-turn (:cid card)] true))}]}

    "Leela Patel: Trained Pragmatist"
    {:events {:agenda-scored {:choices {:req #(and (not (:rezzed %)) (= (:side %) "Corp"))} :msg "add 1 unrezzed card to HQ"


link h1 "LambdaCD" to top page "/"

link h1 "LambdaCD" to top page "/"

--- src/clj/lambdacd/ui/ui_server.clj
+++ src/clj/lambdacd/ui/ui_server.clj
@@ -66,7 +66,8 @@
                       [:body
                         [:div {:class "app l-horizontal" }
                          [:div {:class "app__header"}
-                          [:h1 {:class "app__header__lambdacd"} "LambdaCD"]
+                          [:a {:href "/"}
+                            [:h1 {:class "app__header__lambdacd"} "LambdaCD"]]
                           (if pipeline-name
                             [:span {:class "app__header__pipeline-name" } pipeline-name])]
                          [:div {:id "app" }]]


Add 'Events You've Created' section to events page

--- src/cljs/elevent_client/core.cljs
+++ src/cljs/elevent_client/core.cljs
@@ -732,62 +732,60 @@

 ; TODO: abstract events and events-explore into single component
 (defn events-page []
-  (let [leave-event
-        (fn [attendee-id]
-          ; TODO: this doesn't delete schedules
-          (attendees-endpoint :delete
-                              (d/entity @attendees-db attendee-id)
-                              nil))]
-    #_[:div.sixteen.wide.column
-     [:div.ui.segment
-      [:div
-       [:div.ui.vertical.segment
-        [:div.ui.two.column.grid
-         [:div.column
-          [:h1.ui.header "Events You've Created"]]
-         [:div.right.aligned.column
-          [:a.ui.tiny.labeled.icon.button {:href (event-add-route)}
-           [:i.plus.icon]
-           "Add event"]]]]
-       [:div.ui.vertical.segment
-        [:div.ui.divided.items
-         (for [event (map (fn [[event-id attendee-id]]
-                            (assoc
-                              (into {} (d/entity @events-db event-id))
-                              :AttendeeId attendee-id))
-                          (d/q '[:find ?event-id ?attendee-id
-                                 :in $ ?user-id
-                                 :where
-                                 [?attendee-id :UserId  ?user-id]
-                                 [?attendee-id :EventId ?event-id]]
-                               @attendees-db
-                               (get-in @session [:user :UserId])))]
-           [:div.item
-            [:div.content
-             [:a.header {:href (event-route event)}
-              (:Name event)]
-             [:div.meta
-              [:strong "Date:"]
-              (let [start (from-string (:StartDate event))
-                    end   (from-string (:EndDate   event))]
-                (str (unparse datetime-formatter start)
-                     (when (after? end start)
-                       (str " to " (unparse datetime-formatter end)))))]
-             [:div.meta
-              [:strong "Venue:"]
-              (:Venue event)]
-             [:div.description
-              (:Description event)]
-             [:div.extra
-              [:a.ui.right.floated.small.button {:href (event-schedule-route event)}
-               "Your activities"
-               [:i.right.chevron.icon]]
-              [:a.ui.right.floated.small.button
-               {:on-click #(leave-event (:AttendeeId event))}
-               [:i.red.remove.icon]
-               "Leave event"]]]])]]]
-      [:div.ui.dimmer {:class (when (empty? @events) "active")}
-       [:div.ui.loader]]]
+  (let [leave-event (fn [attendee-id]
+                      ; TODO: this doesn't delete schedules
+                      (attendees-endpoint :delete
+                                          (d/entity @attendees-db attendee-id)
+                                          nil))
+
+        created-events (map #(into {} (d/entity @events-db %))
+                            (d/q '[:find [?event-id ...]
+                                   :in $ ?user-id
+                                   :where
+                                   [?event-id :CreatorId  ?user-id]]
+                                 @events-db
+                                 (get-in @session [:user :UserId])))]
+    [:div.sixteen.wide.column
+     (when (seq created-events)
+       [:div.ui.segment
+        [:div
+         [:div.ui.vertical.segment
+          [:div.ui.two.column.grid
+           [:div.column
+            [:h1.ui.header "Events You've Created"]]
+           [:div.right.aligned.column
+            [:a.ui.tiny.labeled.icon.button {:href (event-add-route)}
+             [:i.plus.icon]
+             "Add event"]]]]
+         [:div.ui.vertical.segment
+          [:div.ui.divided.items
+           (for [event created-events]
+             [:div.item
+              [:div.content
+               [:a.header {:href (event-route event)}
+                (:Name event)]
+               [:div.meta
+                [:strong "Date:"]
+                (let [start (from-string (:StartDate event))
+                      end   (from-string (:EndDate   event))]
+                  (str (unparse datetime-formatter start)
+                       (when (after? end start)
+                         (str " to " (unparse datetime-formatter end)))))]
+               [:div.meta
+                [:strong "Venue:"]
+                (:Venue event)]
+               [:div.description
+                (:Description event)]
+               [:div.extra
+                [:a.ui.right.floated.small.button {:href (event-schedule-route event)}
+                 "Your activities"
+                 [:i.right.chevron.icon]]
+                [:a.ui.right.floated.small.button
+                 {:on-click #(leave-event (:AttendeeId event))}
+                 [:i.red.remove.icon]
+                 "Leave event"]]]])]]]
+        [:div.ui.dimmer {:class (when (empty? @events) "active")}
+         [:div.ui.loader]]])
      [:div.ui.segment
       [:div
        [:div.ui.vertical.segment


Only show JavaScript errors to users when debug? flag is on (#797)

--- src/cljs/main/broadfcui/main.cljs
+++ src/cljs/main/broadfcui/main.cljs
@@ -188,7 +188,11 @@
            (cond
              (not (:config-loaded? @state))
              [config-loader/Component
-              {:on-success #(swap! state assoc :config-loaded? true)}]
+              {:on-success (fn []
+                             (swap! state assoc :config-loaded? true)
+                             (when (config/debug?)
+                               (.addEventListener
+                                js/window "error" (fn [e] (show-js-exception e)))))}]
              (and (not (contains? user-status :signed-in)) (nil? component))
              [:h2 {} "Page not found."]
              public?
@@ -219,7 +223,8 @@
      (modal/set-instance! (@refs "modal"))
      (swap! locals assoc :hash-change-listener (partial react/call :handle-hash-change this))
      (.addEventListener js/window "hashchange" (:hash-change-listener @locals))
-     (.addEventListener js/window "error" (fn [e] (show-js-exception e))))
+     (aset js/window "testJsException"
+           (fn [] (js/setTimeout #(throw (js/Error. "You told me to do this.")) 100) nil)))
    :component-will-receive-props
    (fn []
      (init-nav-paths))


used a DRYer on the lobby select code

used a DRYer on the lobby select code

--- src/cljs/netrunner/gamelobby.cljs
+++ src/cljs/netrunner/gamelobby.cljs
@@ -216,10 +216,11 @@
             [:button {:class "disabled"} "New game"]
             [:button {:on-click #(new-game cursor owner)} "New game"])
           [:div.float-right "Lobby: "
-           [:select.lobbies {:value (om/get-state owner :current-lobby)
-                     :on-change #(om/set-state! owner :current-lobby (.. % -target -value))}
-            [:option {:value "casual"} (str "Casual (" (count (filter #(= "casual" (:lobby %)) games)) ")")]
-            [:option {:value "competitive"} (str "Competitive (" (count (filter #(= "competitive" (:lobby %)) games)) ")")]]]]
+           (let [count-games (fn [lobby] (count (filter #(= lobby (:lobby %)) games)))]
+             [:select.lobbies {:value (om/get-state owner :current-lobby)
+                               :on-change #(om/set-state! owner :current-lobby (.. % -target -value))}
+              [:option {:value "casual"} (str "Casual (" (count-games "casual") ")")]
+              [:option {:value "competitive"} (str "Competitive (" (count-games "competitive") ")")]])]]
          (game-list cursor owner)]

         [:div.game-panel


Get log output in analyse-board optional.

--- src/clojure/clj_chess/analyse.clj
+++ src/clojure/clj_chess/analyse.clj
@@ -19,7 +19,8 @@

 (defn analyse-board [engine board & {depth :depth time :time nodes :nodes
                                      finish-iteration? :finish-iteration?
-                                     search-moves :search-moves}]
+                                     search-moves :search-moves
+                                     log-output :log-output}]
   (if-not (= 1 (count (keep identity [depth time nodes])))
     (throw (Exception. "Exactly one of :depth, :time and :nodes must be supplied"))
     (let [command (go-command depth time nodes finish-iteration? search-moves)
@@ -42,7 +43,8 @@
                        (> (:depth parsed-line)
                           (:depth pv)))
               (uci/send-command engine "stop"))
-            (when parsed-line (prn parsed-line))
+            (when (and parsed-line log-output)
+              (prn parsed-line))
             (recur (<!! engine-output)
                    (if pv?
                      parsed-line


insights: allow d3 __data__ will track right value

- use extra filler bars instead of using a fake range

--- src-cljs/frontend/components/insights.cljs
+++ src-cljs/frontend/components/insights.cljs
@@ -122,7 +122,8 @@
         (.text #(aget % "text")))))

 (defn visualize-insights-bar! [el builds]
-  (let [bar-count 60
+  (let [max-bar-count 60
+        builds (take max-bar-count builds)
         y-max (apply max (mapcat #((juxt :queued_time_minutes :build_time_minutes) %)
                                  builds))
         plot-info {:width (- (:width svg-info) (:left svg-info) (:right svg-info))
@@ -147,9 +148,10 @@
                    (.orient "left")
                    (.tickValues (clj->js y-tick-values))
                    (.tickFormat js/Math.abs))
+        scale-filler (map (partial str "xx-") (range (- max-bar-count (count builds))))
         x-scale (-> (js/d3.scale.ordinal)
                     (.domain (clj->js
-                              (range bar-count)))
+                              `(~@(map :build_num builds) ~@scale-filler)))
                     (.rangeBands #js[0 (:width plot-info)] 0.5))
         svg (-> js/d3
                 (.select el)
@@ -170,7 +172,7 @@
         (.insert "rect")
         (.attr #js {"class" #(str "bar " (aget % "outcome"))
                     "y" #(y-pos-scale (aget % "build_time_minutes"))
-                    "x" (fn [_ i]  (x-scale i))
+                    "x" #(x-scale (aget % "build_num"))
                     "width" (.rangeBand x-scale)
                     "height" #(- y-middle (y-pos-scale (aget % "build_time_minutes")))}))

@@ -179,7 +181,7 @@
         (.insert "rect")
         (.attr #js {"class" "bar queue"
                     "y" y-middle
-                    "x" (fn [_ i]  (x-scale i))
+                    "x" #(x-scale (aget % "build_num"))
                     "width" (.rangeBand x-scale)
                     "height" #(- (y-neg-scale (aget % "queued_time_minutes")) y-middle)}))


Review comment: make a large-ish dropping buffer for JS listen! consumers.

--- src/common/datomish/transact.cljc
+++ src/common/datomish/transact.cljc
@@ -648,8 +648,9 @@
   (a/tap (:listener-mult conn) listener-sink)
   listener-sink)

-(defn- -listen-chan [f]
-  (let [c (a/chan (a/sliding-buffer 10))]
+(defn- -listen-chan
+  [f n]
+  (let [c (a/chan (a/dropping-buffer n))]
     (go-loop []
       (when-let [v (<! c)]
         (do
@@ -664,8 +665,11 @@

   Returns the channel listened to, for future calls to `unlisten-chan!`."
   ([conn f]
-   {:pre [(fn? f)]}
-   (listen-chan! conn (-listen-chan f))))
+   ;; Decently large buffer before dropping, for JS consumers.
+   (listen! conn f 1024))
+  ([conn f n]
+   {:pre [(fn? f) (pos? n)]}
+   (listen-chan! conn (-listen-chan f n))))

 (defn unlisten-chan! [conn listener-sink]
   "Stop putting reports successfully transacted against the given connection onto the given channel."


Removed flush elastic index added for get index-set changes.

--- test/cmr/system_int_test/search/granule_search_index_name_test.clj
+++ test/cmr/system_int_test/search/granule_search_index_name_test.clj
@@ -13,9 +13,6 @@
 (defn set-config-then-reset-fixture
   [f]
   (try
-    ;; flush the elastic index so that the updated index-set doc will be available
-    (index/flush-elastic-index)
-
     ;; This set up the environment variable that configures which collection will
     ;; have its own granule index. This is only for working in the REPL.
     ;; When this test is run in CI the set variable will not influence the cmr-search-app


Fix bug

Fix bug

--- 002.transcribing-dna-to-rna/dna-to-rna.clj
+++ 002.transcribing-dna-to-rna/dna-to-rna.clj
@@ -1,3 +1,3 @@
 (print (clojure.string/replace
   (slurp
-    (first *command-line-args*)) "T" "U"))
+    (second *command-line-args*)) "T" "U"))


Use Langohr 1.6.0

Use Langohr 1.6.0

--- clojure/project.clj
+++ clojure/project.clj
@@ -4,4 +4,4 @@
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
   :dependencies [[org.clojure/clojure     "1.5.1"]
-                 [com.novemberain/langohr "1.5.0"]])
+                 [com.novemberain/langohr "1.6.0"]])


correct loop recur.

correct loop recur.

--- clojure/etl/etl.clj
+++ clojure/etl/etl.clj
@@ -6,10 +6,10 @@
          (zipmap tiles (repeat score))))

 (defn transform [definitions]
-  (loop [[
-          [score tiles] & others] (seq definitions)
-          acc {}]
-    (if (first others)
+  (loop [
+         [[score tiles] & others] (seq definitions)
+         acc {}]
+    (if others
       (recur others (merge-scores acc tiles score))
-      (merge-scores acc tiles score)
-      )))
+      (merge-scores acc tiles score))
+    ))


Fixed typo in hyphens rule.

Fixed typo in hyphens rule.

Simple typo fixed hypens -> hyphens.

--- src/day8/re_frame_10x/styles.cljs
+++ src/day8/re_frame_10x/styles.cljs
@@ -476,7 +476,7 @@
      "-ms-hyphens"     "auto"
      "-moz-hyphens"    "auto"
      "-webkit-hyphens" "auto"
-     "hypens"          "auto"}]])
+     "hyphens"          "auto"}]])

 (def highlight-js-solarized
   ;; From https://github.com/isagalaev/highlight.js/blob/master/src/styles/solarized-light.css


add twitter authorization function

add twitter authorization function

--- src/ghostly/momonga/twitter.clj
+++ src/ghostly/momonga/twitter.clj
@@ -7,6 +7,32 @@
                            RequestToken)))

 (def *twitter* (TwitterFactory/getSingleton))
+
+
+(defn consumer-key-set! [consumer-key consumer-secret]
+  (.setOAuthConsumer *twitter* consumer-key consumer-secret))
+
+
+(defn request-token []
+  (.getOAuthRequestToken *twitter*))
+
+
+(defn authorization-url
+  ([]
+     (let [rtoken (request-token)]
+       (authorization-url rtoken)))
+  ([rtoken]
+     (.getAuthorizationURL rtoken)))
+
+
+(defn access-token [rtoken pin]
+  (let [atoken (.getOAuthAccessToken *twitter* rtoken pin)]
+    (store-access-token atoken)
+    atoken))
+
+
+(defn- store-access-token [atoken]
+  )

 (defn post [msg]


refactor version extraction from tag

refactor version extraction from tag

--- src/github_changelog/semver.clj
+++ src/github_changelog/semver.clj
@@ -1,6 +1,6 @@
 (ns github-changelog.semver
   (:require [clj-semver.core :as semver]
-            [clojure.string :refer [replace-first]]))
+            [clojure.string :refer [starts-with?]]))

 (def newer? semver/newer?)

@@ -9,8 +9,10 @@
        (catch java.lang.AssertionError _e nil)))

 (defn extract [tag-name prefix]
-  (let [pattern (re-pattern (str "^" prefix))]
-    (parse (replace-first tag-name pattern ""))))
+  (parse
+   (if (starts-with? tag-name prefix)
+    (subs tag-name (count prefix))
+    tag-name)))

 (defn get-type [{:keys [minor patch pre-release build]}]
   (cond


Set image background color to white

Set image background color to white

--- src/export_server/browser/raw.clj
+++ src/export_server/browser/raw.clj
@@ -11,7 +11,8 @@
            (org.openqa.selenium.phantomjs PhantomJSDriver PhantomJSDriverService)
            (javax.imageio ImageIO)
            (java.io ByteArrayInputStream ByteArrayOutputStream)
-           (java.awt.image BufferedImage)))
+           (java.awt.image BufferedImage)
+           (java.awt Color)))

 ;=======================================================================================================================
@@ -102,6 +103,8 @@
         ; new-img (.getSubimage img 0 0 (:image-width options) (:image-height options))
         new-img (BufferedImage. (:image-width options) (:image-height options) (.getType img))
         g (.getGraphics new-img)
+        _ (.setColor g Color/WHITE)
+        _ (.fillRect g 0 0 (:image-width options) (:image-height options))
         _ (.drawImage g img 0 0
                       (min (.getWidth img) (:image-width options))
                       (min (.getHeight img) (:image-height options))


Fixed issue #52

Fixed issue #52

--- src/clojure/alfresco_technical_validation/impl/validations/stb.clj
+++ src/clojure/alfresco_technical_validation/impl/validations/stb.clj
@@ -123,6 +123,8 @@
                            AND NOT(n.package =~ 'org.gradle.*')
                            AND NOT(n.package =~ 'proguard.*')
                            AND HAS(m.name)
+                           AND (NOT HAS(n.type)
+                                OR n.type = 'class')
                            AND m.name IN [
                                            'org.alfresco.service.cmr.search.ResultSet',
                                            'java.io.Closeable',


Remove dead code

Remove dead code

--- src/braid/client/quests/subscriptions.cljs
+++ src/braid/client/quests/subscriptions.cljs
@@ -1,10 +1,6 @@
 (ns braid.client.quests.subscriptions
   (:require [reagent.ratom :include-macros true :refer-macros [reaction]]
             [braid.client.state.subscription :refer [subscription]]))
-
-(defmethod subscription :quest-completed?
-  [state [_ quest-id]]
-  (reaction (contains? (get-in @state [:user :completed-quest-ids]) quest-id)))

 (defmethod subscription :completed-quest-count
   [state _]


more cleanup

more cleanup

--- src/babel/index.cljc
+++ src/babel/index.cljc
@@ -3,28 +3,7 @@
   (:require
    #?(:clj [clojure.tools.logging :as log])
    #?(:cljs [babel.logjs :as log])
-   [dag_unify.core :refer [fail? dissoc-paths get-in label-of
-                           strip-refs unify]]))
-
-(defn exception [error-string]
-  #?(:clj
-     (throw (Exception. error-string)))
-  #?(:cljs
-     (throw (js/Error. error-string))))
-
-(defn show-spec [spec]
-  (cond (seq? spec)
-        (map show-spec spec)
-        true
-        (strip-refs (dissoc-paths spec '((:english :initial)
-                                         (:italiano :initial)
-                                         (:synsem :essere)
-                                         (:synsem :agr)
-                                         (:synsem :pronoun)
-                                         (:synsem :sem :tense)
-                                         (:synsem :sem :obj :tense)
-                                         (:synsem :sem :mod)
-                                         (:synsem :infl))))))
+   [dag_unify.core :refer [get-in unify]]))

 (defn map-subset-by-path2 [vals-at-path lexemes path]
   (if (not (empty? vals-at-path))


Can now infer clojure.core/for returns a seq

--- src/hiccup/core.clj
+++ src/hiccup/core.clj
@@ -111,6 +111,13 @@
   (and (not (uneval? x))
        (or (not (vector? x))
            (every? literal? x))))
+
+(defn- not-implicit-map?
+  "True if we can infer that x is not a map."
+  [x]
+  (or (and (seq? x) (= (first x) `for))
+      (not (uneval? x))
+      (not-hint? x Map)))

 (declare compile-html)

@@ -151,7 +158,7 @@
     (and (literal? tag) (map? attrs))
       (compile-lit-tag+attrs tag attrs content)
     ;; e.g. [:span #^String x]
-    (and (literal? tag) (or (not (uneval? attrs)) (not-hint? attrs Map)))
+    (and (literal? tag) (not-implicit-map? attrs))
       (compile-lit-tag+attrs tag {} (cons attrs content))
     ;; e.g. [:span x]
     (literal? tag)
@@ -171,7 +178,7 @@

 (defmethod compile-form `for
   [[_ bindings & body]]
-  `(for ~bindings ~@(compile-html body)))
+  `(apply str (for ~bindings ~@(compile-html body))))

 (defmethod compile-form :default
   [expr]


Removed unused api route for creating downloadable clojure files.

--- src/clj_formal_specifications_app/core.clj
+++ src/clj_formal_specifications_app/core.clj
@@ -11,15 +11,7 @@
     (resp/resource-response "index.html" {:root "public"})
     "text/html"))

-(defn as-clj-file
-  [fname contents]
-  {:status 200
-   :body contents
-   :headers {"Content-Disposition" (str "attachment; filename=\"" fname "\"")
-             "Content-Type" "text/plain"}})
-
-(defroutes api-routes
-  (POST "/api/export" [contents] (as-clj-file "specification.clj" contents)))
+(defroutes api-routes)

 (defroutes site-routes
   (GET "/" [] index)


disable tag validation

disable tag validation

--- src/main/clojure/clojure/tools/analyzer/passes/js/validate.clj
+++ src/main/clojure/clojure/tools/analyzer/passes/js/validate.clj
@@ -24,16 +24,18 @@
   (let [tag (ast t)]
     (if (symbol? tag)
       (if-let [var (resolve-var tag env)]
-        (if (or (= :type (:op var))
+        (symbol (str (:ns var)) (str (:name var)))
+        #_(if (or (= :type (:op var))
                 (:protocol (meta var)))
-          (symbol (:ns var) (:name var))
-          (throw (ex-info (str "Not type/protocol var used as a tag: " t)
+          (symbol (str (:ns var)) (str (:name var)))
+          (throw (ex-info (str "Not type/protocol var used as a tag: " tag)
                           (merge {:var var
                                   :ast (prewalk ast cleanup)}
                                  (source-info env)))))
-        (if (or ('#{boolean string number clj-nil any function object array} tag)
+        tag
+        #_(if (or ('#{boolean string number clj-nil any function object array} tag)
                 (and (namespace tag)
-                     (not (resolve-ns (symbol (namespace tag))))))
+                     (not (resolve-ns (symbol (namespace tag)) env))))
           tag
           (throw (ex-info (str "Cannot resolve: " tag)
                           (merge {:sym tag


better docstrings, some simplification

better docstrings, some simplification

--- src/io/exo/jobs.clj
+++ src/io/exo/jobs.clj
@@ -5,24 +5,18 @@
             [compojure.handler    :as handler]
             [compojure.route      :as route]
             [compojure.core       :refer [defroutes GET POST DELETE context]]
-            [ring.util.response   :refer [response content-type
-                                          status redirect]]))
+            [ring.util.response   :refer [response content-type redirect]]))

 (def ^{:doc "Atom holding our jobs"} db (atom {}))

-(defn uuid
-  "A random UUID"
-  []
-  (str (java.util.UUID/randomUUID)))
-
 (defn create!
-  "Insert a new job"
+  "Insert a new job with a random ID, yields the updated job map"
   [job]
-  (let [id (uuid)]
+  (let [id (str (java.util.UUID/randomUUID))]
     (swap! db assoc id (assoc job :id id))))

 (defn delete!
-  "Remove a job"
+  "Remove a job, yields the updated map"
   [id]
   (swap! db dissoc id))

@@ -37,8 +31,7 @@
 (defroutes job-api
   (GET  "/" []             (redirect "/index.html"))
   (GET  "/jobs" []         (response @db))
-  (POST "/jobs" req        (-> (response (create! (:body req)))
-                               (status 201)))
+  (POST "/jobs" req        (response (create! (:body req))))
   (DELETE "/jobs/:id" [id] (response (delete! id)))
   (route/resources         "/")
   (route/not-found         "
404
"))


Agh quotes

Agh quotes

--- src/korhal/core.clj
+++ src/korhal/core.clj
@@ -50,13 +50,13 @@

 (defn korhal-gameUpdate [this]

-  (println 'updating')
+  (println "updating")

   ;; spawn a drone
   (for [unit (.getMyUnits (:api @this))]
     (when (= (.getTypeID unit) (.getID jnibwapi.types.UnitType$UnitTypes/Zerg_Larva))
       (when (and (>= (.. (:api @this) getSelf getMinerals) 50) (not (:morphed-drone this)))
-        (println 'morphing a drone')
+        (println "morphing a drone")
         (.morph (:api @this) (.getID unit) (.getID jnibwapi.types.UnitType$UnitTypes/Zerg_Drone))
         (swap-keys (.state this) :morphed-drone true))))

@@ -64,7 +64,7 @@
   (for [unit (.getMyUnits (:api @this))]
     (when (= (.getTypeID unit) (.getID jnibwapi.types.UnitType$UnitTypes/Zerg_Drone))
       (when (and (.isIdle unit) (not (= (.getID unit) (:pool-drone @this))))
-        (println 'collecting minerals')
+        (println "collecting minerals")
         (let [mineral? (fn [unit] (= (.getTypeID unit) (.getID jnibwapi.types.UnitType$UnitTypes/Resource_Mineral_Field)))
               mineral (first (filter mineral? (.getNeutralUnits (:api @this))))]
         (.rightClick (.getID unit) (.getID mineral)))))))


destructure if-exists

destructure if-exists

--- src/er_cassandra/model/alia/unique_key.clj
+++ src/er_cassandra/model/alia/unique_key.clj
@@ -328,6 +328,7 @@
     entity :- Entity
     record :- t/MaybeRecordSchema
     {:keys [if-not-exists
+            if-exists
             only-if] :as opts} :- fns/UpsertOptsWithTimestampSchema]
    (with-context deferred-context
      (mlet [primary-table-name (get-in entity [:primary-table :name])


Add oolong.utils/func-or-sym

Add oolong.utils/func-or-sym

--- src/irresponsible/oolong/util.clj
+++ src/irresponsible/oolong/util.clj
@@ -78,6 +78,16 @@
   [form config]
   ((load-symbol form) config))

+(defn func-or-sym
+  "Runs the function either provided or named by the provided symbol
+   args: [form config]
+   returns: whatever form returns
+   throws: if invalid"
+  [form config]
+  (cond (fn? form)        (form config)
+        (qualisym? form)  (run-symbol form config)
+        :else (fatal "Expected function or qualified symbol" {:got form})))
+
 ;; ## Internal functions
 ;;
 ;; These functions deal with the brewing of components and systems


Changed RSS template to use post summaries instead of full contents.

--- src/lambda_blog/templates/rss.clj
+++ src/lambda_blog/templates/rss.clj
@@ -4,8 +4,10 @@
             [ring.util.codec :refer [url-encode]]
             [s-html.tags :refer [deftags link xml] :as tags]))

-(deftags [author category content entry feed id name published updated])
-(def _author author)
+(deftags [author category entry feed id name published summary updated])
+
+(def _author author) ;; FIXME Loose the _.
+(def _summary summary)

 (defn rss-feed [{:keys [entries title url]}]
   [(xml)
@@ -16,11 +18,11 @@
          (link {:href url})
          (updated (now))
          (id url)
-         (map (fn [{:keys [author contents filename path-to-root tags timestamp title]}]
+         (map (fn [{:keys [author filename path-to-root summary tags timestamp title]}]
                 (entry (tags/title {:type :html}
                                    title)
                        (id filename)
-                       (_author (name author)) ;; FIXME Loose the _author.
+                       (_author (name author))
                        (updated timestamp)
                        (published timestamp)
                        (link {:href (path path-to-root filename)})
@@ -29,6 +31,6 @@
                                          :term t
                                          :label t}))
                             tags)
-                       (content {:type :html}
-                                contents)))
+                       (_summary {:type :html}
+                                summary)))
               entries))])


Associative抽象

Associative抽象

--- src/learnclojure/chapt3/core4.clj
+++ src/learnclojure/chapt3/core4.clj
@@ -1,4 +1,5 @@
-(ns learnclojure.chapt3.core4)
+(ns learnclojure.chapt3.core4
+  (:import (java.util HashMap)))
 ;;Associative抽象
 ;;关系型数据结构Associative接口抽象的是把一个key和一个value关联起来的数据结构
 ;;这个接口有四个操作：
@@ -32,5 +33,40 @@
   1 4
   0 -12
   2 :p)
+;;可以用assoc实现和conj一样的效果，把一个值添加到vector最后，但需要显式的告诉vector新的下标
+(assoc v 3 "ddd")
+;;get还能操作set，如果一个key在set中存在，会返回它
+(def s #{1 2 4})
+(get s 1)
+(get s 3)
+(get s 3 "not found!")
+;;它的返回值意味着set里面是值到值本身的映射，这使得set可以满足get的语义，同时也和条件判断里的经典用法一致
+(if (get s 3)
+  (print "it contains '3'")
+  (print "it doesn't contain '3'"))
+;;clojure中map和set本身就支持get语义
+(s 1)
+(m :b)
+
+;;contains?是一个谓词，作用是检查集合中是否包含指定的key
+(contains? m :d)
+(contains? v 3)
+(contains? s 3)
+;;初学者会用contains？检测vector中是否含有指定的值，这是不对的.contains？检测是集合中是否包含某个key
+;;检测集合中是否包含某个值用some
+
+;;get和contains？非常同意，可以高效的操作vector,map,set,java里的map，字符串以及java数组
+(get "clojure" 3)
+(contains? (HashMap.) 1)
+(get (into-array [1 2 3]) 0)
+
+;;小心nil
+;;如果集合中不包含某个key，调用的时候也没有设置默认值,那么会返回nil、但这个key对于的值也可能是nil
+(get {:ethl nil} :ethl)
+;;那么怎么知道是没有这个key还是这个key的值是nil呢？
+;;我们可以使用find，它返回的是键值对如果map里包含指定的key的话，返回nil如果不包含这个key
+(find {:ethl nil} :ethl)
+(find {:ethl nil} :r)

+


Fixed small bug in appengine-clean Leiningen task.

--- src/leiningen/appengine_clean.clj
+++ src/leiningen/appengine_clean.clj
@@ -5,12 +5,13 @@

 (defn appengine-clean [project]
-  (println "cleaning out App Engine application" (:appengine-display-name project))
-  (let [resources-dir (File. (:resources-path project))
+  (let [prj-application (or (:appengine-application project) (:name project))
+        resources-dir (File. (:resources-path project))
         war-dir (File. resources-dir "war")
         WEB-INF-dir (File. war-dir "WEB-INF")
         target-classes-dir (File. WEB-INF-dir "classes")
         target-lib-dir (File. WEB-INF-dir "lib")]
+    (println "cleaning out App Engine application" prj-application)
     ;; delete existing content of target classes/ and lib/
     (lancet/delete {:dir (.getPath target-classes-dir)})
     (lancet/delete {:dir (.getPath target-lib-dir)})))


Shutdown agents after compilation to avoid waiting

Fixes #119.

--- src/leiningen/droid/compile.clj
+++ src/leiningen/droid/compile.clj
@@ -162,7 +162,8 @@
           `(binding [*compiler-options* ~opts]
              (doseq [namespace# '~nses]
                (println "Compiling" namespace#)
-               (clojure.core/compile namespace#)))
+               (clojure.core/compile namespace#))
+             (shutdown-agents))
           project (update-in project [:prep-tasks]
                              (partial remove #{"compile"}))]
       (.mkdirs (io/file (:compile-path project)))


Add scholar cmd

Add scholar cmd

--- src/bolt/config.cljs
+++ src/bolt/config.cljs
@@ -17,6 +17,7 @@
     :lastfm {:url "http://www.last.fm/search?q=%s"}
     :clojuredocs {:alias "cd" :url "http://clojuredocs.org/search?q=%s"}
     :flickr {:alias "fl" :url "http://www.flickr.com/search/?q=%s"}
+    :scholar {:alias "sc" :url "https://scholar.google.com/scholar?q=%s"}

     ;; just for voice
     :github {:alias "gh" :url "https://github.com/search?q=%s&ref=simplesearch"}


Use edn/read-string when parsing numbers.

--- src/lunchlotto/common/utils.clj
+++ src/lunchlotto/common/utils.clj
@@ -11,7 +11,7 @@
   [s]
   (if (and (not (nil? s))
            (re-find #"^-?\d+\.?\d*$" s))
-    (read-string s)))
+    (edn/read-string s)))

 (defn make-translation-dictionary
   "Loads the given EDN file and returns a function that can be used to look up


updated media ns for newer rtc spec

updated media ns for newer rtc spec

--- src/cellf/media.cljs
+++ src/cellf/media.cljs
@@ -1,27 +1,15 @@
 (ns cellf.media
   (:require [cljs.core.async :refer [chan put!]]))

-(def prefixes ["webkit" "moz" "ms"])
-
-(defn find-native [obj fn-name]
-  (let [cap-name (str (.toUpperCase (first fn-name)) (apply str (rest fn-name)))]
-    (loop [names (cons fn-name (map #(str % cap-name) prefixes))]
-      (when (seq names)
-        (if-let [f (aget obj (first names))]
-          (.bind f obj)
-          (recur (rest names)))))))
-
-
 (defn get-media
   ([]
-   (get-media {:video true :audio false}))
+   (get-media {:video {:facingMode "user"} :audio false}))
   ([opts]
    (let [c (chan)]
-     (if-let [native-gum (find-native js/navigator "getUserMedia")]
-       (native-gum
-         (clj->js opts)
-         #(put! c {:status :success
-                   :data   (.createObjectURL js/URL %)})
-         #(put! c {:status :error :data :denied}))
+     (if (.-mediaDevices js/navigator)
+       (->
+         (.getUserMedia (.-mediaDevices js/navigator) (clj->js opts))
+         (.then  #(put! c {:status :success :data %}))
+         (.catch #(put! c {:status :error :data :denied})))
        (put! c {:status :error :data :unsupported}))
      c)))


Add label to SVG axis helper.

Add label to SVG axis helper.

--- src/cljx/c2/svg.cljx
+++ src/cljx/c2/svg.cljx
@@ -3,13 +3,13 @@
 ;;Coordinates to any fn can be 2-vector `[x y]` or map `{:x x :y y}`.
 ^:clj (ns c2.svg
         (:use [c2.maths :only [Pi Tau radians-per-degree
-                               sin cos]]
+                               sin cos mean]]
               [clojure.core.match :only [match]]))

 ^:cljs (ns c2.svg
          (:use-macros [clojure.core.match.js :only [match]])
          (:use [c2.maths :only [Pi Tau radians-per-degree
-                                sin cos]])
+                                sin cos mean]])
          (:require [c2.dom :as dom]))

@@ -22,7 +22,7 @@

 (defn translate [coordinates]
   (let [[x y] (->xy coordinates)]
-       (str "translate(" x "," y ")")))
+    (str "translate(" x "," y ")")))

 (defn scale [coordinates]
   (match [coordinates]
@@ -84,15 +84,22 @@

    > *:major-tick-width* width of ticks (minor ticks not yet implemented), defaults to 6

-   > *:text-margin* distance between axis and start of text, defaults to 9"
+   > *:text-margin* distance between axis and start of text, defaults to 9
+
+   > *:label* axis label, centered on axis; :left and :right orientation labels are rotated by +/- pi/2, respectively
+
+   > *:label-margin* distance between axis and label, defaults to 28"
   [scale ticks & {:keys [orientation
                          formatter
                          major-tick-width
-                         text-margin]
+                         text-margin
+                         label
+                         label-margin]
                   :or {orientation :left
                        formatter str
                        major-tick-width 6
-                       text-margin 9}}]
+                       text-margin 9
+                       label-margin 28}}]

   (let [[x y x1 x2 y1 y2] (match [orientation]
                                  [(:or :left :right)] [:x :y :x1 :x2 :y1 :y2]
@@ -102,13 +109,25 @@
                       [(:or :left :top)] -1
                       [(:or :right :bottom)] 1)]

-    (into [:g {:class (str "axis " (name orientation))}
-           [:line.rule (apply hash-map (interleave [y1 y2] (:range scale)))]]
-          (map (fn [d]
-                 [:g.tick.major-tick {:transform (translate {x 0 y (scale d)})}
-                  [:text {x (* parity text-margin)} (formatter d)]
-                  [:line {x1 0 x2 (* parity major-tick-width)}]])
-               ticks))))
+    [:g {:class (str "axis " (name orientation))}
+     [:line.rule (apply hash-map (interleave [y1 y2] (:range scale)))]
+
+     (map (fn [d]
+            [:g.tick.major-tick {:transform (translate {x 0 y (scale d)})}
+             [:text {x (* parity text-margin)} (formatter d)]
+             [:line {x1 0 x2 (* parity major-tick-width)}]])
+          ticks)
+
+     (when label
+       [:text.label {:transform (str (translate {x (* parity label-margin)
+                                                 y (mean (:range scale))})
+                                     " "
+                                     (match [orientation]
+                                            [:left] (rotate -90)
+                                            [:right] (rotate 90)
+                                            :else ""))}
+        label])
+     ]))

 (def ArcMax (- Tau 0.0000001))


fix namespace error

fix namespace error

--- src/codestat/git.clj
+++ src/codestat/git.clj
@@ -259,7 +259,7 @@
        (group-by :author_name
                  (distinct
                    (map #(select-keys % [:author_name :vcs_url])
-                        (query-commit))))))
+                        (mysql/query-commit))))))

@@ -273,13 +273,13 @@
        (group-by :author_name
                  (distinct
                    (map #(select-keys % [:author_name :id])
-                        (query-commit))))))
+                        (mysql/query-commit))))))

 (defn- get-author-by-commit-id
   [commit-id]
   (:author_name (first
-                  (query-author-by-commit-id commit-id))))
+                  (mysql/query-author-by-commit-id commit-id))))

 (defn get-author-change-line-map
   []
@@ -290,7 +290,7 @@
                                                       (map (fn[r] (+ (:add_line r) (:delete_line r))) (val e)))))
                       (group-by :commit_id
                                 (map #(select-keys % [:commit_id :add_line :delete_line])
-                                     (query-changeset)))))))
+                                     (mysql/query-changeset)))))))

 ;;; search commit and changeset table for this info
 ;;; return seq of map with keys [:author  :change-line]


remove some leftover tap>

remove some leftover tap>

--- src/main/shadow/build/closure.clj
+++ src/main/shadow/build/closure.clj
@@ -878,8 +878,6 @@
                                    (map :resource-id)
                                    (into []))}]))]

-    (tap> [:js-mods modules])
-
     (assoc state ::modules modules)))

 (defn setup
@@ -1217,7 +1215,6 @@
       (fn [modules]
         (->> modules
              (map (fn [{:keys [name js-module] :as mod}]
-                    (tap> [:module-wrap-npm mod])
                     (let [requires
                           (->> (get-js-module-requires state js-module)
                                (map #(.getName %))


redo private docs feature copy on features page

--- src-cljs/frontend/components/outer.cljs
+++ src-cljs/frontend/components/outer.cljs
@@ -330,8 +330,8 @@
                [:span "Share ideas privately."]]
               [:p.feature-copy
                [:span.content-copy
-                "We understand that your team might use proprietary technology or even trade secrets. "
-                "And that's why we built private documents, so you can collaborate with peace of mind. "]]
+                "We understand that your team needs its privacy, that's why we built private documents. "
+                "You should be able to collaborate with peace of mind, knowing that your ideas are safe."]]
               [:a.feature-link {:href "https://precursor.precursorapp.com/document/17592197569407" :target "_blank"}
                [:span.content-copy "Try a private document."]]]
              [:div.feature-media


Added header row for profiles.

Added header row for profiles.

--- src-cljs/kixi/hecuba/tabs/profiles.cljs
+++ src-cljs/kixi/hecuba/tabs/profiles.cljs
@@ -1,6 +1,8 @@
 (ns kixi.hecuba.tabs.profiles
   (:require [om.core :as om :include-macros true]
             [sablono.core :as html :refer-macros [html]]
+            [cljs-time.coerce :as tc]
+            [cljs-time.format :as tf]
             [kixi.hecuba.bootstrap :as bs]))

 (enable-console-print!)
@@ -13,6 +15,12 @@
         first
         :profiles))

+(defn format-time-inst [t format]
+  (if (nil? t)
+    "Undated"
+    (let [date (tc/from-date t)]
+      (tf/unparse (tf/formatter format) date))))
+
 (defn displayable? [d]
   (and d
        (not (re-find #"\w" d))))
@@ -21,6 +29,21 @@
   (if-let [d (displayable? (get m k))]
     d
     "N/A"))
+
+(defn profile-column-width []
+  "col-md-3")
+
+(defn header-row [profiles owner]
+  (reify
+    om/IRenderState
+    (render-state [_ state]
+      (html
+       [:div.col-md-12
+        (for [profile profiles]
+          (let [category (get-in profile [:profile_data :category] "Intervention")
+                timestamp (format-time-inst  (:timestamp profile) "yyyy-MM-dd")]
+            [:div {:class (profile-column-width)}
+             [:h3.text-center category [:br ] [:small timestamp]]]))]))))

 (defn occupancy-row [profiles owner]
   (reify
@@ -31,7 +54,7 @@
        [:div.col-md-12
         (for [profile profiles]
           (let [profile_data (:profile_data profile)]
-            [:div.col-md-4
+            [:div {:class (profile-column-width)}
              (bs/panel
               "Occupancy"
               [:dl
@@ -46,6 +69,7 @@
     (render-state [_ state]
       (html
        [:div.col-md-12
+        (om/build header-row profiles)
         (om/build occupancy-row profiles)
         ;; (om/build measurements profiles)
         ;; (om/build energy profiles)


Whitespace

Whitespace

--- src/midje/checking/checkables.clj
+++ src/midje/checking/checkables.clj
@@ -1,4 +1,4 @@
-(ns ^{:doc "Core Midje functions that process expects and report on their results."}
+(ns ^{:doc "Core Midje functions that process expects and report on their results."}
   midje.checking.checkables
   (:require [commons.clojure.core :refer :all :exclude [any?]]
             [midje.checking.core :refer :all]
@@ -29,27 +29,27 @@

 (defn- check-for-match [actual checkable-map]
   (let [expected (:expected-result checkable-map)]
-    (cond  (extended-= actual expected)
-           (emit/pass)
-
-           (has-function-checker? checkable-map)
-           (emit/fail (merge (minimal-failure-map :actual-result-did-not-match-checker
-                                                  actual checkable-map)
-                             ;; TODO: It is very lame that the
-                             ;; result-function has to be called again to
-                             ;; retrieve information that extended-=
-                             ;; knows and threw away. But it's surprisingly
-                             ;; difficult to use evaluate-checking-function
-                             ;; at the top of the cond
-                             (second (evaluate-checking-function expected actual))))
-
-           (inherently-false-map-to-record-comparison? actual expected)
-           (emit/fail (merge (minimal-failure-map :actual-result-did-not-match-expected-value actual checkable-map)
-                             (map-record-mismatch-addition actual expected)))
-
-           :else
-           (emit/fail (assoc (minimal-failure-map :actual-result-did-not-match-expected-value actual checkable-map)
-                             :expected-result expected)))))
+    (cond (extended-= actual expected)
+          (emit/pass)
+
+          (has-function-checker? checkable-map)
+          (emit/fail (merge (minimal-failure-map :actual-result-did-not-match-checker
+                                                 actual checkable-map)
+                            ;; TODO: It is very lame that the
+                            ;; result-function has to be called again to
+                            ;; retrieve information that extended-=
+                            ;; knows and threw away. But it's surprisingly
+                            ;; difficult to use evaluate-checking-function
+                            ;; at the top of the cond
+                            (second (evaluate-checking-function expected actual))))
+
+          (inherently-false-map-to-record-comparison? actual expected)
+          (emit/fail (merge (minimal-failure-map :actual-result-did-not-match-expected-value actual checkable-map)
+                            (map-record-mismatch-addition actual expected)))
+
+          :else
+          (emit/fail (assoc (minimal-failure-map :actual-result-did-not-match-expected-value actual checkable-map)
+                            :expected-result expected)))))

 (defn- check-for-mismatch [actual checkable-map]
@@ -63,7 +63,7 @@

           (has-function-checker? checkable-map)
           (emit/fail (minimal-failure-map :actual-result-should-not-have-matched-checker actual checkable-map))
-
+
           :else
           (emit/fail (minimal-failure-map :actual-result-should-not-have-matched-expected-value actual checkable-map)))))

@@ -80,7 +80,7 @@
 (defmethod call-count-incorrect? :fake [fake]
   (let [method (:times fake)
         count @(:call-count-atom fake)]
-    (branch-on method
+    (branch-on method
       #(= % :default) (zero? count)
       number?         (not= method count)
       coll?           (not-any? (partial = count) method)


draw-marbles to multi method

draw-marbles to multi method

--- src/nonaga/draw/draw_marbles.cljs
+++ src/nonaga/draw/draw_marbles.cljs
@@ -1,18 +1,24 @@
 (ns nonaga.draw.draw-marbles
-  (:use [nonaga.draw.util :only [hex->svg marble update-state]]))
+  (:use [nonaga.draw.util :only [hex->svg marble update-state event-type]]))

 (defn start-marble-move [component color coord]
   (update-state component #(assoc % :event [:marble-selected color coord])))

-(defn draw-marbles [component state color]
-  (let [etype  (get-in state [:event 0])
-        cp     (get-in state [:event 1])
-        coords (color state)
+(derive :turn-began      ::marble-selectable)
+(derive :marble-selected ::marble-selectable)
+
+(defmulti draw-marbles (fn [_ state _] (event-type state)))
+
+(defmethod draw-marbles :default [component state color]
+  (let [marbles (color state)]
+    (map (partial marble color) (map hex->svg marbles))))
+
+; Color and cp are badly named. Should be color-of-marbles-being-drawn and
+; current player.
+(defmethod draw-marbles ::marble-selectable
+  [component {[t cp] :event :as state} color]
+  (let [coords (color state)
         click  (partial start-marble-move component)]
-    (map (fn [hex svg]
-           (marble color (if (and (or (= etype :turn-began)
-                                      (= etype :marble-selected))
-                                  (= cp color))
-                           (click color hex)) svg))
+    (map (fn [hex svg] (marble color (if (= cp color) (click color hex)) svg))
          coords (map hex->svg coords))))


Re-implement core to gain performance and simplify code #44 - fixed macros to not lose linenumbers/stacktraces

--- src/flatgui/base.clj
+++ src/flatgui/base.clj
@@ -39,7 +39,8 @@
 (defn- gp-replacer [% property]
   (cond
     (and (seq? %) (get-property-call? %))
-    (let [% (if (symbol? (second %)) (conj (drop 2 %) (first %)) %) ;backward compatibility
+    (let [m (meta %)
+          % (if (symbol? (second %)) (conj (drop 2 %) (first %)) %) ;backward compatibility
           % (replace-gp % property)
           path-&-prop (next %)
           path (first path-&-prop)
@@ -51,19 +52,27 @@
                             dyn-path (GetPropertyDynPathClojureFn.)
                             dyn-property (GetDynPropertyClojureFn.)
                             :else (GetPropertyStaticClojureFn.))]
-      (conj path-&-prop get-property-fn))
+      (with-meta (conj path-&-prop get-property-fn) m))
     (and (seq? %) (get-reason-call? %))
-    (list '.getEvolveReason 'component)
+    (with-meta (list '.getEvolveReason 'component) (meta %))
     (old-value-ref? % property)
-    (list (keyword (.substring (name %) (.length old-val-prefix))) 'component)
+    (with-meta (list (keyword (.substring (name %) (.length old-val-prefix))) 'component) (meta %))
     (seq? %) (replace-gp % property)
     (vector? %) (replace-gpv % property)
     (map? %) (replace-gpmap % property)
     :else %))

-(defn replace-gp [form property] (map #(gp-replacer % property) form))
-(defn replace-gpv [v property] (mapv #(gp-replacer % property) v))
-(defn replace-gpmap [form property] (functor/fmap #(gp-replacer % property) form))
+(defn replace-gp [form property]
+  (let [m (meta form)]
+    (with-meta (map #(gp-replacer % property) form) m)))
+
+(defn replace-gpv [v property]
+  (let [m (meta v)]
+    (with-meta (mapv #(gp-replacer % property) v) m)))
+
+(defn replace-gpmap [form property]
+  (let [m (meta form)]
+    (with-meta (functor/fmap #(gp-replacer % property) form) m)))

 ;(defn- gen-evolver [body property] (flatgui.core/replace-gp (gp-replacer body property) property))
 (defn- gen-evolver [body property] (gp-replacer body property))