better copy for info overlay about precursor

--- src-cljs/frontend/components/app.cljs
+++ src-cljs/frontend/components/app.cljs
@@ -194,17 +194,19 @@
                  [:article {:on-click #(.stopPropagation %)}
                   [:h1 "What's this?"]
                   [:p
-                   "Precursor is a collaborative idea tool. "
-                   "Think of it as a notebook with infinite pages – use it to create sketches, "
-                   "rapid prototypes, notes, and everything in between. "
-                   "Share your URL to collaborate and you'll instantly have multiple people "
-                   "working in the same document. "
-                   "It's still a work in progress, so if you have feedback or a great idea "
-                   "for us sketch it up and ping "
+                   "Precursor is a no nonsense prototyping tool. "
+                   "Think of it like a notebook with infinite pages—"
+                   "use it for simple sketching, rapid prototyping, team brainstorming, or just sharing ideas. "
+                   "Share your url or "
+                   [:a {:href "#"} "send invites"]
+                   " and you'll instantly have multiple people collaborating in real-time. "
+                   "Precursor is still young so if you have feedback or a great idea, sketch it up or type it out and ping "
                    [:a {:on-click #(cast! :chat-link-clicked)
                         :role "button"}
                     "@prcrsr"]
-                   " in the chat."]
+                   " in the chat. Or say "
+                   [:a {:href "mailto:hi@prcrsr.com?Subject=I%20have%20feedback"}
+                    "hi@prcrsr.com"]]
                   [:div.info-buttons
                    [:button.info-okay {:on-click #(cast! :overlay-info-toggled)}
                     "Okay, sounds good."]
@@ -212,7 +214,7 @@
                                      :on-click #(analytics/track "Twitter link clicked" {:location "info overlay"})
                                      :title "Keep track of our changes on Twitter."
                                      :target "_blank"}
-                    "What should we add next?"]]]
+                    "Tell us what to add next."]]]
                  (common/mixpanel-badge)]
                 [:figure.overlay-shortcuts {:on-click #(cast! :overlay-closed)
                                             :class (when-not overlay-shortcuts-open? "hidden")}


Move `inner?` definition to existing let.

--- src-cljs/frontend/components/app.cljs
+++ src-cljs/frontend/components/app.cljs
@@ -1,44 +1,46 @@
 (ns frontend.components.app
-  (:require [cljs.core.async :as async :refer [>! <! alts! chan sliding-buffer close!]]
+  (:require [ankha.core :as ankha]
+            [cljs.core.async :as async :refer [>! <! alts! chan sliding-buffer close!]]
+            [clojure.string :as string]
+            [frontend.api :as api]
             [frontend.async :refer [raise!]]
+            [frontend.components.about :as about]
             [frontend.components.account :as account]
-            [frontend.components.about :as about]
+            [frontend.components.add-projects :as add-projects]
             [frontend.components.admin :as admin]
             [frontend.components.aside :as aside]
             [frontend.components.build :as build-com]
+            [frontend.components.changelog :as changelog]
+            [frontend.components.common :as common]
             [frontend.components.dashboard :as dashboard]
             [frontend.components.documentation :as docs]
-            [frontend.components.features :as features]
-            [frontend.components.mobile :as mobile]
-            [frontend.components.press :as press]
-            [frontend.components.add-projects :as add-projects]
-            [frontend.components.insights :as insights]
-            [frontend.components.invites :as invites]
-            [frontend.components.changelog :as changelog]
             [frontend.components.enterprise :as enterprise]
             [frontend.components.enterprise-landing :as enterprise-landing]
             [frontend.components.errors :as errors]
+            [frontend.components.features :as features]
             [frontend.components.footer :as footer]
             [frontend.components.header :as header]
+            [frontend.components.insights :as insights]
             [frontend.components.inspector :as inspector]
             [frontend.components.integrations :as integrations]
+            [frontend.components.invites :as invites]
             [frontend.components.jobs :as jobs]
             [frontend.components.key-queue :as keyq]
+            [frontend.components.landing :as landing]
+            [frontend.components.language-landing :as language-landing]
+            [frontend.components.mobile :as mobile]
+            [frontend.components.opt-in :as opt-in]
+            [frontend.components.org-settings :as org-settings]
             [frontend.components.placeholder :as placeholder]
+            [frontend.components.press :as press]
             [frontend.components.pricing :as pricing]
             [frontend.components.privacy :as privacy]
             [frontend.components.project-settings :as project-settings]
             [frontend.components.security :as security]
             [frontend.components.shared :as shared]
+            [frontend.components.signup :as signup]
             [frontend.components.stories :as stories]
-            [frontend.components.language-landing :as language-landing]
-            [frontend.components.landing :as landing]
-            [frontend.components.org-settings :as org-settings]
-            [frontend.components.opt-in :as opt-in]
-            [frontend.components.common :as common]
             [frontend.components.top-nav :as top-nav]
-            [frontend.components.signup :as signup]
-            [frontend.api :as api]
             [frontend.config :as config]
             [frontend.instrumentation :as instrumentation]
             [frontend.models.feature :as feature]
@@ -47,8 +49,7 @@
             [frontend.utils :as utils :include-macros true]
             [frontend.utils.seq :refer [dissoc-in]]
             [om.core :as om :include-macros true]
-            [om.dom :as dom :include-macros true]
-            [ankha.core :as ankha])
+            [om.dom :as dom :include-macros true])
   (:require-macros [frontend.utils :refer [html]]))

 (def keymap
@@ -126,17 +127,17 @@
               ;; simple optimzation for real-time updates when the build is running
               app-without-container-data (dissoc-in app state/container-data-path)
               dom-com (dominant-component app owner)
-              project (get-in app state/project-path)]
+              project (get-in app state/project-path)
+              inner? (get-in app state/inner?-path)]
           (reset! keymap {["ctrl+s"] persist-state!
                           ["ctrl+r"] restore-state!})
           (html
-           (let [inner? (get-in app state/inner?-path)]
-
-             [:div#app {:class (concat [(if inner? "inner" "outer")]
-                                       (when-not logged-in? ["aside-nil"])
-                                       (if (feature/enabled? :ui-v2) ["ui-v2"] ["ui-v1"])
-                                       ;; The following is meant for the landing ab test to hide old header/footer
-                                       (when (= :pricing (:navigation-point app)) ["pricing"]))}
+           [:div#app {:class (string/join " "
+                               (cond-> [(if inner? "inner" "outer")
+                                        (if (feature/enabled? :ui-v2) "ui-v2" "ui-v1")]
+                                 (not logged-in?) (conj "aside-nil")
+                                 ;; The following is meant for the landing ab test to hide old header/footer
+                                 (= :pricing (:navigation-point app)) (conj "pricing")))}
               (om/build keyq/KeyboardHandler app-without-container-data
                         {:opts {:keymap keymap
                                 :error-ch (get-in app [:comms :errors])}})
@@ -181,7 +182,7 @@
                     (footer/footer)])]]

                 (when (and (config/help-tab-enabled?) (not logged-in?))
-                  (om/build shared/sticky-help-link app))]])))))))
+                  (om/build shared/sticky-help-link app))]]))))))

 (defn app [app owner opts]


Bumps version to 1.48.4-SNAPSHOT

Bumps version to 1.48.4-SNAPSHOT

--- scheduler/project.clj
+++ scheduler/project.clj
@@ -13,7 +13,7 @@
 ;; See the License for the specific language governing permissions and
 ;; limitations under the License.
 ;;
-(defproject cook "1.48.3"
+(defproject cook "1.48.4-SNAPSHOT"
   :description "This launches jobs on a Mesos cluster with fair sharing and preemption"
   :license {:name "Apache License, Version 2.0"}
   :dependencies [[org.clojure/clojure "1.8.0"]


Bumping version to 1.45.1-SNAPSHOT

Bumping version to 1.45.1-SNAPSHOT

--- scheduler/project.clj
+++ scheduler/project.clj
@@ -13,7 +13,7 @@
 ;; See the License for the specific language governing permissions and
 ;; limitations under the License.
 ;;
-(defproject cook "1.45.0"
+(defproject cook "1.45.1-SNAPSHOT"
   :description "This launches jobs on a Mesos cluster with fair sharing and preemption"
   :license {:name "Apache License, Version 2.0"}
   :dependencies [[org.clojure/clojure "1.8.0"]


Snapshot version

Snapshot version

--- scheduler/project.clj
+++ scheduler/project.clj
@@ -13,7 +13,7 @@
 ;; See the License for the specific language governing permissions and
 ;; limitations under the License.
 ;;
-(defproject cook "1.12.0"
+(defproject cook "1.12.1-SNAPSHOT"
   :description "This launches jobs on a Mesos cluster with fair sharing and preemption"
   :license {:name "Apache License, Version 2.0"}
   :dependencies [[org.clojure/clojure "1.8.0"]


extending the footer and adding a credits page

--- src-cljs/bitfondue/core.cljs
+++ src-cljs/bitfondue/core.cljs
@@ -109,15 +109,22 @@
   [:div.footer
    [:div.container
     [:div.row
-     [:div.col-md-4
+     [:div.col-md-3
       [:ul
+       [:li [:h6 "Social"]]
        [:li [:a {:href "http://blog.bitfondue.com"} "Blog"]]
-       [:li [:a {:href "https://github.com/bitfondue"} "GitHub"]]]]
-     [:div.col-md-4]
-     [:div.col-md-4
+       [:li [:a {:href "https://github.com/bitfondue"} "GitHub"]]
+       [:li [:a {:href "https://twitter.com/bitfondue"} "Twitter"]]
+       [:li [:a {:href "https://twitter.com/bitfondue"} "Facebook"]]]]
+     [:div.col-md-3
       [:ul
-       [:li [:a {:href "https://twitter.com/bitfondue"} "Twitter"]]
-       [:li [:a {:href "https://twitter.com/bitfondue"} "Facebook"]]]]]]])
+       [:li [:h6 "Legal"]]
+       [:li [:a (nav-helper "/privacy-policy") "Privacy Policy"]]
+       [:li [:a (nav-helper "/terms-of-service") "Terms of Service"]]
+       [:li [:a (nav-helper "/security") "Security"]]
+       [:li [:a (nav-helper "/credits") "Credits"]]]]
+     [:div.col-md-offset-3.col-md-3
+      [:img {:src "/icons/noun_28353_cc.svg"}]]]]])

 (defn layout
@@ -155,6 +162,20 @@
   [layout
    [:div.container [:h1 "About"]]])

+(defn credits []
+  [layout
+   [:div.credits
+    [:div.jumbotron
+     [:div.container
+      [:h1 "Credits"]]]
+    [:div.container
+     [:div.row.section
+      [:div.col-md-12
+       [:h3 "Visuals"]
+       [:ul
+        [:li
+         [:a {:href "https://thenounproject.com/search/?q=%20fondue&i=28353"} "Fondue by Claire Jones from the Noun Project"]
+         [:p "Strawberry icon used in the footer"]]]]]]]])

 (def login-form
   [:div.col-md-offset-3.col-md-6
@@ -231,6 +252,7 @@
 (defroute "/features" [] (page features))
 (defroute "/pricing" [] (page pricing))
 (defroute "/about" [] (page about))
+(defroute "/credits" [] (page credits))
 (defroute "/login" [] (page login))
 (defroute "/register" [] (page register))
 (defroute "*" [] (page not-found))


clean up cljs.core ns form. consistently use gobject alias over goog.object

--- src/main/cljs/cljs/core.cljs
+++ src/main/cljs/cljs/core.cljs
@@ -10,7 +10,7 @@
   (:require [goog.string :as gstring]
             [goog.object :as gobject]
             [goog.array :as garray])
-  (:import goog.string.StringBuffer))
+  (:import [goog.string StringBuffer]))

 ;; next line is auto-generated by the build-script - Do not edit!
 (def *clojurescript-version*)
@@ -1899,7 +1899,7 @@
   "Return the JavaScript keys for an object."
   [obj]
   (let [keys (array)]
-    (goog.object/forEach obj (fn [val key obj] (.push keys key)))
+    (gobject/forEach obj (fn [val key obj] (.push keys key)))
     keys))

 (defn js-delete
@@ -9809,7 +9809,7 @@
     (if (< i (. name -length))
       (recur (inc i)
         (let [c (.charAt name i)]
-          (if-let [sub (goog.object/get CHAR_MAP c)]
+          (if-let [sub (gobject/get CHAR_MAP c)]
             (str ret sub)
             (str ret c))))
       ret)))
@@ -9827,7 +9827,7 @@
             (str ret
               (.substring munged-name last-match-end
                 (- (. r -lastIndex) (. x -length)))
-              (if (= x "$") "/" (goog.object/get DEMUNGE_MAP x)))
+              (if (= x "$") "/" (gobject/get DEMUNGE_MAP x)))
             (. r -lastIndex)))
         (str ret
           (.substring munged-name last-match-end (.-length munged-name)))))))
