Use new chunks

Use new chunks

--- src/clj_simple_chart/ssb/data/sal_av_petroleumsprodukt_11174.clj
+++ src/clj_simple_chart/ssb/data/sal_av_petroleumsprodukt_11174.clj
@@ -36,54 +36,27 @@
        (map #(reduce merge {} %))
        (sort-by column)))

-(defn prev-indexes [idx n]
-  {:pre [(not (neg? idx)) (pos-int? n)]}
-  (vec (remove neg? (range (inc (- idx n))
-                           (inc idx)))))
-
-(test/is (= [0] (prev-indexes 0 1)))
-(test/is (= [1] (prev-indexes 1 1)))
-(test/is (= [2] (prev-indexes 2 1)))
-
-(test/is (= [0] (prev-indexes 0 3)))
-(test/is (= [0 1] (prev-indexes 1 3)))
-(test/is (= [0 1 2] (prev-indexes 2 3)))
-(test/is (= [1 2 3] (prev-indexes 3 3)))
-(test/is (= [2 3 4] (prev-indexes 4 3)))
-
-(defn chunks [rows n]
-  {:pre (indexed? rows)}
-  (remove nil?
-          (for [i (range 0 (count rows))]
-            (let [indexes (prev-indexes i n)
-                  items (map #(nth rows %) indexes)]
-              (when (= (count indexes) n)
-                items)))))
-
-(defn- cc-inner
+(defn- chunks-inner
   [rows accum n]
   {:pre [(vector? accum)]}
   (cond (empty? rows) (if (= n (count accum)) [accum] [])
         (= n (count accum)) (lazy-seq (cons accum
-                                            (cc-inner (rest rows)
-                                                      (conj (vec (drop 1 accum)) (first rows))
-                                                      n)))
+                                            (chunks-inner (rest rows)
+                                                          (conj (vec (drop 1 accum)) (first rows))
+                                                          n)))
         :else (recur (rest rows)
                      (conj accum (first rows))
                      n)))

-(defn cc [rows n]
-  {:pre [(pos-int? n)
-         (not (map? rows))]}
-  (cc-inner rows [] n))
+(defn chunks [rows n]
+  {:pre [(not (map? rows))
+         (coll? rows)
+         (pos-int? n)]}
+  (chunks-inner rows [] n))

-(test/is (= '([:a] [:b] [:c] [:d] [:e]) (cc [:a :b :c :d :e] 1)))
-(test/is (= '([:a :b] [:b :c] [:c :d] [:d :e]) (cc [:a :b :c :d :e] 2)))
-(test/is (= '([:a :b :c] [:b :c :d] [:c :d :e]) (cc [:a :b :c :d :e] 3)))
-
-(test/is (= '((:a) (:b) (:c) (:d) (:e)) (chunks [:a :b :c :d :e] 1)))
-(test/is (= '((:a :b) (:b :c) (:c :d) (:d :e)) (chunks [:a :b :c :d :e] 2)))
-(test/is (= '((:a :b :c) (:b :c :d) (:c :d :e)) (chunks [:a :b :c :d :e] 3)))
+(test/is (= '([:a] [:b] [:c] [:d] [:e]) (chunks [:a :b :c :d :e] 1)))
+(test/is (= '([:a :b] [:b :c] [:c :d] [:d :e]) (chunks [:a :b :c :d :e] 2)))
+(test/is (= '([:a :b :c] [:b :c :d] [:c :d :e]) (chunks [:a :b :c :d :e] 3)))

 (def data (->> (:data raw-data)
                (map #(dissoc % :kjøpegruppe))


Bump minor version to account for Karma extensions

--- example/project.clj
+++ example/project.clj
@@ -1,4 +1,4 @@
-(defproject lein-doo-example "0.1.4-SNAPSHOT"
+(defproject lein-doo-example "0.1.5-SNAPSHOT"
   :description "Project to test lein-doo. Do not take it as an example"
   :url "https://github.com/bensu/doo"
   :license {:name "Eclipse Public License"


Choosing sensible colors for different biomes

--- src/amindblowingworld/views.clj
+++ src/amindblowingworld/views.clj
@@ -43,7 +43,17 @@
         (let [pos {:x x :y y}
               biome (.get b x y)]
           (case (.name biome)
-            "OCEAN" (.setColor g (Color. 0 0 255))
+            "OCEAN"        (.setColor g (Color. 0 0 255))
+            "ICELAND"      (.setColor g (Color. 255 255 255))
+            "TUNDRA"       (.setColor g (Color. 141 227 218))
+            "ALPINE"       (.setColor g (Color. 141 227 218))
+            "GLACIER"      (.setColor g (Color. 255 255 255))
+            "GRASSLAND"    (.setColor g (Color. 80 173 88))
+            "ROCK_DESERT"  (.setColor g (Color. 105 120 59))
+            "SAND_DESERT"  (.setColor g (Color. 205 227 141))
+            "FOREST"       (.setColor g (Color. 59 120 64))
+            "SAVANNA"      (.setColor g (Color. 171 161 27))
+            "JUNGLE"       (.setColor g (Color. 5 227 34))
             (.setColor g (Color. 255 0 0)))
           (let [pixel-x (* x scale-factor)
                 pixel-y (* y scale-factor)]


Changes related to Clojure r1094

Changes related to Clojure r1094

--- examples/simple.clj
+++ examples/simple.clj
@@ -1,9 +1,9 @@
 ;; processing test

-(clojure/ns p5-example
-			(:use rosado.processing)
-			(:import (javax.swing JFrame JLabel JTextField JButton))
-			(:import (processing.core PApplet)))
+(ns p5-example
+  (:use rosado.processing)
+  (:import (javax.swing JFrame JLabel JTextField JButton))
+  (:import (processing.core PApplet)))

 ;; here's a function which will be called by Processing's (PApplet)


move (defn)s up to top of file

move (defn)s up to top of file

--- src/babel/italiano/grammar.cljc
+++ src/babel/italiano/grammar.cljc
@@ -17,6 +17,18 @@
    #?(:clj [clojure.tools.logging :as log])
    #?(:cljs [babel.logjs :as log])
    [dag_unify.core :refer (fail? get-in merge remove-matching-keys unifyc)]))
+
+(defn exception [error-string]
+  #?(:clj
+     (throw (Exception. (str ": " error-string))))
+  #?(:cljs
+     (throw (js/Error. error-string))))
+
+(defn unify-check [ & vals]
+  (let [result (apply unifyc vals)]
+    (if (fail? result)
+      (exception (str "failed to unify grammar rule with values: " vals))
+      result)))

 (def hc-agreement
   (let [agr (atom :top)]


support 'GET /parse'

support 'GET /parse'

--- src/babel/italiano/workbook.clj
+++ src/babel/italiano/workbook.clj
@@ -100,7 +100,7 @@
                         ]))
    :refer-clojure false
    ;; using 60000 for development: for production, use much smaller value.
-   :timeout 5000
+   :timeout 10000
    :namespace 'babel.italiano.workbook))

@@ -217,6 +217,15 @@
          :body (html/page "Italian Workbook" (workbook-ui request) request)
          :headers {"Content-Type" "text/html;charset=utf-8"}})

+   (GET "/parse/" request
+        {:status 200
+         :body
+         (let [debug (log/info (str "sending string to parser.."))]
+           (str "" (html/tablize
+                    (get-in (strip-refs (first (parse (get (get request :query-params) "string"))))
+                            [:synsem :sem]))))
+         :headers {"Content-Type" "text/html;charset=utf-8"}})
+
    (GET "/q/" request
         {:status 200
          :body (workbookq (get (get request :query-params) "search")


GAWB-1690 followup: Display request access message in lib when no access and no auth domain (#878)

* display request access message when no access and no auth domain

--- src/cljs/main/broadfcui/page/library/library_page.cljs
+++ src/cljs/main/broadfcui/page/library/library_page.cljs
@@ -130,7 +130,8 @@
              {:header "Request Access"
               :message
               [:span {}
-               (if (not-empty (clojure.set/difference ws-auth-domains built-in-groups))
+               (if (or (not-empty (set/difference ws-auth-domains built-in-groups))
+                       (empty? ws-auth-domains))
                  (standard-access-instructions data)
                  [:span {}
                   (let [tcga? (contains? ws-auth-domains "TCGA-dbGaP-Authorized")


Implemented IKeysetCursor support.

Implemented IKeysetCursor support.

--- src-cljs/freactive/core.cljs
+++ src-cljs/freactive/core.cljs
@@ -285,7 +285,7 @@
      (set! (.-register-dep-fn reactive) (make-register-dep reactive))
      reactive)))

-(defn- keyset [coll]
+(defn coll-keyset [coll]
   (cond (map? coll)
         (keys coll)

@@ -325,13 +325,17 @@
       (set! (.-change-ks this) [key])
       (swap-fn assoc key val)
       this)
-    (notifyChild [this child-key new-val]
+    (resetChild [this child-key new-val]
       (doseq [child (get child-cursors child-key)]
         (.updateCursor child new-val)))
+    (notifyKeysetWatches [this removed added]
+      (doseq [[key f] keyset-watches]
+        (f key this removed added)))
     (updateCursor [this new-state]
       (when-not (identical? state new-state)
         (let [old-state state]
           (set! state new-state)
+          (.notifyFWatches this old-state state)
           (if-let [change-ks (.-change-ks this)]
             (let [change-ks (if (keyword? change-ks)
                               [(case change-ks
@@ -348,20 +352,22 @@
                         (when descendant-ks
                           (set! (.-change-ks cur) descendant-ks))
                         (.updateCursor cur new-val))
-                      ;; check for key set change
-                      ))))
+                      (cond
+                        (nil? old-val)
+                        (.notifyKeysetWatches this nil #{change-key})
+                        (nil? new-val)
+                        (.notifyKeysetWatches this #{change-key} nil))))))
               (set! (.-change-key this) nil))
             (cond keyset-watches
-                  (let [old-keys (keyset old-state)
-                        new-keys (keyset state)
+                  (let [old-keys (coll-keyset old-state)
+                        new-keys (coll-keyset state)
                         [removed added both] (diff-set (set old-keys) (set new-keys))]
                     (when (or (not (empty? removed)) (not (empty? added)))
-                      ;; notify key set change
-                      )
+                      (.notifyKeysetWatches this removed added))
                     (doseq [rx removed]
-                      (.notifyChild rx nil))
+                      (.resetChild rx nil))
                     (doseq [ra added]
-                      (.notifyChild ra (get state ra)))
+                      (.resetChild ra (get state ra)))
                     (doseq [rc both]
                       (when-let [cursors (get child-cursors rc)]
                         (when-let [cur (first cursors)]
@@ -376,8 +382,7 @@
                           new-val (get state ckey)]
                       (when-not (identical? old-val new-val)
                         (doseq [cur cursors]
-                          (.updateCursor cur new-val)))))))
-          (.notifyFWatches this old-state state))))
+                          (.updateCursor cur new-val))))))))))
     (rawDeref [this]
       (when (.-dirty this)
         (.updateCursor this (get-fn)))
@@ -438,9 +443,17 @@
       this)

     IKeysetCursor
-    (-keyset [this] (keyset state))
-    (-add-keyset-watch [this key f])
-    (-remove-keyset-watch [this key])
+    (-keyset [this] (coll-keyset state))
+    (-add-keyset-watch [this key f]
+      (when-not (contains? keyset-watches key)
+        (.activate this)
+        (set! (.-watchers this) (inc watchers))
+        (set! (.-keyset-watches this) (assoc keyset-watches key f))))
+    (-remove-keyset-watch [this key]
+      (when (contains? keyset-watches key)
+        (set! (.-watchers this) (dec watchers))
+        (set! (.-keyset-watches this) (dissoc keyset-watches key))
+        (.clean this)))

     IHash
     (-hash [this] (goog/getUid this))


as with English PP reflexivity shared with head preposition's (first argument)

--- src/babel/italiano/grammar.cljc
+++ src/babel/italiano/grammar.cljc
@@ -273,9 +273,12 @@
                                      :synsem {:propernoun is-propernoun?}}
                               :comp {:phrasal false}})) ;; rathole prevention ;; TODO: see if this can be removed.

-                   (unifyc h10
-                           {:rule "prepositional-phrase"
-                            :synsem {:cat :prep}})
+                   (let [reflexive (atom :top)]
+                     (unifyc h10
+                             {:rule "prepositional-phrase"
+                              :synsem {:cat :prep
+                                       :reflexive reflexive}
+                              :head {:synsem {:subcat {:1 {:reflexive reflexive}}}}}))

 ;                   (unifyc h21
 ;                           {:rule "adjunct-prepositional-phrase"


cleanup

cleanup

--- src/babel/italiano/grammar.cljc
+++ src/babel/italiano/grammar.cljc
@@ -3,7 +3,7 @@
   (:require
    [babel.enrich :refer [enrich]]
    [babel.index :refer [create-index map-subset-by-cat map-subset-by-pred]]
-   [babel.italiano.lexicon :refer [deliver-lexicon edn2lexicon lexicon]]
+   [babel.italiano.lexicon :refer [deliver-lexicon lexicon]]
    [babel.italiano.morphology :refer [analyze fo]]
    [babel.parse :as parse]
    [babel.ug :refer [comp-modifies-head comp-specs-head


remove redundant pipeline component

remove redundant pipeline component

--- src/babel/italiano/lexicon.cljc
+++ src/babel/italiano/lexicon.cljc
@@ -113,15 +113,6 @@
                      (= false (get-in % [:synsem :propernoun] false))))
            (and (log/warn (str "ignoring lexical entry with :cat=:noun but no gender specified: " %))
                 false)))
-
-     ;; common nouns need a gender (but propernouns do not need one).
-     ;; TODO: throw error rather than just throwing out entry.
-     (filter-vals
-      #(or (not (and (= :noun (get-in % [:synsem :cat]))
-                     (= :none (get-in % [:synsem :agr :gender] :none))
-                     (= false (get-in % [:synsem :propernoun] false))))
-           (and (log/warn (str "ignoring lexical entry with :cat=:noun but no gender specified: " %))
-                false)))

      ;; filter out entries with no :cat.
      (filter-vals


fix typo in "alto"

fix typo in "alto"

--- src/babel/italiano/lexicon.cljc
+++ src/babel/italiano/lexicon.cljc
@@ -140,7 +140,7 @@
                              :comparative false
                              :arg1 subject-sem
                              :human true}
-                       :subcat {:1 {:cat :noun
+                       :subcat {:1 {:cat :det
                                     :agr subject-agr
                                     :sem subject-sem}
                                 :2 '()}}}))


if generation fails, return empty list, not {:surface ""}

--- src/babel/italiano/workbook.clj
+++ src/babel/italiano/workbook.clj
@@ -35,8 +35,9 @@
 (defn generate
   ([]
    (let [result (engine/generate :top medium)]
-     (conj {:surface (fo result)}
-            result)))
+     (if result
+       (conj {:surface (fo result)}
+             result))))
   ([spec]
    (let [result (engine/generate spec medium)]
      (if result


Reduce code duplication in node type specification

--- src/alder/node-type.cljs
+++ src/alder/node-type.cljs
@@ -8,10 +8,84 @@
      constructor
      export-data])

+(defn- signal-in [index title]
+  {:type :node, :index index, :title title})
+
+(defn- signal-out [index title]
+  {:type :node, :index index, :title title, :data-type :signal})
+
+(defn- number-param-in
+  ([name title default range]
+   {:type :param,
+    :name name,
+    :title title,
+    :default default,
+    :data-type :number,
+    :range range})
+
+  ([name title default]
+   {:type :param,
+    :name name,
+    :title title,
+    :default default,
+    :data-type :number}))
+
+(defn- number-constant-in
+  ([name title default range]
+   {:type :constant,
+    :name name,
+    :title title,
+    :data-type :number,
+    :default default,
+    :range range})
+
+  ([name title default]
+   {:type :constant,
+    :name name,
+    :title title,
+    :data-type :number,
+    :default default}))
+
+(defn- number-accessor-in [name title default]
+  {:type :accessor,
+   :name name,
+   :title title,
+   :data-type :number,
+   :default default})
+
+(defn- string-constant-in [name title default choices]
+  {:type :constant,
+   :name name,
+   :title title,
+   :data-type :string,
+   :default default,
+   :choices choices})
+
+(defn- gate-in [name title]
+  {:type :gate, :name name, :title title})
+
+(defn- gate-out [index title]
+  {:type :node, :index index, :title title, :data-type :gate})
+
+(defn- param-out [index title]
+  {:type :node, :index index, :title title, :data-type :param})
+
+(defn- null-in [index title]
+  {:type :null-node, :index index, :title title})
+
+(defn- null-out [index title]
+  {:type :null-node, :index index, :title title})
+
+(defn- midi-device-accessor-in [name title]
+  {:type :accessor,
+   :name name,
+   :default nil,
+   :title title,
+   :data-type :midi-device,
+   :serializable false})
+
 (def audio-destination-node-type
-  (NodeType. {:signal {:type :node
-                       :index 0
-                       :title "Signal"}}
+  (NodeType. {:signal (signal-in 0 "Signal")}
              {}
              nil
              true
@@ -21,22 +95,10 @@
              {:ignore-export true}))

 (def oscillator-node-type
-  (NodeType. {:frequency {:type :param
-                          :name "frequency"
-                          :default 220
-                          :title "Frequency"
-                          :data-type :number
-                          :range [0 22050]}
-              :waveform {:type :constant
-                         :name "type"
-                         :default "square"
-                         :title "Waveform"
-                         :data-type :string
-                         :choices ["sine" "square" "sawtooth" "triangle"]}}
-             {:signal {:type :node
-                       :index 0
-                       :title "Signal"
-                       :data-type :signal}}
+  (NodeType. {:frequency (number-param-in "frequency" "Frequency" 220 [0 22050])
+              :waveform (string-constant-in "type" "Waveform" "square"
+                                            ["sine" "square" "sawtooth" "triangle"])}
+             {:signal (signal-out 0 "Signal")}
              nil
              false
              "Osc"
@@ -45,18 +107,9 @@
              {:constructor "context.createOscillator()"}))

 (def gain-node-type
-  (NodeType. {:gain {:type :param
-                     :name "gain"
-                     :default 1
-                     :title "Gain"
-                     :data-type :number}
-              :signal-in {:type :node
-                          :index 0
-                          :title "Signal"}}
-             {:signal-out {:type :node
-                           :index 0
-                           :title "Signal"
-                           :data-type :signal}}
+  (NodeType. {:gain (number-param-in "gain" "Gain" 1)
+              :signal-in (signal-in 0 "Signal")}
+             {:signal-out (signal-out 0 "Signal")}
              nil
              false
              "Gain"
@@ -65,33 +118,12 @@
              {:constructor "context.createGain()"}))

 (def adsr-node-type
-  (NodeType. {:gate {:type :gate
-                     :name "gate"
-                     :title "Gate"}
-              :attack {:type :constant
-                       :name "attack"
-                       :default 0.1
-                       :title "Attack"
-                       :data-type :number}
-              :decay {:type :constant
-                      :name "decay"
-                      :default 0.1
-                      :title "Decay"
-                      :data-type :number}
-              :sustain {:type :constant
-                        :name "sustain"
-                        :default 0.8
-                        :title "Sustain"
-                        :data-type :number}
-              :release {:type :constant
-                        :name "release"
-                        :default 0.1
-                        :title "Release"
-                        :data-type :number}}
-             {:envelope {:type :node
-                         :index 0
-                         :title "Envelope"
-                         :data-type :param}}
+  (NodeType. {:gate (gate-in "gate" "Gate")
+              :attack (number-constant-in "attack" "Attack" 0.01)
+              :decay (number-constant-in "decay" "Decay" 0.01)
+              :sustain (number-constant-in "sustain" "Sustain" 0.8)
+              :release (number-constant-in "release" "Release" 0.05)}
+             {:envelope (param-out 0 "Envelope")}
              nil
              false
              "ADSR"
@@ -103,9 +135,7 @@
                                               "/js/audio/adsr_node.js")]}}))

 (def fft-analyser-node-type
-  (NodeType. {:signal-in {:type :node
-                          :index 0
-                          :title "Signal"}}
+  (NodeType. {:signal-in (signal-in 0 "Signal")}
              {}
              {:inspector-fields [:fft]}
              false
@@ -115,9 +145,7 @@
              {:ignore-export true}))

 (def scope-analyser-node-type
-  (NodeType. {:signal-in {:type :node
-                          :index 0
-                          :title "Signal"}}
+  (NodeType. {:signal-in (signal-in 0 "Signal")}
              {}
              {:inspector-fields [:waveform]}
              false
@@ -127,9 +155,7 @@
              {:ignore-export true}))

 (def output-node-type
-  (NodeType. {:signal-in {:type :null-node
-                          :index 0
-                          :title "Signal in"}}
+  (NodeType. {:signal-in (null-in 0 "Signal in")}
              {}
              nil
              false
@@ -140,9 +166,7 @@

 (def input-node-type
   (NodeType. {}
-             {:signal-out {:type :null-node
-                           :index 0
-                           :title "Signal out"}}
+             {:signal-out (null-out 0 "Signal out")}
              nil
              false
              "Input"
@@ -151,46 +175,17 @@
              {:type :input}))

 (def biquad-filter-node-type
-  (NodeType. {:signal-in {:type :node
-                          :index 0
-                          :title "Signal in"}
-              :frequency {:type :param
-                          :name "frequency"
-                          :title "Frequency"
-                          :default 350
-                          :data-type :number
-                          :range [0 22050]}
-              :detune {:type :param
-                       :name "detune"
-                       :title "Detune"
-                       :default 0
-                       :data-type :number
-                       :range [-100 100]}
-              :Q {:type :param
-                  :name "Q"
-                  :title "Quality"
-                  :default 1
-                  :data-type :number
-                  :range [0.0001 1000]}
-              :gain {:type :param
-                     :name "gain"
-                     :title "Gain"
-                     :default 0
-                     :data-type :number
-                     :range [-40 40]}
-              :type {:type :constant
-                     :name "type"
-                     :title "Type"
-                     :default "lowpass"
-                     :data-type :string
-                     :choices ["lowpass" "highpass" "bandpass"
-                               "lowshelf" "highshelf" "peaking"
-                               "notch"
-                               "allpass"]}}
-             {:signal-out {:type :node
-                           :index 0
-                           :title "Signal out"
-                           :data-type :signal}}
+  (NodeType. {:signal-in (signal-in 0 "Signal in")
+              :frequency (number-param-in "frequency" "Frequency" 350 [0 22050])
+              :detune (number-param-in "detune" "Detune" 0 [-100 100])
+              :Q (number-param-in "Q" "Quality" 1 [0.0001 1000])
+              :gain (number-param-in "gain" "Gain" 0 [-40 40])
+              :type (string-constant-in "type" "Type" "lowpass"
+                                        ["lowpass" "highpass" "bandpass"
+                                         "lowshelf" "highshelf" "peaking"
+                                         "notch"
+                                         "allpass"])}
+             {:signal-out (signal-out 0 "Signal out")}
              nil
              false
              "LO Filter"
@@ -199,15 +194,8 @@
              {:constructor "context.createBiquadFilter()"}))

 (def const-source-node-type
-  (NodeType. {:value {:type :accessor
-                      :name "value"
-                      :default 1
-                      :title "Value"
-                      :data-type :number}}
-             {:signal {:type :node
-                       :index 0
-                       :title "Signal out"
-                       :data-type :signal}}
+  (NodeType. {:value (number-accessor-in "value" "Value" 1)}
+             {:signal (signal-out 0 "Signal out")}
              nil
              false
              "Const"
@@ -216,19 +204,9 @@
              {:constructor "new ConstSourceNode(context)"}))

 (def stereo-panner-node-type
-  (NodeType. {:pan {:type :param
-                    :name "pan"
-                    :default 0
-                    :title "Pan"
-                    :data-type :number
-                    :range [-1 1]}
-              :signal-in {:type :node
-                          :index 0
-                          :title "Signal in"}}
-             {:signal-out {:type :node
-                           :index 0
-                           :title "Signal out"
-                           :data-type :signal}}
+  (NodeType. {:pan (number-param-in "pan" "Pan" 0 [-1 1])
+              :signal-in (signal-in 0 "Signal in")}
+             {:signal-out (signal-out 0 "Signal out")}
              nil
              false
              "Pan"
@@ -237,17 +215,9 @@
              {:constructor "context.createStereoPanner()"}))

 (def stereo-splitter-node-type
-  (NodeType. {:signal-in {:type :node
-                          :index 0
-                          :title "Signal in"}}
-             {:left-out {:type :node
-                         :index 0
-                         :title "Left channel out"
-                         :data-type :signal}
-              :right-out {:type :node
-                          :index 1
-                          :title "Right channel out"
-                          :data-type :signal}}
+  (NodeType. {:signal-in (signal-in 0 "Stereo in")}
+             {:left-out (signal-out 0 "Left channel")
+              :right-out (signal-out 1 "Right channel")}
              nil
              false
              "Split"
@@ -256,16 +226,9 @@
              {:constructor "context.createChannelSplitter(2)"}))

 (def stereo-merger-node-type
-  (NodeType. {:left-in {:type :node
-                        :index 0
-                        :title "Left channel in"}
-              :right-in {:type :node
-                         :index 1
-                         :title "Right channel in"}}
-             {:signal-out {:type :node
-                          :index 0
-                           :title "Signal out"
-                           :data-type :signal}}
+  (NodeType. {:left-in (signal-in 0 "Left channel")
+              :right-in (signal-in 1 "Right channel")}
+             {:signal-out (signal-out 0 "Stereo out")}
              nil
              false
              "Merge"
@@ -274,18 +237,9 @@
              {:constructor "context.createChannelMerger(2)"}))

 (def delay-node-type
-  (NodeType. {:signal-in {:type :node
-                          :index 0
-                          :title "Signal in"}
-              :delay-time {:type :param
-                           :name "delayTime"
-                           :data-type :number
-                           :range [0 5]
-                           :title "Delay time"}}
-             {:signal-out {:type :node
-                           :index 0
-                           :title "Signal out"
-                           :data-type :signal}}
+  (NodeType. {:signal-in (signal-in 0 "Signal in")
+              :delay-time (number-param-in "delayTime" "Delay time" 0 [0 5])}
+             {:signal-out (signal-out 0 "Signal out")}
              nil
              false
              "Delay"
@@ -294,43 +248,13 @@
              {:constructor "context.createDelay(5)"}))

 (def compressor-node-type
-  (NodeType. {:signal-in {:type :node
-                          :index 0
-                          :title "Signal in"}
-              :threshold {:type :param
-                          :name "threshold"
-                          :data-type :number
-                          :default -24
-                          :title "Threshold"
-                          :range [-100 0]}
-              :knee {:type :param
-                     :name "knee"
-                     :data-type :number
-                     :default 30
-                     :range [0 40]
-                     :title "Knee"}
-              :ratio {:type :param
-                      :name "ratio"
-                      :data-type :number
-                      :default 12
-                      :range [1 20]
-                      :title "Ratio"}
-              :attack {:type :param
-                       :name "attack"
-                       :data-type :number
-                       :default 0.003
-                       :range [0 1]
-                       :title "Attack"}
-              :release {:type :param
-                        :name "release"
-                        :data-type :number
-                        :default 0.25
-                        :range [0 1]
-                        :title "Release"}}
-             {:signal-out {:type :node
-                           :index 0
-                           :title "Signal out"
-                           :data-type :signal}}
+  (NodeType. {:signal-in (signal-in 0 "Signal in")
+              :threshold (number-param-in "threshold" "Threshold" -24 [-100 0])
+              :knee (number-param-in "knee" "Knee" 30 [0 40])
+              :ratio (number-param-in "ratio" "Ratio" 12 [1 20])
+              :attack (number-param-in "attack" "Attack" 0.003 [0 1])
+              :release (number-param-in "release" "Release" 0.25 [0 1])}
+             {:signal-out (signal-out 0 "Signal out")}
              nil
              false
              "Compressor"
@@ -339,38 +263,14 @@
              {:constructor "context.createDynamicsCompressor()"}))

 (def midi-note-node-type
-  (NodeType. {:device {:type :accessor
-                       :name "device"
-                       :default nil
-                       :title "Device"
-                       :data-type :midi-device
-                       :serializable false}
-              :note-mode {:type :constant
-                          :name "noteMode"
-                          :default "retrig"
-                          :data-type :string
-                          :title "Mode"
-                          :choices ["retrig" "legato"]}
-              :portamento {:type :constant
-                           :name "portamento"
-                           :default 0
-                           :data-type :number
-                           :range [0 5]
-                           :title "Portamento"}
-              :priority {:type :constant
-                         :name "priority"
-                         :default "last-on"
-                         :data-type :string
-                         :title "Priority"
-                         :choices ["last-on" "highest" "lowest"]}}
-             {:gate {:type :node
-                     :index 0
-                     :title "Gate"
-                     :data-type :gate}
-              :frequency {:type :node
-                          :index 1
-                          :title "Frequency"
-                          :data-type :param}}
+  (NodeType. {:device (midi-device-accessor-in "device" "Device")
+              :note-mode (string-constant-in "noteMode" "Mode" "retrig"
+                                             ["retrig" "legato"])
+              :portamento (number-constant-in "portamento" "Portamento" 0)
+              :priority (string-constant-in "priority" "Priority" "last-on"
+                                            ["last-on" "highest" "lowest"])}
+             {:gate (gate-out 0 "Gate")
+              :frequency (param-out 1 "Frequency")}
              nil
              false
              "MIDI Note"
@@ -382,22 +282,9 @@
                                                   "/js/audio/midi_note_node.js")]}}))

 (def midi-cc-node-type
-  (NodeType. {:device {:type :accessor
-                       :name "device"
-                       :default nil
-                       :title "Device"
-                       :data-type :midi-device
-                       :serializable false}
-              :channel {:type :constant
-                        :name "channel"
-                        :default 0
-                        :data-type :number
-                        :range [0 127]
-                        :title "Channel"}}
-             {:value {:type :node
-                      :index 0
-                      :title "Value"
-                      :data-type :param}}
+  (NodeType. {:device (midi-device-accessor-in "device" "Device")
+              :channel (number-constant-in "channel" "Channel" 0 [0 127])}
+             {:value (param-out 0 "Value")}
              {:inspector-fields [:midi-cc-learn]}
              false
              "MIDI CC"
@@ -433,31 +320,27 @@
     (merge basic-nodes midi-nodes)))

 (def all-node-groups
-  (let [generators [[:oscillator oscillator-node-type]
-                    [:const-source const-source-node-type]]
-        filters [[:biquad-filter biquad-filter-node-type]
-                 [:gain gain-node-type]
-                 [:stereo-panner stereo-panner-node-type]
-                 [:stereo-splitter stereo-splitter-node-type]
-                 [:stereo-merger stereo-merger-node-type]
-                 [:delay delay-node-type]
-                 [:compressor compressor-node-type]]
-        envelopes [[:adsr adsr-node-type]]
-        midi-nodes [[:midi-note midi-note-node-type]
-                    [:midi-cc midi-cc-node-type]]
-        analysers [[:scope scope-analyser-node-type]
-                   [:fft fft-analyser-node-type]]
-        interfaces [[:input input-node-type]
-                    [:output output-node-type]
-                    [:audio-destination audio-destination-node-type]]]
-    (concat [{:title "Generators" :node-types generators}
-             {:title "Filters" :node-types filters}
-             {:title "Envelopes" :node-types envelopes}]
-            (if has-midi-support
-              [{:title "MIDI" :node-types midi-nodes}]
-              [])
-            [{:title "Analysers" :node-types analysers}]
-            [{:title "Interfaces" :node-types interfaces}])))
+  (letfn [(lookup [node-type-id]
+            [node-type-id (all-node-types node-type-id)])]
+
+    (let [generators [:oscillator :const-source]
+          filters [:biquad-filter :gain :stereo-panner
+                   :stereo-splitter :stereo-merger
+                   :delay :compressor]
+          envelopes [:adsr]
+          midi-nodes [:midi-note :midi-cc]
+          analysers [:scope :fft]
+          interfaces [:input :output :audio-destination]]
+      (map
+       (fn [m] (update m :node-types (partial map lookup)))
+       (concat [{:title "Generators" :node-types generators}
+                {:title "Filters" :node-types filters}
+                {:title "Envelopes" :node-types envelopes}]
+               (if has-midi-support
+                 [{:title "MIDI" :node-types midi-nodes}]
+                 [])
+               [{:title "Analysers" :node-types analysers}]
+               [{:title "Interfaces" :node-types interfaces}])))))

 (defn get-node-type [node-type-id]
   (all-node-types node-type-id))


after creating a tag, subscribe to it

after creating a tag, subscribe to it

--- src/chat/client/dispatcher.cljs
+++ src/chat/client/dispatcher.cljs
@@ -39,7 +39,8 @@
 (defmethod dispatch! :create-tag [_ tag-name]
   (let [tag (schema/make-tag {:name tag-name})]
     (store/add-tag! tag)
-    (sync/chsk-send! [:chat/create-tag tag])))
+    (sync/chsk-send! [:chat/create-tag tag])
+    (dispatch! :subscribe-to-tag (tag :id))))

 (defmethod dispatch! :unsubscribe-from-tag [_ tag-id]
   (sync/chsk-send! [:user/unsubscribe-from-tag tag-id])


There's no {{project-ns}}.dev

There's no {{project-ns}}.dev

With the current setup there's errors when you run lein repl because it tries to load this file that doesn't exist.

It only exists in the cljs flavour, not clj.

--- src/leiningen/new/reagent/env/dev/clj/reagent/repl.clj
+++ src/leiningen/new/reagent/env/dev/clj/reagent/repl.clj
@@ -1,6 +1,5 @@
 (ns {{name}}.repl
   (:use {{name}}.handler
-        {{project-ns}}.dev
         ring.server.standalone
         [ring.middleware file-info file]))


Need to (:refer-clojure :exclude [partition]) to prevent AOT compilation explosion when using partition layout.

--- src/clj/c2/layout/partition.clj
+++ src/clj/c2/layout/partition.clj
@@ -1,4 +1,5 @@
-(ns c2.layout.partition)
+(ns c2.layout.partition
+  (:refer-clojure :exclude [partition]))

 (defn partition [root & {:keys [sort children value size output-key]


Wrap base URL middleware

Wrap base URL middleware

--- src/clj/sparqlab/middleware.clj
+++ src/clj/sparqlab/middleware.clj
@@ -7,7 +7,9 @@
             [ring.middleware.webjars :refer [wrap-webjars]]
             [ring.middleware.format :refer [wrap-restful-format]]
             [ring-ttl-session.core :refer [ttl-memory-store]]
-            [ring.middleware.defaults :refer [site-defaults wrap-defaults]])
+            [ring.middleware.defaults :refer [site-defaults wrap-defaults]]
+            [ring.util.request :refer [request-url]]
+            [cemerick.url :refer [map->URL url]])
   (:import [javax.servlet ServletContext]))

 (defn wrap-context [handler]
@@ -52,6 +54,18 @@
       ;; since they're not compatible with this middleware
       ((if (:websocket? request) handler wrapped) request))))

+(defn wrap-base-url
+  "Add base URL to Ring request."
+  [handler]
+  (fn [request]
+    (let [base-url (-> request
+                       request-url
+                       url
+                       (dissoc :query :path)
+                       (assoc :path (:context request))
+                       map->URL)]
+      (handler (assoc request :base-url base-url)))))
+
 (defn wrap-base [handler]
   (-> ((:middleware defaults) handler)
       wrap-webjars
@@ -60,4 +74,5 @@
             (assoc-in [:security :anti-forgery] false)
             (assoc-in [:session :store] (ttl-memory-store (* 60 30)))))
       wrap-context
-      wrap-internal-error))
+      wrap-internal-error
+      wrap-base-url))


remove trace output

remove trace output

--- src/clj_money/serialization.clj
+++ src/clj_money/serialization.clj
@@ -53,10 +53,6 @@
   [storage-spec account]
   (if (:parent-id account)
     (let [parent (accounts/find-by-name storage-spec (:entity-id account) (:parent-id account))]
-
-      (pprint {:resolve-parent account
-               :parent parent})
-
       (assoc account :parent-id (:id parent)))
     account))


Wire everything together finally in the main ns

--- src/cljs/comic_reader/main.cljs
+++ src/cljs/comic_reader/main.cljs
@@ -2,6 +2,8 @@
   (:require
     [comic-reader.api :as api]
     [comic-reader.ui.base :as base]
+    [comic-reader.ui.image :as image]
+    [comic-reader.ui.reader :as reader]
     [comic-reader.ui.site-list :as site-list]
     [comic-reader.ui.comic-list :as comic-list]
     [reagent.core :as reagent]
@@ -22,6 +24,8 @@

 (defn setup! []
   (api/setup!)
+  (image/setup!)
+  (reader/setup!)
   (site-list/setup!)
   (comic-list/setup!)

@@ -73,9 +77,7 @@
   (case page-key
     :site-list [site-list/site-list-container]
     :comic-list [comic-list/comic-page-container]
-    :reader [:div [:h1 "Read a Comic!"]
-             [:pre (pr-str {:site-id @(re-frame/subscribe [:site-id])
-                            :comic-id @(re-frame/subscribe [:comic-id])})]]
+    :reader [reader/view]
     nil [:span ""]
     [base/four-oh-four]))


Use specter!

Use specter!

--- src/cljs/learn_specter/app.cljs
+++ src/cljs/learn_specter/app.cljs
@@ -73,11 +73,11 @@
 (defn add-ellipse
   "Adds an ellipse at the end of a list, to indicate that the list is shown incomplete."
   [s]
-  (clojure.string/replace s #"\)(\n)*$" "\n ...)"))
+  (clojure.string/replace s #"\](\n)*$" " ...]"))

 (defn dataset-preview
   [dataset]
-  (let [first-movies (take 2 @dataset)]
+  (let [first-movies (s/select [(s/srange 0 2) s/ALL] @dataset)]
     [:div
      "The dataset used for the excercises has the following form:"
      [:pre (-> first-movies pprint with-out-str add-ellipse)]]))


Fix a bug where :inside-se was :inside-sw instead

--- src/com/hypirion/clj_xchart.clj
+++ src/com/hypirion/clj_xchart.clj
@@ -120,7 +120,7 @@
   {:inside-n  Styler$LegendPosition/InsideN
    :inside-ne Styler$LegendPosition/InsideNE
    :inside-nw Styler$LegendPosition/InsideNW
-   :inside-se Styler$LegendPosition/InsideSW
+   :inside-se Styler$LegendPosition/InsideSE
    :inside-sw Styler$LegendPosition/InsideSW
    :outside-e Styler$LegendPosition/OutsideE})


Allow fact shape to be not a FactShape :(

--- src/aurora/language.cljs
+++ src/aurora/language.cljs
@@ -86,9 +86,7 @@
    (assert (array? values) (pr-str values))
    (Fact. nil values nil))
   ([shape values]
-   (assert (instance? FactShape shape) (pr-str shape))
    (assert (array? values) (pr-str values))
-   (assert (= (alength values) (alength (.-keys shape))) (pr-str values shape))
    (Fact. shape values nil)))

 (defn fact-ix [fact ix]
@@ -367,7 +365,7 @@
         (Fact. shape sink)))))

 (defn pattern->deconstructor [pattern]
-  (let [id (.-id (.-shape pattern))
+  (let [shape (.-shape pattern)
         seen? (atom {})
         constant-values #js []
         constant-ixes #js []
@@ -387,7 +385,7 @@
           (apush constant-values value)
           (apush constant-ixes ix))))
     (fn [fact]
-      (when (= id (.-id (.-shape fact)))
+      (when (= shape (.-shape fact))
         (let [source (.-values fact)]
           (loop [i 0]
             (if (< i (alength constant-values))


Add todo on bytes ns.

Add todo on bytes ns.

--- src/buddy/core/bytes.clj
+++ src/buddy/core/bytes.clj
@@ -58,3 +58,5 @@
   (byte-array (for [ar parts
                     i ar] i)))

+
+;; TODO: add bytebuffer related abstractions here


Fix invite bug

Fix invite bug

--- src/antlion_clojure/bot.clj
+++ src/antlion_clojure/bot.clj
@@ -16,17 +16,16 @@
       (do (redis/set-checking-question? user question)
           [(map->Payload {:type :message
                           :user user
-                          :subtype
-                          (if (= "channel_leave" subtype)
-                            :channel_invite
-                            :group_invite)
                           :channel channel
                           :text (str "ﾄｲﾃﾈ!\n----------\n"
                                      question)})
            (map->Payload {:type :message
                           :user user
-                          :channel channel
-                          :subtype :channel_invite})])
+                          :subtype
+                          (if (= "channel_leave" subtype)
+                            :channel_invite
+                            :group_invite)
+                          :channel channel})])
       (map->Payload {:type :message
                      :user user
                      :channel channel


Make source emitted by `cljs.closure/output-main-file` idempotent

--- src/clj/cljs/closure.clj
+++ src/clj/cljs/closure.clj
@@ -775,7 +775,7 @@
   (let [asset-path (or (:asset-path opts)
                        (util/output-directory opts))]
     (output-one-file opts
-      (str "document.write('<script src=\"" asset-path "/goog/base.js\"></script>');"
+      (str "if(typeof goog == \"undefined\") document.write('<script src=\"" asset-path "/goog/base.js\"></script>');"
            "document.write('<script src=\"" asset-path "/cljs_deps.js\"></script>');"
            "document.write('<script>goog.require(\"" (comp/munge (:main opts)) "\");</script>');"))))


eliminate reflection warnings from cljs.js-deps

--- src/clj/cljs/js_deps.clj
+++ src/clj/cljs/js_deps.clj
@@ -1,7 +1,11 @@
 (ns cljs.js-deps
   (:require [clojure.java.io :as io]
             [clojure.string :as string])
-  (:import java.io.File))
+  (:import java.io.File
+           java.net.URL
+           java.net.URLClassLoader
+           java.util.zip.ZipFile
+           java.util.zip.ZipEntry))

 ; taken from pomegranate/dynapath
 ; https://github.com/tobias/dynapath/blob/master/src/dynapath/util.clj
@@ -10,16 +14,24 @@
 If no ClassLoader is provided, RT/baseLoader is assumed."
   ([] (all-classpath-urls (clojure.lang.RT/baseLoader)))
   ([cl]
-     (->> (iterate #(.getParent %) cl)
+     (->> (iterate #(.getParent ^ClassLoader %) cl)
        (take-while identity)
        reverse
-       (filter (partial instance? java.net.URLClassLoader))
-       (mapcat #(.getURLs %))
+       (filter (partial instance? URLClassLoader))
+       (mapcat #(.getURLs ^URLClassLoader %))
        distinct)))

+(defn ^ZipFile zip-file [jar-path]
+  (cond
+    (instance? File jar-path) (ZipFile. ^File jar-path)
+    (string? jar-path) (ZipFile. ^String jar-path)
+    :else
+    (throw
+      (IllegalArgumentException. (str "Cannot construct zipfile from " jar-path)))))
+
 (defn jar-entry-names* [jar-path]
-  (with-open [z (java.util.zip.ZipFile. jar-path)]
-    (doall (map #(.getName %) (enumeration-seq (.entries z))))))
+  (with-open [z (zip-file jar-path)]
+    (doall (map #(.getName ^ZipEntry %) (enumeration-seq (.entries ^ZipFile z))))))

 (def jar-entry-names (memoize jar-entry-names*))

@@ -52,12 +64,12 @@
     (map io/file)
     (reduce
       (fn [files jar-or-dir]
-        (let [name (.toLowerCase (.getName jar-or-dir))
+        (let [name (.toLowerCase (.getName ^File jar-or-dir))
               ext  (.substring name (inc (.lastIndexOf name ".")))]
-          (->> (when (.exists jar-or-dir)
+          (->> (when (.exists ^File jar-or-dir)
                  (cond
-                   (.isDirectory jar-or-dir)
-                   (find-js-fs (str (.getAbsolutePath jar-or-dir) "/" path))
+                   (.isDirectory ^File jar-or-dir)
+                   (find-js-fs (str (.getAbsolutePath ^File jar-or-dir) "/" path))

                    (#{"jar" "zip"} ext)
                    (find-js-jar jar-or-dir path)
@@ -229,7 +241,7 @@
   (first
     (filter
       (fn [res]
-        (re-find #"(\/google-closure-library-0.0*|\/google-closure-library\/)" (.getPath res)))
+        (re-find #"(\/google-closure-library-0.0*|\/google-closure-library\/)" (.getPath ^URL res)))
       (enumeration-seq (.getResources (.getContextClassLoader (Thread/currentThread)) path)))))

 (defn goog-dependencies*


Sorting the files by name is probably a good plan.

--- src/clj/freefrog/cli.clj
+++ src/clj/freefrog/cli.clj
@@ -31,6 +31,7 @@
                     file-seq
                     (filter #(.isFile %))
                     (filter #(not (.startsWith (.getName %) ".")))
+                    (sort-by #(.getName %))
                     (map slurp)
                     (reduce l/execute-governance {})))
     (println "Please specify a directory full of governance files.")))


Create ping path

Create ping path

--- src/clj/ozwiena/core.clj
+++ src/clj/ozwiena/core.clj
@@ -50,6 +50,8 @@
                                    (catch Exception e (-> (response (str e))
                                                           (status 500)))))

+  (GET "/ping" [] (str "Pong!"))
+
   (route/resources "/")
   (route/not-found "Page not found"))


Change crypto.hash to use new byte types

--- src/caesium/crypto/hash.clj
+++ src/caesium/crypto/hash.clj
@@ -1,8 +1,8 @@
 (ns caesium.crypto.hash
-  (:require [caesium.binding :refer [sodium defconsts]]
-            [caesium.byte-bufs :refer [buflen]]))
+  (:require [caesium.binding :as b]
+            [caesium.byte-bufs :as bb]))

-(defconsts [sha256-bytes sha512-bytes])
+(b/defconsts [sha256-bytes sha512-bytes])

 (defn sha256-to-buf!
   "Hashes a message with optional key into a given output buffer using
@@ -10,17 +10,17 @@

   You only want this to manage the output byte array yourself. Otherwise, you
   want [[sha256]]."
-  [^bytes buf ^bytes msg]
-  (.crypto_hash_sha256 sodium buf msg (long (buflen msg))))
+  [buf msg]
+  (b/✨ sha256 buf msg))

 (defn sha256
   "Computes the SHA-256 hash of message in the given byte array.

   This is higher-level than [[sha256-to-buf!]] because you don't have to
   allocate your own output buffer."
-  [^bytes msg]
+  [msg]
   (let [buf (byte-array sha256-bytes)]
-    (sha256-to-buf! buf msg)
+    (sha256-to-buf! (bb/->indirect-byte-buf buf) (bb/->indirect-byte-buf msg))
     buf))

 (defn sha512-to-buf!
@@ -29,15 +29,15 @@

   You only want this to manage the output byte array yourself. Otherwise, you
   want [[sha512]]."
-  [^bytes buf ^bytes msg]
-  (.crypto_hash_sha512 sodium buf msg (long (buflen msg))))
+  [buf msg]
+  (b/✨ sha512 buf msg))

 (defn sha512
   "Computes the SHA-512 hash of message in the given byte array.

   This is higher-level than [[sha512-to-buf!]] because you don't have to
   allocate your own output buffer."
-  [^bytes msg]
+  [msg]
   (let [buf (byte-array sha512-bytes)]
-    (sha512-to-buf! buf msg)
+    (sha512-to-buf! (bb/->indirect-byte-buf buf) (bb/->indirect-byte-buf msg))
     buf))


Calculate square ids in a function rather than in place

--- src/cljs/chess/core.cljs
+++ src/cljs/chess/core.cljs
@@ -47,6 +47,11 @@
   (let [[f r] (vec p)]
     [(- 8 (parse-int r)) (file->i f)]))

+(defn from-board-ks
+  "The complement of to-board-ks"
+  [x y]
+  (str (i->file x) (- 8 y)))
+
 (defn in
   "Get the contents of a square on the board. Nil if empty"
   [board sq]
@@ -92,8 +97,8 @@
         (render [_]
           (apply dom/div #js {:className "board"}
                    (map-indexed
-                    (fn [i r] (apply dom/div #js {:className "row" :id (- 8 i)}
-                                   (map-indexed (fn [j s] (dom/div #js {:className "square" :id (str (i->file j) (- 8 i))}
+                    (fn [i r] (apply dom/div #js {:className "row"}
+                                   (map-indexed (fn [j s] (dom/div #js {:className "square" :id (from-board-ks j i)}
                                                          (if s
                                                            (dom/div #js {:className (str "piece " (colour s) " " (pieces s))} nil)))) r)))
                     (:board app))))))


Making *go-import-prefix* a map so we can control where packages lib better. Refactoring emit :ns

--- src/cljs/go/compiler.clj
+++ src/cljs/go/compiler.clj
@@ -52,7 +52,21 @@

 (def cljs-reserved-file-names #{"deps.cljs"})

-(def ^:dynamic *go-import-prefix* "github.com/hraberg/cljs.go/")
+(def go-cljs-import-prefix "github.com/hraberg/cljs.go/")
+(def ^:dynamic *go-import-prefix* (zipmap '[goog
+                                            goog.string
+                                            goog.array
+                                            goog.object
+                                            js
+                                            js.Math
+                                            cljs.core
+                                            cljs.reader
+                                            clojure.data
+                                            clojure.set
+                                            clojure.string
+                                            clojure.walk
+                                            clojure.zip]
+                                          (repeat go-cljs-import-prefix)))
 (def ^:dynamic *go-return-name* nil)
 (def ^:dynamic *go-return-tag* nil)
 (def ^:dynamic *go-protocol-fn* nil)
@@ -1066,10 +1080,7 @@
             (emitln " return " return)
             (emits "}()")))))))

-(def provided-lib? '#{goog goog.string goog.array goog.object
-                      js js/Math
-                      cljs.core cljs.reader
-                      clojure.data clojure.set clojure.string clojure.walk clojure.zip})
+(def js-base-libs '#{js js.Math goog})

 (defmethod emit* :ns
   [{:keys [name requires uses imports require-macros env]}]
@@ -1080,18 +1091,18 @@
   (emitln "package " (last (string/split (str (munge name)) #"\.")))
   (emitln)
   (emitln "import (")
-  (when-not (= name 'cljs.core)
-    (emitln "\t" "cljs_core" " " (wrap-in-double-quotes (str *go-import-prefix* "cljs/core"))))
-  (emitln "\t" (wrap-in-double-quotes (str *go-import-prefix* "js")))
-  (emitln "\t" (wrap-in-double-quotes (str *go-import-prefix* "js/Math")))
-  (emitln "\t" (wrap-in-double-quotes (str *go-import-prefix* "goog"))) ;; gets imported indirectly in JS I think?
-  (doseq [lib (distinct (concat (map #(symbol (string/replace % #"(.+)(\..+)$" "$1")) (vals imports))
+  (doseq [lib (distinct (concat (when-not (= name 'cljs.core)
+                                  '[cljs.core])
+                                js-base-libs
+                                (map #(symbol (string/replace % #"(.+)(\..+)$" "$1")) (vals imports))
                                 (vals (apply dissoc requires (keys imports))) (vals uses)))]
-    (emitln "\t" (string/replace (munge lib) "." "_") " "
+    (emitln "\t" (when-not (js-base-libs lib)
+                   (str (string/replace (munge lib) "." "_") " "))
             (wrap-in-double-quotes
-             (str (when (provided-lib? lib)
-                    *go-import-prefix*)
-                  (string/replace lib #"[._]" "/")))))
+             (str (*go-import-prefix* lib)
+                  (-> lib
+                      (string/replace #"[._]" "/")
+                      (string/replace #"[-]" "_"))))))
   (emitln ")")
   (emitln))


Add live-reloading to cljs.

Add live-reloading to cljs.

--- src/cljs/quil/sketch.clj
+++ src/cljs/quil/sketch.clj
@@ -4,12 +4,27 @@
   `(binding [quil.sketch/*applet* ~applet]
      ~@body))

+(defn wrap-fns
+  "Wrap fns allows dynamic redefinition of function such as draw, update
+  in cljs. This is achieved by wrapping all provided functions to
+  anonymous functions such that 'my-draw' function turns into
+  (fn [& args] (apply my-draw args)). This adds a level of indirection
+  so that when quil calls draw, it invokes anonymous function which in
+  turn always calls my-draw by name and if you redefine - new version
+  will be used. Hence we need this cryptic macro."
+  [opts]
+  (into {}
+        (for [[k v] opts]
+          (if (symbol? v)
+            [k `(if (fn? ~v) (fn [& ~'args] (apply ~v ~'args)) ~v)]
+            [k v]))))

 (defmacro defsketch
   [app-name & options]
   (let [raw-opts (apply hash-map options)
-        opts     (merge {:host (str app-name)}
-                        raw-opts)]
+        opts     (->> raw-opts
+                      (merge {:host (str app-name)})
+                      wrap-fns)]
     `(do
        (defn ~(vary-meta app-name assoc :export true) []
          (quil.sketch/sketch


Unify  implementations

Unify  implementations

--- src/cljx/revue/util.cljx
+++ src/cljx/revue/util.cljx
@@ -5,7 +5,8 @@
   machine."
   (:require #+cljs [cljs.reader :as reader]
             ;; Maybe use clojure.core/read-string for Clojure?
-            #+clj [clojure.edn :as reader]
+            ;; #+clj [clojure.edn :as reader]
+            #+clj [clojure.tools.reader :as reader]
             #+clj [clojure.pprint :as pprint]))

@@ -40,9 +41,9 @@
 ;;; the `error` and `warning` functions.  Later we will have to
 ;;; add a better error-handling protocol.

-;;; <!--
+;;; @MargDisable
 ;;; TODO: Replace these functions with more useful implementations
-;;; -->
+;;; @MargEnable

 (defn error
   "The `error` function is a simple wrapper around `throw` that
@@ -52,8 +53,6 @@
   [& msg]
   (throw (#+clj java.lang.Exception. #+cljs js/Error.
                 (apply str msg))))
-
-

 (def ^:dynamic *print-warnings*
   "If `*print-warnings*` is truthy, warning messages are printed to
@@ -94,7 +93,8 @@

 (defn singleton?
   "Returns true iff `coll` contains exactly one element,
-  i.e., `(singleton? x)` is always equivalent to `(= (count x) 1)`"
+  i.e., `(singleton? x)` is always equivalent to `(= (count x) 1)` but
+  more efficient for collections where `count` is not O(1).''"
   [coll]
   (and (not (empty? coll))
        (not (next coll))))
@@ -144,36 +144,28 @@
 ;;; Utilities for reading the program source
 ;;; ========================================

-#+clj
+;;; @MargDisable
+;;; TODO: Improve the error handling for this
+;;; @MargEnable
+
 (defn read-program-from-string
-  "Read all forms from the input string."
+  "Read all forms from the input string and return them as sequence.
+  Return the sequence `[::syntax-error]` if reading fails."
   [string]
   (try
-    (with-open [stream (-> (java.io.StringReader. string)
-                           clojure.lang.LineNumberingPushbackReader.)]
-      (loop [form (read stream false stream)
-             forms []]
-        (if (identical? form stream)
-          forms
-          (recur (read stream false stream)
-                 (conj forms form)))))
-    (catch java.lang.Exception e
-      [::syntax-error])))
-
-#+cljs
-(defn read-program-from-string
-  "Read all forms from the input string."
-  [string]
-  (try
-    (let [stream (cljs.reader/push-back-reader string)]
-      (loop [form (cljs.reader/read stream false stream nil)
-             forms []]
-        (if (identical? form stream)
-          forms
-          (recur (cljs.reader/read stream false stream nil)
-                 (conj forms form)))))
-    (catch js/Error e
-      [::syntax-error])))
+    (#+clj with-open #+cljs let
+           [stream
+            #+clj (-> (java.io.StringReader. string)
+                      clojure.lang.LineNumberingPushbackReader.)
+            #+cljs (reader/push-back-reader string)]
+           (loop [form (reader/read stream false stream)
+                  forms []]
+             (if (identical? form stream)
+               forms
+               (recur (reader/read stream false stream)
+                      (conj forms form)))))
+    (catch #+clj java.lang.Exception #+cljs js/Error e
+           [::syntax-error])))

 ;;; Local Environment for Compiler and VM
 ;;; =====================================
@@ -198,6 +190,8 @@
   environment frames."
   (frames [this]))

+;;; We need the `->Env` constructor for creating new environments in
+;;; `conj`.
 (declare ->Env)

 #+clj
@@ -345,6 +339,11 @@
 (defmethod print-method Env [env writer]
   (.write writer (str "#" (print-str (class env)) "{:frames " (frames env) "}")))

+(defn env [& frames]
+  "Return a new environment containing `frames` in the given
+  order (i.e., `(first frames)` is the first frame, etc.)."
+  (->Env (vec (map vec (reverse frames)))))
+
 (defn env-value
   "Return the value at position `[frame slot]` in `vm-state`'s
   environment.  This is similar to `(get-in env [frame slot])` but
@@ -356,6 +355,7 @@
     (nth frame-vector slot)))

 (defn in-env? [env var]
+  "Return the a pair `[frame]`"
   (loop [frames (frames env) n-frame 0]
     (if (empty? frames)
       false
@@ -369,7 +369,10 @@
         result
         (recur (rest frames) (inc n-frame))))))

-;;; Alternative implementation of `in-env?`.
+;;; @MargDisable
+;;; Alternative implementation of `in-env?`.  I'm not sure which one I
+;;; prefer, neither one seems as elegant as it should be.
+
 #_
 (defn in-env? [env var]
   (first
@@ -381,13 +384,13 @@
                      [n-frame pos-in-frame]
                      nil))
                  (frames env))))
-
-
-;;; <!--
+;;; @MargEnable
+
+;;; @MargDisable
 ;;; Evaluate this (e.g., with C-x C-e in Cider) to run the tests for
 ;;; this namespace:
 ;;; (clojure.test/run-tests 'revue.util-test)
 ;;; Evaluate this to run the test for all namespaces:
 ;;; (clojure.test/run-all-tests #"^revue\..*-test")
-;;; -->
-
+;;; @MargEnable
+


Experiment more with meta-errors

Experiment more with meta-errors

--- src/clojush/evaluate.clj
+++ src/clojush/evaluate.clj
@@ -751,6 +751,16 @@
                          (= e p1e) 2
                          :else 3)))
                 (vec (repeat (count (:errors ind)) 3)))
+              #_(if (:parent1-errors ind)
+                (vec (for [[e p1e] (mapv #(vector %1 %2)
+                                         (:errors ind)
+                                         (:parent1-errors ind))]
+                       (cond
+                         (zero? e) 0
+                         (< e p1e) 1
+                         (= e p1e) 3
+                         :else 2)))
+                (vec (repeat (count (:errors ind)) 2)))
               (if (:parent1-errors ind)
                 (vec (for [[e p1e] (mapv #(vector %1 %2)
                                          (:errors ind)
@@ -758,7 +768,7 @@
                        (cond
                          (zero? e) 0
                          (< e p1e) 1
-                         (= e p1e) 3
+                         (= e p1e) 2
                          :else 2)))
                 (vec (repeat (count (:errors ind)) 2)))
               ;


Fix issue: #9

Fix issue: #9

--- src/cerber/stores/token.clj
+++ src/cerber/stores/token.clj
@@ -9,7 +9,7 @@
             [cerber.stores.user :as user]
             [cerber.error :as error]
             [cerber.helpers :as helpers]
-            [clojure.string :refer [join]]))
+            [clojure.string :refer [join split]]))

 (defn default-valid-for []
   (-> app-config :tokens :valid-for))
@@ -173,7 +173,7 @@
     {:client-id client_id
      :user-id user_id
      :login login
-     :scope scope
+     :scope (set (split scope #" "))
      :secret secret
      :created-at created_at
      :expires-at expires_at}))


docstring tweak

docstring tweak

--- src/clj/cljs/source_map.clj
+++ src/clj/cljs/source_map.clj
@@ -153,9 +153,9 @@
       [] lines)))

 (defn encode
-  "Take an internal nested sorce map representation represented as
-   nested sorted maps of file, line, column and return a source map v3
-   JSON string."
+  "Take an internal source map representation represented as nested
+   sorted maps of file, line, column and return a source map v3 JSON
+   string."
   [m opts]
   (let [lines (atom [[]])
         names->idx (atom {})


Change copy

Change copy

--- src/clj/robinson/render.clj
+++ src/clj/robinson/render.clj
@@ -979,7 +979,7 @@
         selected-hotkeys (get-in state [:world :selected-hotkeys])
         start-inventory  (sg/start-inventory)]
     (clear (state :screen))
-    (put-string screen 20 5 "Pick up to three things to take:")
+    (put-string screen 20 5 "Choose up to three things to take with you:")
     (render-list screen 20 7 60 (count start-inventory)
                                 (map (fn [item] {:s (format "%c%c%s" (get item :hotkey)
                                                                        (if (contains? selected-hotkeys (get item :hotkey))


minor cleanup

minor cleanup

--- src/cljs/lambdacd/time.cljs
+++ src/cljs/lambdacd/time.cljs
@@ -35,7 +35,6 @@
     (format-duration-in-seconds sec)))

 (defn format-ago [s1]
-  (if s1
-    (let [m (js/moment s1)]
-      (.fromNow m))
-    nil))+  (when s1 (-> s1
+                    (js/moment)
+                    (.fromNow))))


Improve AIs

Improve AIs

--- src/cljs/triboard/core.cljs
+++ src/cljs/triboard/core.cljs
@@ -186,15 +186,17 @@
        + (second %))
     (get-in game [:moves player])))

-(defn best-immediate-move
-  "Return the move with the highest immediate score increase for the provided player"
-  [game player]
-  (best-immediate-move-with game player identity))
+#_(defn best-immediate-move
+   "Return the move with the highest immediate score increase for the provided player"
+   [game player]
+   (best-immediate-move-with game player identity))

 (defn worst-immediate-loss
-  "Return the next game move that would reduce the score the most for the provided player"
-  [game player]
-  (let [move-filter #(= player (:looser %))
+  "Return the next game move:
+   * Executed by the 'player'
+   * That would reduce the score for 'looser'"
+  [game player looser]
+  (let [move-filter #(= looser (:looser %))
         move (best-immediate-move-with game (:player game) move-filter)]
     (transduce (map (comp count :taken)) + (second move))
     ))
@@ -205,6 +207,7 @@
    * The worse immediate lost afterwards"
   [game player]
   (let [moves (get-in game [:moves player])
+        others (remove #{player} players)
         outcomes (map (fn [[m _]] [m (play-move game m)]) moves)]
     (first
       (apply max-key second
@@ -212,7 +215,14 @@
           (fn [[m outcome]]
             [m (-
                  (get-in outcome [:scores player])
-                 (worst-immediate-loss outcome player))])
+
+                 ;;Compute the values for the other players
+                 (apply max
+                   (map
+                     #(worst-immediate-loss outcome % player)
+                     others))
+
+                 )])
           outcomes)))
     ))


naming scheme cleanup

naming scheme cleanup

--- frontend/components/landing-b.cljs
+++ frontend/components/landing-b.cljs
@@ -23,11 +23,11 @@
             controls-ch (om/get-shared owner [:comms :controls])]
         (html [:div.home.page
                [:section.home-intro
-                [:a.intro-action-btn "Sign Up Free"]
-                [:div.intro-action-overlay]
-                [:nav.outer-navigation
-                 [:a.latest-link "What is Continuous Integration?"]
-                 [:a.login-link "Log In"]]
+                [:a.intro-action "Sign Up Free"]
+                [:div.intro-overlay]
+                [:nav.intro-nav
+                 [:a.intro-nav-promote "What is Continuous Integration?"]
+                 [:a.intro-nav-login "Log In"]]
                 [:div.intro-brand
                  (common/ico :logo)]
                 [:div.intro-slogan


Update doc stg

Update doc stg

--- src/aerobio/core.clj
+++ src/aerobio/core.clj
@@ -1,7 +1,14 @@
 (ns aerobio.core
-  "A robust, flexible clj aerobio with full tree graphs, function nodes,
-   superior error handling, logging, caching, etc.
-  "
+  "A robust, flexible streaming job server for open ended
+  bioinformatic analyses. Capabilities for full DAG job flow graphs,
+  function nodes, superior error handling, logging, caching, etc.
+
+  Supports dynamic open ended services written in Clojure, R, Python,
+  Perl, and any Linux/Unix command line tool. Supports nodes with
+  multiple inputs and outputs - utilizing pipes in cases of tools not
+  able to include multiple streaming input.
+  "
+
   {:author "Jon Anthony"}

   (:gen-class)


Add function for getting a hiccup image tag

--- src/clj/comic_reader/scrape.clj
+++ src/clj/comic_reader/scrape.clj
@@ -12,3 +12,14 @@
 (defn fetch-list [{:keys [url selector normalize]}]
   (when (every? (complement nil?) [url selector normalize])
     (map normalize (html/select (fetch-url url) selector))))
+
+(defn enlive->hiccup [{:keys [tag attrs content]}]
+  (if (nil? content)
+    [tag attrs]
+    [tag attrs content]))
+
+(defn fetch-image-tag [url]
+  (-> (fetch-url url)
+      (html/select [:div#imgholder :a :img#img])
+      first
+      enlive->hiccup))


tests for Parasite on Architect, Parasite ice trashing

--- src/clj/test/cards-programs.clj
+++ src/clj/test/cards-programs.clj
@@ -188,6 +188,29 @@
     (is (empty? (:prompt (get-runner))) "No prompt to host Parasite")
     (is (= 1 (count (get-in @state [:runner :rig :facedown]))) "Parasite installed face down")))

+(deftest parasite-architect
+  "Parasite - Installed on untrashable Architect should keep gaining counters past 3 and make strength go negative"
+  (do-game
+    (new-game (default-corp [(qty "Architect" 3) (qty "Hedge Fund" 3)])
+              (default-runner [(qty "Parasite" 3) (qty "Grimoire" 1)]))
+    (play-from-hand state :corp "Architect" "HQ")
+    (let [arch (get-in @state [:corp :servers :hq :ices 0])]
+      (core/rez state :corp arch)
+      (take-credits state :corp)
+      (play-from-hand state :runner "Grimoire")
+      (play-from-hand state :runner "Parasite")
+      (prompt-select :runner arch)
+      (let [psite (first (:hosted (refresh arch)))]
+        (is (= 1 (:counter (refresh psite))) "Parasite has 1 counter")
+        (take-credits state :runner)
+        (take-credits state :corp)
+        (take-credits state :runner)
+        (take-credits state :corp)
+        (take-credits state :runner)
+        (take-credits state :corp)
+        (is (= 4 (:counter (refresh psite))) "Parasite has 4 counters")
+        (is (= -1 (:current-strength (refresh arch))) "Architect at -1 strength")))))
+
 (deftest parasite-gain-counter
   "Parasite - Gain 1 counter every Runner turn"
   (do-game
@@ -206,6 +229,46 @@
         (take-credits state :corp)
         (is (= 1 (:counter (refresh psite))) "Parasite gained 1 virus counter at start of Runner turn")
         (is (= 6 (:current-strength (refresh wrap))) "Wraparound reduced to 6 strength")))))
+
+(deftest parasite-hivemind-instant-ice-trash
+  "Parasite - Use Hivemind counters when installed; instantly trash ICE if counters >= ICE strength"
+  (do-game
+    (new-game (default-corp [(qty "Enigma" 3) (qty "Hedge Fund" 3)])
+              (default-runner [(qty "Parasite" 1) (qty "Grimoire" 1) (qty "Hivemind" 1) (qty "Sure Gamble" 1)]))
+    (play-from-hand state :corp "Enigma" "HQ")
+    (let [enig (get-in @state [:corp :servers :hq :ices 0])]
+      (core/rez state :corp enig)
+      (take-credits state :corp)
+      (play-from-hand state :runner "Sure Gamble")
+      (play-from-hand state :runner "Grimoire")
+      (play-from-hand state :runner "Hivemind")
+      (let [hive (get-in @state [:runner :rig :program 0])]
+        (is (= 2 (:counter (refresh hive))) "Hivemind has 2 counters")
+        (play-from-hand state :runner "Parasite")
+        (prompt-select :runner enig)
+        (is (= 1 (count (:discard (get-corp)))) "Enigma trashed instantly")
+        (is (= 4 (:memory (get-runner))))
+        (is (= 2 (count (:discard (get-runner)))) "Parasite trashed when Enigma was trashed")))))
+
+(deftest parasite-ice-trashed
+  "Parasite - Trashed along with host ICE when its strength has been reduced to 0"
+  (do-game
+    (new-game (default-corp [(qty "Enigma" 3) (qty "Hedge Fund" 3)])
+              (default-runner [(qty "Parasite" 3) (qty "Grimoire" 1)]))
+    (play-from-hand state :corp "Enigma" "HQ")
+    (let [enig (get-in @state [:corp :servers :hq :ices 0])]
+      (core/rez state :corp enig)
+      (take-credits state :corp)
+      (play-from-hand state :runner "Grimoire")
+      (play-from-hand state :runner "Parasite")
+      (prompt-select :runner enig)
+      (let [psite (first (:hosted (refresh enig)))]
+        (is (= 1 (:counter (refresh psite))) "Parasite has 1 counter")
+        (is (= 1 (:current-strength (refresh enig))) "Enigma reduced to 1 strength")
+        (take-credits state :runner)
+        (take-credits state :corp)
+        (is (= 1 (count (:discard (get-corp)))) "Enigma trashed")
+        (is (= 1 (count (:discard (get-runner)))) "Parasite trashed when Enigma was trashed")))))

 (deftest progenitor-host-hivemind
   "Progenitor - Hosting Hivemind, using Virus Breeding Ground. Issue #738"


mobile yelp url

mobile yelp url

--- src/cljs/montheway/mmodern.cljs
+++ src/cljs/montheway/mmodern.cljs
@@ -50,7 +50,8 @@
        [:div
         {:class "media-body"}
         [:h4
-         [:a {:href (:url biz)}
+         [:a {:href (str "yelp:///biz/"
+                         (last (clojure.string/split (:url biz) #"/")))}
           (str (:id biz) ". " (:name biz))]]
         [:table {:class "table table-condensed"}
          [:tbody


Rendering optimization

Rendering optimization

--- src/cljs/todogo_cljs/views.cljs
+++ src/cljs/todogo_cljs/views.cljs
@@ -18,14 +18,14 @@
         todo-list-title (re-frame/subscribe [:todo-list-title])]
     (fn []
       [:div {:class "base-container"}
-       (c/nav-bar @main-menu-visible)
+       [c/nav-bar @main-menu-visible]
        [:div {:class "container"}
-        [:div {:class "col-12 "}
-         (c/bread-crumbs
-           [[:span [:span {:class "fa fa-lg fa-home"}]]])]
+        [:div {:class "col-12"}
+         [c/bread-crumbs
+           [[:span [:span {:class "fa fa-lg fa-home"}]]]]]
         [:div {:class "col-lg-4 col-md-4"}
-         (c/create-todo-list-form @todo-list-title)
-         (c/todo-lists @lists)]]
+         [c/create-todo-list-form @todo-list-title]
+         [c/todo-lists @lists]]]
        c/footer])))

 (defn todo-list-panel []
@@ -37,18 +37,18 @@
         todo-list-title (re-frame/subscribe [:todo-list-title])]
     (fn []
       [:div {:class "base-container"}
-       (c/nav-bar @main-menu-visible)
+       [c/nav-bar @main-menu-visible]
        [:div {:class "container"}
-        [:div {:class "col-12 "}
-         (c/bread-crumbs
+        [:div {:class "col-12"}
+         [c/bread-crumbs
            [[:a {:href "#/"} [:span {:class "fa fa-lg fa-home"}]]
-            [:span (:title @todo-list)]])]
+            [:span (:title @todo-list)]]]]
         [:div {:class "col-lg-4 col-md-4 hidden-sm hidden-xs"}
-         (c/create-todo-list-form @todo-list-title)
-         (c/todo-lists @lists)]
+         [c/create-todo-list-form @todo-list-title]
+         [c/todo-lists @lists]]
         [:div {:class "col-lg-4 col-md-4"}
-         (c/create-todo-form @todo-list @todo-text)
-         (c/todos @todos)]
+         [c/create-todo-form @todo-list @todo-text]
+         [c/todos @todos]]
         [:div {:class "col-lg-4 col-md-4 hidden-sm hidden-xs"}]]
        c/footer])))

@@ -63,28 +63,28 @@
         todo-list-title (re-frame/subscribe [:todo-list-title])]
     (fn []
       [:div {:class "base-container"}
-       (c/nav-bar @main-menu-visible)
+       [c/nav-bar @main-menu-visible]
        [:div {:class "container"}
-        [:div {:class "col-12 "}
-         (c/bread-crumbs
+        [:div {:class "col-12"}
+         [c/bread-crumbs
            [[:a {:href "#/"} [:span {:class "fa fa-lg fa-home"}]]
             [:a {:href (str "#/lists/" (:id @todo-list))} (:title @todo-list)]
-            [:span (:title @todo)]])]
+            [:span (:title @todo)]]]]
         [:div {:class "col-lg-4 col-md-4 hidden-sm hidden-xs"}
-         (c/create-todo-list-form @todo-list-title)
-         (c/todo-lists @lists)]
+         [c/create-todo-list-form @todo-list-title]
+         [c/todo-lists @lists]]
         [:div {:class "col-lg-4 col-md-4 hidden-sm hidden-xs"}
-         (c/create-todo-form @todo-list @todo-text)
-         (c/todos @todos)]
+         [c/create-todo-form @todo-list @todo-text]
+         [c/todos @todos]]
         [:div {:class "col-lg-4 col-md-4"}
-         (c/edit-todo-form @todo)]]
+         [c/edit-todo-form @todo]]]
        c/footer])))

 (defn about-panel []
   (let [main-menu-visible (re-frame/subscribe [:main-menu-visible])]
     [:div {:class "base-container"}
-     (c/nav-bar @main-menu-visible)
+     [c/nav-bar @main-menu-visible]
      [:div {:class "container"}
       [:h2 "Sign in page"]
       [:div [:a {:href "#/"} "go to the home page"]]]
@@ -95,9 +95,9 @@
         user-login (re-frame/subscribe [:user-login])
         form-errors (re-frame/subscribe [:form-errors])]
     [:div {:class "base-container"}
-     (c/nav-bar @main-menu-visible)
+     [c/nav-bar @main-menu-visible]
      [:div {:class "container"}
-      (c/sign-in-form @user-login @form-errors)]
+      [c/sign-in-form @user-login @form-errors]]
      c/footer]))

 (defn sign-up-panel []
@@ -105,9 +105,9 @@
         user-login (re-frame/subscribe [:user-login])
         form-errors (re-frame/subscribe [:form-errors])]
     [:div {:class "base-container"}
-     (c/nav-bar @main-menu-visible)
+     [c/nav-bar @main-menu-visible]
      [:div {:class "container"}
-      (c/sign-up-form @user-login @form-errors)]
+      [c/sign-up-form @user-login @form-errors]]
      c/footer]))


Removed extra whitespace

Removed extra whitespace

--- src/cljs/zetawar/events/ui.cljs
+++ src/cljs/zetawar/events/ui.cljs
@@ -218,7 +218,7 @@
   (let [game (app/current-game db)
         cur-faction-color (game/current-faction-color game)
         [repairer-q repairer-r] (app/selected-hex db)
-        [wounded-q  wounded-r]  (app/targeted-hex db)]
+        [wounded-q wounded-r] (app/targeted-hex db)]
     {:dispatch [[:zetawar.events.game/execute-action
                  {:action/type :action.type/repair-other-unit
                   :action/faction-color cur-faction-color


Added more policy definitions, to ensure the macros are expanding properly.  Looking good\!

--- src/clojure/alfresco/behave.clj
+++ src/clojure/alfresco/behave.clj
@@ -1,5 +1,6 @@
 ;
 ; Copyright (C) 2011,2012 Carlo Sciolla
+;               2014      Peter Monks rewritten around fn-generating macros
 ;
 ; Licensed under the Apache License, Version 2.0 (the "License");
 ; you may not use this file except in compliance with the License.
@@ -20,36 +21,23 @@
   (:import [org.alfresco.repo.policy JavaBehaviour
                                      Behaviour$NotificationFrequency]))

-;; no static String to use here, unfortunately
+;; Not available from the ServiceRegistry, unfortunately...
 (defn policy-component
   []
   (c/get-bean "policyComponent"))

-(comment
-(defn- bind-class-behaviour!
-  [policy-qname binding-type-qname behaviour]
-  (.bindClassBehaviour (policy-component)
-                       policy-qname
-                       (m/qname binding-type-qname)
-                       behaviour)
-  nil)
-)
-
-(def ^:private policies
-  [
-    ['on-add-aspect!  org.alfresco.repo.node.NodeServicePolicies$OnAddAspectPolicy  'onAddAspect  '[node qname]]
-    ['on-create-node! org.alfresco.repo.node.NodeServicePolicies$OnCreateNodePolicy 'onCreateNode '[child-assoc-ref]]
-  ])
-
-(defmacro ^:private gen-behaviour-registration-fn
+(defmacro ^:private gen-policy-registration-fn
+  "Generates a registration function for an Alfresco policy.
+  fn-name:       the name of the generated Clojure function
+  policy-if:     the Alfresco interface of the selected policy
+  policy-method: the Java method in that interface that needs to be implemented by the custom behaviour
+  params:        the parameters that method takes"
   [fn-name policy-if policy-method params]
-;  `(def ~fn-name
   `(defn ~fn-name
      ~(str "Registers the function f as a handler for behaviour " policy-if
-           ", for the given qname. f must accept " (count params)
-           " parameters: " (clojure.string/join ", " params)
+           ", for the given qname. f must accept parameters: "
+           "[" (clojure.string/join " " params) "]"
            "\nNote: Handlers only fire on transaction commit.")
-;     (fn [~'qname ~'f]
      [~'qname ~'f]
      (let [p# (reify ~policy-if
                 (~policy-method [~'this ~@params]
@@ -61,64 +49,41 @@
                             ~(symbol (str policy-if "/QNAME"))
                             (m/qname ~'qname)
                             b#)
-       nil)));)
+       nil)))

-(gen-behaviour-registration-fn on-add-aspect!  org.alfresco.repo.node.NodeServicePolicies$OnAddAspectPolicy  onAddAspect  [node qname])
-(gen-behaviour-registration-fn on-create-node! org.alfresco.repo.node.NodeServicePolicies$OnCreateNodePolicy onCreateNode [child-assoc-ref])
+(defn- third
+  "The third item in the given collection."
+  [col]
+  (first (next (next col))))

-(comment
-(defmacro ^:private gen-behaviour-registration-fns
+(defn- fourth
+  "The fourth item in the given collection."
+  [col]
+  (first (next (next (next col)))))
+
+(def ^:private policies
+  "A list of all of the Alfresco policies supported by lambdalf.  This list is used by the macro below to
+  generate the various registration methods and Alfresco Java API interop boilerplate."
+  [
+    ;clojure-fn-name        alfresco-policy-class                                                policy-method       policy-method-parameters
+    ['on-create-node!       'org.alfresco.repo.node.NodeServicePolicies$OnCreateNodePolicy       'onCreateNode       '[child-assoc-ref]]
+    ['on-update-node!       'org.alfresco.repo.node.NodeServicePolicies$OnUpdateNodePolicy       'onUpdateNode       '[node]]
+    ['on-move-node!         'org.alfresco.repo.node.NodeServicePolicies$OnMoveNodePolicy         'onMoveNode         '[old-child-assoc-ref new-child-assoc-ref]]
+    ['on-update-properties! 'org.alfresco.repo.node.NodeServicePolicies$OnUpdatePropertiesPolicy 'onUpdateProperties '[node before-props after-props]]
+    ['on-delete-node!       'org.alfresco.repo.node.NodeServicePolicies$OnDeleteNodePolicy       'onDeleteNode       '[child-assoc-ref is-node-archived?]]
+    ['on-restore-node!      'org.alfresco.repo.node.NodeServicePolicies$OnRestoreNodePolicy      'onRestoreNode      '[child-assoc-ref]]
+
+    ['on-add-aspect!        'org.alfresco.repo.node.NodeServicePolicies$OnAddAspectPolicy        'onAddAspect        '[node aspect-qname]]
+    ['on-remove-aspect!     'org.alfresco.repo.node.NodeServicePolicies$OnRemoveAspectPolicy     'onRemoveAspect     '[node aspect-qname]]
+  ])
+
+(defmacro ^:private gen-policy-registration-fns
+  "Generates all policy registration fns defined in the 'policies' vector."
   []
   `(do ~@(for [policy policies]
-           (let [fn-name#          (first policy)
-                 interface#        (first (next policy))
-                 interface-method# (first (next (next policy)))
-                 args#             (first (next (next (next policy))))]
-             `(println fn-name# interface# interface-method# args#)))))
-;           `(gen-behaviour-registration-fn ~fn-name#
-;                                           ~interface#
-;                                           ~interface-method#
-;                                           ~args#)))))
+           `(gen-policy-registration-fn ~(first  policy)
+                                        ~(second policy)
+                                        ~(third  policy)
+                                        ~(fourth policy)))))

-(gen-behaviour-registration-fns)
-)
-
-
-
-
-
-
-;####TODO: consider adding 3-arity version that receives a notification frequency (perhaps as a keyword?)
-(comment
-(defn on-add-aspect!
-  "Registers the given function f as the handler for the onAddAspect policy of the given QName.
-   The function f must accept 2 parameters:
-   1. NodeRef
-   2. QName"
-  [qname f]
-  (let [p (reify NodeServicePolicies$OnAddAspectPolicy
-            (onAddAspect [this node-in qname-in]
-              (f node-in (m/qname-str qname-in))))
-        b (JavaBehaviour. p
-                          "onAddAspect"
-                          Behaviour$NotificationFrequency/TRANSACTION_COMMIT)]
-    (bind-class-behaviour! NodeServicePolicies$OnAddAspectPolicy/QNAME qname b)))
-)
-
-;####TODO: consider adding 3-arity version that receives a notification frequency (perhaps as a keyword?)
-(comment
-(defn on-create-node!
-  "Registers the given function f as the handler for the onCreateNode policy of the given QName.
-   The function f must accept 1 parameter:
-   1. ChildAssociationRef"
-   [qname f]
-   (let [p (reify NodeServicePolicies$OnCreateNodePolicy
-             (onCreateNode [this child-assoc-ref]
-               (f child-assoc-ref)))
-         b (JavaBehaviour. p "onCreateNode" Behaviour$NotificationFrequency/TRANSACTION_COMMIT)]
-    (bind-class-behaviour! NodeServicePolicies$OnCreateNodePolicy/QNAME qname b)))
-)
-
-; ####TODO: add fns for other policy types
-; OR (better)
-; generate the functions somewhat like https://github.com/xsc/jansi-clj/blob/master/src/jansi_clj/core.clj#L104
+(gen-policy-registration-fns)


Fix minor inconsistences introduced in previous commit on hash namespace.

--- src/clojure/buddy/core/hash.clj
+++ src/clojure/buddy/core/hash.clj
@@ -55,8 +55,8 @@
       buffer))

   String
-  (make-digest [^String input ^keying alg]
-    (make-digest (->byte-array input) algorithm))
+  (make-digest [^String input ^Keyword alg]
+    (make-digest (->byte-array input) alg))

   java.io.InputStream
   (make-digest [^java.io.InputStream input ^Keyword alg]


SELECT imap command now clears /Recent flags and has been refactored to be more clear.

--- src/clojure/neveragain/imap.clj
+++ src/clojure/neveragain/imap.clj
@@ -103,6 +103,11 @@
                          tags.name = \"\\Recent\" AND
                          messages.recipient_id = ?;")

+(def clear-recent-sql "DELETE FROM tags
+                       WHERE
+                         owner_id = ? AND
+                         name = \"\\Recent\";")
+
 ; All messages in a box without the \Seen tag on them
 (def unread-count-sql "SELECT COUNT(*) AS count FROM messages
                        LEFT OUTER JOIN tags ON
@@ -142,21 +147,31 @@
            {:response "NO That's not your mailbox."
             :session session}
          :else
-          {:response
-            [(str (:count (first (j/query db [inbox-count-sql
-                                              (:id selected-user)])))
-                  " EXISTS")
-             (str (:count (first (j/query db [recent-count-sql
-                                              (:id selected-user)])))
-                  " RECENT")
-             (format "OK [UNSEEN %d]"
-                     (:seq_num (first (j/query db [first-unread-seq-num-sql
-                                                   (:id selected-user)]))))
-             (format "FLAGS (%s)"
-                     (string/join ", "
-                       (map :name
-                            (j/query db [flags-in-mailbox
-                                         (:id selected-user)]))))
-             "OK SELECT command complete"]
-           :session (assoc session :selected-box selected-user) })))))
+           (let [user-id (:id selected-user)
+                 exists-count (->> [inbox-count-sql user-id]
+                                   (j/query db)
+                                   first
+                                   :count)
+                 recent-count (->> [recent-count-sql user-id]
+                                   (j/query db)
+                                   first
+                                   :count)
+                 unseen-seq-num (->> [first-unread-seq-num-sql user-id]
+                                     (j/query db)
+                                     first
+                                     :seq_num)
+                 flags-list (->> [flags-in-mailbox user-id]
+                                 (j/query db)
+                                 (map :name)
+                                 (string/join ", "))]
+             ; We just told the user about all those messages, so clear the
+             ; /Recent flags
+             (j/execute! db [clear-recent-sql user-id])

+             ; And give them our response
+             {:response [(format "%d EXISTS" exists-count)
+                         (format "%d RECENT" recent-count)
+                         (format "OK [UNSEEN %d]" unseen-seq-num)
+                         (format "FLAGS (%s)" flags-list)
+                         "OK SELECT command complete"]
+              :session (assoc session :selected-box selected-user) }))))))


Made FETCH field parsing CFG recognize subfields.

--- src/clojure/neveragain/imap.clj
+++ src/clojure/neveragain/imap.clj
@@ -350,24 +350,38 @@
      :number #{:diget '(:diget :number)}
      :bound #{\* :number}}})

+(def long-args "1 (INTERNALDATE UID RFC822.SIZE FLAGS BODY.PEEK[HEADER.FIELDS (date subject from to cc message-id in-reply-to references x-priority x-uniform-type-identifier x-universally-unique-identifier received-spf x-spam-status x-spam-flag)])")
+
 (def fetch-fields-grammar
   {:start-symbol :S
    :prod-rules {
      :S #{:field-name '(\( :WSP :field-name+ :WSP \))}
-     :field-name+ #{'(:field-name :WSP :field-name+) :field-name}
+     :field-name+ #{'(:field-name :WSP :field-name+) :ε}
      :field-name #{"BODY" :ebody :pbody "ENVELOPE" "FLAGS" "INTERNALDATE" "UID"
                    "RFC822" "RFC822.HEADER" "RFC822.SIZE" "RFC822.TEXT"}
-     :ebody #{'("BODY[" :section+ \])}
-     :pbody #{'("BODY.PEAK[" :section+ \])}
-     :section+ #{'(:section :section+) :section}
-     :section #{"HEADER" "TEXT" "MIME" :header-fields}
-     :header-fields #{}
-     :WSP #{'(\space :WSP) '(\tab :WSP) :ε}}})
+     :ebody #{(-> (seq "BODY[") (list :section+ \]) (flatten))}
+     :pbody #{(-> (seq "BODY.PEEK[") (list :section+ \]) (flatten))}
+     :section+ #{'(:section :WSP :section+) :section}
+     :section #{"HEADER" "TEXT" "MIME" :header-fields}
+     :header-fields #{(-> "HEADER.FIELDS"
+                          seq (list :WSP \( :hfield+ \)) flatten)}
+     :hfield+ #{'(:hfield :WSP :hfield+) :ε}
+     :hfield #{:atext+}
+     :atext+ #{'(:atext :atext+) :atext}
+     :atext (set-lib/union (set (map char (concat (range 48 58)
+                                                  (range 65 90)
+                                                  (range 97 122))))
+                           #{\! \# \$ \% \& \' \* \- \/
+                             \= \? \^ \_ \` \{ \| \} \~})
+     :WSP #{:ε '(\space :WSP) '(\tab :WSP)}}})

 (def fetch-range-pda (pp/cfg-to-ndpda fetch-range-grammar))
-(def fetch-fields-pda (pp/cfg-to-ndpda fetch-fields-grammar))
-
-;(clojure.pprint/pprint (pp/expand-strings fetch-fields-grammar))
+(def fetch-fields-pda (-> fetch-fields-grammar
+                          (pp/expand-strings)
+                          (pp/cfg-to-ndpda)))
+
+;(clojure.pprint/pprint fetch-fields-pda)
+

 (defn parseInt [x] (Integer/parseInt x))

@@ -443,10 +457,12 @@
       nil ; Args list is too long, something is wrong
       [(|_|n54ƒ3 seq-nums (if UID "id" "seq_num"))
        (let [[valid captured] (pp/parse fetch-fields-pda item-names
-                                        #{:field-name})]
+                                        #{:field-name :hfield :section})]
          (pp/extract item-names captured))])))

-(def long-args "1 (INTERNALDATE UID RFC822.SIZE FLAGS BODY.PEEK[HEADER.FIELDS (date subject from to cc message-id in-reply-to references x-priority x-uniform-type-identifier x-universally-unique-identifier received-spf x-spam-status x-spam-flag)])")
+;(def long-args "1 (INTERNALDATE UID RFC822.SIZE FLAGS BODY.PEEK[HEADER.FIELDS (date subject from to cc message-id in-reply-to references x-priority x-uniform-type-identifier x-universally-unique-identifier received-spf x-spam-status x-spam-flag)])")
+
+;(def long-args "1 (INTERNALDATE UID RFC822.SIZE BODY.PEEK[MIME HEADER.FIELDS(date)])")

 ;(clojure.pprint/pprint (last (parse-fetch-args long-args)))


load tools into the right place

load tools into the right place

--- src/clojure/staircase/tasks.clj
+++ src/clojure/staircase/tasks.clj
@@ -29,7 +29,7 @@
     (doseq [tool-name names
             :let [tool-settings (settings tool-name)
                   repo-uri  (:uri tool-settings)
-                  repo-path (str "tools/" (name tool-name))
+                  repo-path (str "resources/tools/" (name tool-name))
                   options   (or (:options tool-settings) {})]]
       (info "Updating" repo-path "from" repo-uri "with options:" (prn-str options))
       (let [repo         (load-or-clone repo-uri repo-path options)


logging improvements

logging improvements

--- src/babel/forest.clj
+++ src/babel/forest.clj
@@ -110,12 +110,26 @@
                                 (string/join ","
                                              (map morph
                                                   result))))
-                          (log/debug (str "results of attaching lexemes to: " (get-in parent [:rule]) ":"
-                                          (string/join ","
-                                                       (map #(wrapped-morph morph %1)
-                                                            result))))
+                          (if (empty? result)
+                            (log/warn (str "failed to attach any lexemes to: " (get-in parent [:rule])))
+                            (log/debug (str "results of attaching lexemes to: " (get-in parent [:rule]) ":"
+                                            (string/join ","
+                                                         (map #(wrapped-morph morph %1)
+                                                              result)))))
                           result)))
                     candidate-parents)
+
+            phrasal-children-candidates
+            (lightning-bolt grammar lexicon
+                            (get-in parent [:head])
+                            (+ 1 depth)
+                            index parent morph)
+
+            debug (if (empty? phrasal-children-candidates)
+                    (log/warn (str "NO PHRASAL CANDIDATES FOUND FOR candidate-parents: "
+                                   (string/join ","
+                                                (map #(get-in % [:rule]) candidate-parents)))))
+
             phrasal ;; 2. generate list of all phrases where the head child of each parent is itself a phrase.
             ;; recursively call lightning-bolt with (+ 1 depth).
             (if (< depth maxdepth)


[#8072] Fix crash on deleting group chat

--- src/status_im/ui/screens/profile/group_chat/views.cljs
+++ src/status_im/ui/screens/profile/group_chat/views.cljs
@@ -97,7 +97,7 @@
             current-pk   [:account/public-key]]
     (when current-chat
       (let [shown-chat            (merge current-chat changed-chat)
-            admin?                (admins current-pk)
+            admin?                (get admins current-pk)
             allow-adding-members? (and admin?
                                        (< (count members) constants/max-group-chat-participants))]
         [react/view profile.components.styles/profile


fix initializing database from environment

--- src/babel/korma.clj
+++ src/babel/korma.clj
@@ -120,8 +120,9 @@
                                  url)

                            (env :database-url)
-                           (log/info (str "using environment's DATABASE_URL:"
-                                          (env :database-url)))
+                           (do (log/info (str "using environment's DATABASE_URL:"
+                                              (env :database-url)))
+                               (env :database-url))

                            true (do (log/info
                                      (str "using default database url:"


more logging

more logging

--- src/babel/over.cljc
+++ src/babel/over.cljc
@@ -55,7 +55,10 @@
     (let [result (unify (copy parent)
                         {:head (copy head)})]
       (if (not (= :fail result))
-        (list result)))))
+        (list result)
+        (log/debug (str "fail-path:" (dag_unify.core/fail-path
+                                      (copy parent)
+                                      {:head (copy head)})))))))

 (defn overc [parent comp]
   "add given child as the complement of the parent"


redefine constant to use (pmap) rather than (map) in most places

--- src/babel/over.cljc
+++ src/babel/over.cljc
@@ -16,7 +16,7 @@
 ;; using (get-fail-path) is one example.

 ;; use map or pmap.
-(def ^:const mapfn map)
+(def ^:const mapfn pmap)

 ;; tree-building functions: useful for developing grammars.
 (defn into-list-of-maps [arg]


Fix bug in generating method signatures for Java bridge

The handling of & was incorrect, and resulted in duplicate
method signatures.

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

--- src/conexp/contrib/java.clj
+++ src/conexp/contrib/java.clj
@@ -51,8 +51,7 @@
     arglist
     (let [[a b] (split-with #(not= '& %) arglist)]
       (if (not-empty b)
-        `(vec (list* ~@(map dissect-arglist a)
-                     ~(dissect-arglist (second b))))
+        (vec (concat (map dissect-arglist a) (list (with-meta (second b) {:tag "[Ljava.lang.Object;"}))))
         (vec (map dissect-arglist arglist))))))

 (defn- function-signatures
@@ -69,12 +68,10 @@
                          Lattice conexp.fca.lattices.Lattice
                          Context conexp.fca.contexts.Context
                          tag))))]
-    (if-not arglists
-      nil
-      (for [arglist arglists]
-        [new-name
-         (vec (map tag (dissect-arglist arglist)))
-         return]))))
+    (for [arglist arglists]
+      [new-name
+       (vec (map tag (dissect-arglist arglist)))
+       return])))

 (defn- generate-definition
   "Generates function definition with name new-name, calling orig-name
@@ -83,9 +80,8 @@
   (when (not-empty arglists)
     `(defn ~(symbol (str prefix new-name))
        ~@(for [args arglists]
-           (let [arglist-split (dissect-arglist args)]
-             `(~args
-               (apply ~(symbol orig-name) ~(dissect-arglist args))))))))
+           `(~(dissect-arglist args)
+             (apply ~(symbol orig-name) ~(dissect-arglist args)))))))

 ;;;