service distribution access

service distribution access

#46

--- src/clj/swarmpit/authorization.clj
+++ src/clj/swarmpit/authorization.clj
@@ -16,16 +16,16 @@
   true)

 (defn- admin-access
-  [request]
-  (let [role (get-in (:identity request) [:usr :role])]
+  [{:keys [identity]}]
+  (let [role (get-in identity [:usr :role])]
     (if (= "admin" role)
       true
       (error {:code    403
               :message "Unauthorized admin access"}))))

 (defn- owner-access
-  [{:keys [path-params] :as request}]
-  (let [user (get-in (:identity request) [:usr :username])
+  [{:keys [path-params identity]}]
+  (let [user (get-in identity [:usr :username])
         entity (cc/get-doc (:id path-params))]
     (if (= (:owner entity) user)
       true
@@ -33,14 +33,27 @@
               :message "Unauthorized owner access"}))))

 (defn- distribution-access
-  [{:keys [path-params] :as request}]
-  (let [user (get-in (:identity request) [:usr :username])
+  [{:keys [path-params identity]}]
+  (let [user (get-in identity [:usr :username])
         entity (cc/get-doc (:id path-params))]
     (if (or (= (:owner entity) user)
             (:public entity))
       true
       (error {:code    403
               :message "Unauthorized distribution access"}))))
+
+(defn- service-distribution-access
+  [{:keys [json-params identity]}]
+  (let [user (get-in identity [:usr :username])
+        distribution-id (get-in json-params ["distribution" "id"])]
+    (if (nil? distribution-id)
+      true
+      (let [entity (cc/get-doc distribution-id)]
+        (if (or (= (:owner entity) user)
+                (:public entity))
+          true
+          (error {:code    403
+                  :message "Unauthorized distribution access"}))))))

 (def rules [{:pattern #"^/admin/.*"
              :handler {:and [authenticated-access admin-access]}}
@@ -55,7 +68,7 @@
              :request-method :get
              :handler        {:and [authenticated-access distribution-access]}}
             {:pattern        #"^/distribution/registries/[a-zA-Z0-9]*$"
-             :request-method #{:get :delete}
+             :request-method #{:get :delete :post}
              :handler        {:and [authenticated-access owner-access]}}
             {:pattern        #"^/distribution/dockerhub/[a-zA-Z0-9]*/repositories$"
              :request-method :get
@@ -64,8 +77,11 @@
              :request-method :get
              :handler        {:and [authenticated-access distribution-access]}}
             {:pattern        #"^/distribution/dockerhub/[a-zA-Z0-9]*$"
-             :request-method #{:get :delete}
+             :request-method #{:get :delete :post}
              :handler        {:and [authenticated-access owner-access]}}
+            {:pattern        #"^/services$"
+             :request-method :post
+             :handler        {:and [authenticated-access service-distribution-access]}}
             {:pattern #"^/.*"
              :handler {:and [authenticated-access]}}])


config BE client #180

config BE client
#180

--- src/clj/swarmpit/docker/client.clj
+++ src/clj/swarmpit/docker/client.clj
@@ -123,6 +123,26 @@
   (let [uri (str "/secrets/" id "/update")]
     (post uri {:version version} secret)))

+;; Config
+
+(defn configs
+  []
+  (get "/configs"))
+
+(defn config
+  [id]
+  (-> (str "/configs/" id)
+      (get)))
+
+(defn delete-config
+  [id]
+  (-> (str "/configs/" id)
+      (delete)))
+
+(defn create-config
+  [config]
+  (post "/configs/create" config))
+
 ;; Node

 (defn nodes


parse event and prepare for handling #165

--- src/cljs/swarmpit/eventsource.cljs
+++ src/cljs/swarmpit/eventsource.cljs
@@ -1,25 +1,40 @@
 (ns swarmpit.eventsource
-  (:require [swarmpit.routes :as routes]))
+  (:require [swarmpit.routes :as routes]
+            [clojure.walk :refer [keywordize-keys]]))

-(defn subscribe
-  [uri]
-  (js/EventSource. uri))
+(defn parse-event
+  [event]
+  (-> (.-data event)
+      (js/JSON.parse)
+      (js->clj)
+      (keywordize-keys)))

-(defn add-listener!
-  [evs eventname callback]
-  (.addEventListener evs eventname callback))
+(defn handle-docker-event!
+  [event-message]
+  "TODO: Handler docker events"
+  (print event-message))
+
+(defn handle-event!
+  [event-data]
+  (let [event-source (:From event-data)
+        event-message (:Message event-data)]
+    (case event-source
+      "DOCKER" (handle-docker-event! event-message)
+      (print (str "Unknown event source: " event-source)))))

 (defn init!
   []
-  (let [event-source (subscribe (routes/path-for-backend :events))]
-    (add-listener! event-source "message"
-                   (fn [event]
-                     (let [data (.-data event)]
-                       (print data))))
-    (add-listener! event-source "open"
-                   (fn [_]
-                     (print "Swarmpit event connection was opened")))
-    (add-listener! event-source "error"
-                   (fn [event]
-                     (let [state (.-readyState event)]
-                       (print state))))))
+  (let [event-source (js/EventSource. (routes/path-for-backend :events))]
+    (.addEventListener event-source "message"
+                       (fn [event]
+                         (let [event-data (parse-event event)]
+                           (handle-event! event-data))))
+    (.addEventListener event-source "open"
+                       (fn [_]
+                         (print "Swarmpit event connection was opened")))
+    (.addEventListener event-source "error"
+                       (fn [event]
+                         (let [state (.-readyState event)]
+                           (print state))))))
+
+


Of course it makes no sense to create sample data there

--- src/cljs/todo_list/views/main.cljs
+++ src/cljs/todo_list/views/main.cljs
@@ -4,9 +4,6 @@

 (defn- add-task [text]
   (swap! tasks #(conj % {:text text, :status :notdone})))
-
-(add-task "One task")
-(add-task "Other task")

 (defn- show-task [task]
   "Show a single task"


Fix stupid rest bug.

Fix stupid rest bug.

--- src/cljx/geschichte/p2p/fetch.cljx
+++ src/cljx/geschichte/p2p/fetch.cljx
@@ -87,7 +87,7 @@
                 ;; then blobs
                 (when-not (empty? nblbs)
                   (debug "fetching new blobs" nblbs "from" peer)
-                  (<! (go-loop [[to-fetch r] nblbs]
+                  (<! (go-loop [[to-fetch & r] nblbs]
                         (when to-fetch
                           ;; TODO recheck store to avoid double fetching
                           (>! out {:topic :binary-fetch


convert log-root to canonical path in case it is relative

--- storm-core/src/clj/backtype/storm/daemon/logviewer.clj
+++ storm-core/src/clj/backtype/storm/daemon/logviewer.clj
@@ -33,17 +33,17 @@
 (defn tail-file [path tail root-dir]
   (let [flen (.length (clojure.java.io/file path))
         skip (- flen tail)]
-    (if (.startsWith path root-dir)
+    (if (.startsWith path (.getCanonicalPath (File. root-dir)))
     (with-open [input (clojure.java.io/input-stream path)
                 output (java.io.ByteArrayOutputStream.)]
       (if (> skip 0) (.skip input skip))
-      (let [buffer (make-array Byte/TYPE 1024)]
-        (loop []
-          (let [size (.read input buffer)]
-            (when (and (pos? size) (< (.size output) tail))
-              (do (.write output buffer 0 size)
-                  (recur))))))
-      (.toString output)) "File not found")
+        (let [buffer (make-array Byte/TYPE 1024)]
+          (loop []
+            (let [size (.read input buffer)]
+              (when (and (pos? size) (< (.size output) tail))
+                (do (.write output buffer 0 size)
+                    (recur))))))
+        (.toString output)) "File not found")
     ))

 (defn log-root-dir


CMR-348: Removed unnecessary parameter validation test.

--- test/cmr/search/test/services/parameter_validation.clj
+++ test/cmr/search/test/services/parameter_validation.clj
@@ -72,10 +72,7 @@
            (pv/orbit-number-validation :granule (assoc valid-params :orbit-number "A,10")))))
   (testing "Non-numeric stop-orbit-number"
     (is (= [(on-msg/invalid-orbit-number-msg)]
-           (pv/orbit-number-validation :granule (assoc valid-params :orbit-number "10,A")))))
-  (testing "Start orbit-number greater than stop orbit-number"
-    (is (= [(on-msg/invalid-orbit-number-msg)]
-           (pv/orbit-number-validation :granule (assoc valid-params :orbit-number "10,1"))))))
+           (pv/orbit-number-validation :granule (assoc valid-params :orbit-number "10,A"))))))

 (deftest temporal-format-validation :collection-start-date-test
   (testing "valid-start-date"


Include auth to core

Include auth to core

--- frontend/src/crunsher/core.cljs
+++ frontend/src/crunsher/core.cljs
@@ -3,6 +3,7 @@
             [om.dom :as dom :include-macros true]
             [goog.dom :as gdom]
             [crunsher.data.pokemon]
+            [crunsher.communication.auth]
             [crunsher.utils.extensions]
             [crunsher.utils.lib :as lib]
             [crunsher.views :as views]


correct usage print

correct usage print

--- src/leiningen/sync.clj
+++ src/leiningen/sync.clj
@@ -50,14 +50,14 @@
         ""
         "Usage:"
         ""
-        "  *  lein [options] sync \"project-1,project-2,project-3\""
+        "  *  lein sync [options] \"project-1,project-2,project-3\""
         ""
         "Options:"
         options-summary
         ""
         "To specify the namespaces and resources to be shared, you must define them in project.clj. i.e"
         ":ns-sync {:namespaces  [\"namespace.to.be.sync.1\" \"namespace.to.be.sync.2\"]"
-        "          :resources   [\"resource.to.be.sync.1\"  \"resource.to.be.sync.2\"]}"
+        "          :resources   [\"resource.to.be.sync.1\"  \"resource.to.be.sync.2\" ]}"
         ""]
        (str/join \newline)))


Delete fns find-ver-part-projs and likely-project-shas

These are not needed now that we use git tags to track semantic version changes.

--- src/leiningen/voom.clj
+++ src/leiningen/voom.clj
@@ -291,55 +291,6 @@
       (when-not (= 128 (:exit (ex-data e)))
         (println "Ignoring error:" (pr-str e)))
       nil)))