@@ -9844,8 +9844,8 @@
         (symbol (str name) (str sym)) nil)))
   (findInternedVar [_ sym]
     (let [k (munge (str sym))]
-      (when (goog.object/contains obj k)
-        (Var. #(goog.object/get obj k)
+      (when (gobject/contains obj k)
+        (Var. #(gobject/get obj k)
           (symbol (str name) (str sym)) nil))))
   (getMappings [_]
     @mappings)
@@ -9866,10 +9866,10 @@
             (cond
               (nil? ctxt) nil
               (nil? xs) ctxt
-              :else (recur (goog.object/get ctxt (first xs)) (next xs))))]
+              :else (recur (gobject/get ctxt (first xs)) (next xs))))]
     (if-not js/COMPILED
       (let [segs (-> ns str (.split "."))]
-        (when (goog.object/get (. goog/dependencies_ -nameToPath) (str ns))
+        (when (gobject/get (. goog/dependencies_ -nameToPath) (str ns))
           (condp identical? *target*
             "nodejs" (find-ns* js/global segs)
             "default" (find-ns* js/window segs)
@@ -9883,7 +9883,7 @@
     (letfn [(step [ret k]
               (let [var-sym (symbol (demunge k))]
                 (assoc ret
-                  var-sym (Var. #(goog.object/get ns-obj k)
+                  var-sym (Var. #(gobject/get ns-obj k)
                             (symbol (str sym) (str var-sym)) nil))))]
       (reduce step {} (js-keys ns-obj)))))


Back out previous change, as we need a for (not a doseq) to construct the nested elements

--- src/main/clojure/cascade.clj
+++ src/main/clojure/cascade.clj
@@ -58,9 +58,9 @@
     `(fn ~fn-params (template ~@template-forms)))

 (defmacro template-for
-  "Executes a doseq on the bindings, with the body evaluated as an implicit template."
+  "Executes a for list comprehension on the bindings, with the template forms evaluated as an implicit template."
   [bindings & template-forms]
-  `(doseq ~bindings (template ~@template-forms)))
+  `(combine (for ~bindings (template ~@template-forms))))

 (def #^{:doc "A DOM text node for a line break."}
   linebreak


Расширение функционала dataform

Расширение функционала dataform

--- radiolamp-6P3/src/r6p3/dataform.clj
+++ radiolamp-6P3/src/r6p3/dataform.clj
@@ -124,8 +124,8 @@
 ;;;*
 ;;;**************************************************************************************************

-(defn rbs-data [{{:keys [entitys]} :main-map
-                 {:keys [fields]}  :rbs-sheme}]
+(defn rbs-data [{{:keys [entitys]} :main-map ;;{:keys [fields]}  :rbs-scheme
+                 }]

   (if (empty? entitys) {} ;; если еще не проиниц. пропускаем
       (->> entitys seq
@@ -143,6 +143,32 @@
             {}))))

+(defn rbs-data-as-fields-ids-map
+  [{{:keys [entitys]} :main-map
+    {:keys [fields]}  :rbs-scheme}]
+  (let [rbtype-to-sql-field (reduce-kv
+                             (fn [a field {:keys [rbtype]}]
+                               (assoc a rbtype field))
+                             {} fields)]
+    (if (empty? entitys) {} ;; если еще не проиниц. пропускаем
+        (->> entitys seq
+             (reduce
+              (fn [a [k ent]]
+                (->> (kc/select ent
+                                (kc/fields :id :keyname :rbtype)
+                                (kc/where (not (= :rbtype nil))))
+                     (group-by :rbtype)
+                     (reduce-kv
+                      (fn [a k v]
+                        (assoc a (rbtype-to-sql-field k)
+                               (reduce
+                                (fn [a {:keys [id keyname]}]
+                                  (assoc a id keyname))
+                                {} v)))
+                      a)))
+              {})))))
+
+
 ;;; END Korma tools
 ;;;..................................................................................................

@@ -208,19 +234,3 @@

 (defn fill-row-rb-values [dataform-scheme row]
   (first (fill-rows-rb-values dataform-scheme [row])))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


s/error/warn/: doesn't rise to the level of an error

--- src/babel/forest.cljc
+++ src/babel/forest.cljc
@@ -270,7 +270,7 @@
                               (if (< 0 (- (count complement-candidate-lexemes) 5))
                                 (str ".. and "
                                      (- (count complement-candidate-lexemes) 5) " more."))))]
-                (log/error message)
+                (log/warn message)
 ;                (throw (exception message)))
 )
               (do (log/debug (str "add-complement after adding complement: "


limiting user routes to admin

limiting user routes to admin

--- src/celestial/api.clj
+++ src/celestial/api.clj
@@ -157,7 +157,7 @@
          (success {:msg "new type saved" :type type :opts props})))

 (defroutes app-routes
-  hosts jobs users (route/not-found "Not Found"))
+  hosts jobs (friend/wrap-authorize users #{(sec/roles "admin")}) (route/not-found "Not Found"))

 (defn error-wrap
   "A catch all error handler"


Fix entrypoint so help and version options work

--- src/civil_ci/core.clj
+++ src/civil_ci/core.clj
@@ -10,6 +10,8 @@

 Usage:
   civil-ci [options] <config-path>
+  civil-ci -h | --help
+  civil-ci -v | --version

 Options:
   -h --help                     Show this screen.


* src/clj/cljs/core.clj: wip

* src/clj/cljs/core.clj: wip

--- src/clj/cljs/core.clj
+++ src/clj/cljs/core.clj
@@ -255,7 +255,12 @@
                                                      meths (if ifn?
                                                              (map adapt-params meths)
                                                              meths)]
-                                                 [`(set! ~(symbol pf) (fn ~@meths))]))
+                                                 (if (or ifn? (vector? (first meths))) ;; deal w/ ifn later
+                                                   [`(set! ~(symbol pf) (fn ~@meths))]
+                                                   (map (fn [[sig & body :as meth]]
+                                                          `(set! ~(symbol (str pf "__" (count sig)))
+                                                                 (fn ~meth)))
+                                                        meths))))
                                              sigs)))))]
         `(do ~@(mapcat assign-impls impl-map))))))

@@ -413,8 +418,15 @@
                           ~@sig))))
         method (fn [[fname & sigs]]
                  (let [sigs (take-while vector? sigs)
-                       slot (symbol (str prefix (name fname)))]
-                   `(defn ~fname ~@(map #(expand-sig fname slot %) sigs))))]
+                       slot (symbol (str prefix (name fname)))
+                       arity-name-fn (if (clojure.core/> (count sigs) 1)
+                                       (fn [sym sig] (symbol (str sym "__" (count sig))))
+                                       (fn [sym sig] sym))]
+                   `(defn ~fname ~@(map (fn [sig]
+                                          (expand-sig fname
+                                                      (arity-name-fn slot sig)
+                                                      sig))
+                                        sigs))))]
     `(do
        (def ~psym (~'js* "{}"))
        ~@(map method methods))))


CLJS-1053: REPLs need import special fn

CLJS-1053: REPLs need import special fn

--- src/clj/cljs/repl.clj
+++ src/clj/cljs/repl.clj
@@ -516,6 +516,23 @@
             identity opts)
           (when is-self-require?
             (set! ana/*cljs-ns* restore-ns)))))
+     'import
+     (fn self
+       ([repl-env env form]
+        (self repl-env env form nil))
+       ([repl-env env [_ & specs :as form] opts]
+        (evaluate-form repl-env env "<cljs repl>"
+          (with-meta
+            `(~'ns ~ana/*cljs-ns*
+               (:import
+                 ~@(map
+                     (fn [quoted-spec-or-kw]
+                       (if (keyword? quoted-spec-or-kw)
+                         quoted-spec-or-kw
+                         (second quoted-spec-or-kw)))
+                     specs)))
+            {:merge true :line 1 :column 1})
+          identity opts)))
      'require-macros
      (fn self
        ([repl-env env form]


Add repl restart function helper.

Add repl restart function helper.

--- src/clj/pfrt/main.clj
+++ src/clj/pfrt/main.clj
@@ -33,6 +33,12 @@
 (defn stop []
   (app/stop main-app))

+;; Helper function that executes
+;; stop and start.
+(defn restart []
+  (start)
+  (stop))
+
 ;; Main entry point
 (defn -main
   [& args]


Allow seeding of event logs to sanitize passwords.

This will make it easier to share sanitized event logs for development
with real-life data without compromising sensitive bits.

--- src/clojars/event.clj
+++ src/clojars/event.clj
@@ -61,13 +61,14 @@

 (defn seed
   "Seed event log with initial values from SQLite DB"
-  []
+  [[& sanitize?]]
   (sql/with-connection (config :db)
     (sql/with-query-results groups ["SELECT * FROM groups"]
       (doseq [{:keys [name user]} groups]
         (record :membership {:group name :username user :added-by nil})))
     (sql/with-query-results users ["SELECT * FROM users"]
       (doseq [{:keys [user password email created ssh_key pgp_key]} users]
-        (record :user {:username user :email email :password password
+        (record :user {:username user :email email
+                       :password (or sanitize? password)
                        :ssh-key ssh_key :pgp-key pgp_key
                        :at created :from "sqlite"})))))


working with midi example

working with midi example

--- src/examples/midi.clj
+++ src/examples/midi.clj
@@ -1,37 +1,56 @@
-(ns examples.basic
+(ns examples.midi
   (:use overtone.live))

-; Some of the examples gathered here were found on this page:
-; http://en.wikibooks.org/wiki/Designing_Sound_in_SuperCollider/Print_version
-; which come originally from the book Designing Sound by Andy Farnell.
-
 (refer-ugens)
-
-; When a multiplication is done involving UGen objects, then
-; multiply UGens will be produced with the operands as their
-; inputs.  (Note that synthdefs can have doc strings too.)
-(defsynth pedestrian-crossing
-  "Street crossing in Britain."
-  []
-  (* 0.2 (sin-osc 2500) (lf-pulse 5)))
-
-; You can mix signals by adding them together.  The soundcard can take audio
-; data between -1 and 1, so if you add up signals remember to multiply
-; by a fractional number or else you will have clipping distortion.
-(defsynth trancy-waves [note 40 amp 0.8 gate 1]
-  (* amp (env-gen (perc 0.001 0.5) gate 1 0 1 :free)
-     (rlpf
-        (+ (saw (midicps note))
-        (saw (midicps (+ 9 note)))
-        (sin-osc (midicps (- 12 note))))
-        (midicps note) 0.6)))
-
 (def kb (midi-in "axiom"))

+(defsynth pad [freq 440 vel 0.4 amt 0.3 gate 1.0]
+  (let [vel        (+ 0.5 (* 0.5 vel))
+        env        (env-gen (adsr 0.01 0.1 0.7 0.1) gate 1 0 1 :free)
+        f-env      (env-gen (perc 1 3))
+        src        (saw [freq (* freq 1.01)])
+        signal     (rlpf (* 0.3 src)
+                         (+ (* 0.6 freq) (* f-env 2 freq)) 0.2)
+        k          (/ (* 2 amt) (- 1 amt))
+        distort    (/ (* (+ 1 k) signal) (+ 1 (* k (abs signal))))
+        gate       (pulse (* 2 (+ 1 (sin-osc:kr 0.05))))
+        compressor (compander distort gate 0.01 1 0.5 0.01 0.01)
+        dampener   (+ 1 (* 0.5 (sin-osc:kr 0.5)))
+        reverb     (free-verb compressor 0.5 0.5 dampener)
+        echo       (comb-n reverb 0.4 0.3 0.5)]
+    (* vel env echo)))
+
+(def midi-log* (ref []))
+(def controls* (ref {}))
+(def notes* (ref {}))
+
 (defn midi-player [event ts]
-  (trancy-waves (:note event) (/ (:vel event) 128.0)))
+  (dosync (alter midi-log* conj event))
+  (pad (midi->hz (:note event)) 0.8 (/ (get @controls* 71) 127.0)))

-(midi-handle-events kb midi-player)
+(midi-handle-events kb #'midi-player)
+
+(defn midi-listener [event ts]
+  (println "listener: " event)
+  (try
+    (dosync (alter midi-log* conj event))
+    (condp = (:cmd event)
+      :control-change (dosync (alter controls* assoc (:data1 event) (:data2 event)))
+      :note-on (let [note (:note event)
+                     id   (get @notes* note)]
+                 (if id (ctl id :gate 0))
+                 (dosync (alter notes* assoc note
+                                (pad (midi->hz note)
+                                     (/ (:vel event) 128.0)
+                                     (/ (get @controls* 71) 127.0)))))
+      :note-off (ctl (get @notes* (:note event)) :gate 0)
+      true)
+    (catch java.lang.Exception e (println "midi-listener exception: \n" e))))
+
+(defn control-watcher [ctl-num, _, old-val, new-val]
+  (println ctl-num ":" new-val))
+
+(midi-handle-events kb #'midi-listener)

 (midi-handle-events kb (fn [event ts] (dosync (alter conj mlog* event))))

@@ -43,99 +62,3 @@
                    (send [msg timestamp] (dosync (alter midi-log* conj msg))))]
     (.setReceiver (:transmitter input) receiver)))

-; The functions representing UGens support what's called multi-channel
-; expansion.  What this means is that if pass a collection of N arguments
-; where a single value is expected, then N instances of the UGen will
-; be created, each using the successive values.
-(defsynth dial-tone [freq-a 350 freq-b 440]
-  (apply + (* (sin-osc [freq-a freq-b]) 0.2)))
-
-; Takes an input signal coming in from a selectable bus, and plays it out
-; through a series of filters..
-(defsynth transmission-interference [in-bus 10]
-  (let [sig (clip2 (in in-bus) 0.9)
-        sig (bpf sig 2000 1/12)
-        sig (+ (bpf (* 0.5 sig) 400 1/3)
-               (* (clip2 sig 0.4) 0.15))]
-    (* (hpf (hpf sig 90) 90) 100)))
-
-; Synths can also communicate back to us.  Here we use the send-trig
-; UGen, which sends a "/tr" trigger message every time it gets an
-; input trigger.  The message includes an id number, and the current
-; input value of its last input.
-(on "/tr" #(println "trigger: " %))
-
-(defsynth trigger-finger []
-  (send-trig:kr (impulse:kr 0.2) 200 (sin-osc:kr 1)))
-
-(defn wah-wah [freq depth]
-  (* depth (sin-osc:kr freq)))
-
-(defsynth ticker [freq 2]
-  (* (sin-osc 440) (env-gen (perc 0.1 0.2) (sin-osc:kr freq))))
-
-(defsynth sizzle [bus 0 amp 0.4 depth 10 freq 220 lfo 8]
-  (out bus (* amp (saw (+ freq (wah-wah lfo depth))))))
-
-; It's typical to use a pulse as a sort of on off switch like this.
-(defsynth line-two []
-  (* (sin-osc [480 440]) (lf-pulse 1/6 0 1/3)))
-
-(defsynth busy-signal []
-  (let [on-off (lpf (lf-pulse 2) 100)]
-    (* 0.2
-       (apply + (* (sin-osc [480 620]) on-off)))))
-
-; Need to make a call?
-(def DTMF-TONES {1 [697, 1209]
-                 2 [770, 1209]
-                 3 [852, 1209]
-                 4 [697, 1336]
-                 5 [770, 1336]
-                 6 [852, 1336]
-                 7 [697, 1477]
-                 8 [770, 1477]
-                 9 [852, 1477]
-                 \* [697, 1633]
-                 0 [770, 1633]
-                 \# [852, 1633]})
-
-(defsynth dtmf [freq-a 770 freq-b 1633 gate 1]
-  (let [sig (* 0.2 (+ (sin-osc freq-a) (sin-osc freq-b)))
-        env (env-gen (asr 0.001 1 0.001) gate 1 0 1 :free)]
-    (* sig env)))
-
-(defn dial-number [num-seq]
-  (loop [t (now)
-         nums num-seq]
-    (when nums
-      (let [t-on  (+ t 200 (rand-int 200))
-            t-off (+ t-on 200 (rand-int 80))
-            [a b] (get DTMF-TONES (first nums))]
-        (at t-on (dtmf a b))
-        (at t-off (dtmf :ctl :gate 0))
-        (recur t-off (next nums))))))
-
-; Try this:
-;  (dial-number [2 5 9 3 3 7 7])
-
-;(defsynth two-tone-alarm []
-;  (let [t1 (sin-osc 600)
-;        t2 (sin-osc 800)
-;        ctl (lpf:kr (lf-pulse:kr 2) 70)]
-;           // We switch between the tones using LFPulse, but soften the crossfade with the low-pass:
-;           var control = LPF.kr(LFPulse.kr(2), 70);
-;           var out = SelectX.ar(control, [tone1, tone2]);
-;           Pan2.ar(out * 0.1)
-
-;(defsynth alarm []
-;  (let [freq (duty:kr 0.05 0
-;                freq = Duty.kr(0.05, 0, Dseq([723, 932, 1012], inf));
-;                freq = LPF.kr(freq, 70);
-;                out = SinOsc.ar(freq);
-;                operations = [out, (out * pi).sin, (out * pi).cos, ((out+0.25) * pi).cos];
-;                out = Select.ar(MouseX.kr(0,4).poll, operations);
-;                Pan2.ar(out * 0.1)
-;              }).play
-
-


Fix indenting

Fix indenting

--- src/frontend/core.clj
+++ src/frontend/core.clj
@@ -25,7 +25,7 @@
   (compojure.route/resources "/vendor/font-awesome" {:root "components/font-awesome"
                                                      :mime-types {:svg "image/svg"}})
   (compojure.route/resources "/vendor/material-design-icons" {:root "components/material-design-icons"
-                                                     :mime-types {:svg "image/svg"}})
+                                                              :mime-types {:svg "image/svg"}})
   (compojure.route/resources "/vendor/octicons" {:root "components/octicons"
                                                  :mime-types {:svg "image/svg"}})
   (GET "/docs/manifest-dev.json" []


Remove conf/load from server.clj.

Remove conf/load from server.clj.

--- src/incise/server.clj
+++ src/incise/server.clj
@@ -12,7 +12,6 @@
             [clojure.stacktrace :refer [print-cause-trace]]
             [org.httpkit.server :refer [run-server]]))

-(conf/load)
 (defroutes routes
   (files "/" {:root (conf/get :out-dir)})
   (not-found (html5 [:h1 "404"])))


update function name

update function name

--- src/metabase/core.clj
+++ src/metabase/core.clj
@@ -95,7 +95,7 @@
 (defn init
   "General application initialization function which should be run once at application startup."
   []
-  (log/info (format "Starting Metabase version %s..." (config/mb-version)))
+  (log/info (format "Starting Metabase version %s..." ((config/mb-version-info) :long)))
   ;; First of all, lets register a shutdown hook that will tidy things up for us on app exit
   (.addShutdownHook (Runtime/getRuntime) (Thread. ^Runnable destroy))
   (log/debug "Using Config:\n" (with-out-str (clojure.pprint/pprint config/config-all)))


more second person in docstrings

more second person in docstrings

--- src/mireact/core.cljs
+++ src/mireact/core.cljs
@@ -32,7 +32,7 @@
   (mireact-props (.-props c)))

 (defn transact!
-  "Sets the components state to f applied to its current state and
+  "Set the components state to f applied to its current state and
   args."
   [c f & args]
   (.setState c (fn [react-state _]
@@ -43,8 +43,8 @@
 ;; cases om/set-state! and om/update-state! are used with a single key
 ;; --
 (defn update!
-  "Sets the components state at k to f applied to its current state
-  and args. See also: transact!"
+  "Set the components state at k to f applied to its current state and
+  args. See also: transact!"
   [c k f & args]
   (apply transact! c update k f args))


Only create instrument when needed

Only create instrument when needed

--- src/musicbox/one.cljs
+++ src/musicbox/one.cljs
@@ -112,13 +112,12 @@
         instrument)))

 (defn update-size [instrument canvas-id]
-  (let [{w :w h :h} (util/get-window-size)]
-    (do (util/set-canvas-size! canvas-id w h)
+  (let [{w :w h :h :as window-size} (util/get-window-size)]
+    (do (util/set-canvas-size! canvas-id window-size)
         (.scrollTo js/window 0 0) ;; Safari leaves window part scrolled down after turn
         (assoc (assoc instrument :h h) :w w))))

 (let [canvas-id "canvas"
-      instrument (update-size (create-instrument (scales/c-minor)) canvas-id)
       c-app-state (chan)
       c-instrument (chan)
       c-orientation-change (util/listen js/window :orientation-change)
@@ -131,6 +130,7 @@

   (go
    (let [draw-ctx (util/get-ctx canvas-id)]
+     (util/set-canvas-size! canvas-id (util/get-window-size))
      (draw-start-screen draw-ctx)
      (loop [instrument (<! c-instrument)]
        (let [[data c] (alts! [c-instrument (timeout 30)])]
@@ -141,7 +141,7 @@

   (go
    (<! c-app-state)
-   (loop [instrument instrument]
+   (loop [instrument (update-size (create-instrument (scales/c-minor)) canvas-id)]
      (>! c-instrument instrument)
      (let [[data c] (alts! [c-touch-start c-touch-end
                             c-orientation-change])]
@@ -150,4 +150,5 @@
          (recur (reduce fire-event-on-instrument
                         instrument
                         (touch-data->touches data)))))))
-  )
+
+  )


Correct sha1 computation

Correct sha1 computation

--- src/naughtmq/core.clj
+++ src/naughtmq/core.clj
@@ -35,7 +35,7 @@
   (let [lib-path (str "native/" (arch) "/" (os) "/" lib-name)
         tmp-dir  (io/file (str (System/getProperty "java.io.tmpdir")
                             "/naughtmq/"
-                            (-> lib-path io/resource slurp p/sha1)
+                            (-> lib-path io/resource io/input-stream p/sha1)
                             "/"))
         tmp-path (-> (str tmp-dir "/" lib-name) io/file)]
     (if (not (.exists tmp-dir)) (.mkdirs tmp-dir))


fix site option connection during multiple layout

--- src/one_hyde/core.clj
+++ src/one_hyde/core.clj
@@ -41,7 +41,7 @@
   [parent-option layout-fn]
   (fn [site & contents]
     ((get-layout (:layout parent-option))
-       (merge site parent-option)
+       (merge parent-option site)
        (layout-fn site contents))))

 (defn get-layout


show om post in overview

show om post in overview

--- src/pc/views/blog.clj
+++ src/pc/views/blog.clj
@@ -40,7 +40,7 @@
    Be careful for daylight savings time!"
   [
    {:slug "optimizing-om-apps"
-    :display-in-overview false}
+    :display-in-overview true}
    {:slug "blue-ocean-made-of-ink"
     :display-in-overview true}
    {:slug "private-docs-early-access"


dissoc original ip

dissoc original ip

--- src/proxmox/model.clj
+++ src/proxmox/model.clj
@@ -4,10 +4,11 @@
     [celestial.model :refer (clone hypervisor)]
     [celestial.common :refer (get!)]))

-(defmethod clone :proxmox [spec {:keys [machine] :as clone-spec}]
+(defmethod clone :proxmox [spec {:keys [machine]}]
   "Clones the model replace unique identifiers in the process"
   (-> spec
       (dissoc-in* [:proxmox :vmid])
+      (dissoc-in* [:machine :ip])
       (update-in [:machine] #(merge % machine))
       ))


:use -> :require

:use -> :require

--- src/shale/handler.clj
+++ src/shale/handler.clj
@@ -2,12 +2,11 @@
   (:require [ring.adapter.jetty :as jetty]
             [clj-json [core :as json]]
             [shale.periodic :as periodic]
-            [shale.nodes :as nodes])
+            [shale.nodes :as nodes]
+            [shale.resources :refer [assemble-routes]]
+            [ring.middleware.multipart-params :refer [wrap-multipart-params]]
+            [compojure.handler :refer [api]])

-  (:use
-    [shale.resources :only  [assemble-routes]]
-    [ring.middleware.multipart-params :only  [wrap-multipart-params]]
-    [compojure.handler :only  [api]])
   (:gen-class))

 (defn ignore-trailing-slash


Continue on markov chain building

Continue on markov chain building

--- src/shokunin/word.clj
+++ src/shokunin/word.clj
@@ -39,25 +39,40 @@

 (defn word-link
-  "Turn a tri-gram into a word-chain entry."
-  [[t1 t2 t3]]
-  {[t1 t2] (if t3 #{t3} #{})})
+  "Turn an (arbitrary) n-gram into a markov chain entry."
+  [[& ts]] {(butlast ts) (list (last (rest ts)))})

 (defn word-chain
-  "Use everything but the last word in an n-gram as a key to the set of words that follow them."
+  "Build a word chain out of word tokens."
   [word-seq]
-  (let [tri-grams (n-gram 3 word-seq)]
-    (apply merge-with clojure.set/union (map word-link tri-grams))))
+  (let [word-seq* (concat [:start] word-seq [:end])
+        tri-grams (n-gram 3 word-seq*)]
+    (apply merge-with concat (map word-link tri-grams))))

-(defn file-word-chain
+(defn sentence-tokens
+  "Turn a seq of words into sentences."
+  [word-seq]
+  (re-seq #"(?:[^\.\?\!]+[\.\?\!]\s*)" word-seq))
+
+
+(defn word-tokens
+  "Turn a sentence into a markov chain ready seq of words."
+  [sentence]
+  (re-seq #"(?:\w[\w\'\-]*|[\,\.\?\!\:\;])" sentence))
+
+;; still need to count probability of transition somewhere
+(-> "a b 1 a b x a b x a b x" word-tokens word-chain)
+
+(defn parse-file
   "Build a word chain from the file contents."
-  [path]
+  [path tokenizer parser]
   (with-open [file (clojure.java.io/reader path)]
-     (word-chain (mapcat (comp tokenize lower-case)
-                         (line-seq file)))))
+     (doall (parser (mapcat tokenizer (line-seq file))))))

-;; (def indy-chain (file-word-chain "resources/01/declaration.txt"))
-;; (sort-by #(count (val %)) > indy-chain)

+(defn naive-bayes [& ps]
+  (let [prob (apply * ps)
+        not-p (apply * (map #(- 1 %) ps))]
+    (/ prob (+ prob not-p))))


lexer: add delimiters and operators. Still missing: numbers.

--- src/skylark/lexer.clj
+++ src/skylark/lexer.clj
@@ -6,7 +6,7 @@
 ;; See Python 2 Documentation: https://docs.python.org/2/reference/lexical_analysis.html

 ;; This lexer is written in monadic style.
-;; type State = InputStream×IndentStack×OutputStream
+;; type State = InputStream×OutputStream×IndentStack×DelimStack
 ;; monad PythonLexer α = State → α×State
 ;;
 ;; The output is a sequence of vector of the form: [type data info]
@@ -15,14 +15,15 @@
 ;; start and end position (each a vector [line column] counting from 1).

 ;; File information, if any, to include together with token position
-(def ^:dynamic *file* false)
+(def ^:dynamic *file* nil)

 (defn init-state [input]
-  [(delta/positioned-stream input {:line-offset 1 :column-offset 0}) '(0) ()])
+  [(delta/positioned-stream input {:line-offset 1 :column-offset 0}) () '(0) ()])

 (defn σ-in [σ] (σ 0))
-(defn σ-indent-stack [σ] (σ 1))
-(defn σ-out [σ] (σ 2))
+(defn σ-out [σ] (σ 1))
+(defn σ-indent-stack [σ] (σ 2))
+(defn σ-delim-stack [σ] (σ 3))

 (defn in-char [in] (let [[[x]] in] x))
 (defn in-position [in] (let [[[_ l c]] in] [l c]))
@@ -48,7 +49,7 @@
   ([]
      (&error {}))
   ([details]
-     (fn [[in _ _]]
+     (fn [[in]]
        (let [[l c] (in-position in)]
          (fail (conj details [:file *file*] [:line l] [:column c]))))))
 (def &fail (&error))
@@ -79,10 +80,8 @@
 (defn &position [σ] [(in-column (σ-in σ)) σ])
 (defn &column [σ] [(in-column (σ-in σ)) σ])
 (defn &indent-stack [σ] [(σ-indent-stack σ) σ])
-(defn &read-char [[in is out]] [(in-char in) [(rest in) is out]])
-(defn &emit [& α] (fn [[in is out]] [nil [in is (apply conj out α)]]))
-(defn &done? [σ] [(done? σ) σ])
-(defn &flush [[in is out]] [(reverse out) [in is ()]])
+(defn &read-char [[in out is ds]] [(in-char in) [(rest in) out is ds]])
+(defn &emit [& α] (fn [[in out is ds]] [nil [in (apply conj out α) is ds]]))
 (defn &neof [σ] ((if (done? σ) (&error {:r "unexpected EOF"}) &nil) σ))
 (defn &eof [σ] ((if (done? σ) &nil (&error {:r "expected EOF"})) σ))

@@ -106,7 +105,7 @@
   ([s start end]
      (if (< start end)
        (&bind (&char= (nth s start)) (fn [_] (&string= s (inc start) end)))
-       &nil)))
+       (&return s))))

 (defn &optional [m]
   (&or m &nil))
@@ -130,16 +129,26 @@
        (&char= \newline)
        &eof))

+(def &comment-eol
+  (&do (&optional (&do (&char= \#) (&repeat (&char-if-not crlf)))) &eol))
+
 (def &backslash (&char= \\))

 (def &leading-whitespace-raw
   (&do &whitespace &column))

+(def &implicit-line-continuation
+  (fn [[in out is ds :as σ]]
+    ((if (empty? ds) &fail &comment-eol) σ)))
+
 (def &line-continuation
-  (&do &backslash &eol))
+  (&or
+   &implicit-line-continuation
+   (&do &backslash &eol)))

 (def &whitespace
-  (&repeat (&or (&char-if whitespace) &line-continuation)))
+  (&repeat (&or (&char-if whitespace)
+                &line-continuation)))

 (def &leading-whitespace-continued
   (&let
@@ -154,21 +163,18 @@
     (+ col0 col1)))

 (defn &indent [column]
-  (fn [[in [top :as is] out :as σ]]
+  (fn [[in out [top :as is] ds :as σ]]
     (let [pos (in-position in)
           info [*file* pos pos]
           tok+ #(conj % [%2 nil info])]
       (if (> column top)
-        [nil [in (conj is column) (tok+ out :indent)]]
+        [nil [in (tok+ out :indent) (conj is column) ds]]
         (loop [[top & ris :as is] is
                out out]
           (cond
-           (= column top) [nil [in is out]]
+           (= column top) [nil [in out is ds]]
            (or (empty? ris) (> column top)) ((&error {:r "invalid dedentation"}) σ)
            :else (recur ris (tok+ out :dedent))))))))
-
-(def &comment-eol
-  (&do (&optional (&do (&char= \#) (&repeat (&char-if-not crlf)))) &eol))

 (defn char-range [first last]
   (map char (range (int first) (inc (int last)))))
@@ -180,11 +186,11 @@
 (def letters_digits (clojure.set/union letters_ digits))

 (def keywords
-  (let [l '[and as assert break class continue
+  (let [l '(and as assert break class continue
             def del elif else except exec
             finally for from global if import in is
             lambda not or pass print raise return try
-            while with yield]]
+            while with yield)]
     (into {} (map #(vector % (keyword %)) l))))

 (def &ident-or-keyword
@@ -197,7 +203,7 @@
          info [*file* start end]]
      (if-let [k (keywords s)]
        [k nil info]
-       [:ident s info]))))
+       [:id s info]))))

 (defn char-lower-case [c]
   (when c (char (java.lang.Character/toLowerCase (int c)))))
@@ -272,7 +278,7 @@
           \v (&return \u000b) ;; ASCII Vertical Tab (VT)
           \N (if (= ub \u) &named-char &fail)
           \x &latin1-char ;; \xhh Character with hex value hh
-          \u &unicode-char-16 ;; \uxxxx	Character with 16-bit hex value xxxx (Unicode only)
+          \u &unicode-char-16 ;; \uxxxx Character with 16-bit hex value xxxx (Unicode only)
           \U &unicode-char-32 ;; \Uxxxxxxxx Character with 32-bit hex value xxxxxxxx (Unicode only)
           (if (oct-digit c) &octal-char &fail)))]
    x))
@@ -302,10 +308,44 @@
     _ (&string-end-quote long? q)]
    [:string [s long? q ub r]]))

+(def &numeric-literal
+  (&error {:r "&numeric-literal is not implemented yet"}))
+
+(def delimiters
+  '("@" "," ":" "." "`" "=" ";"
+    "+=" "-=" "*=" "/=" "//" "%="
+    "&=" "|=" "^=" ">>=" "<<=" "**="))
+
+(def operators
+  '("+" "-" "*" "**" "/" "//" "%"
+    "<<" ">>" "&" "|" "^" "~"
+    "<=" ">=" "==" "!=" "<>" "<" ">"))
+
+(def delimiters-and-operators
+  ;; Order matters: prefixes must come afterwards, or we must use a better decision algorithm.
+  (sort-by count > (concat delimiters operators)))
+
+(def &delimiter-or-operator
+  (&let [s (&or* (map #(&string= %) delimiters-and-operators))]
+    [(keyword s) nil]))
+
+(def paren-closer {\( \) \[ \] \{ \}})
+
+(def &paren
+  (&or
+   (&bind (&char-if #{\( \[ \{})
+          #(fn [[in out is ds]]
+             [[% nil] [in out is (conj ds (paren-closer %))]]))
+   (&bind (&char-if #{\) \] \}})
+          #(fn [[in out is ds :as σ]]
+             [[% nil]
+              [in out is (if (= % (first ds)) (rest ds) ((&error {:r "Unmatched delimiter"}) σ))]]))))
+
 (def &token
   (&let
    [start &position
-    [type data] (&or &string-literal &ident-or-keyword)
+    [type data] (&or &string-literal &numeric-literal
+                     &paren &ident-or-keyword &delimiter-or-operator)
     end &position
       (&emit [type data [*file* start end]])]
    nil))
@@ -315,23 +355,23 @@
     [_ &neof
      column &leading-whitespace
      _ (&or &comment-eol ;; skip blank lines
-               (&do
-                (&indent column)
-                (&repeat (&do &token &whitespace))
-                &comment-eol
-                (&bind &position
-                          (fn [pos] (&emit [:newline nil [*file* pos pos]])))))]
+            (&do
+             (&indent column)
+             (&repeat (&do &token &whitespace))
+             &comment-eol
+             (&bind &position
+                       (fn [pos] (&emit [:newline nil [*file* pos pos]])))))]
     nil))

-(defn &finish [[in is out]]
+(defn &finish [[in out is ds :as σ]]
   (let [pos (in-position in)
-        info [*file* pos pos]]
+        info [*file* pos pos]
+        tok+ #(conj % [%2 nil info])]
     (loop [[top & ris] is
-           out out
-           dedent? false]
-      (if (> top 1) (recur ris (conj out [:dedent nil info]) true)
-          [(reverse (conj (if dedent? (conj out [:newline nil info]) out) [:endmarker nil info]))
-           [() '(1) ()]]))))
+           out out]
+      (if (> top 1) (recur ris (tok+ out :dedent))
+          [(reverse (tok+ out :endmarker))
+           [in () '(0) ds]]))))

 (def &python
   (&do (&repeat &logical-line) &eof &finish))
@@ -340,16 +380,21 @@
   (first (&python (init-state input))))

 (comment
-  (defn test-python-lexer [input]
+  (defn test-lex* [input]
     (try (python-lexer input) (catch clojure.lang.ExceptionInfo x (.data x))))

-  (test-python-lexer "
-def hello \"abcd\"
-  foo\\
-bar '1 2 3'
+  (defn test-lex [input]
+    (map (fn [[a b _]] [a b]) (test-lex* input)))
+
+  (test-lex* "
+def hello (world, *more)
+  print()
+  \"a b\" + 'c d' + \\
+  foo['abcd',
+bar, \"1 2 3\",
      # comment
-  baz
-def quux
-  ur\"x\"")
-  (python-lexer "def hello abcd\n  foo\n  baz\ndef quux\n  ur\"x\\\"\"")
+  baz]
+def quux ()
+  {ur\"x\": \"a\"}")
+  (try-python-lexer "def hello abcd\n  foo\n  baz\ndef quux\n  ur\"x\\\"\"")
 );comment


Ensure that we render every frame.

Ensure that we render every frame.

Before this change, rendering would often skip frames, because
(apparently) steps of the algorithms were continuing to process
while the rendering was happening, and especially for large grids
the render would take long enough for several algorithm steps, and
the next frame would render all of the progress that had happened
since the previous frame.

With this change, we can force every frame to render.  That really
slows things down a lot, but it opens the way to optimized,
incremental rendering that will make the animation both fast and
smooth.

--- src/snergly/core.cljs
+++ src/snergly/core.cljs
@@ -15,6 +15,8 @@

 (declare reconciler)

+(def sync-by-frame true)
+
 (defn set-maze-params! [& kvpairs]
   (assert (= 0 (mod (count kvpairs) 2)) "Arguments must be pairs of keys and values")
   (om/transact! reconciler
@@ -31,20 +33,26 @@
   {:app/algorithms (sort algs/algorithm-names)
    :app/analyses ["none" "distances" "path" "longest path"]
    :maze {:algorithm ""
-          :rows 10
-          :columns 10
+          :rows      10
+          :columns   10
           :cell-size 10
-          :grid nil
-
-          :analysis "none"
+          :grid      nil
+          :anim-chan (async/chan)
+
+          :analysis  "none"
           :start-row 0
           :start-col 0
-          :end-row 0
-          :end-col 0
-
-          :active nil}})
-
-(defn produce-distances-async [{:keys [start-row start-col] :as maze-params} grid-key color-family maze]
+          :end-row   0
+          :end-col   0
+
+          :active    nil}})
+
+(defn sync-chan [frame-chan]
+  (if sync-by-frame
+    frame-chan
+    (async/timeout 0)))
+
+(defn produce-distances-async [{:keys [start-row start-col anim-chan] :as maze-params} grid-key color-family maze]
   (let [prev-distances (:distances maze)
         [start-row start-col] (if prev-distances (:max-coord prev-distances) [start-row start-col])
         analysis-fn #(algs/distances-seq maze [start-row start-col])
@@ -58,11 +66,11 @@
                                                   :color-family color-family
                                                   :max-distance (:max distances)})]
                    (set-maze-params! :grid (atom grid))
-                   (async/<! (async/timeout 0))
+                   (async/<! (sync-chan anim-chan))
                    (recur grid)))
                grid))))

-(defn produce-path-async [{:keys [end-row end-col] :as maze-params} longest? maze]
+(defn produce-path-async [{:keys [end-row end-col anim-chan] :as maze-params} longest? maze]
   (let [prev-distances (:distances maze)
         [end-row end-col] (if longest? (:max-coord prev-distances) [end-row end-col])
         analysis-fn #(algs/path-seq maze prev-distances [end-row end-col])
@@ -74,7 +82,7 @@
                  (let [grid (assoc grid :path {:distances distances
                                                :color-family :red})]
                    (set-maze-params! :grid (atom grid))
-                   (async/<! (async/timeout 0))
+                   (async/<! (sync-chan anim-chan))
                    (recur grid)))
                grid))))

@@ -89,7 +97,7 @@
                     (partial produce-distances-async maze-params :dist2 :blue)
                     (partial produce-path-async maze-params true)]))

-(defn produce-maze-async [{:keys [rows columns algorithm] :as maze-params}]
+(defn produce-maze-async [{:keys [rows columns algorithm anim-chan] :as maze-params}]
   (println (str "algorithm: " algorithm))
   (set-maze-params! :active "Carving maze …")
   (let [grid (grid/make-grid rows columns)
@@ -97,12 +105,12 @@
         result-chan (algs/seq-channel algorithm-fn)]
     (go
       (set-maze-params! :grid (atom grid))
-      (async/<! (async/timeout 0))
+      (async/<! (sync-chan anim-chan))
       (loop [prev-maze nil]
         (if-let [new-maze (async/<! result-chan)]
           (do
             (set-maze-params! :grid (atom new-maze))
-            (async/<! (async/timeout 0))
+            (async/<! (sync-chan anim-chan))
             (recur new-maze))
           (do
             (set-maze-params! :active nil)
@@ -151,6 +159,10 @@
   [_ form-value _]
   form-value)

+(defmethod produce-maze-value :anim-chan
+  [_ form-value _]
+  form-value)
+
 (defmethod produce-maze-value :grid
   [_ new-value {:keys [maze] :as state}]
   (let [{:keys [algorithm rows columns grid]} maze]
@@ -175,23 +187,21 @@
 (defui MazeDisplay
   static om/IQuery
   (query [this]
-    '[{:maze [:grid :rows :columns :cell-size :algorithm :active]}])
+    '[{:maze [:grid :rows :columns :cell-size :algorithm :active :anim-chan]}])
   Object
   (componentDidMount [this]
-    (println "componentDidMount called.")
-    (let [{:keys [grid cell-size sync-chan] :as maze} (om/props this)
+    (let [{:keys [grid cell-size anim-chan] :as maze} (om/props this)
           c @thecanvas
           g (.getContext c "2d")]
       (image/image-grid g @grid cell-size)
-      ; (go (when sync-chan (async/>! sync-chan true)))
+      (go (async/>! anim-chan true))
       ))
   (componentDidUpdate [this prev-props prev-state]
-    (println "componentDidUpdate called.")
-    (let [{:keys [grid cell-size sync-chan] :as maze} (om/props this)
+    (let [{:keys [grid cell-size anim-chan] :as maze} (om/props this)
           c @thecanvas
           g (.getContext c "2d")]
       (image/image-grid g @grid cell-size)
-      ; (go (when sync-chan (async/>! sync-chan true)))
+      (go (async/>! anim-chan true))
       ))
   (render [this]
     (let [{:keys [grid rows columns algorithm cell-size active] :as maze} (om/props this)]


condense customer logos

condense customer logos


Bump gravatar pod dep

Bump gravatar pod dep

--- src/io/perun.clj
+++ src/io/perun.clj
@@ -339,7 +339,7 @@
         (pm/set-meta fileset updated-metas)))))

 (def ^:private gravatar-deps
-  '[[gravatar "0.1.0"]])
+  '[[gravatar "1.1.1"]])

 (def ^:private +gravatar-defaults+
   {:filterer identity


oops--fix default gap

oops--fix default gap

--- src/tictag/config.clj
+++ src/tictag/config.clj
@@ -23,7 +23,7 @@

    :tagtime-seed {:default "666"
                   :conversion #(Integer. %)}
-   :tagtime-gap {:default (str (* 2 60))
+   :tagtime-gap {:default (str (* 45 60))
                  :doc "The number of seconds between pings on average, default: 30*60 (30 minutes)"
                  :conversion #(Integer. %)}})


remove println

remove println

--- src/transit/core.cljs
+++ src/transit/core.cljs
@@ -83,7 +83,7 @@
      (t/writer (name type)
        (opts-merge
          #js {:mapIterator
-              (fn [m] (println "map iterator!") (MapIterator. (seq m)))
+              (fn [m] (MapIterator. (seq m)))
               :handlers
               #js [cljs.core/Keyword               (keyword-handler)
                    cljs.core/Symbol                (symbol-handler)


use `(boolean (seq ...))` for predicate function

--- src-cljs/frontend/models/build.cljs
+++ src-cljs/frontend/models/build.cljs
@@ -167,7 +167,7 @@
        (#{"not_running" "running" "queued" "scheduled"} (:lifecycle build))))

 (defn has-pull-requests? [build]
-  (seq (:pull_request_urls build)))
+  (boolean (seq (:pull_request_urls build))))

 (defn can-merge-at-least-one-pr? [build]
   (and (= "success" (:outcome build))


New keyword-selectors added.

New keyword-selectors added.

--- src/me/lomin/alive/core.cljc
+++ src/me/lomin/alive/core.cljc
@@ -71,4 +71,19 @@
                                   (string/split class-str #" ")))]))

 (defmethod spectree-keyword/selector :# [ns k ns+k]
-  (tree-search/selector [#(= (name k) (:id (second %)))]))+  (tree-search/selector [#(= (name k) (:id (second %)))]))
+
+
+(defmethod spectree-keyword/selector :> [ns k ns+k]
+  [seqable? #(= k (first %))])
+
+(defmethod spectree-keyword/selector :>. [ns k ns+k]
+  [seqable? #(if-let [class-str (:class (second %))]
+               (some #{(name k)}
+                     (string/split class-str #" ")))])
+
+(defmethod spectree-keyword/selector :># [ns k ns+k]
+  [seqable? #(= (name k) (:id (second %)))])
+
+(defmethod spectree-keyword/selector :key [_ k _]
+  (specter/must k))


day 14 working

day 14 working

--- src/adventofcode/day14.clj
+++ src/adventofcode/day14.clj
@@ -2,18 +2,44 @@
   (:require [clojure.java.io :as io]
             [clojure.string :as str]))

-(defn parse-line [line]
-    (let [[_ name speed fly rest] (re-find #"^(\w+) can fly (\d+) km/s for (\d+) seconds, but then must rest for (\d+) seconds")]
-        (list name (parse-srting speed) (parse-string fly) (parse-string rest))))
+(defn line->list [line]
+  (let [[_ name speed fly rest] (re-find #"^(\w+) can fly (\d+) km/s for (\d+) seconds, but then must rest for (\d+) seconds" line)]
+    (list name (read-string speed) (read-string fly) (read-string rest))))

-(def reindeers (->> "day14.txt"
-                io/resource
-                io/file
-                slurp
-                str/split-lines
-                (reduce
-                    (fn [res [name speed fly rest]
-                         (assoc-in res name {:speed speed
-                                             :fly fly
-                                             :rest rest})])
-                    {})))
+(def input-reindeers (->> "day14.txt"
+                          io/resource
+                          io/file
+                          slurp
+                          str/split-lines
+                          (map line->list)
+                          (reduce
+                           (fn [m [name speed fly rest]]
+                             (assoc m name {:speed speed
+                                            :fly fly
+                                            :rest rest}))
+                           {})))
+
+(defn distance [reindeers name time]
+  (let [{:keys [speed fly rest]} (get reindeers name)
+        intervals-count (quot time (+ fly rest))
+        time-remain (rem time (+ fly rest))]
+    (+
+     (* speed fly intervals-count)
+     (* speed (min time-remain fly)))))
+
+(defn winner [reindeers time]
+  (->> (keys reindeers)
+       (reduce #(assoc %1 %2 (distance reindeers %2 time))
+               {})
+       (sort-by second >)
+       first
+       first))
+
+(def part-one (->> (keys input-reindeers)
+                   (map #(distance input-reindeers % 2503))
+                   (apply max)))
+
+(def part-two (->> (for [i (range 1 2504)] (winner input-reindeers i))
+                   frequencies
+                   (apply max-key val)
+                   second))


added missing dependency

added missing dependency

--- trackit-all/project.clj
+++ trackit-all/project.clj
@@ -16,6 +16,7 @@
                  [samsara/trackit-ganglia  #=(ver)]
                  [samsara/trackit-graphite #=(ver)]
                  [samsara/trackit-influxdb #=(ver)]
+                 [samsara/trackit-newrelic #=(ver)]
                  [samsara/trackit-riemann  #=(ver)]
                  [samsara/trackit-statsd   #=(ver)]
                  ])


use pmap rather than map for lexemes before writing sentences

--- src/babel/espanol/writer.clj
+++ src/babel/espanol/writer.clj
@@ -36,21 +36,22 @@

         ;; for debugging: use map: in-order rather than interleaved by multiple workers.
         ;; for production: use pmap.
+        ;;        use-map-fn pmap
         use-map-fn map

         root-verbs
         (zipmap
          (keys lexicon)
-         (map (fn [lexeme-set]
-                (filter (fn [lexeme]
-                          (and
-                           ;; how to only generate for a single infinitive (for testing/development):
-                           ;;                           (= (get-in lexeme [:espanol :espanol]) "abandonar")
-                           (= (get-in lexeme [:synsem :cat]) :verb)
-                           (= (get-in lexeme [:synsem :infl]) :top)
-                           (not (= :top (get-in lexeme [:synsem :sem :pred] :top)))))
-                        lexeme-set))
-              lexemes))
+         (use-map-fn (fn [lexeme-set]
+                       (filter (fn [lexeme]
+                                 (and
+                                  ;; how to only generate for a single infinitive (for testing/development):
+                                  ;;                           (= (get-in lexeme [:espanol :espanol]) "abandonar")
+                                  (= (get-in lexeme [:synsem :cat]) :verb)
+                                  (= (get-in lexeme [:synsem :infl]) :top)
+                                  (not (= :top (get-in lexeme [:synsem :sem :pred] :top)))))
+                               lexeme-set))
+                     lexemes))
         root-verb-array
         (reduce concat
                 (use-map-fn (fn [key]


add exceptions to prevent throwing exceptions in case of generation failure

--- src/babel/espanol/writer.clj
+++ src/babel/espanol/writer.clj
@@ -84,17 +84,35 @@
                                                                      (catch Exception e
                                                                        (cond

-                                                                        ;; TODO: make this conditional on
-                                                                        ;; there being a legitimate reason for the exception -
-                                                                        ;; e.g. the verb is "funzionare" (which takes a non-human
-                                                                        ;; subject), but we're trying to generate with
-                                                                        ;; {:agr {:person :1st or :2nd}}, for which the only lexemes
-                                                                        ;; are human.
-                                                                        false
-
-                                                                        (log/warn (str "ignoring exception: " e))
-                                                                        true
-                                                                       (throw e))))
+                                                                         ;;conditional on
+                                                                         ;; there being a legitimate reason for the exception -
+
+                                                                         ;; The verb is "funzionare" (which takes a non-human
+                                                                         ;; subject), but we're trying to generate with
+                                                                         ;; {:agr {:person :1st or :2nd}}, for which the only lexemes
+                                                                         ;; are human.
+                                                                         (and
+                                                                          (= (get-in spec [:root :espanol :espanol])
+                                                                             "funcionar")
+                                                                          (or (= (get-in spec [:comp :synsem :agr :person])
+                                                                                :1st)
+                                                                              (= (get-in spec [:comp :synsem :agr :person])
+                                                                                :2nd)))
+                                                                         (log/warn (str "ignoring exception(1): " e))
+
+                                                                         (and
+                                                                          (= (get-in spec [:root :espanol :espanol])
+                                                                             "llamarse")
+                                                                          (get-in spec [:comp :synsem :arg :number]
+                                                                                :plur))
+                                                                         (log/warn (str "ignoring exception(2): " e))
+
+                                                                         true
+                                                                         (do
+                                                                           (log/error (str "Going to throw exception since we "
+                                                                                "couldn't generate any expression for spec:"
+                                                                                spec))
+                                                                           (throw e)))))
                                                                    ))
                                                                [:sing :plur]))))
                                                      [:1st :2nd :3rd]))))


working on some new ideas to speed up generation

--- src/babel/english/lab.cljc
+++ src/babel/english/lab.cljc
@@ -11,6 +11,20 @@

 (defn parse [surface-string]
   (english/parse surface-string model false)) ;; false: don't truncate.
+
+(defn nursery
+  "very fast and easy sentences."
+  []
+  (let [spec {:synsem {:cat :verb
+                       :subcat []}
+              :comp {:phrasal false}
+              :head {:phrasal false}}]
+    (repeatedly
+     #(println
+       (morph (binding [babel.generate/println? false
+                        babel.generate/truncate? true]
+                (time (generate spec model)))
+              :show-notes false)))))

 (defn downtown []
   (let [specs
@@ -30,7 +44,7 @@

 (declare wait)

-(defn basecamp []
+(defn relative-clauses []
   ;; TODO: improve performance by using {:mod {:first {:obj :modified}}.
   (let [specs
         [
@@ -54,6 +68,7 @@
                                                 (wait wait-ms-for-generation (fn [] (generate spec model))))))]
                       (or (and (not (empty? result)) result)
                           "TIMEOUT.")))))))
+(defn basecamp [])

 (defn nextcamp []
   (let [parse (-> "the small dogs you see" parse first)]


Removed commented-out code.

Removed commented-out code.

--- src/blutwurst/database.clj
+++ src/blutwurst/database.clj
@@ -12,7 +12,6 @@
    `(let [~connection-name (DriverManager/getConnection (:connection-string ~spec))
           ~meta-data-name (.getMetaData ~connection-name)
           ~result-name (apply ~fun (list ~meta-data-name))]
-      ;(.close ~connection-name)
       ~result-name)
  ))

@@ -70,15 +69,14 @@
 (defn- retrieve-keys
  "This function is responsible for building an adjacency matrix illustrating the key relationships
  between tables."
- [spec tables] nil)
+ [spec tables] tables)

 (defn retrieve-table-graph [spec]
  "This function accepts a connection specification and produces a table graph."
  (let [table-list (->> spec
                        retrieve-tables
                        (retrieve-columns spec)
-                      ; (retrieve-keys spec)
-                       )]
+                       (retrieve-keys spec))]
      {
       :tables table-list
      }))


fixup! avoid unnecessary string concatenation

--- src/bract/core/inducer.clj
+++ src/bract/core/inducer.clj
@@ -170,7 +170,7 @@
   (if (kdef/ctx-launch? context)
     (let [launcher (-> (kdef/ctx-config context)
                      kdef/cfg-launcher)]
-      (echo/echo "Launcher name: " launcher)
+      (echo/echo "Launcher name:" launcher)
       (launcher context))
     (do
       (echo/echo "Launch not enabled, skipping launch.")


Use a character whitelist for slugify (instead of a blacklist)

--- src/braid/common/util.cljc
+++ src/braid/common/util.cljc
@@ -48,6 +48,9 @@
   (let [pattern #"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"]
     (and (string? email) (re-matches pattern email))))

+(defn remove-non-whitelist-characters [text]
+  (string/replace text (re-pattern #"[^a-z^A-Z^0-9^\-]*") ""))
+
 (defn slugify
   "Converts text to a slug-safe representation"
   [text]
@@ -55,4 +58,4 @@
     (-> text
         string/trim
         string/lower-case
-        (string/replace #"[ -+|,/?%#&\.\!:$'@]*" ""))))
+        remove-non-whitelist-characters)))


"implement" unspent-amounts

"implement" unspent-amounts

--- src/bitsplit_cli/client.cljs
+++ src/bitsplit_cli/client.cljs
@@ -34,8 +34,8 @@
     (addresses [this]
         (-> wallet .-addresses js->clj))
     (unspent-amounts [this]
-        (let [unspent (->> coin .-accounts (map account->amount))]
-            (apply merge unspent)))
+      (throw
+        (js/Error. "Synchronous unspent-amounts not a thing")))
     (unspent-channel [this]
         (let [return (a/chan)]
             (js/setInterval


don't close-over panel-items

don't close-over panel-items

--- src/braid/mobile/panels.cljs
+++ src/braid/mobile/panels.cljs
@@ -29,7 +29,7 @@
                                   (-> x
                                       (min xmax)
                                       (max xmin)))
-                          max-n (dec (count panel-items))
+                          max-n (dec (@state :panel-count))
                           new-n (bound (+ pos-n delta-n) 0 max-n)
                           snap-x (- (* w new-n))]

@@ -43,6 +43,9 @@
                               :pos-x (+ (@state :pos-x-start)
                                         (- (@state :touch-x)
                                            (@state :touch-x-start)))))
+
+        set-panel-count! (fn [panel-count]
+                           (swap! state assoc :panel-count panel-count))

         get-dragging? (fn []
                         (reaction (@state :dragging?)))
@@ -63,15 +66,16 @@
                      (let [x (.-clientX (aget (.-changedTouches e) 0))
                            dragging? (get-dragging?)]
                        (when @dragging?
-                         (drag-end!))))
-        ]
+                         (drag-end!))))]
     (r/create-class
-      {
-       :component-did-mount
+      {:component-did-mount
        (fn []
          (.addEventListener js/document "touchstart" touch-start!)
          (.addEventListener js/document "touchmove" touch-move!)
          (.addEventListener js/document "touchend" touch-end!))
+       :component-will-update
+       (fn [this _]
+         (set-panel-count! (count (first (r/children this)))))
        :component-will-unmount
        (fn []
          (.removeEventListener js/document "touchstart" touch-start!)


no message

no message

--- src/tabledoc.clj
+++ src/tabledoc.clj
@@ -10,8 +10,8 @@

 (h/deftemplate tbl-list-template "templates/all_tables.html" [tables]
   [:a] (h/clone-for [t tables]
-                    (h/do-> (h/set-attr :href (str (t :owner) "/" (t :table_name)))
-                            (h/content (t :table_name))
+                    (h/do-> (h/set-attr :href (str t ".html"))
+                            (h/content t)
                             )))

 (h/deftemplate tbl-template "templates/tbl.html" [tab-info]
@@ -56,11 +56,11 @@
 ;; (print
 ;;  (apply str (scheam-list-template ["HR" "SH" "OH" "XYS"])))

-(defn gen-tab-file [owner tab-name]
-  (with-open [w (writer (str "xxx/" tab-name ".html"))]
-    (.write w
-            (apply str (tbl-template (get-tab-info owner tab-name))))))
+(defn gen-tab-files [owner]
+  (doseq [tab-name (get-tables owner)]
+    (with-open [w (writer (str "xxx/" tab-name ".html"))]
+      (.write w (apply str (tbl-template (get-tab-info owner tab-name)))))))

-(doseq [t (get-tables "HR")]
-  (println (t :table_name))
-  (gen-tab-file (t :owner) (t :table_name)))
+(defn gen-tab-list [owner]
+  (with-open [w (writer (str "xxx/tables.html"))]
+    (.write w (apply str (tbl-list-template (get-tables owner))))))


c-or-r -> c, seems to be the common name for that parameter

--- src/tudu/ui.cljs
+++ src/tudu/ui.cljs
@@ -15,8 +15,8 @@
 (def initial-state {:tudu.item/editing clean-item-editing
                     :tudu/items nil})

-(defn close-item [c-or-r id]
-  (om/transact! c-or-r `[(tudu.item/close {:id ~id}) :tudu/items]))
+(defn close-item [c id]
+  (om/transact! c `[(tudu.item/close {:id ~id}) :tudu/items]))

 (defui TodoItemUI
   static om/IQuery
@@ -52,18 +52,18 @@

 (def todo-list-ui (om/factory TodoListUI))

-(defn on-change-cb [c-or-r callback]
+(defn on-change-cb [c callback]
   (fn [e]
     (let [target (.-target e)
           value (.-value target)]
-      (callback c-or-r value))))
+      (callback c value))))

-(defn task-title-change [c-or-r text]
-  (om/transact! c-or-r `[(tudu.item.editing/set-title {:value ~text})
+(defn task-title-change [c text]
+  (om/transact! c `[(tudu.item.editing/set-title {:value ~text})
                             :tudu.item/editing]))

-(defn create-task [c-or-r task]
-  (om/transact! c-or-r `[(tudu.item/create {:value ~task})
+(defn create-task [c task]
+  (om/transact! c `[(tudu.item/create {:value ~task})
                             :tudu.item/editing :tudu/items]))

 (defui NewTodoItemUI


fix rest handlers

fix rest handlers

--- src/clj/swarmpit/handler.clj
+++ src/clj/swarmpit/handler.clj
@@ -57,13 +57,13 @@
     (->> (api/users)
          (resp-ok))))

-(defmethod dispatch :user [{:keys [route-params]}]
-  (fn [_]
+(defmethod dispatch :user [_]
+  (fn [{:keys [route-params]}]
     (->> (api/user (:id route-params))
          (resp-ok))))

-(defmethod dispatch :user-create [{:keys [params]}]
-  (fn [_]
+(defmethod dispatch :user-create [_]
+  (fn [{:keys [params]}]
     (let [payload (keywordize-keys params)]
       (if (some? (api/create-registry payload))
         (resp-created)
@@ -76,8 +76,8 @@
     (->> (api/registries)
          (resp-ok))))

-(defmethod dispatch :registry [{:keys [route-params]}]
-  (fn [_]
+(defmethod dispatch :registry [_]
+  (fn [{:keys [route-params]}]
     (->> (api/registry (:id route-params))
          (resp-ok))))


gitlab registry handler #341

gitlab registry handler
#341

--- src/clj/swarmpit/handler.clj
+++ src/clj/swarmpit/handler.clj
@@ -420,7 +420,8 @@
                :v2 (api/registries-v2 owner)
                :dockerhub (api/dockerhubs owner)
                :ecr (api/registries-ecr owner)
-               :acr (api/registries-acr owner))
+               :acr (api/registries-acr owner)
+               :gitlab (api/registries-gitlab owner))
              (resp-ok))
         (resp-error 400 (str "Unknown registry type [" registry "]"))))))

@@ -433,7 +434,8 @@
                :v2 (api/registry-v2 id)
                :dockerhub (api/dockerhub id)
                :ecr (api/registry-ecr id)
-               :acr (api/registry-acr id))
+               :acr (api/registry-acr id)
+               :gitlab (api/registry-gitlab id))
              (resp-ok))
         (resp-error 400 (str "Unknown registry type [" registry "]"))))))

@@ -446,7 +448,8 @@
               :v2 (api/delete-v2-registry id)
               :dockerhub (api/delete-dockerhub id)
               :ecr (api/delete-ecr-registry id)
-              :acr (api/delete-acr-registry id))
+              :acr (api/delete-acr-registry id)
+              :gitlab (api/delete-gitlab-registry id))
             (resp-ok))
         (resp-error 400 (str "Unknown registry type [" registry "]"))))))

@@ -459,7 +462,8 @@
                :v2 (api/registry-v2-repositories id)
                :dockerhub (api/dockerhub-repositories id)
                :ecr (api/registry-ecr-repositories id)
-               :acr (api/registry-acr-repositories id))
+               :acr (api/registry-acr-repositories id)
+               :gitlab (api/registry-gitlab-repositories id))
              (resp-ok))
         (resp-error 400 (str "Unknown registry type " registry))))))

@@ -512,6 +516,17 @@
     (catch Exception e
       (resp-error 400 (get-in (ex-data e) [:body :error])))))

+(defmethod registry-create :gitlab
+  [_ payload]
+  (try
+    (api/registry-gitlab-info payload)
+    (let [response (api/create-gitlab-registry payload)]
+      (if (some? response)
+        (resp-created (select-keys response [:id]))
+        (resp-error 400 "Gitlab registry account already linked")))
+    (catch Exception e
+      (resp-error 400 (get-in (ex-data e) [:body :error])))))
+
 (defmethod dispatch :registry-create [_]
   (fn [{:keys [params identity route-params]}]
     (let [owner (get-in identity [:usr :username])
@@ -557,6 +572,15 @@
   (try
     (api/registry-acr-info payload)
     (api/update-acr-registry id payload)
+    (resp-ok)
+    (catch Exception e
+      (resp-error 400 (get-in (ex-data e) [:body :error])))))
+
+(defmethod registry-update :gitlab
+  [_ payload id]
+  (try
+    (api/registry-gitlab-info payload)
+    (api/update-gitlab-registry id payload)
     (resp-ok)
     (catch Exception e
       (resp-error 400 (get-in (ex-data e) [:body :error])))))


scroll message list when receiving new messages

--- src/cljs/netrunner/chat.cljs
+++ src/cljs/netrunner/chat.cljs
@@ -65,6 +65,11 @@
             (let [ch (<! (om/get-state owner :channel-ch))]
               (om/set-state! owner :channel ch)))))

+    om/IDidUpdate
+    (did-update [this prev-props prev-state]
+      (let [div (om/get-node owner "message-list")]
+        (aset div "scrollTop" (.-scrollHeight div))))
+
     om/IRenderState
     (render-state [this state]
       (sab/html
@@ -76,7 +81,7 @@
            (om/build channel-view {:channel ch :active-channel (:channel state)}
                      {:init-state {:channel-ch (:channel-ch state)}}))]
         [:div.chat-box
-         [:div.blue-shade.panel.message-list
+         [:div.blue-shade.panel.message-list {:ref "message-list"}
           (om/build-all message-view (get-in cursor [:channels (:channel state)]))]
          (om/build msg-input-view state)]]))))


Docstring

Docstring

--- src/cyanite_remover/core.clj
+++ src/cyanite_remover/core.clj
@@ -409,6 +409,7 @@
       obsolete)))

 (defn- collect-path-info
+  "Add a path to the paths info database."
   [path]
   (let [path-name (:path path)
         path-info {:leaf (:leaf path)}]


Use the options 'sort' everywhere

Use the options 'sort' everywhere

--- src/cyanite_remover/core.clj
+++ src/cyanite_remover/core.clj
@@ -87,9 +87,7 @@
   "Get paths from a paths-rollups list."
   [paths-rollups]
   (->> paths-rollups
-       (map first)
-       (distinct)
-       (sort)))
+       (map first)))

 (defn- dry-mode-warn
   "Warn about dry mode."
@@ -382,7 +380,8 @@
   (let [threshold (:threshold options default-obsolete-metrics-threshold)
         from (timec/to-epoch (time/minus (time/now) (time/seconds threshold)))
         title "Checking metrics"
-        paths-rollups (combine-paths-rollups paths [(first rollups)])]
+        paths-rollups (combine-paths-rollups paths [(first rollups)])
+        sort (if (:sort options) sort #(do %))]
     (prog/set-progress-bar!
      "[:bar] :percent :done/:total Elapsed :elapseds ETA :etas")
     (prog/config-progress-bar! :width pbar-width)
@@ -405,7 +404,8 @@
           obsolete-paths (->> futures
                               (process-futures)
                               (remove nil?)
-                              (get-paths-from-paths-rollups))
+                              (get-paths-from-paths-rollups)
+                              (sort))
           _ (clog/info (str "Found obsolete metrics on "
                             (count obsolete-paths) " paths"))
           obsolete (combine-paths-rollups obsolete-paths rollups)]


improve logging

improve logging

--- src/babel/forest.cljc
+++ src/babel/forest.cljc
@@ -184,18 +184,20 @@
                                        (and (not (fail?
                                                   (unifyc (get-in child [:synsem] :top)
                                                           (get-in child-in-bolt [:synsem] :top)))))))
-              debug (log/debug (str "add-complement pre-filtered lexeme size:  " (count complement-candidate-lexemes)))
+              debug (log/debug (str "add-complement: pre-filtered lexeme size:  " (count complement-candidate-lexemes)))
               filtered-lexical-complements (filter (fn [lexeme]
                                                      (complement-pre-check lexeme bolt path))
                                                    complement-candidate-lexemes)
-              debug (log/debug (str "add-complement post-filtered lexeme size: " (count filtered-lexical-complements)))
+              debug (log/debug (str "add-complement: pre/post-filtered lexeme size: "
+                                    (count complement-candidate-lexemes)
+                                    (count filtered-lexical-complements)))
               shuffled-candidate-lexical-complements (lazy-shuffle filtered-lexical-complements)

               return-val
               (filter (fn [result]
                         (not (fail? result)))
                       (map (fn [complement]
-                             (let [debug (log/debug (str "adding complement to: ["
+                             (let [debug (log/debug (str "adding complement: ["
                                                          (get-in bolt [:rule]) " '"
                                                          (morph bolt) "']: "
                                                          "trying lexical complement:'" (morph complement) "'"))
@@ -205,11 +207,11 @@
                                                         (copy complement)))
                                    is-fail? (fail? result)]
                                (if is-fail?
-                                 (log/debug (str "fail-path-between(bolt=val1/comp=val2):"
+                                 (log/debug (str "add-complement: fail-path-between(bolt=val1/comp=val2):"
                                                  (fail-path-between (strip-refs (get-in bolt path))
                                                                     (strip-refs complement))))

-                                 (log/debug (str "success:" (:rule result) " returning: '" (morph result) "'")))
+                                 (log/debug (str "add-complement: success:" (:rule result) " returning: '" (morph result) "'")))

                                (if is-fail? :fail result)))

@@ -218,14 +220,14 @@
                              (log/debug (str "generating phrasal complements with cat: " (get-in spec [:synsem :cat])))
                              (let [phrasal-complements (generate-all spec grammar lexicon cache morph)]
                                (if (not (empty? phrasal-complements))
-                                 (log/debug (str "phrasal complements were not empty; first: "
+                                 (log/debug (str "add-complement: phrasal complements were not empty; first: "
                                                  (get-in (first phrasal-complements) [:rule])))
                                  ;; phrasal complements were empty.
                                  (if (= true (get-in spec [:phrasal] false))
-                                   (log/warn (str "no phrasal complements of: " (:cat spec)
+                                   (log/warn (str "add-complement: no phrasal complements of: " (:cat spec)
                                                   " could be generated."))))

-                               (if (lexemes-before-phrases)
+                               (if (lexemes-before-phrases depth)
                                  (lazy-cat shuffled-candidate-lexical-complements phrasal-complements)
                                  (do
                                    (if (not (empty? phrasal-complements))
@@ -234,8 +236,8 @@
                                    (lazy-cat phrasal-complements shuffled-candidate-lexical-complements)))))))]
           (let [run-time (- (current-time) start-time)]
             (if (empty? return-val)
-
-              ;; else, no complements could be added to this bolt: Throw an exception
+              ;; else, no complements could be added to this bolt: Throw an exception or log/warn. debateable about which to do
+              ;; in which circumstances.
               (let [log-limit 1000
                     log-fn (fn [message] (log/warn message))
                     throw-exception-if-no-complements-found false


logging message changes

logging message changes

--- src/babel/forest.cljc
+++ src/babel/forest.cljc
@@ -220,8 +220,8 @@
               filtered-lexical-complements (filter (fn [lexeme]
                                                      (complement-pre-check lexeme bolt path))
                                                    complement-candidate-lexemes)
-              debug (log/debug (str "pre-filtered size: " (count complement-candidate-lexemes)))
-              debug (log/debug (str "filtered size: " (count filtered-lexical-complements)))
+              debug (log/debug (str "add-complement pre-filtered lexeme size:  " (count complement-candidate-lexemes)))
+              debug (log/debug (str "add-complement post-filtered lexeme size: " (count filtered-lexical-complements)))
               shuffled-candidate-lexical-complements (lazy-shuffle filtered-lexical-complements)

               return-val


ugly fix

ugly fix

--- src/blogiseq/site.clj
+++ src/blogiseq/site.clj
@@ -87,7 +87,7 @@
       (utils/parse-resource "misc_header.html"))] ; include this as-is. this deserves some polishing
    [:body
     (fill-template
-      (utils/parse-edn-resource "layout.edn" default-layout)
+      (utils/parse-edn-resource "layout.edn" (str default-layout))
       (generate-menu-navi "meta.edn")
       content)]])


Clarify doc string

Clarify doc string

--- src/catalog/vubis.clj
+++ src/catalog/vubis.clj
@@ -261,8 +261,8 @@
   "Get the accompanying material for `item`. Use
   `accompanying-material` and `accompanying-material-legacy`. If
   `accompanying-material-legacy-other` use that instead of
-  `accompanying-material-legacy`. Return `nil` if none of the input
-  values are non-nil."
+  `accompanying-material-legacy`. Return `nil` if all of the input
+  values are nil."
   [{:keys [accompanying-material accompanying-material-legacy accompanying-material-legacy-other]}]
   (let [materials [accompanying-material (or accompanying-material-legacy
                                              accompanying-material-legacy-other)]]


Indentation fixes

Indentation fixes

--- src/cfpb/qu/query.clj
+++ src/cfpb/qu/query.clj
@@ -82,7 +82,7 @@
                                          (and
                                            (not= value "")
                                            (dimensions (name key)))) params))
-                   (cast-dimensions slice))
+                      (cast-dimensions slice))
      :clauses (into {} (filter (fn [[key value]]
                                  (and
                                    (not= value "")
@@ -97,11 +97,11 @@
   "Create a Mongo find map from the query."
   [query]
   (let [mongo (q/partial-query
-    (q/find (get-in query [:mongo :match]))
-    (q/limit (->int (or (:limit query) default-limit)))
-    (q/skip (->int (or (:offset query) default-offset)))
-    (q/sort (get-in query [:mongo :sort] {}))
-    (q/fields (or (get-in query [:mongo :project]) {})))]
+                (q/find (get-in query [:mongo :match]))
+                (q/limit (->int (or (:limit query) default-limit)))
+                (q/skip (->int (or (:offset query) default-offset)))
+                (q/sort (get-in query [:mongo :sort] {}))
+                (q/fields (or (get-in query [:mongo :project]) {})))]
     mongo))

 (defn mongo-aggregation


default to :target "1.5" for compile-java

--- src/cake/tasks/compile.clj
+++ src/cake/tasks/compile.clj
@@ -9,15 +9,16 @@
 (defn compile-java [src]
   (let [start (System/currentTimeMillis)]
     (when (.exists src)
-      (ant Javac (assoc (:java-compile *project*)
-                   :destdir     (file "classes")
-                   :classpath   (classpath)
-                   :srcdir      (path src)
-                   :fork        true
-                   :verbose     (verbose?)
-                   :debug       true
-                   :debug-level "source,lines"
-                   :failonerror true)))
+      (ant Javac (merge {:destdir     (file "classes")
+                         :classpath   (classpath)
+                         :srcdir      (path src)
+                         :fork        true
+                         :verbose     (verbose?)
+                         :debug       true
+                         :debug-level "source,lines"
+                         :target      "1.5"
+                         :failonerror true}
+                        (:java-compile *project*))))
     (when (some #(newer? % start) (file-seq (file "classes")))
       (bake-restart))))


Add some vertical space to title page

Add some vertical space to title page

--- src/catalog/layout/fop.clj
+++ src/catalog/layout/fop.clj
@@ -529,12 +529,12 @@
        (mapcat #(format-sexp (get subitems %) % 1 path-to-numbers false) (keys subitems))])]])

 (defn- image [path]
-  [:fo:block
+  [:fo:block {:space-before "120mm"}
    [:fo:external-graphic {:src path}]])

 (defn- impressum [date]
   (let [creator "SBS Schweizerische Bibliothek für Blinde, Seh- und Lesebehinderte"]
-    [:fo:block-container
+    [:fo:block-container {:space-before "10mm"}
      (block "Herausgeber:")
      (block creator)
      (block "Grubenstrasse 12")


Fix background color for issue 1

Fix background color for issue 1

--- src/catalog/layout/fop.clj
+++ src/catalog/layout/fop.clj
@@ -484,7 +484,7 @@

 (def issue-colors
   "Defines the bg colors used for the cover page of the respective issues"
-  {1 [100 90 10 0]
+  {1 [85 65 0 0]
    2 [69 0 31 7]
    3 [0 25 100 5]
    4 [33 71 0 0]


Test of 2 entry put.

Test of 2 entry put.

--- src/cbfg/grouper-test.cljs
+++ src/cbfg/grouper-test.cljs
@@ -41,7 +41,14 @@
                     (e n
                        (atake tg r)
                        {:b :B}
-                       (atake tg r))))
+                       (atake tg r)))
+                  (do
+                    (aput tg (:put-ch g) [:a (fn [_] :A)])
+                    (aput tg (:put-ch g) [:b (fn [_] :B)])
+                    (e n
+                       (atake tg (:take-all-ch g))
+                       {:a :A :b :B}
+                       nil)))
            "pass"
            (str "FAIL: on test-grouper #" @n)))))


adding job reset api

adding job reset api

--- src/celestial/api/jobs.clj
+++ src/celestial/api/jobs.clj
@@ -22,6 +22,7 @@
     [celestial.persistency [types :as t] [users :as u]]
     [celestial.persistency.actions :refer (find-action-for)]
     [celestial.jobs :as jobs :refer (enqueue)]
+    [celestial.redis :refer (clear-locks)]
     [es.jobs :as es]
     [swag.core :refer (GET- POST- PUT- DELETE- defroutes- errors)]
     [celestial.security :refer (current-user)]
@@ -129,7 +130,13 @@
         {:keys [envs] :as user} (u/get-user username)
         {:keys [total hits]} (es/paginate (* (- page* 1) offset*) offset* envs)]
        (success {:jobs (map #(-> % :_source add-tid-link) hits) :total total})))
-
+
+  (POST- "/jobs/reset" []
+      {:nickname "reset" :summary "Reset all jobs and locks"}
+       (jobs/clear-all)
+       (clear-locks)
+       (success "jobs cleared"))
+
   (GET- "/jobs/done/:tid" [^:string tid ]
       {:nickname "getDoneJobByTid" :summary "Get a done job using its tid"}
     (let [job (es/get tid)]


remove broken experiment that managed to slip into the codebase

--- src/overtone/studio/core.clj
+++ src/overtone/studio/core.clj
@@ -195,8 +195,7 @@
                               :fx-chain []
                               :player player#
                               :args arg-names#}
-                             player#)
-         inst# (with-meta inst# {:type ::instrument})]
+                             player#)]

      (load-synthdef sdef#)
      (add-instrument inst#)


Fix 2 bugs when running dummy project.

Fix 2 bugs when running dummy project.

--- src/circle/backend/git.clj
+++ src/circle/backend/git.clj
@@ -39,7 +39,7 @@
         (when ~f
           (.delete ~f))))))

-(def git-ssh-path "./git_ssh.sh")
+(def git-ssh-path (fs/abspath "git_ssh.sh"))

 (defn git-fn*
   "Takes a seq of stevedore code. Executes it locally, with GIT_SSH and GIT_SSH_KEY set up."
@@ -89,7 +89,7 @@
     (if (repo-exists? path)
       (when update
         (checkout path "master") ;; you have to be on a branch to pull
-        (pull path))
+        (pull path :ssh-key ssh-key))
       (clone url :path path :ssh-key ssh-key))))

 (defn latest-local-commit


test for leave-play effects of hosted Corp cards that get trashed

--- src/clj/test/core-game.clj
+++ src/clj/test/core-game.clj
@@ -135,6 +135,26 @@
       (core/score state :corp {:card (refresh ai)})
       (is (not (nil? (get-content state :remote1 0)))))))

+(deftest trash-corp-hosted
+  "Hosted Corp cards are included in all-installed and fire leave-play effects when trashed"
+  (do-game
+    (new-game (default-corp [(qty "Worlds Plaza" 1) (qty "Director Haas" 1)])
+              (default-runner))
+    (play-from-hand state :corp "Worlds Plaza" "New remote")
+    (let [wp (get-content state :remote1 0)]
+      (core/rez state :corp wp)
+      (card-ability state :corp wp 0)
+      (prompt-select :corp (find-card "Director Haas" (:hand (get-corp))))
+      (is (= 4 (:click-per-turn (get-corp))) "Corp has 4 clicks per turn")
+      (is (= 2 (count (core/all-installed state :corp))) "all-installed counting hosted Corp cards")
+      (take-credits state :corp)
+      (run-empty-server state "Server 1")
+      (let [dh (first (:hosted (refresh wp)))]
+        (prompt-select :runner dh)
+        (prompt-choice :runner "Yes") ; trash Director Haas
+        (prompt-choice :runner "Done")
+        (is (= 3 (:click-per-turn (get-corp))) "Corp down to 3 clicks per turn")))))
+
 (deftest trash-seen-and-unseen
   "Trash installed assets that are both seen and unseen by runner"
   (do-game


Detect prime numbers during prime factors computation

--- src/clj_mrazik/irc_bot.clj
+++ src/clj_mrazik/irc_bot.clj
@@ -98,7 +98,10 @@

 (defn print-prime-factors
     [input]
-    (str input " = " (clojure.string/join " x " (primefactors (Integer/parseInt input)))))
+    (let [factors (primefactors (Integer/parseInt input))]
+        (if (<= (count factors) 1)
+            (str input " is a prime number")
+            (str input " = " (clojure.string/join " x " factors)))))

 (defn print-gcd
     [input]


Rename to header and footer

Rename to header and footer

--- src/cljs/cglossa/core.cljs
+++ src/cljs/cglossa/core.cljs
@@ -11,19 +11,20 @@
 (defonce app-state (into {} (map-vals atom state)))
 (defonce app-data (into {} (map-vals atom data)))

-(defn navbar []
+(defn header []
   [:div.navbar.navbar-fixed-top [:div.navbar-inner [:div.container [:span.brand "Glossa"]]]])

-(defn bottom [_ {:keys [categories]}]
+(defn footer [_ {:keys [categories]}]
   [:div (for [cat @categories]
      [:div cat])])

 (defn app [s d]
   [:div
-   [navbar]
+   [header]
    [:div.container-fluid
-    [centre/top s d]]
-   [bottom s d]])
+    [centre/top s d]
+    [centre/bottom s d]]
+   [footer s d]])

 (defn ^:export main []
   (reagent/render-component


redo ordering short-circuit logic

redo ordering short-circuit logic

I realized I made an error by thinking that graph orderings are
completely determined by their first layer. This is only true if
there are no leaf nodes anywhere but the first and last layers. To
correct for this, I'm now tracking whether we've seen entire
orderings before, rather than just first layers.

--- src/cljs/fatlip/order.cljs
+++ src/cljs/fatlip/order.cljs
@@ -501,22 +501,23 @@
         rev-sparse-graph (rev sparse-graph)]
     (->>
      (cycle [sparse-graph rev-sparse-graph])
-     (reduce (fn [[orderings first-layers first-layer :as reduced-info]
+     (reduce (fn [[orderings ordering-set first-layer :as reduced-info]
                   input-graph]
-               ;; Graph orderings are determined by the first layer. If we've
-               ;; seen this first layer before, then we can be sure that we're
-               ;; about to enter a cycle, and can thus short circuit
-               (if (or (contains? first-layers first-layer)
+               (if (or (contains? ordering-set first-layer)
                        (= max-sweeps (count reduced-info)))
-                 (reduced [orderings first-layers first-layer])
+                 (reduced [orderings])
                  (let [graph (SparseGraph->OrderedGraph input-graph
                                                         first-layer)
                        layers (:layers graph)]
-                   ;; The last layer of the current ordering is the first layer
-                   ;; of the next
-                   [(conj orderings graph)
-                    (conj first-layers first-layer)
-                    (layers last-layer-idx)])))
+                   ;; If we see a graph that we've seen before, this is the
+                   ;; beginning of a cycle, and we can stop processing
+                   (if (contains? ordering-set graph)
+                     (reduced [orderings])
+                     ;; The last layer of the current ordering is the first
+                     ;; layer of the next
+                     [(conj orderings graph)
+                      (conj ordering-set first-layer)
+                      (layers last-layer-idx)]))))
              [[] #{} first-ordered-layer])
      first
      ;; This is sort of ugly, but once we order the nodes, we still have to


Fix part of last-form who got overwritten somehow

--- src/cljs/replumb/repl.cljs
+++ src/cljs/replumb/repl.cljs
@@ -727,7 +727,8 @@
         read #(read-string {:eof eof} source)]
     (loop [first-form (read)
            second-form (read)]
-      (if (identical? eof second)
+      (if (identical? eof second-form)
+        first-form
         (recur second-form (read))))))

 (defn process-load-file


Getting repository tree for chosen repository works

It doesn't yet cache trees, but it does keep the last
selected one in the db

--- src/cljs/repodoc/core.cljs
+++ src/cljs/repodoc/core.cljs
@@ -55,7 +55,7 @@

 ;; Data

-(def db {:data (get REPO "tree")
+(def db {:data nil
          :start 0
          :editing #{}
          :opened #{}
@@ -83,6 +83,22 @@
                   (swap! cdb #(assoc % key val)))
             :query (fn [key]
                  (get @cdb key))}))
+
+(defn get-repository-tree
+  [username repository sha]
+  (request {:url (str "https://api.github.com/repos/"
+                      username "/" repository
+                      "/git/trees/" sha "?recursive=1")}
+           (fn [data]
+             (updatedb [:repository] repository)
+             (updatedb [:username] username)
+             (updatedb [:data] (get data "tree")))))
+
+(defn get-repository-data
+  [username repository]
+  (request {:url (str "https://api.github.com/repos/" username "/" repository "/commits")}
+           (fn [commits]
+             (get-repository-tree username repository (get (first commits) "sha")))))

 ;; Handlers

@@ -211,7 +227,11 @@
 (defn ctrl []
   "https://api.github.com/repos/jussiarpalahti/repodoc/commits"
   (let [username (route_param "user")
-        repository (route_param "repository")]))
+        repository (route_param "repository")]
+    (if (or
+        (not= username (querydb [:username]))
+        (not= repository (querydb [:repository])))
+      (get-repository-data username repository))))

 (defn viewer
   [ctrl]