-
-(defn re-quote [s]
-  (s/replace s #"\." "\\\\."))
-
-;; This is not right, at least when asking for the latest version
-(defn find-ver-part-projs
-  [gitdir prj-name ver-part]
-  (let [ver-ptn (re-pattern (str (re-quote ver-part) #"[-.].*"))
-        qprj (re-quote prj-name)
-        prj-ptn (if (= (name prj-name) (namespace prj-name))
-                  (str "(" (re-quote (name prj-name)) "|" qprj ")")
-                  qprj)
-        git-ptn (str #"\(defproject\s+" prj-ptn #"\s+\"" ver-ptn \")
-        _ (prn :git-ptn git-ptn)
-        {:keys [lines]} (git {:gitdir gitdir} "log" "--name-only" "--all" "--pretty=format:%H"
-                             "-G" git-ptn "--" "project.clj" "**/project.clj")]
-    (->> lines
-         (reductions (fn [[sha v] line]
-                       (cond
-                        (empty? line) [nil nil]
-                        sha [sha {:sha sha :file line}]
-                        :else [line nil]))
-                     [nil nil])
-         (keep second)
-         (keep
-          (fn [{:keys [sha file]}]
-            (let [{:keys [group name version]} (read-project gitdir sha file)]
-              (prn group name version)
-              (when (and (re-matches ver-ptn version)
-                         (= prj-name (symbol group name)))
-                {:sha sha
-                 :v version}))))
-         first)))
-
-(defn likely-project-shas
-  "Return lazy seq of maps with :sha and :file keys, each representing
-  a sha of the given gitdir that has a change to the project.clj named
-  in the map. Ordered by newest to oldest."
-  [gitdir]
-  (let [r (git {:gitdir gitdir} "log" "--name-only" "--all"
-               "--pretty=format:%H" "--" "project.clj" "**/project.clj")]
-    (->> (:lines r)
-         (reductions (fn [[sha v] line]
-                       (cond
-                        (empty? line) [nil nil]
-                        sha [sha {:sha sha :file line}]
-                        :else [line nil]))
-                     [nil nil])
-         (keep second))))

 (defn report-progress
   "Eagerly consume xs, but return a lazy seq that reports progress


got specify files working recursively on directories

--- src/duffel/fs.clj
+++ src/duffel/fs.clj
@@ -51,21 +51,39 @@
         (partial util/index-when hostname-matches)
         (partial util/index-when #(= "_default" %))))

+(defmulti explode-file list?)
+(defmethod explode-file false [file-name]
+    (let [spec-split-ret (host-specifier-split file-name)
+          specifier      (last spec-split-ret)
+          ext-split-ret  (extension-split (first spec-split-ret))
+          extension      (last  ext-split-ret)
+          base-name      (first ext-split-ret)]
+    { :base-name base-name
+      :specifier specifier
+      :extension extension
+      :file-name file-name
+      :is-dir?   false    }))
+
+(defmethod explode-file true [dir]
+    (let [dir-name       (first dir)
+          dir-ls         (rest  dir)
+          spec-split-ret (host-specifier-split dir-name)
+          specifier      (last spec-split-ret)
+          ext-split-ret  (extension-split (first spec-split-ret))
+          extension      (last  ext-split-ret)
+          base-name      (first ext-split-ret)]
+    { :base-name base-name
+      :specifier specifier
+      :extension extension
+      :file-name dir-name
+      :dir-ls    dir-ls
+      :is-dir?   true    }))
+
 (defn explode-files-in-list
     "Take a list of filenames and turn them into file structs containing info
     about their real name, extension, and host specifier"
     [file-list]
-    (map #(
-        let [spec-split-ret (host-specifier-split %)
-              specifier      (last spec-split-ret)
-              ext-split-ret  (extension-split (first spec-split-ret))
-              extension      (last  ext-split-ret)
-              base-name      (first ext-split-ret)]
-        { :base-name base-name
-          :specifier specifier
-          :extension extension
-          :file-name %        }
-    ) file-list))
+    (map explode-file file-list))

 (defn remove-empty-file-structs
     "Looks through list of file structs and removes any with empty names"
@@ -103,6 +121,19 @@
     [file-map]
     (map #(narrow-group (val %)) file-map))

+(defn directory-consolidate
+    "If file-struct has :dir-ls then it is a directory. Call specify-files
+    on the value at :dir-ls, then cons the file-struct (with :dir-ls dissociated)
+    to the front."
+    [file-struct]
+    (if (contains? file-struct :dir-ls)
+        (cons (dissoc file-struct :dir-ls) (specify-files (file-struct :dir-ls)))
+        file-struct))
+
+(defn directory-recursion
+    [file-structs]
+    (map directory-consolidate file-structs))
+
 (defn specify-files
     "Given a list of file names (presumably all in the same folder) goes and performs
     all the steps needed to narrow down which files we want to actually use for this
@@ -113,4 +144,5 @@
          (explode-files-in-list)
          (remove-empty-file-structs)
          (group-by-basename)
-         (narrow-groups)))
+         (narrow-groups)
+         (directory-recursion)))


skip whitespace at end of DATABASE_URL, if any


FIXMEs and crap

FIXMEs and crap

--- src/grimoire/doc.clj
+++ src/grimoire/doc.clj
@@ -21,9 +21,44 @@
           (fn? @v)     "fn"
           :else        "var")))

+(defn var->thing [{:keys [groupid artifactid version]} var]
+  ;; FIXME: get the ns, name out of the var & make a :def thing
+  )
+
+(defn var->src
+  "Adapted from clojure.repl/source-fn. Returns a string of the source code for
+  the given var, if it can find it. Returns nil if it can't find the source.
+
+  Example: (var->src #'clojure.core/filter)"
+
+  [v]
+  {:pre [(var? v)]}
+  (when-let [filepath (:file (meta v))]
+    (when-let [strm (.getResourceAsStream (RT/baseLoader) filepath)]
+      (with-open [rdr (LineNumberReader. (InputStreamReader. strm))]
+        (dotimes [_ (dec (:line (meta v)))] (.readLine rdr))
+        (let [text (StringBuilder.)
+              pbr (proxy [PushbackReader] [rdr]
+                    (read [] (let [i (proxy-super read)]
+                               (.append text (char i))
+                               i)))]
+          (if (= :unknown *read-eval*)
+            (throw (IllegalStateException. "Unable to read source while *read-eval* is :unknown."))
+            (read (PushbackReader. pbr)))
+          (str text))))))
+
 (defn write-docs-for-var [config var]
-  ;; FIXME
-  )
+  (let [docs (-> (meta var)
+                 (assoc  :src (var->src var))
+                 (update :name name)
+                 (update :ns   ns->name))
+        type (cond (:macro? docs) :macro
+                   (fn? @var)     :fn
+                   true           :var)
+        docs (assoc docs :type type)]
+    (api/write-meta config
+                    (var->thing config var)
+                    docs)))

 (defn write-docs-for-specials [config]
   (doseq [[sym fake-meta] @#'clojure.repl/special-doc-map]
@@ -42,15 +77,16 @@

     ;; write per symbol docs
     (doseq [var ns-vars]
-      (write-docs-for-var ns-dir var))
+      (write-docs-for-var config var))

     (when (= ns 'clojure.core)
-      (write-docs-for-specials ns-dir)))
+      (write-docs-for-specials config)))

   (println "Finished" ns)
   nil)

 (defn -main [groupid artifactid version & args]
-  (doseq [ns (tns.f/find-namespaces (clojure.java.classpath/classpath))]
+  (doseq [ns (tns.f/find-namespaces
+              (clojure.java.classpath/classpath))]
     (require ns)
     (write-docs-for-ns config ns)))


Whitespace

Whitespace

--- src/grimoire/doc.clj
+++ src/grimoire/doc.clj
@@ -118,8 +118,10 @@
   [x]
   (cond (symbol? x)
         ,,(name x)
+
         (string? x)
         ,,x
+
         :else
         ,,(throw
            (Exception.


Added tst-words & more functions

Added tst-words & more functions

--- src/hangman/core.clj
+++ src/hangman/core.clj
@@ -17,25 +17,49 @@
        (str/split-lines )
        (map str/trim ) ))

-(def words-by-length
+(def tst-words [
+  "is" "at" "by" "up"
+  "act" "add" "ace" "and" "ask" "abe" "ads"
+  "bad" "bug" "bed" "bet"  "big" "bit"
+  "cat" "car" "can" "cob" "con" "cop" "cup"
+  "work" "love" "hate" "jobs" "able" "ball" ] )
+
+(defn words-by-length
   "Maps word length to word values.  Each key is a word length. Each value is a collection
   of all words of that length.  Keys are absent if no words of that length are present."
-  (group-by count all-words) )
+  [word-seq]
+  (group-by count word-seq) )

-(def max-word-length
-  "The maximum length of any word."
-  (apply max (keys words-by-length)) )
+(defn max-word-length
+  "The maximum length of any word in a sequence."
+  [word-seq]
+  (apply max (map count word-seq) ))

 (defn to-word-array
   "Returns all words of the specified length as a 2D array (vector of vectors).
   First index selects a given word, 2nd index selects chars from that word."
-  [word-length]
+  [word-seq word-length]
   { :pre  [ (integer? word-length) ]
     :post [ (vector? %) ] }
   (vec
-    (map vec (words-by-length word-length)) ))
+    (map vec ((words-by-length word-seq) word-length)) ))

-(defn get-array-column
+(defn num-rows
+  "Given a 2D array (vector of vectors), return the number of rows (1st dimension)."
+  [word-array]
+  { :pre  [ (vector? word-array) ]
+    :post [] }
+  (count word-array) )
+
+(defn num-cols
+  "Given a 2D array (vector of vectors), return the number of columns (2nd dimension)."
+  [word-array]
+  { :pre  [ (vector?  word-array)
+            (vector? (word-array 0)) ]
+    :post [] }
+  (count (word-array 0)) )
+
+(defn get-array-col
   "Given a 2D array (vector of vectors), return a vector of elements
   from the specified column."
   [word-array col-idx]
@@ -52,19 +76,41 @@
     :post [ (vector? %) ] }
   (word-array row-idx) )

+(defn words-of-length
+  "Returns a seq of words of the specified length."
+  [word-length]
+  { :pre  [ (integer? word-length) ]
+    :post [ (vector? %) ] }
+  (vec
+    (get words-by-length word-length [] ) ))
+
+(defn freqs-by-col
+  "For each column of a 2D array, computes an element frequency map. Returns as
+  a vector indexed by column."
+  [word-array]
+  { :pre  [ (vector? word-array)
+            (< 0 (num-rows word-array) )
+            (< 0 (num-cols word-array) ) ]
+    :post [ (vector? %) ] }
+  (vec
+    (for [idx (range 0 (inc (num-cols word-array) )) ]
+      (frequencies (get-array-col idx)) )))
+
+
 (defn run-tests []
   ; Manipulation of strings/vectors/character seq's
   (assert (= (vec "abcd")                [\a \b \c \d] ))
   (assert (= (str/join  (vec "abcd"))    "abcd" ))
   (assert (= (apply str (vec "abcd"))    "abcd" ))

+  ; Test array slicing functions
   (let [ tstArr [ [:a :b :c] [1 2 3] [\a \b \c]] ]
-    (assert (= (get-array-row    tstArr 0) [:a :b :c] ))
-    (assert (= (get-array-row    tstArr 1) [ 1  2  3] ))
-    (assert (= (get-array-row    tstArr 2) [\a \b \c] ))
-    (assert (= (get-array-column tstArr 0) [:a  1 \a] ))
-    (assert (= (get-array-column tstArr 1) [:b  2 \b] ))
-    (assert (= (get-array-column tstArr 2) [:c  3 \c] ))
+    (assert (= (get-array-row tstArr 0) [:a :b :c] ))
+    (assert (= (get-array-row tstArr 1) [ 1  2  3] ))
+    (assert (= (get-array-row tstArr 2) [\a \b \c] ))
+    (assert (= (get-array-col tstArr 0) [:a  1 \a] ))
+    (assert (= (get-array-col tstArr 1) [:b  2 \b] ))
+    (assert (= (get-array-col tstArr 2) [:c  3 \c] ))
   )

   ; Use of (frequencies...) and (merge-with...)
@@ -78,18 +124,6 @@
              {\a 1 \b 2 \c 3} ))
 )

-(defn words-of-length
-  "Returns a seq of words of the specified length."
-  [word-length]
-  { :pre  [ (integer? word-length) ]
-    :post [ ] }
-  (get words-by-length word-length [] ) )
-
-; (def data-map
-;   "A map of data keyed by word length"
-;   (doseq [curr-len (range 4 (inc 4)) ]
-;     (apply merge-with +
-;       (map frequencies (words-of-length curr-len)) )))

 (defn main []
   (println "main: enter")


Fix strange indent

Fix strange indent

--- src/io/perun/rss.clj
+++ src/io/perun/rss.clj
@@ -12,11 +12,9 @@
      :author      (:author-email file)}))

 (defn generate-rss-str [files options]
-  (let [rss-options  {
-          :title       (or (:title options) (:site-title options))
-          :description (:description options)
-          :link        (or (:link options) (:base-url options))
-        }
+  (let [rss-options  {:title       (or (:title options) (:site-title options))
+                      :description (:description options)
+                      :link        (or (:link options) (:base-url options))}
         items        (rss-definitions (filter :name files))
         rss-str      (apply rss-gen/channel-xml rss-options items)]
     rss-str))


added button to see source from error screen

--- src/cellf/core.cljs
+++ src/cellf/core.cljs
@@ -11,6 +11,7 @@
 (def capture-size 250)
 (def tick-ms      150)
 (def resize-ms    200)
+(def source-url   "https://github.com/dmotz/cellf")

 (defonce img-cache (atom []))

@@ -250,12 +251,14 @@
       (cond
         media-error
           (dom/div nil
+            (dom/h1 nil "!!!")
             (if (= media-error :denied)
               "Sorry, Cellf doesn't work without camera access."
               (str
                 "Sorry, it looks like your device or browser doesn't support camera access. "
                 "Try Cellf using Chrome or Firefox on a device that supports WebRTC."))
-            (dom/button #js {:onClick get-camera!} "try again"))
+            (dom/button #js {:onClick get-camera!} "try again")
+            (dom/button #js {:onClick #(js/open source-url)} "view cellf source"))

         no-stream?
           (dom/div nil
@@ -302,7 +305,7 @@
             (dom/h1 nil "About Cellf")
             (dom/p nil
               "Cellf was created by Dan Motzenbecker and is "
-              (dom/a #js {:href "https://github.com/dmotz/cellf"} "open source")
+              (dom/a #js {:href source-url} "open source")
               " on Github. "
               "For more experiments like this, visit "
               (dom/a #js {:href "http://oxism.com"} "oxism.com")


Set name for embedded CLI thread.

Set name for embedded CLI thread.

--- src/cli4clj/cli.clj
+++ src/cli4clj/cli.clj
@@ -375,6 +375,7 @@
                        (start-cli adjusted-user-options#))))
                    (recur)))
        (.setDaemon true)
+       (.setName "cli4clj Embedded CLI")
        (.start))
      in-fn#))


core/prefix to def

core/prefix to def

--- src/prais2/routes.cljs
+++ src/prais2/routes.cljs
@@ -23,7 +23,7 @@
 ;; window location to token: :todo. Change this if changing prefix
 ;;;
 (defn get-token! []
-  (if (= (core/prefix) "#")
+  (if (= core/prefix "#")
     (.. js/window -location -hash)
     (.. js/window -location -pathname)))


wait-for-git has status :waiting while waiting for new revision

--- src/lambdacd/git.clj
+++ src/lambdacd/git.clj
@@ -27,7 +27,8 @@
           {:status :success :revision new-revision-output}
           nil)))))

-(defn- wait-for-revision-changed-from [last-seen-revision repo-uri branch]
+(defn- wait-for-revision-changed-from [last-seen-revision repo-uri branch ctx]
+  (async/>!! (:result-channel ctx) [:status :waiting])
   (loop [result (revision-changed-from last-seen-revision repo-uri branch)]
     (if (nil? result)
       (do (Thread/sleep 1000)
@@ -47,7 +48,7 @@
   "step that waits for the head of a branch to change"
   [ctx repo-uri branch]
   (let [last-seen-revision (last-seen-revision-for-this-step ctx)
-        wait-for-result (wait-for-revision-changed-from last-seen-revision repo-uri branch)]
+        wait-for-result (wait-for-revision-changed-from last-seen-revision repo-uri branch ctx)]
     (persist-last-seen-revision wait-for-result)))

 (defn- checkout [ctx repo-uri revision]


Use status 301 and 308

Use status 301 and 308

--- modules/reitit-ring/src/reitit/ring.cljc
+++ modules/reitit-ring/src/reitit/ring.cljc
@@ -123,9 +123,10 @@
   [{:keys [method] :or {method :both}}]
   (let [redirect-handler (fn redirect-handler [request]
                            (let [uri (:uri request)
+                                 status (if (= (:method request) :get) 301 308)
                                  maybe-redirect (fn maybe-redirect [path]
                                                   (if (r/match-by-path (::r/router request) path)
-                                                    {:status 308 ; permanent redirect
+                                                    {:status status
                                                      :headers {"Location" path}
                                                      :body ""}))]
                              (if (str/ends-with? uri "/")


cleanup

cleanup

--- src/sormilla/video.clj
+++ src/sormilla/video.clj
@@ -114,70 +114,4 @@
       (finally
         (reset! image nil)))))

-;;
-;; here be dragons...
-;;
-
-(comment
-
-  (drone/init-drone)
-  (init-video-streaming!)
-  (:video (:telemetry @sormilla.system/status))
-
-  (sormilla.system/shutdown!)
-  (reset! sormilla.system/status {:run true})
-  (comm/send-commands! [[:led 0 1.0 0]])
-  (comm/send-commands! [[:config "video:video_on_usb" true]])
-  (comm/send-commands! [comm/comm-reset
-                        comm/trim
-                        comm/enable-navdata
-                        comm/ctrl-ack
-                        comm/land
-                        comm/leds-active])
-
-  (:video (:telemetry @sormilla.system/status))
-
-
-(defn parse-file []
-  (let [in (io/input-stream (io/file "sormilla-20130825-164933.h264"))
-        decoder (make-decoder in)]
-    (try
-      (doseq [i (range 10)]
-        (ImageIO/write (decoder) "png" (io/file (str "image-" i ".png"))))
-      (println "success!")
-      (catch Exception e
-        (println "failure" e)
-        (.printStackTrace e))
-      (finally
-        (try (.close in) (catch Exception e))))))
-
-(parse-file)
-
 ; ffmpeg -f h264 -an -i capture.h264 stream.m4v
-)
-
-(defn capture []
-  (let [socket (doto (Socket.)
-                 (.setSoTimeout 2000)
-                 (.connect (InetSocketAddress. comm/drone-ip 5555)))
-        in (.getInputStream socket) #_(io/input-stream socket)
-        out (io/output-stream (io/file "capture.h264"))
-        buffer (byte-array 1024)]
-    (try
-      (doto (.getOutputStream socket)
-        (.write (byte-array (map bin/ubyte [1 0 0 0])))
-        (.flush))
-      (doseq [n (range 2048)]
-        (when (zero? (mod n 100)) (println (str "frame " n "...")))
-        (.write out buffer 0 (.read in buffer 0 1024)))
-      (println "success!")
-      (catch Exception e
-        (println "failure" e)
-        (.printStackTrace e))
-      (finally
-        (try (.close socket) (catch Exception e))
-        (try (.close out) (catch Exception e))))))
-
-(comment
-  (capture)
-)


add multi field fill and fill plus submit for strong and weak structural markup

--- src/crison/core.clj
+++ src/crison/core.clj
@@ -52,16 +52,27 @@
     (Thread/sleep 2000)
     (screenshot (:screenshot x))))

-(defmethod decode :submit! [{:keys [submit!] :as x}]
-  (let [input (first submit!)
-        v (:text! input)
-        srch (dissoc input :text!)]
-        (-> driver (wc/find-element srch) (wc/input-text v))
-        (-> driver (wc/find-element (last submit!)) wc/click)
-        (screenshot (:screenshot x))))
+(defn compute-fill [{:keys [fill-submit!] :as x}]
+  (let [head (butlast fill-submit!)]
+    (println "head : " head)
+    (doseq [e head]
+      (let [txt-val (:text! e)
+            field (dissoc e :text!)]
+        (-> driver (wc/find-element field) (wc/input-text txt-val))))))

-(defmethod decode :search! [x]
-  (wf/quick-fill-submit driver (:search! x)) (Thread/sleep 2000) (screenshot (:screenshot x)))
+(defmethod decode :fill-submit! [{:keys [fill-submit!] :as x}]
+  (if (seq (filter #(:text! %) (butlast fill-submit!)))
+    (compute-fill x)
+    (wf/quick-fill-submit driver (:fill! x)))
+  (-> driver (wc/find-element (last fill-submit!)) wc/click)
+  (screenshot (:screenshot x)))
+
+(defmethod decode :fill! [{:keys [fill!] :as x}]
+  (if (seq (filter #(:text! %) (butlast fill!)))
+    (compute-fill x)
+    (wf/quick-fill-submit driver (:fill! x)))
+  (Thread/sleep 2000)
+  (screenshot (:screenshot x)))

 (defmethod decode :title [x] (title? (:title x)))


Whitespace fixes

Whitespace fixes

--- src/mdr2/archive.clj
+++ src/mdr2/archive.clj
@@ -52,7 +52,7 @@
    :flags "x"
    :transaktions_status "pending"})

-(defn container-id
+(defn container-id
   "Return the name of a archive spool directory for a given production"
   [{:keys [id iso-path]}]
   (cond
@@ -77,7 +77,7 @@
   the spool directory as ready for archiving and concludes the
   archiving process from the point of view of the production system."
   [production]
-  (let [new-job
+  (let [new-job
         {:verzeichnis (container-id production)
          ;; :id (container-id production)
          ;; :verzeichnis (container-path production)
@@ -94,27 +94,27 @@
   [{:keys [path] :as production}]
   (let [tmp-path (.getPath (fs/temp-dir "mdr2"))
         ;; FIXME: it might be better to allow for different manifest names
-        manifest (.getPath (file path "package.opf"))]
+        manifest (.getPath (file path "package.opf"))]
     (pipeline/audio-encoder {:input manifest :output tmp-path})
     (assoc production :encoded-path tmp-path)))

-(defn create-iso
-  "Pack a production in an iso file.
+(defn create-iso
+  "Pack a production in an iso file.
 Return a map with an additional key `iso-path` where the iso is located"
   [{:keys [encoded-path title publisher]
     :or {title "FIXME:" publisher "FIXME:"} ; title and publisher shouldn't be empty
     :as production}]
   (let [iso-path (.getPath (file (fs/tmpdir) (fs/temp-name "mdr2" ".iso")))]
-    (sh "genisoimage"
-        "-quiet"
-        "-r"
+    (sh "genisoimage"
+        "-quiet"
+        "-r"
         "-publisher" publisher
         "-V" title ; volume ID (volume name or label)
         "-J" ; Generate Joliet directory records in addition to regular ISO9660 filenames.
         "-o" iso-path encoded-path)
     (assoc production :iso-path iso-path)))

-(defn copy-files
+(defn copy-files
   "Copy a production to the archive spool dir"
   ;; FIXME: this fails if there is already an archiving in progress
   ;; because it will create another copy inside the already existing
@@ -125,12 +125,12 @@
         iso-archive-path (.getPath (file archive-path iso-archive-name))]
     ;; if the production has an iso archive that, otherwise just
     ;; archive the raw unencoded files
-    (if iso-path
+    (if iso-path
       (fs/copy+ iso-path iso-archive-path)
       (fs/copy-dir path archive-path)))
   production)

-(defn create-rdf
+(defn create-rdf
   "Create an rdf file and place it in the archive spool directory"
   [production]
   (let [rdf (rdf/rdf production)
@@ -153,7 +153,7 @@
       create-rdf ; create an rdf file
       add-to-db)) ; add it to the db so that the agadir machinery will pick it up

-(defn archive-distribution-master
+(defn archive-distribution-master
   "Archive a distribution master .i.e. a DTB encoded with mp3 and packed up in one or more iso files"
   [production]
   (-> production
@@ -169,4 +169,3 @@
   [production]
   (archive-master production)
   (archive-distribution-master production))
-


Fixed typo.

Fixed typo.

--- src/dragon/blog.clj
+++ src/dragon/blog.clj
@@ -73,7 +73,7 @@
   []
   (map (fn [x]
          {:file x})
-       (util/get-files (config/posts-path-))))
+       (util/get-files (config/posts-path-src))))

 (defn process
   [uri-base]


Use exception instead of string

Use exception instead of string

--- src/tenor/entities.clj
+++ src/tenor/entities.clj
@@ -10,7 +10,7 @@
         (Integer. (nth components 1))
         (str (nth components 2) (nth components 3))
         (Integer. (nth components 4)))
-      "Invalid notation")))
+      (throw (Exception. "Invalid notation")))))

 (defn time-signature [beat-count & [sig]]
   (cond


Open url in platform friendly way

Open url in platform friendly way

--- src/lt/plugins/ltfiles/browse.cljs
+++ src/lt/plugins/ltfiles/browse.cljs
@@ -1,6 +1,8 @@
 (ns lt.plugins.ltfiles.browse
+  "Browser related commands"
   (:require [lt.objs.tabs :as tabs]
             [lt.plugins.ltfiles.util :as util]
+            [lt.objs.platform :as platform]
             [lt.objs.command :as cmd]))

 (defn tab-open-current-url []
@@ -23,9 +25,8 @@
               :exec tab-open-current-url})

-;; OSX-specific for now
 (defn system-open-current-url []
-   (util/sh (str "open " (util/current-word))))
+  (platform/open (util/current-word)))

 (cmd/command {:command :ltfiles.system-open-current-url
               :desc "ltfiles: opens url under cursor in system browser"


avoid reconciler name clashing with the card name

--- src/main/devcards_om_next/core.clj
+++ src/main/devcards_om_next/core.clj
@@ -10,7 +10,7 @@
    (when (utils/devcards-active?)
      (let [card-name? (not (nil? (:card-name options)))
            card-name (when card-name?
-                       (symbol (:card-name options)))
+                       (symbol (str (:card-name options) "-reconciler")))
            make-reconciler `(fn [state#]
                               (om.next/reconciler
                                 {:state state#


fix lexicon

fix lexicon

--- src/babel/english/writer.clj
+++ src/babel/english/writer.clj
@@ -17,7 +17,7 @@
 ;; false: throw error and stop further generation; true: tolerate errors: log/error and continue generation.
 (def ^:const allow-generation-error true)

-(def lexicon (-> (-> ((-> models :en)) deref) :lexicon))
+(def lexicon (-> models :en deref :lexicon))

 (defn rewrite-lexicon []
   (write-lexicon "en" lexicon))


Fix typo in requires

Fix typo in requires

--- src/braid/server/handler.clj
+++ src/braid/server/handler.clj
@@ -16,7 +16,7 @@
             [braid.server.routes.client :refer [desktop-client-routes
                                                 mobile-client-routes
                                                 resource-routes]]
-            [braid.server.routes.api.public :refer [api-private-routes]]
+            [braid.server.routes.api.public :refer [api-public-routes]]
             [braid.server.routes.api.private :refer [api-private-routes]]
             [braid.server.routes.bots :refer [bot-routes]]
             [environ.core :refer [env]]


Find and run all clj_record/test/*-test.clj files.

--- clj_record/test/main.clj
+++ clj_record/test/main.clj
@@ -29,8 +29,11 @@

 (println "Setup complete.")

-(let [test-files ["util-test" "core-test" "validation-test" "associations-test"]
-      base-ns (re-find #"^\w*.*\." (str *ns*))]
+(let [test-files  (for [f (.list (.getParentFile (java.io.File. *file*)))
+                        :when (re-find #"-test.clj$" f)]
+                    (re-find #"[^.]+" f))
+      base-ns (re-find #"^\w*.*\." (str *ns*))
+      test-namespaces (map #(symbol (str base-ns %)) test-files)]
   (doseq [file test-files]
     (load file))
-  (apply test-is/run-tests (map #(symbol (str base-ns %)) test-files)))
+  (apply test-is/run-tests test-namespaces))


Update lispychat.clj

Update lispychat.clj

--- src/extras/lispychat.clj
+++ src/extras/lispychat.clj
@@ -1,3 +1,5 @@
+
+
 (ns extras.lispychat
   (:use lamina.core
         aleph.http
@@ -39,16 +41,10 @@
       (wrap-resource "public")
       (wrap-file-info)))

-(defn start-lispy-chat-server [& args])
-
 (def chat-channel (ref ()))
 (defn send-msg [msg]
   (enqueue @chat-channel (str "iyye> " msg)))

-(def lispy-chat-IO (bios/create-IO "lispy-chat" start-lispy-chat-server (bios/create-InputSources false []) (bios/->OutputActuators false [send-msg])))
-(dosync (alter bios/AvatarsIOList conj lispy-chat-IO))
-
-(def lispy-chat-process-input (partial bios/process-input lispy-chat-IO))

 (defn chat-init [ch])
 (defn chat-handler [ch room]
@@ -67,6 +63,7 @@
       (ref-set chat-channel ch)
       (chat-handler ch "iyye"))
     (enqueue ch (wrapped-sync-app request))))
+
 (defroutes app-routes
            "Routes requests to their handler function. Captures dynamic variables."
            (GET ["/chat/iyye"] {}
@@ -80,10 +77,14 @@
 (defn start-lispy-chat-server [& args]
   "Main thread for the server which starts an async server with
   all the routes we specified and is websocket ready."
+  (log/info "start http server")
   (start-http-server (wrap-ring-handler app-routes)
                      {:host "localhost" :port 8080 :websocket true}))

-; move to iyye!
+(def lispy-chat-IO (bios/create-IO "lispy-chat" start-lispy-chat-server (bios/create-InputSources false []) (bios/->OutputActuators false [send-msg])))
+
+(def lispy-chat-process-input (partial bios/process-input lispy-chat-IO))
+
 (defn chat-init [ch]
   "register callback for receive msg"
   (receive-all ch lispy-chat-process-input))


Improves user-links and adds flash to layout.

--- src/cadence/views/common.clj
+++ src/cadence/views/common.clj
@@ -1,5 +1,8 @@
 (ns cadence.views.common
-  (:require [clojure.string :as string])
+  (:require [clojure.string :as string]
+            [cemerick.friend :as friend]
+            [cadence.model :as m]
+            [cadence.model.flash :as flash])
   (:use noir.core
         hiccup.core
         hiccup.page-helpers))
@@ -24,12 +27,18 @@

 (defpartial user-links []
   [:li.dropdown
-   [:a.dropdown-toggle
-    {:data-toggle "dropdown"}
-    [:i.icon-user.icon-white] " User " [:b.caret]]
-   [:ul.dropdown-menu
-    [:li [:a {:href "/signup"} [:i.icon-check] " Sign Up"]]
-    [:li [:a {:href "/login"} [:i.icon-share] " Log In"]]]])
+   (if (friend/anonymous?)
+     (html [:a.dropdown-toggle
+            {:data-toggle "dropdown"}
+            [:i.icon-user.icon-white] " User " [:b.caret]]
+           [:ul.dropdown-menu
+            [:li [:a {:href "/signup"} [:i.icon-check] " Sign Up"]]
+            [:li [:a {:href "/login"} [:i.icon-share] " Log In"]]])
+     (html [:a.dropdown-toggle
+            {:data-toggle "dropdown"}
+            [:i.icon-user.icon-white] " " (m/identity) " " [:b.caret]]
+           [:ul.dropdown-menu
+            [:li [:a {:href "/logout"} [:i.icon-off] " Log Out"]]]))])

 (defpartial layout [& content]
   (base-layout
@@ -50,10 +59,16 @@
          (user-links)]
         ]]]]
     [:div#main-wrapper
-     [:div#main.container content]]))
+     [:div#main.container
+      (when-let [{:keys [type message]} (flash/get)]
+        (let [type (name type)]
+          [:div {:id "flash" :class (str "alert alert-" type)}
+           [:a.close {:data-dismiss "alert"} "x"]
+           [:strong (string/capitalize type) ": "] message]))
+      content]]))

 (defpartial control-group [params]
-  (let [name (string/lower-case (:name params))]
+  (let [name (string/replace (string/lower-case (:name params)) #"\s" "-")]
     [:div.control-group
      [:label.control-label {:for name} (str (:name params) ": ")]
      [:div.controls


Remove duplicate def.

Remove duplicate def.

--- src/onyx/schema.cljc
+++ src/onyx/schema.cljc
@@ -689,20 +689,3 @@
 (def Event
   (-> (information-model->schema (i/model :event-map))
       (assoc (restricted-ns :onyx.core) s/Any)))
-
-(def WindowState
-  (s/constrained
-   {:window-extension WindowExtension
-    :trigger-states [TriggerState]
-    :window Window
-    :state {s/Any s/Any}
-    :state-event (s/maybe StateEvent)
-    :event-results [StateEvent]
-    :init-fn Function
-    :create-state-update Function
-    :apply-state-update Function
-    :super-agg-fn (s/maybe Function)
-    (s/optional-key :new-window-state-fn) Function
-    (s/optional-key :grouping-fn) (s/cond-pre s/Keyword Function)}
-   record? 'record?))
-


Fix atom init value

Fix atom init value

--- src/gol/client.cljs
+++ src/gol/client.cljs
@@ -44,15 +44,12 @@
   [count width height]
   (set (take count (distinct (repeatedly (fn [] [(rand-int width) (rand-int height)]))))))

-(def state (atom (let [count   300
-                       timeout 250
-                       width   30
-                       height  30]
+(def state (atom (let [count 300 width 30 height 30]
                    {:gen     (rand-state count width height)
-                    :count   300
+                    :count   count
                     :timeout 250
-                    :width   30
-                    :height  30
+                    :width   width
+                    :height  height
                     :pause   false})))

 (def main-component


facts about inverse

facts about inverse

--- src/latte/fun.clj
+++ src/latte/fun.clj
@@ -141,3 +141,30 @@
     (q/the T (lambda [x T] (equal U (f x) y))
            ((bijective-unique T U f) b y))))

+(defthm inverse-surjective
+  "The inverse function of a bijection, is surjective."
+  [[T :type] [U :type] [f (==> T U)] [b (bijective T U f)]]
+  (surjective U T (inverse T U f b)))
+
+(proof inverse-surjective
+    :script
+  (have <a> (injective T U f) :by ((bijective-is-injective T U f) b))
+  (have inv-f (==> U T) :by (inverse T U f b))
+  (assume [x T]
+    (have y U :by (f x))
+    (have <b> (equal U (f (inv-f y)) (f x))
+          :by (q/the-prop T
+                          (lambda [z T] (equal U (f z) y))
+                          (((bijective-unique T U f) b) y)))
+    (have <c> (equal T (inv-f y) x) :by (<a> (inv-f y) x <b>))
+    (have <d> (exists [y U] (equal T (inv-f y) x))
+          :by ((q/ex-intro U (lambda [z U] (equal T (inv-f z) x)) y)
+               <c>))
+    (qed <d>)))
+
+(defthm inverse-injective
+  "The inverse function of a bijection, is injective."
+  [[T :type] [U :type] [f (==> T U)] [b (bijective T U f)]]
+  (injective U T (inverse T U f b)))
+
+


fix db-properties

fix db-properties

--- src/modus/system/db_connection.clj
+++ src/modus/system/db_connection.clj
@@ -23,7 +23,7 @@

 (defn psql-db-properties
   []
-  {:url           (str "jdbc:postgresql:" (System/getProperty "DB_CONNSTR" "//localhost:5432/modus"))
+  {:url           (str "jdbc:postgresql://" (System/getProperty "DB_CONNSTR" "localhost:5432/modus"))
    :username      (System/getProperty "DB_USERNAME" (System/getProperty "user.name"))
    :password      (System/getProperty "DB_PASSWORD" "")
    :max-pool-size (int-system-property "DB_MAX_POOL_SIZE" 10)})


execute and exit helper for node test runner

--- src/clj/shadow/cljs/node.clj
+++ src/clj/shadow/cljs/node.clj
@@ -157,11 +157,10 @@

     (cljs/with-logged-time
       [logger (format "Execute: %s" (pr-str script-args))]
-      (let [proc (.start pb)]
-        ;; FIXME: what if this doesn't terminate?
-        (.waitFor proc))))
-
-  state)
+      (let [proc (.start pb)
+            ;; FIXME: what if this doesn't terminate?
+            exit-code (.waitFor proc)]
+        (assoc state ::exit-code exit-code)))))

 (defn setup-test-runner [state test-namespaces]
   (let [test-runner-src
@@ -235,3 +234,10 @@
   ;; return unmodified state!
   state
   )
+
+(defn execute-all-tests-and-exit! [state]
+  (let [state (-> state
+                  (make-test-runner)
+                  (execute! "node" :script))]
+    (System/exit (::exit-code state))))
+


Fixes visual offset problem.

Fixes visual offset problem.

--- src/clj/triangulate/core.clj
+++ src/clj/triangulate/core.clj
@@ -7,6 +7,12 @@
             [triangulate.memcached :as m])
   (:import [polyline PolylineDecoder]
            [polyline Location]))
+
+(def offset
+  "The distance between two intersections uses points
+   directly in the middle of each intersection. We want
+   a little distance to where cars actually stop."
+  10)

 (defn polyline-from-google [src dst]
   (let [query-params {:origin src :destination dst :sensor false}
@@ -67,7 +73,8 @@
        "," extender))

 (defn target-coordinates [src dst gap extender]
-  (let [formatted-src (format-intx src extender)
+  (let [gap (+ gap offset)
+        formatted-src (format-intx src extender)
         formatted-dst (format-intx dst extender)
         coordinates (reverse (decode-polyline (polyline formatted-src formatted-dst)))
         pairs (partition 2 1 coordinates)


Fix problem with new all-publics not being able to display info about clojure.core//

--- src/clj_ns_browser/utils.clj
+++ src/clj_ns_browser/utils.clj
@@ -65,6 +65,14 @@
   "Returns whether a ns is on the classpath but not loaded/required (yet)."
   [ns]
   (let [nss (str ns)] (get (all-ns-unloaded) nss)))
+
+
+;; "clojure.core//" appears to be a special case not handled well by
+;; the function symbol.
+(defn better-symbol [fqn]
+  (if (= fqn "clojure.core//")
+    (symbol "clojure.core" "/")
+    (symbol fqn)))

 (defn fqname
@@ -81,7 +89,7 @@
           :else (fqname *ns* n)))
   ([ns n]
     (let [n-str (str n)
-          n-sym (symbol n-str)]
+          n-sym (better-symbol n-str)]
       (if (some #(= % n-str) special-forms) n-str
         (if-let [n-ns (find-ns n-sym)]
           (str n-ns)
@@ -92,7 +100,7 @@
                                (find-ns (symbol (str ns))))]
               (if-let [var-n (when (var? n) (str (.ns n) "/" (.sym n)))]
                 var-n
-                (let [n-sym (symbol (str n))]
+                (let [n-sym (better-symbol (str n))]
                   (when-let [v-n (try (ns-resolve ns-ns n-sym)(catch Exception e))]
                     (if (var? v-n)
                       (str (.ns v-n) "/" (.sym v-n))
@@ -251,14 +259,6 @@
 ;; var?

 ;; (in-ns 'clj-ns-browser.utils)
-
-
-;; "clojure.core//" appears to be a special case not handled well by
-;; the function symbol.
-(defn better-symbol [fqn]
-  (if (= fqn "clojure.core//")
-    (symbol "clojure.core" "/")
-    (symbol fqn)))

 (defn eval-sym [sym]
@@ -326,7 +326,7 @@
   "Given a FQN, return the doc or source code as string, based on options."
   [fqn doc-opt]
   (when-not (or (nil? fqn) (= fqn "") (nil? doc-opt))
-    (let [is-ns? (find-ns (symbol fqn))]
+    (let [is-ns? (find-ns (better-symbol fqn))]
       (case doc-opt
         ;; quick to write, if a little inefficient
         "All" (if is-ns?


work on protocols

work on protocols

--- src/cljs/fluch/terminal.cljs
+++ src/cljs/fluch/terminal.cljs
@@ -38,16 +38,70 @@
                    ::options]))

 (defprotocol ITerminal
-  (init [this]))
+  (init [this])
+  (current-position [this])
+  (move-to! [this col row])
+  (put-char! [this char])
+  (up-char! [this])
+  (right-char! [this])
+  (down-char! [this])
+  (left-char! [this])
+  (in> [this input options])
+  (refresh! [this])
+  (out< [this options])
+  (out<< [this callback options]))

 (defrecord Terminal [screen cursor event-channel in-channel out-channel options]
   ITerminal
   (init [{:keys [event-channel] :as this}]
     (events/init this)
+
+    ;; Track Events
     (go-loop []
       (let [{:keys [type] :as event} (<! event-channel)]
         (.log js/console "Received Event" event))
-      (recur))))
+      (recur)))
+
+  (current-position [{:keys [cursor]}]
+    @cursor)
+
+  (move-to! [{:keys [cursor]} col row]
+    (reset! cursor [col row]))
+
+  (put-char! [{:keys [screen] :as this} char]
+    (let [[i j] (current-position this)]
+      (reset! screen (screen/put-char @screen char i j {}))))
+
+  (up-char! [this]
+    (let [[i j] (current-position this)]
+      (when (> j 0)
+        (move-to! this i (dec j)))))
+
+  (right-char! [{:keys [screen] :as this}]
+    (let [[i j] (current-position this)
+          {:keys [rows cols]} @screen]
+      (when (< i (dec cols))
+        (move-to! this (inc i) j))))
+
+  (down-char! [{:keys [screen] :as this}]
+    (let [[i j] (current-position this)
+          {:keys [rows cols]} @screen]
+      (when (< j (dec rows))
+        (move-to! this i (inc j)))))
+
+  (left-char! [this]
+    (let [[i j] (current-position this)]
+      (when (> i 0)
+        (move-to! this (dec i) j))))
+
+  (in> [this input options])
+
+  (refresh! [{:keys [screen]}]
+    (screen/refresh! @screen))
+
+  (out< [this options])
+
+  (out<< [this callback options]))

 (defn terminal
   [screen


Simplify Topic Function of Event Bus

Simplify Topic Function of Event Bus

--- src/cljs/lens/event_bus.cljs
+++ src/cljs/lens/event_bus.cljs
@@ -26,7 +26,7 @@
 (defn init-bus []
   (let [publisher (async/chan)]
     {:publisher publisher
-     :publication (async/pub publisher #(:topic %))}))
+     :publication (async/pub publisher :topic)}))

 (defn register-for-unlisten [owner topic ch]
   (om/update-state! owner ::subs #(conj % [topic ch])))


Simplify precond for maptrans

Simplify precond for maptrans

--- src/com/puppetlabs/utils.clj
+++ src/com/puppetlabs/utils.clj
@@ -49,19 +49,6 @@
     (satisfies? ICoerce x)
     (to-date-time x)))

-;; TODO: no one besides us is ever going to use this, but I'm not sure where
-;; else to put it.  Seems goofy to create a "utils.internal" namespace?
-(defn keywords-fn-pair?
-  "Predicate that expects to be passed a two-element list; the first element
-  should be a list of keywords, and the second element should be a function.
-  This is the data structure required by some of our map utility functions, so
-  this is mostly used to validate input to those functions via preconditions."
-  [[ks fn]]
-  (and
-    (coll? ks)
-    (every? keyword? ks)
-    (ifn? fn)))
-
 ;; ## I/O

 (defn lines
@@ -162,7 +149,7 @@
   Example: `(maptrans {[:a, :b] inc [:c] dec} {:a 1 :b 1 :c 1})` yields `{:a 2, :c 0, :b 2}`"
   [keys-fns m]
   {:pre [(map? keys-fns)
-         (every? keywords-fn-pair? keys-fns)
+         (every? (fn [[ks fn]] (and (coll? ks) (ifn? fn))) keys-fns)
          (map? m)]}
   (let [ks (keys keys-fns)]
     (reduce (fn [m k] (mapvals (keys-fns k) m k)) m ks)))


Drop time precision a little bit.

Drop time precision a little bit.

--- src/player/core.cljs
+++ src/player/core.cljs
@@ -96,7 +96,7 @@
                    }})

 (set! heval/frame-length (/ 1 30))
-(set! heval/time-units-per-frame 10000)
+(set! heval/time-units-per-frame 1000)
 (set! heval/time-unit (/ heval/frame-length heval/time-units-per-frame))
 (set! heval/precision 0.01)


Docstring

Docstring

--- src/cyanite_remover/core.clj
+++ src/cyanite_remover/core.clj
@@ -45,6 +45,7 @@
   (swap! inspecting? (fn [_] true)))

 (defn- get-sort-or-not-fn
+  "Get sort or dummy function."
   [sort?]
   (if sort? sort #(do %)))


Change color of sub/run and fsm-trigger

Change color of sub/run and fsm-trigger

--- src/day8/re_frame/trace.cljs
+++ src/day8/re_frame/trace.cljs
@@ -143,10 +143,10 @@
         (list [:tr {:key   id
                     :style {:color (case op-type
                                      :sub/create "green"
-                                     :sub/run "red"
+                                     :sub/run "#fd701e"
                                      :event "blue"
                                      :render "purple"
-                                     :re-frame.router/fsm-trigger "red"
+                                     :re-frame.router/fsm-trigger "#fd701e"
                                      nil)}}
                [:td {:style row-style} (str op-type)]
                [:td {:style row-style} operation]


Unescape references before searching them in the DOM (Fix #8)

--- src/discuss/integration.cljs
+++ src/discuss/integration.cljs
@@ -8,6 +8,7 @@
             [discuss.extensions]
             [discuss.communication :as com]
             [discuss.utils.common :as lib]
+            [discuss.utils.views :as vlib]
             [discuss.sidebar :as sidebar]
             [discuss.tooltip :as tooltip]))

@@ -75,7 +76,7 @@
 (defn convert-reference
   "Find parent of reference, split it into parts and wrap the original reference for highlighting and interaction."
   [ref]
-  (let [ref-text (:text ref)
+  (let [ref-text (vlib/html->str (:text ref))
         ref-url  (:url ref)
         doms-raw (.getElementsByTagName js/document "*")
         doms     (minify-doms doms-raw)


Reinstate saving

Reinstate saving

--- src/dungeon_crusade/core.clj
+++ src/dungeon_crusade/core.clj
@@ -1,5 +1,6 @@
 ;; ## A roguelike focused on immutability.##
 ;;
+(set! *warn-on-reflection* true)
 (ns dungeon-crusade.core
   (:use dungeon-crusade.main
         clojure.stacktrace))


Expose field functions

Expose field functions

--- src/tick/alpha/api.clj
+++ src/tick/alpha/api.clj
@@ -1,7 +1,15 @@
 ;; Copyright © 2016-2017, JUXT LTD.

 (ns tick.alpha.api
-  (:refer-clojure :exclude [+ - * / inc dec max min range time int long complement < <= > >= << >> extend atom swap! swap-vals! compare-and-set! reset! reset-vals!])
+  (:refer-clojure
+   :exclude [+ - * / inc dec max min
+             range time int long complement
+             < <= > >= << >>
+             extend
+             atom swap! swap-vals! compare-and-set!
+             reset! reset-vals!
+             second
+             ])
   (:require
    [clojure.spec.alpha :as s]
    [tick.core :as core]
@@ -52,7 +60,7 @@
 (def november Month/NOVEMBER)
 (def december Month/DECEMBER)

-;; Constructors
+;; Construction and coercion

 (defn date
   ([] (core/date (today)))
@@ -60,6 +68,12 @@
 (defn time
   ([] (core/time (now)))
   ([v] (core/time v)))
+
+(defn millisecond [t] (core/millisecond t))
+(defn second [t] (core/second t))
+(defn minute [t] (core/minute t))
+(defn hour [t] (core/hour t))
+
 (defn day
   ([] (core/day (today)))
   ([v] (core/day v)))


Avoid redundant checks on bounds

Avoid redundant checks on bounds

--- src/tick/interval.cljc
+++ src/tick/interval.cljc
@@ -97,7 +97,7 @@
   (in [i zone] (interval (t/in (t/beginning i) zone) (t/in (t/end i) zone))))

 (defn bounds [& args]
-  (interval
+  (make-interval
     (apply t/min (map t/beginning args))
     (apply t/max (map t/end args))))


Set :none as optimization level for watch script.

--- scripts/watch.clj
+++ scripts/watch.clj
@@ -5,7 +5,7 @@
    :target :nodejs
    :output-to "out/tests.js"
    :output-dir "out"
-   :optimizations :advanced
+   :optimizations :none
    :pretty-print true
    :language-in  :ecmascript5
    :language-out :ecmascript5


get rid of unquote

get rid of unquote

--- src/fink_nottle/internal.clj
+++ src/fink_nottle/internal.clj
@@ -37,8 +37,8 @@
                   ~(keyword target-name) ~'creds
                   (merge (plumbing.map/keyword-map ~@args) ~'extra))]
     `(do
-       (defn ~(with-meta fname!  {:doc ~doc}) ~args' ~body)
-       (defn ~(with-meta fname!! {:doc ~doc}) ~args' (<?! ~body)))))
+       (defn ~(with-meta fname!  {:doc doc}) ~args' ~body)
+       (defn ~(with-meta fname!! {:doc doc}) ~args' (<?! ~body)))))

 (defmacro defissuers [service-name t->args]
   `(do


defn width-height

defn width-height

--- src/glory_of_empires/map.clj
+++ src/glory_of_empires/map.clj
@@ -54,10 +54,11 @@
          scale-str (if (nil? scale) "" (str "scale(" scale ")")) ]
     { :transform (str scale-str " " translate) } ))

+(defn- width-height [ loc ] { :width (first loc) :height (last loc) } )
+
 (defn- piece-to-svg [ { logical-pos :logical-pos system :system :as tile } ]
   [ :g (transform { :translate (screen-loc logical-pos) })
-    [ :image { :x 0 :y 0 :width (first tile-size) :height (last tile-size)
-               "xlink:href" (str resources-url "Tiles/" (system :image)) } ] ] )
+    [ :image (merge { :x 0 :y 0 } (width-height tile-size) { "xlink:href" (str resources-url "Tiles/" (system :image)) } ) ] ] )

 (defn bounding-rect [ map-pieces ]
   (let [ s-locs (screen-locs map-pieces) ]
@@ -66,7 +67,7 @@
 (defn rect-size [ [ min-corner max-corner ] ] (map - max-corner min-corner))

 (defn- svg [ size & content ]
-  (concat [ :svg { :width (first size) :height (last size) "xmlns:xlink" "http://www.w3.org/1999/xlink" } ] content ))
+  (concat [ :svg (merge (width-height size) { "xmlns:xlink" "http://www.w3.org/1999/xlink" } ) ] content ))

 (defn map-to-svg [ map-pieces scale ]
   (let [ bounds (bounding-rect map-pieces)


Increase update check timeout.

Increase update check timeout.

--- src/gorilla_repl/version.clj
+++ src/gorilla_repl/version.clj
@@ -18,7 +18,7 @@
   [current]
   (http/get
     (str update-url current)
-    {:timeout 10000 :as :text}
+    {:timeout 30000 :as :text}
     (fn [{:keys [status headers body error]}]
       (if error
         (println "Unable to reach update server.")


How to search in parallel

How to search in parallel

--- src/adventofcode1/twentyfour.clj
+++ src/adventofcode1/twentyfour.clj
@@ -54,6 +54,15 @@

 ;; specter ideas: for example how to go to any eelement
 ;; https://github.com/nathanmarz/specter/issues/57
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; parallel ideas.
+;; stest/gen uses pmap, which uses (future x) + (deref x)
+;; it derefs (.. Runtime getRuntime availableProcessors) (== 4)
+;; elements at a time
+

 ;; (def max-width 10)
 ;; (def max-height 5)


Enforce sort order on list-versions

Enforce sort order on list-versions

--- src/grimoire/api/fs/read.clj
+++ src/grimoire/api/fs/read.clj
@@ -31,9 +31,11 @@
         artifact (thing->artifact thing)
         _        (assert artifact)
         handle   (thing->handle config :else artifact)]
-    (for [d     (.listFiles handle)
-          :when (.isDirectory d)]
-      (->T :version artifact (.getName d)))))
+    (->> (for [d     (reverse (sort (.listFiles handle)))
+             :when (.isDirectory d)]
+         (->T :version artifact (.getName d)))
+      (sort-by :name)
+      reverse)))

 (defmethod api/list-namespaces :filesystem [config thing]
   (let [thing   (ensure-thing thing)


Refactor the import functionality using the -> macro

--- src/mdr2/abacus.clj
+++ src/mdr2/abacus.clj
@@ -46,73 +46,102 @@
     (into {} (for [[key path] param-mapping]
                [key ($x:text (str root path) xml)]))))

-(defn- file-startswith? [f xs]
-  (some #(.startsWith % (.getName f)) xs))
+(defn file-startswith? [f xs]
+  (some #(.startsWith (.getName f) %) xs))
+
+(defn get-all-files []
+  "Return all files from the `import-dir`"
+  (filter #(.isFile %)
+          (file-seq (file import-dir))))
+
+(defn delete-files!
+  "Delete all given `files`"
+  [files]
+  (doseq [f files] (delete-file f)))

 (defn open-production?
   "Is the given `file` an export for opening a production?"
   [file]
   (file-startswith? file ["SN1_" "SN10_"]))

+(defn import-new-production
+  "Import a new production from file `f`"
+  [f]
+  (msg/publish (msg/queue "create") (read-file f))
+  f)
+
 (defn import-new-productions
   "Import new productions from ABACUS and put them on the create queue"
   []
-  (doseq [f (filter #(and (.isFile %)
-                          (open-production? %)
-                          (validation/valid-open? %))
-                    (file-seq (file import-dir)))]
-    (msg/publish "queue.create" (read-file f))
-    (delete-file f)))
+  (->>
+   (get-all-files)
+   (filter open-production?)
+   (filter validation/valid-open?)
+   (map import-new-production)
+   (delete-files!)))

 (defn recorded-production?
   "Is the given `file` an export for a production that has been recorded?"
   [file]
   (file-startswith? file ["SN3_" "SN12_"]))

+(defn import-recorded-production
+  "Import a recorded production from file `f`"
+  [f]
+  (let [{product-number :productNumber} (read-file f)
+        production (production/find-by-productnumber product-number)]
+    (msg/publish (msg/queue "archive") production)
+    f))
+
 (defn import-recorded-productions
   "Import recorded productions from ABACUS and put them on the archive queue"
   []
-  (doseq [f (filter #(and (.isFile %)
-                          (recorded-production? %)
-                          (validation/valid-recorded? %))
-                    (file-seq (file import-dir)))]
-    (let [{product-number :productNumber} (read-file f)
-          production (production/find-by-productnumber product-number)]
-      (msg/publish "queue.archive" production)
-      (delete-file f))))
+  (->>
+   (get-all-files)
+   (filter recorded-production?)
+   (filter validation/valid-recorded?)
+   (map import-recorded-production)
+   (delete-files!)))

 (defn status-request?
   "Is the given `file` an status request for a production?"
   [file]
   (file-startswith? file ["SNStatus_"]))

+(defn import-status-request [f]
+  (let [{product-number :productNumber} (read-file f)
+        production (production/find-by-productnumber product-number)]
+    (msg/publish (msg/queue "notify-abacus") production)
+    f))
+
 (defn import-status-requests
   "Import status requests from ABACUS and put them on the queue"
   []
-  (doseq [f (filter #(and (.isFile %)
-                          (status-request? %)
-                          (validation/valid-status-request? %))
-                    (file-seq (file import-dir)))]
-    (let [{product-number :productNumber} (read-file f)
-          production (production/find-by-productnumber product-number)]
-      (msg/publish "queue.notify-abacus" production)
-      (delete-file f))))
+  (->>
+   (get-all-files)
+   (filter status-request?)
+   (filter validation/valid-status-request?)
+   (map import-status-request)
+   (delete-files!)))

 (defn metadata-update?
   "Is the given `file` an metadata update for a production?"
   [file]
   (file-startswith? file ["SNMeta_"]))

+(defn import-metadata-update [f]
+  (msg/publish (msg/queue "metadata-update") (read-file f))
+  f)
+
 (defn import-metadata-updates
   "Import metadata updates from ABACUS and put them on the queue"
   []
-  (doseq [f (filter #(and (.isFile %)
-                          (metadata-update? %)
-                          (validation/valid-metadata-sync? %))
-                    (file-seq (file import-dir)))]
-    (let [production (read-file f)]
-      (msg/publish "queue.metadata-update" production)
-      (delete-file f))))
+  (->>
+   (get-all-files)
+   (filter metadata-update?)
+   (filter validation/valid-metadata-sync?)
+   (map import-metadata-update)
+   (delete-files!)))

 (defn escape
   "Escape a string `s` for ABACUS consumption"


making services lazy

making services lazy

--- src/vsphere/vijava.clj
+++ src/vsphere/vijava.clj
@@ -28,15 +28,17 @@
 (defn connect [{:keys [url username password]}]
   (ServiceInstance. (URL. url) username password true))

-(def services (into [] (repeatedly 2 #(agent (connect (get* :hypervisor :vsphere))))))
+(def services
+  (memoize (fn []  (into [] (repeatedly 2 #(agent (connect (get* :hypervisor :vsphere))))))))

 (defmacro with-service
-  "Uses recycled service instances see http://bit.ly/YRsiNo"
+  "Uses recycled service instances see http://bit.ly/YRsiNo,
+  We try to keep all agents busy still rand isn't fair (cycle would work better)."
   [body]
-  `(let [a# (services (rand-int (count services))) p# (promise)]
+  `(let [a# ((services) (rand-int (count (services)))) p# (promise)]
      (send a# (fn [s#]
                 (try
-                  (binding [service s#] (deliver p# ~body) s#)
+                  (binding [service s#] (debug (.hashCode service)) (deliver p# ~body) s#)
                   (catch Throwable e# (deliver p# e#) s#))))
      (let [res# @p#]
        (when (instance? Throwable res#)
@@ -116,12 +118,10 @@
 (comment
   (clone {:datacenter "playground"}
          {:template "ubuntu-13.04_puppet-3.1" :hostname "foo" :disk-format :sparse :cpus 1 :memory 512})
-  (repeatedly 40 (fn []  (future )))
+  (map deref (repeatedly 40 (fn []  (future (status "foo") ))))
   (status "foo")
   (power-on "foo")
-  (power-off "foo")
-
-  )
+  (power-off "foo"))


fix hits total when using filter

fix hits total when using filter

--- src/wb_es/web/core.clj
+++ src/wb_es/web/core.clj
@@ -8,15 +8,16 @@
        (cons (when-let [type-value (:type options)]
                {:type {:value (clojure.string/replace type-value #"_" "-")}}))
        (filter identity)
-       (assoc-in {} [:bool :must])))
+       (assoc-in {} [:bool :filter])))
+

 (defn search [q options]
   (let [query {:query
                {:bool
-                {:filter (get-filter options)
-                 :should [{:term {:wbid q}}
-                          {:match {:label q}}
-                          {:match {:_all q}}]}}}
+                {:must [(get-filter options)
+                        {:bool {:should [{:term {:wbid q}}
+                                         {:match {:label q}}
+                                         {:match {:_all q}}]}}]}}}

         response
         (http/get (format "%s/%s/_search?size=%s&from=%s"


fix users for weekly digest job

fix users for weekly digest job

--- src/chat/server/email_digest.clj
+++ src/chat/server/email_digest.clj
@@ -112,7 +112,7 @@
 (defjob WeeklyDigestJob
   [ctx]
   (timbre/debugf "Starting weekly email job")
-  (let [user-ids (daily-update-users)
+  (let [user-ids (weekly-update-users)
         cutoff (time/minus (time/now) (time/days 7))]
     (doseq [uid user-ids]
       (when-let [threads (seq (updates-for-user-since uid cutoff))]


Don't bother with showfn? etc unless we are doing color.

--- src/zprint/zprint.cljc
+++ src/zprint/zprint.cljc
@@ -124,9 +124,10 @@

 (defn showfn?
   "Show this thing as a function?"
-  [fn-map f]
-  (when (not (string? f))
-    (let [f-str (str f)]
+  [{:keys [fn-map color?], :as options} f]
+  (when (and color? (not (string? f)))
+    (let [f-str (str f)
+          fn-map (:fn-map options)]
       (or (fn-map f-str)
           (re-find #"clojure" f-str)
           (if (symbol? f)
@@ -146,10 +147,9 @@
 (defn show-user-fn?
   "Show this thing as a user defined function?  Assumes that we
   have already handled any clojure defined functions!"
-  [options f]
-  (when (not (string? f))
-    (let [f-str (str f)
-          user-fn-map (:user-fn-map options)]
+  [{:keys [user-fn-map color?], :as options} f]
+  (when (and color? (not (string? f)))
+    (let [f-str (str f)]
       (or (get user-fn-map f-str)
           (if (symbol? f)
             ; This is necessary because f can be a symbol that
@@ -709,8 +709,12 @@
 (defn zcolor-map
   "Look up the thing in the zprint-color-map.  Accepts keywords or
   strings."
-  [{:keys [color-map], :as options} key-or-str]
-  (color-map (if (keyword? key-or-str) key-or-str (str->key key-or-str))))
+  [{:keys [color-map color?], :as options} key-or-str]
+  ; If we aren't doing color, don't even bother to do the lookup
+  (if color?
+  (color-map (if (keyword? key-or-str) key-or-str (str->key key-or-str)))
+  :none
+  ))

 ;;
@@ -5175,7 +5179,7 @@

 (defn fzprint*
   "The pretty print part of fzprint."
-  [{:keys [width rightcnt fn-map hex? shift-seq dbg? dbg-print? in-hang?
+  [{:keys [width rightcnt hex? shift-seq dbg? dbg-print? in-hang?
            one-line? string-str? string-color depth max-depth trim-comments?
            in-code? max-hang-depth max-hang-span max-hang-count next-inner],
     :as options} indent zloc]
@@ -5336,7 +5340,7 @@
                       (zstring zloc))
                     (if string-color string-color (zcolor-map options :string))
                     :element]]
-                (showfn? fn-map (zsexpr zloc)) [[zstr (zcolor-map options :fn)
+                (showfn? options (zsexpr zloc)) [[zstr (zcolor-map options :fn)
                                                  :element]]
                 (show-user-fn? options (zsexpr zloc))
                   [[zstr (zcolor-map options :user-fn) :element]]


TODO notes

TODO notes

--- src/kixi/hecuba/web/amon.clj
+++ src/kixi/hecuba/web/amon.clj
@@ -139,3 +139,8 @@
     (add-bidi-routes system config
                      (make-routes (make-handlers (select-keys system [:commander :querier])))))
   (stop [_ system] system))
+
+
+;; TODO Entity PUTs
+;; TODO Device PUTs
+;; TODO Measurement GETs


Add a flip function.

Add a flip function.

--- src/useful/fn.clj
+++ src/useful/fn.clj
@@ -103,3 +103,8 @@
        (condp #(% %2) direction
          #{:desc :descending -} (comp - f)
          #{:asc :ascending +} f))))
+
+(defn flip
+  "Create a function that applies f to its arguments reversed, 'flipping'
+   the argument order."
+  [f] #(apply f (reverse %&)))


revise Hades Shard fix to flip all cards in Archives face up

--- src/clj/game/cards-resources.clj
+++ src/clj/game/cards-resources.clj
@@ -211,8 +211,9 @@

    "Hades Shard"
    {:abilities [{:msg "access all cards in Archives"
-                 :effect (effect (trash card {:cause :ability-cost})
-                                 (handle-access (get-in @state [:corp :discard])))}]
+                 :effect (req (trash state side card {:cause :ability-cost})
+                              (swap! state update-in [:corp :discard] #(map (fn [c] (assoc c :seen true)) %))
+                              (handle-access state side (get-in @state [:corp :discard])))}]
     :install-cost-bonus (req (if (and run (= (:server run) [:archives]) (= 0 (:position run)))
                                [:credit -7 :click -1] nil))
     :effect (req (when (and run (= (:server run) [:archives]) (= 0 (:position run)))


Improve documentation in `quil.helpers.drawing`.

--- src/clj/quil/helpers/drawing.clj
+++ src/clj/quil/helpers/drawing.clj
@@ -4,14 +4,17 @@
   "Takes either a seq of x y (and z) point coords tuples or two
   separate lists of x and y (and z) coords independently and creates a
   lazy list of line args (vectors of 4 (or 6) elements) suitable for
-  use with the line fn.
+  use with the [[quil.core/line]] function.

+  Examples:
+  ```
   (line-join-points [1 2 3] [4 5 6])     ;=> ([1 4 2 5] [2 5 3 6])
   (line-join-points [[1 4] [2 5] [3 6]]) ;=> ([1 4 2 5] [2 5 3 6])
   (line-join-points [[1 4 0] [2 5 1] [3 6 2]]) ;=> ([1 4 0 2 5 1]
-                                                    [2 5 1 3 6 2])
+                                               ;    [2 5 1 3 6 2])
   (line-join-points [1 2 3] [4 5 6] [0 1 2])   ;=> ([1 4 0 2 5 1]
-                                                    [2 5 1 3 6 2])"
+                                               ;    [2 5 1 3 6 2])
+  ```"
   ([interleaved-points]
    (lazy-seq
     (let [head (take 2 interleaved-points)]


Add js error tracking for all pages.

Add js error tracking for all pages.

--- src/clj/quil_site/views/page.clj
+++ src/clj/quil_site/views/page.clj
@@ -20,7 +20,13 @@
   })(window,document,'ga');

   ga('create', 'UA-51485241-2', 'auto');
-  ga('send', 'pageview');"]
+  ga('send', 'pageview');
+  window.onerror = function(message) {
+    ga('send', 'exception', {
+      exDescription: message,
+      exFatal: false
+    });
+  };"]

    (let [css-files (conj (:css-files opts [])
                          "/css/bootstrap.min.css"


add :after-save step

add :after-save step

--- src/clj_money/models/helpers.clj
+++ src/clj_money/models/helpers.clj
@@ -90,7 +90,7 @@
     (with-storage [s storage-spec]
       (let [validated (validate options s model)]
         (if (validation/valid? validated)
-          (process-options options s validated :before-save :create :after-read)
+          (process-options options s validated :before-save :create :after-save :after-read)
           validated)))))

 (defn update-fn


Enable to limit the number of selected options in multi-select

--- src/cljs/db_quiz/components.cljs
+++ src/cljs/db_quiz/components.cljs
@@ -153,13 +153,15 @@
   The group is labelled with label-key's value from the translation map.
   Values of the available buttons are given in options as a collection of [value label] pairs.
   Label can be either a string or a keyword that will be looked up in the translation map."
-  [id label-key options]
+  [id label-key options & {:keys [max-selected]}]
   (let [id-str (string/join "." (map name id))
         click (fn [current-id update-fn]
                 (swap! app-state (fn [state] (update-in state id #(update-fn % current-id)))))]
     (fn [id label-key options]
-      (let [current-value (get-in @app-state id)]
-        [:div.form-group
+      (let [current-value (get-in @app-state id)
+            can-select-more? (or (nil? max-selected)
+                                 (< (count current-value) max-selected))]
+        [:div.form-group
          [label-element id-str (t label-key)]
          [:div.col-sm-8.btn-group-vertical {:id id-str
                                             :role "group"}
@@ -167,6 +169,7 @@
                        :let [active? (current-value current-id)
                              update-fn (if active? disj conj)]]
                    [:button {:class (btn-class-fn active?)
+                             :disabled (not (or active? can-select-more?))
                              :key label
                              :on-click (partial click current-id update-fn)}
                     (t label)]))]]))))
@@ -259,7 +262,8 @@
   (let [options [[:cs "Česky"]
                  [:en "English"]]
         click-fn (fn [language]
-                     (swap! app-state #(assoc % :language language))
+                     (swap! app-state (comp #(assoc-in % [:options :selectors] #{})
+                                            #(assoc % :language language)))
                      (.set cookies "language" (name language)))]
     (fn []
       (let [language (:language @app-state)]
@@ -306,7 +310,8 @@
       (let [language (:language @app-state)]
         [multi-select [:options :selectors]
                       :home.domains/label
-                      (language selectors)]))))
+                      (language selectors)
+                      :max-selected 3]))))

 (defn google-spreadsheet-options
   []


Add buttons to lookup hyphenation patterns

--- src/cljs/hyphen_keeper/core.cljs
+++ src/cljs/hyphen_keeper/core.cljs
@@ -178,12 +178,25 @@
    (when (not= :none (:kind @feedback))
      [feedback-alert])])

+(defn- button [label href disabled]
+  [:a.btn.btn-default {:href href :target "_blank" :disabled disabled} label])
+
+(defn hyphenation-lookup [word]
+  (let [disabled (when (string/blank? word) "disabled")]
+    [:div.row
+     [:div.btn-group {:role "group" :aria-label "Buttons for hyphenation lookup"}
+      (button "Duden" (str "http://www.duden.de/suchen/dudenonline/" word) disabled)
+      (button "TU Chemnitz" (str "http://dict.tu-chemnitz.de/?query=" word) disabled)
+      (button "PONS" (str "http://de.pons.eu/dict/search/results/?l=dede&q=" word) disabled)]]))
+
 (defn hyphenation-list []
   [:div.container
    [:h1 "Hyphenation"]
    [:div.row
     [:div.col-md-6
      [new-hyphenation]]]
+   [:h1 "Lookup"]
+   [hyphenation-lookup @word]
    [:h1 "Similar words"]
    [:div.row
     [:table#hyphenations.table.table-striped


Add gRPC configuration

Add gRPC configuration

--- src/clojure_fabric/grpc_core.clj
+++ src/clojure_fabric/grpc_core.clj
@@ -36,6 +36,26 @@
            [org.hyperledger.fabric.protos.msp Identities$SerializedIdentity]
            [com.google.protobuf ByteString Timestamp]))

+
+(defonce ^:dynamic *grpc-configuration*
+  ;; From Java SDK
+  {:proposal-wait-time 20000
+   :channel-configu-wait-time 15000
+   :orderer-retry-wait-time 200
+   :orderer-wait-time 3000
+   ;;   :eventhub-connection-wait-time 1000
+   :genesisblock-wait-time 5000
+   })
+
+(defmacro with-overriding-grpc-configuration
+  [[& new-config-key-vals] & body]
+  `(binding [*grpc-configuration* (assoc *grpc-configuration* ~@new-config-key-vals)]
+     ~@body))
+
+(defn grpc-config-value
+  [k]
+  (*grpc-configuration* k))
+
 (defn make-chaincode-id
   ([name]
    (make-chaincode-id name {}))
@@ -212,9 +232,3 @@
                                   {:algorithm (:key-algorithm crypto-suite)})
                          (ByteString/copyFrom)))
       (.build)))
-
-(defn send-proposal-to-peers
-  [proposal peers]
-  ;; - timeout value. I.e. how long to wait?
-  ;; - tx-id, channel-id,
-  )


remove stray TODOs

remove stray TODOs

--- src/main/compassus/core.cljs
+++ src/main/compassus/core.cljs
@@ -276,8 +276,3 @@
        :reconciler       reconciler
        :root-class       (make-root-class opts')}
       (atom {}))))
-
-
-;; TODO:
-;; - docstrings
-;; - codox


Rewritten multipart library to use ServletFileUpload courtesy of Adam Blinkinsop

--- src/compojure/http/multipart.clj
+++ src/compojure/http/multipart.clj
@@ -5,78 +5,38 @@
 ;; using this software in any fashion, you are agreeing to be bound by the
 ;; terms of this license. You must not remove this notice, or any other, from
 ;; this software.
+;; Modified by Adam Blinkinsop <blinks@acm.org> in August 2009.

 (ns compojure.http.multipart
   "Add multipart form handling to Compojure. Relies on the Apache Commons
    FileUpload library."
   (:use clojure.contrib.def)
   (:use compojure.map-utils)
-  (:import org.apache.commons.fileupload.FileUpload)
-  (:import org.apache.commons.fileupload.RequestContext)
-  (:import org.apache.commons.fileupload.disk.DiskFileItemFactory)
-  (:import org.apache.commons.fileupload.disk.DiskFileItem))
+  (:import [org.apache.commons.fileupload.servlet ServletFileUpload]))

-(defn multipart-form?
-  "Does a request have a multipart form?"
+(defn multipart?
+  "Does this request contain multipart content?"
   [request]
-  (if-let [content-type (:content-type request)]
-    (.startsWith content-type "multipart/form-data")))
+  (ServletFileUpload/isMultipartContent request))

-(defvar- file-upload
-  (FileUpload.
-    (doto (DiskFileItemFactory.)
-      (.setSizeThreshold -1)
-      (.setFileCleaningTracker nil)))
-  "Uploader class to save multipart form values to temporary files.")
+(defvar- upload (ServletFileUpload.))

-(defn- request-context
-  "Create a RequestContext object from a request map."
+(defn field-seq
+  "Map field names to values, which will either be a simple string or map.
+
+  Multipart values will be maps with content-type, name (original filename),
+  and stream (an open input stream object)."
   [request]
-  (proxy [RequestContext] []
-    (getContentType []       (:content-type request))
-    (getContentLength []     (:content-length request))
-    (getCharacterEncoding [] (:character-encoding request))
-    (getInputStream []       (:body request))))
-
-(defn- file-map
-  "Create a file map from a DiskFileItem."
-  [#^DiskFileItem item]
-  {:disk-file-item item
-   :filename       (.getName item)
-   :size           (.getSize item)
-   :content-type   (.getContentType item)
-   :tempfile       (.getStoreLocation item)})
-
-(defn parse-multipart-params
-  "Parse a map of multipart parameters from the request."
-  [request]
-  (reduce
-    (fn [param-map, #^DiskFileItem item]
-      (assoc-vec param-map
-        (keyword (.getFieldName item))
-        (if (.isFormField item)
-          (if (zero? (.getSize item))
-            ""
-            (.getString item))
-          (file-map item))))
-    {}
-    (.parseRequest
-       file-upload
-       (request-context request))))
-
-(defn get-multipart-params
-  "Retrieve multipart params from the request."
-  [request]
-  (if (multipart-form? request)
-    (parse-multipart-params request)
-    {}))
+  (map (fn [i] {(keyword (.getFieldName i))
+                (if (.isFormField i)
+                  (.getParameter request (.getFieldName i))
+                  {:content-type (.getContentType i)
+                   :name (.getName i)
+                   :stream (.openStream i)})})
+       (.getItemIterator upload request)))

 (defn with-multipart
-  "Decorate a Ring handler with multipart parameters."
   [handler]
   (fn [request]
-    (let [params  (get-multipart-params request)
-          request (-> request
-                    (assoc :multipart-params params)
-                    (assoc :params (merge (request :params) params)))]
+    (let [req (merge request {:params (merge (field-seq request))})]
       (handler request))))


Add a primitive in-memory (C* compliant) store to start working on tests.

--- src/io/cyanite/store.clj
+++ src/io/cyanite/store.clj
@@ -55,6 +55,38 @@
     (fetch! [this from to paths])
     (insert! [this metric])))

+(defn memory-store
+  "Extremely inefficient memory store for testing/mocking purposes"
+  []
+  (let [state (atom {})]
+    (reify
+      component/Lifecycle
+      (start [this] this)
+      (stop [this] this)
+      MetricStore
+      (fetch! [this from to paths]
+        (let [st @state]
+         (mapcat
+          (fn [path]
+            (->> (get st path)
+                 (filter
+                  (fn [[time _]]
+                    (and (>= time from)
+                         (<= time to))))
+                 (map
+                  (fn [[time point]]
+                    {:id    path
+                     :time  time
+                     :point point}))))
+          paths)))
+      (insert! [this metric]
+        (swap! state
+               (fn [old]
+                 (update-in old
+                            [(select-keys metric [:path :resolution])
+                             (:time metric)]
+                            (constantly (select-keys metric [:max :min :sum :mean])))))))))
+
 (defmulti build-store (comp (fnil keyword "cassandra-v2") :type))

 (defmethod build-store :cassandra-v2
@@ -65,6 +97,10 @@
   [options]
   (empty-store))

+(defmethod build-store :memory
+  [options]
+  (memory-store))
+
 (defn query! [store from to paths]
   (let [raw-series         (fetch! store from to paths)
         [precision series] (p/normalize raw-series)]


Additional RethinkDB data manipulation notes.

--- REPL_notes.clj
+++ REPL_notes.clj
@@ -32,11 +32,13 @@
 ;; RethinkDB usage
 (def conn2 [:host "127.0.0.1" :port 28015 :db "open_company"])

+;; Get a company
 (aprint (with-open [c (apply r/connect conn2)]
   (-> (r/table "companies")
       (r/get "buffer")
       (r/run c))))

+;; Update the sections in a company
 (with-open [c (apply r/connect conn2)]
   (-> (r/table "companies")
       (r/get "open")
@@ -46,22 +48,25 @@
 (with-open [c (apply r/connect conn2)]
   (-> (r/table "companies")
       (r/get "open")
+      (r/replace (r/fn [company]
+        (r/without company [:mission])))
+      (r/run c)))
+
+;; Empty out the stakeholder update template
+(with-open [c (apply r/connect conn2)]
+  (-> (r/table "companies")
+      (r/get "open")
       (r/update {:stakeholder-update (r/literal {:title "" :sections []})})
       (r/run c)))

+;; Mark a company as public/private
 (with-open [c (apply r/connect conn2)]
   (-> (r/table "companies")
       (r/get "startup-city")
       (r/update {:public true})
       (r/run c)))

-(with-open [c (apply r/connect conn2)]
-  (-> (r/table "companies")
-      (r/get "open")
-      (r/replace (r/fn [company]
-        (r/without company [:mission])))
-      (r/run c)))
-
+;; Remove a sub-property of a topic from a company
 (with-open [c (apply r/connect conn2)]
   (-> (r/table "companies")
       (r/get "startup-city")
@@ -69,38 +74,71 @@
         (r/without company [{:competition {:icon true}}])))
       (r/run c)))

+;; Update a sub-property of a section for a company
+(with-open [c (apply r/connect conn2)]
+  (-> (r/table "companies")
+      (r/get "open")
+      (r/update {:finances {:body "
It's time to learn. That's it, really. Put it in the hands of people we admire and trust, and LEARN FAST.

"}})
+      (r/run c)))
+
+;; Get all the topic revisions for a company
 (aprint (with-open [c (apply r/connect conn2)]
   (-> (r/table "sections")
     (r/get-all ["buffer"] {:index "company-slug"})
     (r/run c))))

+;; Get all the topic revisions of a specific type for a company
 (aprint (with-open [c (apply r/connect conn2)]
   (-> (r/table "sections")
-    (r/get-all [["green-labs" "update"]] {:index "company-slug-section-name"})
+    (r/get-all [["open" "finances"]] {:index "company-slug-section-name"})
     (r/run c))))

+;; Remove all the topic revisions of a specific type for a company
 (with-open [c (apply r/connect conn2)]
   (-> (r/table "sections")
     (r/get-all [["open" "finances"]] {:index "company-slug-section-name"})
     (r/delete)
     (r/run c)))

+;; Get a topic revisions by ID
+(aprint (with-open [c (apply r/connect conn2)]
+  (-> (r/table "sections")
+    (r/get-all ["21c9ddd4-6d1c-47a5-b6c1-1308fed08523"] {:index "id"})
+    (r/run c))))
+
+;; Delete a topic revision by ID
+(with-open [c (apply r/connect conn2)]
+  (-> (r/table "sections")
+    (r/get-all ["c4b035a9-f33a-40a3-9c5f-49632e5f32d8"] {:index "id"})
+    (r/delete)
+    (r/run c)))
+
+;; Update a property of a topic revision by ID
+(with-open [c (apply r/connect conn2)]
+  (-> (r/table "sections")
+    (r/get-all ["5ee22ac8-91ba-408f-9afb-e7546512ce90"] {:index "id"})
+    (r/update {:created-at "2016-12-03T16:23:11.560Z" :updated-at "2016-12-03T16:23:11.560Z"})
+    (r/run c)))
+
+;; Remove a property from all topic revisions
 (with-open [c (apply r/connect conn2)]
   (-> (r/table "sections")
     (r/replace (r/fn [section]
       (r/without section [:core])))
     (r/run c)))

-(aprint (with-open [c (apply r/connect conn2)]
-  (-> (r/table "sections")
-    (r/get-all ["21c9ddd4-6d1c-47a5-b6c1-1308fed08523"] {:index "id"})
-    (r/run c))))
+;; Get all the stakeholder updates for a company
+(with-open [c (apply r/connect conn2)]
+  (-> (r/table "stakeholder_updates")
+    (r/get-all ["message-io"] {:index "company-slug"})
+    (r/run c)))

+;; Update the property of a stakeholder update by update slug
 (with-open [c (apply r/connect conn2)]
-  (-> (r/table "companies")
-      (r/get "open")
-      (r/update {:update {:body "
It's time to learn. That's it, really. Put it in the hands of people we admire and trust, and LEARN FAST.

"}})
-      (r/run c)))
+  (-> (r/table "stakeholder_updates")
+    (r/get-all [["open" "investor-update-december-2016-819e6"]] {:index "company-slug-slug"})
+    (r/update {:marketing {:headline ""}})
+    (r/run c)))

 ;; Provide a new slug for a company
 (with-open [c (apply r/connect conn2)]


Use -> to simply main function...again

Use -> to simply main function...again

--- src/whitman/core.clj
+++ src/whitman/core.clj
@@ -10,7 +10,6 @@
 (defn -main [& args]
   (if (< (count args) 1)
       (exit 1 "No configuration file specified")
-      (let [cfg (-> (nth args 0)
-                    config/read-config)
-            user-agent (get cfg "user-agent")]
-        (println cfg))))
+      (-> (nth args 0)
+          config/read-config
+          println)))


Minor perf improvements

Minor perf improvements

--- src/onyx/messaging/aeron.clj
+++ src/onyx/messaging/aeron.clj
@@ -24,9 +24,8 @@
   (format "udp://%s:%s" addr port))

 (defrecord AeronMessenger
-    [peer-group messaging-group publication-group short-circuitable?
-     publications virtual-peers acking-daemon acking-ch send-idle-strategy
-     compress-f]
+  [peer-group messaging-group publication-group short-circuitable? publications virtual-peers
+   acking-daemon send-idle-strategy compress-f monitoring publication-pool short-ids acking-ch]
   component/Lifecycle

   (start [component]
@@ -352,8 +351,9 @@

 (defn ack-segments-short-circuit [ch acks]
   (when ch
-    (doseq [ack acks]
-      (>!! ch ack))))
+    (run! (fn [ack]
+            (>!! ch ack))
+          acks)))

 (defn complete-message-short-circuit [ch completion-id]
   (when ch
@@ -386,7 +386,7 @@
     (let [pub-man (get-publication (:publication-pool messenger) conn-spec)
           buf ^UnsafeBuffer (protocol/build-acker-messages acker-id acks)
           size (.capacity buf)]
-      (extensions/emit (:onyx.core/monitoring event) (->MonitorEventBytes :peer-send-bytes size))
+      (extensions/emit (:monitoring messenger) (->MonitorEventBytes :peer-send-bytes size))
       (pubm/write pub-man buf 0 size))))

 (defmethod extensions/internal-complete-segment AeronMessenger
@@ -401,7 +401,6 @@
   [messenger event retry-id {:keys [peer-task-id channel] :as conn-spec}]
   (if ((:short-circuitable? messenger) channel)
     (retry-segment-short-circuit (:retry-ch (lookup-channels messenger peer-task-id)) retry-id)
-    (let [idle-strategy (:send-idle-strategy messenger)
-          pub-man (get-publication (:publication-pool messenger) conn-spec)
+    (let [pub-man (get-publication (:publication-pool messenger) conn-spec)
           buf (protocol/build-retry-msg-buf peer-task-id retry-id)]
       (pubm/write pub-man buf 0 protocol/retry-msg-length))))


Support /dropdata to drop all perm data.

--- src/org/scode/httpgctest.clj
+++ src/org/scode/httpgctest.clj
@@ -36,11 +36,20 @@
    :headers {}
    :body (str "size is now " (count @data))}))

+(defn serve-dropdata [request]
+  (let [old-size (count @data)]
+    (dosync (alter data (fn [d] {})))
+    {:status 200
+     :headers {}
+     :body (str "dropped " old-size)}))
+
 (defroutes greeter
   (GET "/gengarbage"
        serve-gengarbage)
   (GET "/gendata"
-       serve-gendata))
+       serve-gendata)
+  (GET "/dropdata"
+       serve-dropdata))

 (defn -main [& args]
   (run-server {:port 9191}


WIP: login should call backend

WIP: login should call backend

--- test/cljs/ohds/new-login-test.cljs
+++ test/cljs/ohds/new-login-test.cljs
@@ -25,7 +25,13 @@
       (is (= :login
              (:page result)))))

-  (testing "Login checks with backend for result")
+  (testing "Login checks with backend for result"
+    (with-redefs [http/post
+                  (fn [url data]
+                    (is (= url "/login"))
+                    "user-token")]
+
+      ))
   (testing "Logging in after failed login clears error report")
   (testing "Successful login triggers location hierarchy requests")
   (testing "Unsuccessful login does not trigger location hierarchy requests")


+head-infl

+head-infl

--- src/babel/english/grammar.cljc
+++ src/babel/english/grammar.cljc
@@ -272,8 +272,10 @@

                    (unify-check h00
                                 modified
-                                (let [head-sem (atom :top)]
+                                (let [head-sem (atom :top)
+                                      head-infl (atom :top)]
                                   {:synsem {:subcat '()
+                                            :infl head-infl
                                             :sem head-sem
                                             :cat :verb}
                                    :comp {:synsem {:cat :prep
@@ -281,6 +283,7 @@
                                                    :sem head-sem}}
                                    :head {:modified false
                                           :synsem {:cat :verb
+                                                   :infl head-infl
                                                    :subcat '()
                                                    :sem head-sem}}
                                    :rule "s-modified-with-adjunct-head-first"}))


add {:modal-with :root} for "can" and "may"

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -404,22 +404,20 @@
    "call" {:synsem {:cat :verb
                     :sem {:pred :call}}}
    "can"
-    (let [modal-subject (atom {:cat :noun})
-          common {:english {:participle "being able to"
-                            :past "could"
-                            :present {:3sing "can"}
-                            :future "be able to"
-                            :conditional "be able to"}
-                  :synsem {:cat :verb
-                           :sem {:pred :can}
-                           :subcat {:1 modal-subject}}}]
-      [(unify common)
-       (unify common
-              {:synsem {:2 {:cat :verb
-                            :infl :root ;; note: not :infinitive
-                            :subcat {:1 modal-subject
-                                     :2 '()}}
-                        :3 '()}})])
+   {:english {:participle "being able to"
+              :past "could"
+              :imperfect {:1sing "used to be able to"
+                          :2sing "used to be able to"
+                          :3sing "used to be able to"
+                          :1plur "used to be able to"
+                          :2plur "used to be able to"
+                          :3plur "used to be able to"}
+              :present {:3sing "can"}
+              :future "be able to"
+              :conditional "be able to"}
+    :modal-with :root
+    :synsem {:cat :verb
+             :sem {:pred :be-able-to}}}

    "car" {:synsem {:cat :noun
                    :sem {:pred :car}}}
@@ -1296,6 +1294,7 @@
                               :3plur "may"}
                     :future "be able to"
                     :conditional "be able to"}
+          :modal-with :root
           :synsem {:cat :verb
                    :sem {:pred :may}}}


remove :gender from "table", not significant in english

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -1672,8 +1672,7 @@
    "support" {:synsem {:cat :verb
                        :sem {:pred :support}}}

-   "table" {:synsem {:agr {:gender :masc}
-                     :cat :noun
+   "table" {:synsem {:cat :noun
                      :sem {:pred :table}}}

    "take" (let [common {:synsem {:cat :verb}


+second,small

+second,small

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -1452,7 +1452,11 @@
                      :sem {:pred :scrub}}
             :english {:participle "scrubbing"
                       :past "scrubbed"}}
-
+
+   "second" (unify adjective
+                  {:sem {:mod {:pred :first}
+                         :comparative false}})
+
    "see"  {:synsem {:cat :verb
                     :sem {:pred :see}}
            :english {:past "saw"
@@ -1508,6 +1512,16 @@
                            :discrete false
                            :pred :sleep}}
             :english {:past "slept"}}
+
+
+   "small"
+   (unify adjective
+          {:synsem {:cat :adjective
+                    :sem {:mod {:pred :small}
+                          :comparative false}
+                    :subcat {:1 {:cat :det}
+                             :2 '()}}})
+

    "snap" {:synsem {:cat :verb
                     :sem {:pred :snap-pictures}}


added chiamarsi

added chiamarsi

--- src/babel/italiano/lexicon.clj
+++ src/babel/italiano/lexicon.clj
@@ -564,6 +564,21 @@
      "chiacchierare" {:synsem {:cat :verb
                                :sem {:pred :chat}}}

+     "chiamarsi" (let [subject-semantics (ref {:animate true})
+                   subject-agr (ref :top)]
+               {:synsem {:cat :verb
+                         :essere true
+                         :sem {:pred :be-called
+                               :reflexive true
+                               :subj subject-semantics
+                               :obj subject-semantics}
+                         :subcat {:1 {:agr subject-agr
+                                      :sem subject-semantics}
+                                  :2 {:agr subject-agr
+                                      :pronoun true
+                                      :reflexive true
+                                      :sem subject-semantics}}}})
+
      "chiedere" {:synsem {:cat :verb
                           :sem {:subj {:human true}
                                 :pred :chiedere}}


Fix comment of unit/conversion-medium

Fix comment of unit/conversion-medium

--- src/bakyeono/litedocx/unit.clj
+++ src/bakyeono/litedocx/unit.clj
@@ -54,7 +54,8 @@
     [n unit]))

 (defn- conversion-medium
-  "Takes a keyword of unit and returns its preffered conversion medium."
+  "Takes a keyword of unit and returns the preffered conversion medium of the
+  unit."
   [u]
   (cond (metric-set u) [m-per-unit unit-per-m]
         (inch-set u) [inch-per-unit unit-per-inch]))


change run-dev port to 3000, co-exist with walmart atlas 8080

--- src/minuette/service.clj
+++ src/minuette/service.clj
@@ -138,4 +138,4 @@
               ;; to enable Tomcat)
               ;;::bootstrap/host "localhost"
               ::bootstrap/type :jetty
-              ::bootstrap/port 8080})
+              ::bootstrap/port 3000})


Fix test_new.

Fix test_new.

--- test/test_new.clj
+++ test/test_new.clj
@@ -5,5 +5,5 @@

 (deftest test-new
   (sh "lein" "new" "a.b/test-new-proj")
-  (is (.exists (file "test-new-proj" "src" "a" "b" "test_new_proj.clj")))
+  (is (.exists (file "test-new-proj" "src" "a" "b" "test_new_proj" "core.clj")))
   (delete-file-recursively (file "test-new-proj") false))


Fix error.

Fix error.

--- src/oc/email/content.clj
+++ src/oc/email/content.clj
@@ -296,7 +296,7 @@
 (defn- post-attribution [entry]
   (let [publisher-name (-> entry :publisher :name)
         post-date (post-date (:published-at entry))
-        attribution (when (pos? (:comment-count entry))
+        attribution (when (pos? (or (:comment-count entry) 0))
                       (text/attribution 2 (:comment-count entry) "comment" (:comment-authors entry)))
         paragraph-text (str publisher-name " on " post-date
                          (when-not (s/blank? attribution)