optimization pass (on par with Hiccup now)

--- src/rum/server_render.clj
+++ src/rum/server_render.clj
@@ -4,12 +4,35 @@
   (:import
     [clojure.lang IPersistentVector ISeq Named Numbers Ratio Keyword]))

-;; From Weavejester's Hiccup
-;; https://github.com/weavejester/hiccup/blob/master/src/hiccup/compiler.clj#L32
-(def ^{:doc "Regular expression that parses a CSS-style id and class from a tag name."
-       :private true}
-  re-tag #"([^\s\.#]+)(?:#([^\s\.#]+))?(?:\.([^\s#]+))?")
-
+
+(defn append!
+  ([^StringBuilder sb s0] (.append sb s0))
+  ([^StringBuilder sb s0 s1]
+    (.append sb s0)
+    (.append sb s1))
+  ([^StringBuilder sb s0 s1 s2]
+    (.append sb s0)
+    (.append sb s1)
+    (.append sb s2))
+  ([^StringBuilder sb s0 s1 s2 & rest]
+    (.append sb s0)
+    (.append sb s1)
+    (.append sb s2)
+    (doseq [s rest]
+      (.append sb s))))
+
+
+(defprotocol ToString
+  (^String to-str [x] "Convert a value into a string."))
+
+
+(extend-protocol ToString
+  Keyword (to-str [k] (name k))
+  Ratio   (to-str [r] (str (float r)))
+  String  (to-str [s] s)
+  Object  (to-str [x] (str x))
+  nil     (to-str [_] ""))
+

 (def ^{:doc "A list of elements that must be rendered without a closing tag."
        :private true}
@@ -18,36 +41,10 @@
     "meta" "param" "source" "track" "wbr"})

-;;; to-str
-
-(defprotocol ToString
-  (^String to-str [x] "Convert a value into a string."))
-
-
-(extend-protocol ToString
-  Keyword
-  (to-str [k] (name k))
-  Ratio
-  (to-str [r] (str (float r)))
-  String
-  (to-str [s] s)
-  Object
-  (to-str [x] (str x))
-  nil
-  (to-str [_] ""))
-
-
-(defn ^String as-str
-  "Converts its arguments into a string using to-str."
-  [& xs]
-  (apply str (map to-str xs)))
-
-
 (defn container-tag? [tag content]
-  (or content (not (void-tags tag))))
-
-
-;;; other
+  (or content
+      (not (contains? void-tags tag))))
+

 (def attr-mapping
   {:class-name "class"
@@ -57,9 +54,8 @@

 (defn react-attr->html ^String [attr]
-  (let [attr-str (-> (or (attr-mapping attr)
-                         (as-str attr))
-                     (str/lower-case))]
+  (let [^String attr-str (or (attr-mapping attr)
+                             (str/lower-case (to-str attr)))]
     (if (or (.startsWith attr-str "data-")
             (.startsWith attr-str "aria-")
             (.startsWith attr-str "-"))
@@ -69,8 +65,8 @@

 (defn escape-html
   "Change special characters into HTML character entities."
-  [^String text]
-  (.. ^String text
+  ^String [^String text]
+  (.. text
     (replace "&"  "&")
     (replace "<"  "<")
     (replace ">"  ">")
@@ -97,11 +93,6 @@
     (-> (into (dissoc tag-attrs :class)
               (dissoc attrs :class))
         (assoc :class class))))
-
-
-(defn strip-css
-  "Strip the # and . characters from the beginning of `s`."
-  [s] (if s (str/replace s #"^[.#]" "")))

 (defn match-tag
@@ -117,8 +108,13 @@
                            :default
                              [(first matches) (rest matches)])]
     [tag-name
-     (first (map strip-css (filter #(= \# (first %1)) names)))
-     (vec (map strip-css (filter #(= \. (first %1)) names)))]))
+     (->> names
+          (filter #(.startsWith ^String % "#"))
+          (map #(subs % 1))
+          first)
+     (->> names
+          (filter #(.startsWith ^String % "."))
+          (mapv #(subs % 1)))]))

 (defn normalize-element
@@ -151,7 +147,7 @@

 (defn normalize-css-key [k]
-  (-> (as-str k)
+  (-> (to-str k)
       (str/replace #"[A-Z]" (fn [ch] (str "-" (str/lower-case ch))))
       (str/replace #"^ms-" "-ms-")))

@@ -159,14 +155,14 @@
 (defn normalize-css-value [key value]
   (cond
     (contains? unitless-css-props key)
-      (escape-html (as-str value))
+      (escape-html (to-str value))
     (number? value)
       (str value (when (not= 0 value) "px"))
     (and (string? value)
          (re-matches #"\s*(\d+)\s*" value))
       (recur key (-> value str/trim Long/parseLong))
     :else
-      (escape-html (as-str value))))
+      (escape-html (to-str value))))

 (defn render-style [value]
@@ -175,14 +171,14 @@
              :let [key   (normalize-css-key k)
                    value (normalize-css-value key v)]]
          (str key ":" value ";"))
-       (str/join "")))
+       (str/join)))

 (defn normalize-classes* [cs]
   (cond
     (sequential? cs) (mapcat normalize-classes* cs)
     (set? cs)        (mapcat normalize-classes* cs)
-    :else            [(as-str cs)]))
+    :else            [(to-str cs)]))

 (defn normalize-classes [cs]
@@ -192,43 +188,41 @@
       (str/join " " cs))))

-(defn render-attr [[name value]]
-  (let [name (as-str name)]
+(defn render-attr! [name value sb]
+  (let [name (to-str name)]
     (cond
-      (true? value)    (str " " name "=\"\"")
-      (not value)      ""
+      (true? value)    (append! sb " " name "=\"\"")
+      (not value)      :nop
       (= "style" name) (let [style (render-style value)]
-                         (if (str/blank? style)
-                           ""
-                           (str " style=\"" style "\"")))
+                         (when-not (str/blank? style)
+                           (append! sb " style=\"" style "\"")))
       (= "class" name) (when-let [value (normalize-classes value)]
-                         (str " class=\"" value "\""))
-      :else            (str " " name "=\"" (as-str value) "\""))))
-
-
-(defn render-attr-map [attrs]
-  (->> attrs
-    (map render-attr)
-    (str/join "")))
+                         (append! sb " class=\"" value "\""))
+      :else            (append! sb " " name "=\"" (to-str value) "\""))))
+
+
+(defn render-attrs! [attrs sb]
+  (doseq [[key value] attrs]
+    (render-attr! key value sb)))

 ;;; render html

 (defprotocol HtmlRenderer
-  (-render-html [this parent *key]
+  (-render-html [this parent *key sb]
     "Turn a Clojure data type into a string of HTML with react ids."))

 (defn -render-element
   "Render an element vector as a HTML element."
-  [element *key]
+  [element *key sb]
   (let [[tag attrs content] (normalize-element element)
         key                 @*key
         _                   (vswap! *key inc)
         attrs               (cond-> attrs
                               true       (dissoc :key)
-                              (== key 1) (assoc :data-reactroot "")
+                              (== key 1) (assoc  :data-reactroot "")
                               true       (assoc  :data-reactid key))
         inner-html          (:dangerouslysetinnerhtml attrs)
         attrs               (if inner-html
@@ -241,52 +235,53 @@
       (when-not (:__html inner-html)
         (throw (Exception. "Invariant Violation: `props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information."))))

+    (append! sb "<" tag)
+    (render-attrs! attrs sb)
+
     (if (container-tag? tag content)
-      (str "<" tag (render-attr-map attrs) ">"
-           (if inner-html
-             (:__html inner-html)
-             (-render-html content element *key))
-           "</" tag ">")
-      (str "<" tag (render-attr-map attrs) "/>"))))
+      (do
+        (append! sb ">")
+        (if inner-html
+          (append! sb (:__html inner-html))
+          (-render-html content element *key sb))
+        (append! sb "</" tag ">"))
+      (append! sb "/>"))))

 (extend-protocol HtmlRenderer
   IPersistentVector
-  (-render-html [this parent *key]
-    (-render-element this *key))
+  (-render-html [this parent *key sb]
+    (-render-element this *key sb))

   ISeq
-  (-render-html [this parent *key]
-    (str/join ""
-      (for [element this]
-        (-render-html element this *key))))
+  (-render-html [this parent *key sb]
+    (doseq [element this]
+      (-render-html element this *key sb)))

   Named
-  (-render-html [this parent *key]
-    (name this))
+  (-render-html [this parent *key sb]
+    (append! sb (name this)))

   String
-  (-render-html [this parent *key]
+  (-render-html [this parent *key sb]
     (if (> (count parent) 1)
       (let [key @*key]
         (vswap! *key inc)
-        (str "<!-- react-text: " key " -->"
-             (escape-html this)
-             "<!-- /react-text -->"))
-      (escape-html this)))
+        (append! sb "<!-- react-text: " key " -->" (escape-html this) "<!-- /react-text -->"))
+      (append! sb (escape-html this))))

   Object
-  (-render-html [this parent *key]
-    (-render-html (str this) parent *key))
+  (-render-html [this parent *key sb]
+    (-render-html (str this) parent *key sb))

   nil
-  (-render-html [this parent *key]
-    ""))
+  (-render-html [this parent *key sb]
+    :nop))

 ;; https://github.com/facebook/react/blob/master/src/shared/utils/adler32.js
-(defn adler32 [^String s]
-  (let [l (count s)
+(defn adler32 [^StringBuilder sb]
+  (let [l (.length sb)
         m (bit-and l -4)]
     (loop [a (int 1)
            b (int 0)
@@ -294,10 +289,10 @@
            n (min (+ i 4096) m)]
      (cond
        (< i n)
-       (let [c0 (int (.charAt s i))
-             c1 (int (.charAt s (+ i 1)))
-             c2 (int (.charAt s (+ i 2)))
-             c3 (int (.charAt s (+ i 3)))
+       (let [c0 (int (.charAt sb i))
+             c1 (int (.charAt sb (+ i 1)))
+             c2 (int (.charAt sb (+ i 2)))
+             c3 (int (.charAt sb (+ i 3)))
              b  (+ b a c0
                      a c0 c1
                      a c0 c1 c2
@@ -309,7 +304,7 @@
        (recur a b i (min (+ i 4096) m))

        (< i l)
-       (let [c0 (int (.charAt s i))]
+       (let [c0 (int (.charAt sb i))]
          (recur (+ a c0) (+ b a c0) (+ i 1) n))

        :else
@@ -321,7 +316,7 @@
 (defn render-html
   ([src] (render-html src nil))
   ([src opts]
-    (let [result   (-render-html src nil (volatile! 1))
-          checksum (adler32 result)]
-      (str/replace-first result " data-reactid=\"1\""
-        (str " data-reactid=\"1\" data-react-checksum=\"" checksum "\"")))))
+    (let [sb (StringBuilder.)]
+      (-render-html src nil (volatile! 1) sb)
+      (.insert sb (.indexOf sb ">") (str " data-react-checksum=\"" (adler32 sb) "\""))
+      (str sb))))


part-time-simple: remove incorrect docstring.

--- src/riemann/streams.clj
+++ src/riemann/streams.clj
@@ -494,11 +494,6 @@
   nothing. (create) may be invoked partway through a window, and should be
   idempotent, as it will be run inside of (swap!).

-  IMPORTANT: part-time-simple is analogous to, but not the same as,
-  part-time-fast. Part-time-fast ignored the return value of (add) and expected
-  that (add) would mutate its own state. Part-time-simple handles state for
-  you: (add state event) is expected to return the new state.
-
   Concurrency guarantees:

   (create) may be called multiple times for a given time slice.


add core.clj

add core.clj

error: pathspec 'src/clj_money/core.clj' did not match any file(s) known to git

--- src/clj_money/core.clj
+++ src/clj_money/core.clj
@@ -0,0 +1,10 @@
+(ns clj-money.core
+  (:require [clj-time.format :refer [unparse-local-date
+                                     formatters]])
+  (:import org.joda.time.LocalDate))
+
+(defmethod print-method LocalDate [this ^java.io.Writer w]
+  (doto w
+    (.write "#local-date \"")
+    (.write (unparse-local-date (:year-month-day formatters) this))
+    (.write "\"")))


CMR-4621: Add a test to verify the queue broker wrapper moves messages to a failed state after all retries are exhausted.

error: pathspec 'message-queue-lib/test/cmr/message_queue/test/queue/queue_broker_wrapper_test.clj' did not match any file(s) known to git

--- message-queue-lib/test/cmr/message_queue/test/queue/queue_broker_wrapper_test.clj
+++ message-queue-lib/test/cmr/message_queue/test/queue/queue_broker_wrapper_test.clj
@@ -0,0 +1,51 @@
+(ns cmr.message-queue.test.queue.queue-broker-wrapper-test
+  "Functions for testing the queue broker wrapper we use for testing."
+  (:require
+    [clojure.test :refer :all]
+    [cmr.common.lifecycle :as lifecycle]
+    [cmr.message-queue.queue.memory-queue :as memory-queue]
+    [cmr.message-queue.queue.queue-protocol :as queue-protocol]
+    [cmr.message-queue.test.queue-broker-wrapper :as queue-broker-wrapper]))
+
+(def queue-name "test-queue")
+
+(def queue-config
+  "Message queue configuration for the test."
+  {:queues [queue-name]
+   :exchanges ["test-exchange"]
+   :queues-to-exchanges {"test-queue" ["test-exchange"]}})
+
+(defn- retry-handler
+  "A handler that forces a retry"
+  [& args]
+  (throw (Exception. "force retry")))
+
+(defn- get-number-of-retries
+  "Returns the number of times a message was retried."
+  [message message-history]
+  (let [relevant-messages (->> message-history
+                               (keep #(first (:messages %)))
+                               (filter #(= (:name message) (:name %))))
+        retry-counts (keep :retry-count relevant-messages)]
+    (apply max 0 retry-counts)))
+
+(defn- get-final-state
+  "Returns the final state of a message."
+  [message-history]
+  (-> message-history last :action :message :state))
+
+(deftest retries-exhausted-test
+  (let [queue-broker (memory-queue/create-memory-queue-broker queue-config)
+        queue-wrapper (lifecycle/start
+                        (queue-broker-wrapper/create-queue-broker-wrapper queue-broker) nil)
+        message {:name "test-retries"}]
+    ;; Add a listener that will always return a failure when processing a message
+    (queue-protocol/subscribe queue-wrapper queue-name retry-handler)
+    (queue-protocol/publish-to-queue queue-wrapper queue-name message)
+    (queue-broker-wrapper/wait-for-terminal-states queue-wrapper)
+    (let [message-history (queue-broker-wrapper/get-message-queue-history queue-wrapper queue-name)
+          number-of-retries (get-number-of-retries message message-history)
+          final-state (get-final-state message-history)]
+      (is (= 5 number-of-retries))
+      (is (= :failure final-state)))
+    (lifecycle/stop queue-wrapper nil)))


added boolean type hint

added boolean type hint

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/clojure-ml/cml.git/'


increment-keys cleanup

increment-keys cleanup

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/terrancesnyder/engulf.git/'


Dotfiles: add leiningen profiles

Dotfiles: add leiningen profiles

error: pathspec 'lein/profiles.clj' did not match any file(s) known to git

--- lein/profiles.clj
+++ lein/profiles.clj
@@ -0,0 +1,2 @@
+{:user {:plugins [[swank-clojure "1.4.2"]
+                  [lein-localrepo "0.4.0"]]}}


Revert "Improve consistency in sequence function implementation."

This reverts commit c2df72df15a7cdcbbc66da64fc929c203c532d0d.

--- src/cats/core.cljc
+++ src/cats/core.cljc
@@ -289,11 +289,11 @@
   (let [ctx (get-current-context (first mvs))]
     (with-monad ctx
       (reduce (fn [mvs mv]
-                (mlet [v mv
-                       vs mvs]
-                  (return (conj vs v))))
-              (return [])
-              mvs))))
+                 (mlet [v mv
+                        vs mvs]
+                       (return (cons v vs))))
+              (return '())
+              (reverse mvs)))))

 (defn mapseq
    "Given a function that takes a value and puts it into a


experimental lang2

experimental lang2

error: pathspec 'src/ysmiraak/lang2.clj' did not match any file(s) known to git

--- src/ysmiraak/lang2.clj
+++ src/ysmiraak/lang2.clj
@@ -0,0 +1,243 @@
+(ns ysmiraak.lang
+  (:refer-clojure :exclude [var?]))
+
+;; goals
+;; 1. unify terms and types (basic constructors shared by types and data)
+;; 2. unify composition and application (????)
+;; 3. compositional lambda calculus (variables and their evaluation rules)
+;; 4. asap beta reduction (partial evaluation)
+
+;; val  = data                -- what evaluates to itself
+;; var  = symbol              -- what serves as a placeholder
+;; expr = val | var | [expr]  -- what can be (partially) evaluated
+;; form = expr | term
+;; term = expr & vars
+;; vars = set var
+;; args = vec var
+
+;; term = form | var | val
+;; form = expr & vars
+;; expr = beta | forall
+;;
+;; expr are always wrapped in form
+;; vars only reduces during evaluation
+;;
+;; val    => val
+;; var    => val | var
+;; form   => form | var | val
+;; beta   => form | beta | var | val
+;; forall => forall
+
+(defrecord Var    [name])         (defn var?    [x] (instance?  Var    x))
+(defrecord Form   [expr vars])    (defn form?   [x] (instance?  Form   x))
+(defrecord Beta   [sexp])         (defn beta?   [x] (instance?  Beta   x))
+(defrecord Forall [term args])    (defn forall? [x] (instance?  Forall x))
+(defprotocol Expr)                (defn expr?   [x] (satisfies? Expr   x))
+(extend-protocol Expr Beta Forall)
+
+(defprotocol Term
+  "
+
+  fv
+
+  ev
+
+  - substitutes all keys in expr to vals in env (: map var val)
+  - beta reduces a term whose expr has a Forall as head
+
+  "
+  (fv [this])
+  (ev [this env]))
+
+(extend-protocol Term
+
+  Var
+  (fv [this] #{this})
+  (ev [this env] (env this this))
+
+  Form
+  (fv [this] (:vars this))
+  (ev [{:keys [expr vars]} env]
+    (let [;; evaluates expr if necessary
+          term (if (some vars (keys env)) (ev expr env) expr)
+          vars (if (form? term) (:vars term) (reduce disj vars (keys env)))
+          term (if (form? term) (:expr term) term)
+          ;; now term is not a form
+          term (if (and (beta? term) (empty? vars))
+                 (as-> (:sexp term) [head & body]
+                   (apply head body))
+                 term)]
+      (if (expr? term)
+        (Form. term vars)
+        term)))
+
+  Beta
+  (ev [this env]
+    (as-> (:sexp this) [head & body :as sexp]
+      ;; evalutes sexp if necessary
+      (cond->> sexp (seq env) (map #(ev % env)))
+      (if (and (form? head) (forall? (:expr head)))
+        (let [{:keys [expr vars]} head
+              {:keys [term args]} expr
+              env (zipmap args body)
+              num (count body)]
+          (case (compare (count args) num)
+            ;; curry
+            1 (-> (ev term env)
+                  (Forall. (subvec args num))
+                  (Form. (reduce disj vars (keys env))))
+            ;; beta-reduce
+            0 (as-> (ev term env) term
+                (if (expr? term)
+                  (Form. term (reduce disj vars (keys env)))
+                  term))
+            (throw (ex-info "arity error" {:args args :vals body}))))
+        (Beta. sexp))))
+
+  Forall
+  (ev [{:keys [term args]} env]
+    (let [env  (reduce dissoc env args) ; evalutes term if necessary
+          term (cond-> term (seq env) (ev env))]
+      (if (and (form? term) (forall? (:expr term)))
+        (as-> (:expr term) expr ; uncurries
+          (assoc expr :args (into args (:args expr))))
+        (Forall. term args))))
+
+  Object
+  (fv [this] #{})
+  (ev [this env] this)
+
+  nil
+  (fv [this] #{})
+  (ev [this env] this))
+
+(defn ?%
+  "takes a term and interleaving var-terms and values, (partially)
+  evaluates the term according to the binding.
+
+  similar to let, this can be seen as performing a lambda-abstraction
+  immediately followed by a beta reduction (a left-left lambda).
+
+  ```
+  ((fn [a b] phi) x y)
+  (let [a x b y] phi)
+  (?% phi a x b y)
+  (? (% phi a b) x y)
+  ```
+
+  "
+  [term & {:as env}]
+  (ev term env))
+
+(defn ?
+  "funcall, the counit of product-exponential adjunction"
+  ([& terms]
+   (as-> (ev (Beta. terms) {}) term
+     (if (beta? term)
+       (ev (Form. term (apply clojure.set/union (map fv terms))) {})
+       term)))
+  ([]))
+
+(defn %
+  "forall"
+  ([term & args] ; currently args can only be vars
+   (-> (Forall. term (vec args))
+       (ev {})
+       (Form. (reduce disj (if (form? term) (:vars term) #{}) args))
+       (ev {})))
+  ([term] term))
+
+(defn !
+  "produces a fresh or named var"
+  ([name] (Var. name))
+  ([] (! (gensym "!"))))
+
+(comment
+
+  (def a (! 'a))
+  (def b (! 'b))
+  (def c (! 'c))
+
+  (def phi (? + a b))
+  (def chi (% phi b))
+  (def psi (% chi a))
+
+  ;; binding
+  (= (-> phi (% b) (% a))
+     (-> phi (% a b)))
+
+  ;; currying
+  (= 4 (? psi 2 2))
+  (= 4 (? (? psi 2) 2))
+
+  ;; partial eval
+  (=    (? + a 2)          (? chi 2))
+  (= (% (? + a 2) a)    (% (? chi 2) a))
+  (=    (? + 2 2)    (? (% (? chi 2) a) 2))
+
+  (= 1 (? (% (? (% a a) 1) a) 0))
+  (= 4 (? (% (? apply ? chi [2]) a) 2))
+
+  (? map (partial ? psi) (range) (range))
+
+  ;; non-terminating term
+  (? (% (? ? a a) a) (% (? ? a a) a))
+
+  ;; todo test recursion
+
+  )
+
+(comment ; todo goal 1
+
+  ;; let
+  ;; - A B C be types
+  ;; - a b c be variables
+  ;; - x y z be values
+
+  ;; types all the way down
+  ($ Type A x nil)
+
+  ;; A -> B
+  ($ Type
+     (%'   A       B)
+     (% ($ A a) ($ B (... a ...)))
+     nil)
+
+  ;; forall (a : A) . C(a)
+  ($ Type
+     (%'   A       Type)
+     (% ($ A a)    (C a))
+     (% ($ A a) ($ (C a) (... a ...)))
+     nil)
+
+  ;; forall (a : A , b : B) . C(a)
+  ($ Type
+     (%'   A       Type    Type)
+     (% ($ A a)    B       (C a))
+     (% ($ A a) ($ B b) ($ (C a) (... a ... b ...)))
+     nil)
+
+  ;; exists (a : A , b : B) . C(a)
+  ($ Type
+     (&'   A       Type    Type)
+     (& ($ A a)    B       (C a))
+     (& ($ A x) ($ B y) ($ (C x) (... x ... y ...)))
+     nil)
+
+  ;; exists (a : A) . C(a)
+  ($ Type
+     (&'   A       Type)
+     (& ($ A a)    (C a))
+     (& ($ A x) ($ (C x) (... x ...)))
+     nil)
+
+  ;; (A, B)
+  ($ Type
+     (&    A       B)
+     (& ($ A x) ($ B y))
+     nil)
+
+  )
+
+;; todo
+;; - test how to replace var using env


Fix column titles in Raw SQL queries with lots of columns

--- src/metabase/driver/generic_sql/native.clj
+++ src/metabase/driver/generic_sql/native.clj
@@ -43,7 +43,7 @@
                (let [[columns & [first-row :as rows]] (jdbc/query t-conn sql, :as-arrays? true)]
                  {:rows    rows
                   :columns columns
-                  :cols    (for [[column first-value] (zipmap columns first-row)]
+                  :cols    (for [[column first-value] (partition 2 (interleave columns first-row))]
                              {:name      column
                               :base_type (value->base-type first-value)})})


Compound components and js events.

Compound components and js events.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/inchingforward/eon.git/'


Move Midje 101 stuff to here from elsewhere.

error: pathspec 'test/com/nomistech/clojure_the_language/midje_test.clj' did not match any file(s) known to git

--- test/com/nomistech/clojure_the_language/midje_test.clj
+++ test/com/nomistech/clojure_the_language/midje_test.clj
@@ -0,0 +1,818 @@
+(ns com.nomistech.clojure-the-language.midje-test
+  (:require [midje.sweet :refer :all]
+            ;; [com.nomistech.clojure-the-language.midje :refer :all]
+            ))
+
+;;;; Most of these facts evaluate to `true`. A few examples fail and
+;;;; evaluate to `false`. I only show results when false.
+
+;;;; Many/most of these examples are direct copies of examples in the
+;;;; Midje documentation.
+
+;;;; ___________________________________________________________________________
+;;;; Basic syntax
+
+(fact 3 => 3)
+
+(fact "Description" 3 => 3)
+
+(fact "Description"
+      3 => 3
+      4 => 4
+      5 => 5)
+
+;;;; ___________________________________________________________________________
+;;;; Some Terminology
+
+;;;; /x => y/ is a /checkable/.
+
+;;;; ___________________________________________________________________________
+;;;; What's the exact syntax?
+
+;;;; See https://github.com/marick/Midje/wiki/Syntax-and-a-little-semantics
+
+;;; Comment this out because it messes things up when I run tests.
+;; (fact
+;;  "The descriptions go with the fact, not with the checkables." 3 => 3
+;;  "Not a description, just a form somewhere" 3 => 4)
+;; ;; FAIL "The descriptions go with the fact, not with the checkables."
+;; ;; => false
+
+(fact :x :y)
+;; Ah! I guess without the `=>` Midje just passes stuff on to be evaluated:
+(fact)
+(comment
+  (fact (println 1) (println 2))
+  ;; 1
+  ;; 2
+  )
+;;;; ___________________________________________________________________________
+;;;; Future facts
+
+(future-fact "Description" (plop 6) => 7)
+;; WORK TO DO "Description" at (NO_SOURCE_FILE:1)
+;; => nil
+
+(fact "Description" (plop 6) =future=> 7)
+;; WORK TO DO "Description - on `(plop 6)`" at (NO_SOURCE_FILE:1)
+
+
+;;;; ___________________________________________________________________________
+
+;;;; You cannot test Midje using Midje (or at least using the features
+;;;; of Midje that are described to a beginner). The fact that `fact`
+;;;; returns values can't be tested. And (not surprisingly) the inner
+;;;; failure gets reported. (Maybe there's something less simplistic
+;;;; you can do. You should take a look at how Midje is tested.)
+
+;;;; Ah! But there's `=test=>`.  I think that might be what you'd need.
+
+;;; Comment this out because it messes things up when I run tests.
+;; (fact (fact 3 => 4)
+;;       => false)
+;; ;; => false
+
+;;;; ___________________________________________________________________________
+;;;; Functions on the RHS
+
+(fact 3 => odd?)
+(fact 3 => (if true odd? even?))
+(fact 3 =not=> (if false odd? even?))
+
+;;;; ___________________________________________________________________________
+;;;; Terminology:
+
+;;;; In the above, the RHS of the `=>` is called a /checker/.
+;;;; - Q. Is this true when the RHS is a simple value?
+
+;;;; ___________________________________________________________________________
+;;;; Regular expressions on the RHS
+
+(fact "aabbcc" => #"a+b+c+")
+
+;;;; ___________________________________________________________________________
+;;;; =not=> and =deny=> (synonyms, I think, though hard to tell by looking at
+;;;; their definitions)
+
+(fact 3 =not=> 4)
+(fact 3 =deny=> 4)
+
+;;;; ___________________________________________________________________________
+;;;; Example from docs
+
+(defn each-element-is-one-of [expected-elements]
+  (fn [actual]
+    (every? (set expected-elements) actual)))
+
+(fact [1 2] => (each-element-is-one-of [1 2 3 4]))
+
+;;;; I think we can do this more naturally like this:
+
+;;;; - Now a more natural way of doing the `each-element-is-one-of`
+;;;;   example above:
+
+(fact [1 2] => #(clojure.set/subset? % [1 2 3 4]))
+
+;;;; Perhaps what you say is true for subset, but you have `details=`
+;;;; in Tea Knots (tea-knots.domain.tasks-test) and that seems useful.
+
+;;;; ___________________________________________________________________________
+;;;; `truthy` and `falsey`
+
+(fact 3 =not=> true)
+(fact 3 => truthy)
+
+(fact 3 =not=> falsey)
+(fact false => falsey)
+(fact nil => falsey)
+
+;;;; ___________________________________________________________________________
+;;;; `anything` or `irrelevant`
+
+;;;; These are synonyms.
+;;;; Used for "don't care" arguments in prerequisites.
+;;;; Could also use it to say that you make no assertions about
+;;;; the result of a function.
+;;;; jsk: I'm not sure when you'd use the latter.
+
+(fact 3 => anything)
+
+;;;; ___________________________________________________________________________
+;;;; `exactly'
+
+;;;; Avoid the special interpretation of functions on the RHS of checkables.
+;;;; jsk: Seems like a bad name to me.
+;;;;      In fact I'd prefer a special syntax like `(satisfies ...)`
+;;;;      rather than the special interpretaion of functions and regexs.
+
+(fact odd? =not=> odd?)
+;; (even though you might expect
+;; java.lang.IllegalArgumentException: Argument must be an integer)
+;; as you get for (odd? odd?) -- I think Midje catches exceptions)
+
+(fact odd? => (exactly odd?))
+
+;;;; ___________________________________________________________________________
+;;;; `roughly`
+
+;;;; True if the actual value is within number ± range.
+;;;; If range is not given, it's taken to be 1/1000th of number.
+
+(fact 3.003 => (roughly 3))
+(fact 3.004 =not=> (roughly 3))
+(fact 3.004 => (roughly 3 0.004))
+
+;;;; jsk: There's imprecise representation to be taken into account here.
+
+;;;;___________________________________________________________________________
+;;;; `throws`
+
+;;;; Can check for exception class, for error message using string or regex,
+;;;; and using a predicate.
+
+;;;; **** Documentation error: predicates apply to the exception, not
+;;;;      the message.
+
+(defn my-throw []
+  (throw (java.io.IOException. "My error message.")))
+
+(fact 3 =not=> (throws))
+
+(fact (my-throw) => (throws))
+(fact (my-throw) => (throws java.io.IOException))
+(fact (my-throw) => (throws "My error message."))
+(fact (my-throw) => (throws #"error"))
+(fact (my-throw) => (throws #(instance? java.io.IOException %)))
+
+(fact (my-throw) => (throws "My error message."
+                            #"error"
+                            #(instance? java.io.IOException %)
+                            java.io.IOException))
+
+(fact (my-throw) => (throws "My error message."
+                            "My error message."
+                            #"error"
+                            #"error"
+                            #(instance? java.io.IOException %)
+                            #(instance? java.io.IOException %)
+                            java.io.IOException))
+
+;;;; **** Documentation error: It says there can be a most one class
+;;;;      argument, but (**** and this might be useful with to specify
+;;;;      a superclass and a subclass)...
+
+(fact (my-throw) => (throws Exception java.io.IOException))
+
+;;;; ___________________________________________________________________________
+;;;; Checking sequential collections
+
+;;;; just
+;;;; Use extended equaility.
+;;;; **** Why is it called "just"?  It makes no sense to me.
+
+(fact
+ [1 2 3] => (just [odd? even? odd?]))
+
+(fact
+ ["a" "aa" "aaa"] (just [#"a+" #"a+" #"a+"]))
+
+(fact
+ "You can omit the brackets (**** jsk: yeuch!)"
+ [1 2 3] => (just odd? even? odd?))
+
+(fact
+ "extended equality only applies to the top level"
+ [[[1]]] =not=> (just [[[odd?]]])
+ [[[1]]] =not=> [[(just odd?)]])
+
+(fact
+ "you have to do this"
+ [[[1]]] => (just (just (just odd?))))
+
+
+;;;; just and not caring about order
+
+(fact
+ [2 1 3] => (just #{1 2 3})
+ [2 1 3] => (just [1 2 3] :in-any-order)
+ [2 1 3] => (just 1 2 3 :in-any-order) ; **** jsk: yeuch++!
+ [1 3] => (just [odd? 1] :in-any-order) ; doesn't over-commit to matches
+ )
+
+;;;; contains
+;;;; For matching subsequences.
+
+(facts
+ (letfn [(a? [x] (#{:a "a"} x))
+         (b? [x] (#{:b "b"} x))]
+   ;; match a subsequence
+   (fact [0 :a :b "a" 0] =>     (contains [b? a?]))
+   (fact [0 :a :b "a" 0] =not=> (contains [a? a?]))
+   (fact [0 :a :b "a" 0] =>     (contains [b?]))
+   (fact [0 :a :b "a" 0] =>     (contains b?))
+   ;; :in-any-order
+   (fact [0 :a :b 0]   =>     (contains #{b? a?}))
+   (fact [0 :a :b 0]   =>     (contains [b? a?] :in-any-order))
+   (fact [0 :a 0 :b 0] =not=> (contains [b? a?] :in-any-order))
+   ;; :gaps-ok
+   (fact [0 :a :b "a" 0] => (contains [a? a?] :gaps-ok))
+   ;; :in-any-order and :gaps-ok
+   (fact [0 :a 0 :b 0] => (contains [b? a?] :in-any-order :gaps-ok))
+   ;; Marick: "Note: the algorithm used for this complicated case is
+   ;; inefficient and also won't work on longer sequences. I keep
+   ;; hoping someone will replace it."
+   ))
+
+;;; Only for use with extended equality.
+;;; So, unlike `has-prefix` and `has-suffix`.
+;;; **** Feels wrong.
+;;; This raises an exception:
+;;;   (fact [1 2 3] => (contains? 2 3))
+
+;;;; **** The word "contains" feels wrong because it's usually used
+;;;;      for elements rather than subsequences.
+;;;;      See examples below.
+
+(facts
+ (letfn [(a? [x] (#{:a "a"} x))
+         (b? [x] (#{:b "b"} x))]
+   (fact "Leaving off brackets with a single item has the meaning I expect"
+         [0 :a 0] => (contains a?))
+   (facts "**** What I'd expect the word 'contains' to mean, and
+                what you have to do instead"
+          (fact "I'd expect this to succeed with `=>`"
+                [0 :a [:b "a"] 0] =not=> (contains [b? a?]))
+          (fact "What you have to do instead"
+                [0 :a [:b "a"] 0] => (contains (just [b? a?]))))))
+
+;;;; has-prefix
+
+;;; **** Marick says "Whereas contains finds matches anywhere within the
+;;; sequence, has-prefix forces the match to be at the beginning". But
+;;; there's also the fact that `contains` uses extended equality and
+;;; `has-prefix` does not.
+
+(fact "has-prefix is anchored to the left"
+      [1 2 3] =not=> (has-prefix [2 3]) ; it's not a prefix
+      [1 2 3] =>     (has-prefix [1 2])
+      [1 2 3] =not=> (has-prefix [2 1]) ; order matters
+      [1 2 3] =>     (has-prefix [2 1] :in-any-order)
+      [1 2 3] =>     (has-prefix #{2 1}))
+
+;;;; has-suffix
+
+;;; Like `has-prefix`.
+
+;;;; n-of Marick: "These are used to avoid giving just a sequence of n
+;;;; identical elements"
+
+(fact "one checker to match exactly N elements."
+      ["a"] => (one-of "a")
+      [:k :w] => (two-of keyword?)
+      ["a" "aa" "aaa"] => (three-of #"a+")
+      ;; ...
+      [1 3 5 7 9 11 13 15 17] => (nine-of odd?)
+      ["a" "b" "c" "d" "e" "f" "g" "h" "i" "j"] => (ten-of string?)
+      ;; to go above ten-of
+      (repeat 100 "a") => (n-of "a" 100)
+      ;; nesting
+      [[2 4] [6 8]] => (two-of (two-of even?)))
+
+;;;; has
+
+(facts
+ (fact "You can do this"
+       [2 3 4] =>     (partial some odd?)
+       [2 4 6] =not=> (partial some odd?))
+ (fact "Some more elaborate uses of partial will not work as you expect,
+        because of a mistake in Midje's design (which will be fixed)."
+       [[1] [2]] => (partial every? (just [1])))
+ (fact "Use `has` instead"
+       [[1] [2]] =not=> (has every? (just [1])))
+ (fact "`has` allows regular expressions"
+       ["ab" "aab" "aaab"] => (has every? #"a+b")
+       [1 2 3] => (has not-any? #"a+b")))
+
+;;;; ___________________________________________________________________________
+;;;; Collection checkers and strings
+
+;;;; Marick: "Because Clojure treats strings as a sequence of
+;;;; characters, the sequence checkers checkers apply. Given regular
+;;;; expressions, they're seldom useful."
+
+;;;; See https://github.com/marick/Midje/wiki/Collection-checkers-and-strings.
+
+;;;; ___________________________________________________________________________
+;;;; Checking maps and records
+
+(defrecord R [x y])
+(defrecord NotR [x y])
+
+(fact
+ ;; That the left-hand side below is a record is irrelevant:
+ (R. 1 2) => {:x 1, :y 2}
+ ;; The contents of the left are compared to the right in exactly
+ ;; the same way as if both sides were maps:
+ {:x 1, :y 2} => {:x 1, :y 2})
+
+(fact
+ ;; (**** The example has an extra right parenthesis.)
+ "using a record on the right implies that you care about *both* contents and type"
+ ;; **** bug: The following two fail; thay also fails with `=>`.
+ ;;           (Hmmm, so how well tested is Midje?)
+ ;; {:x 1, :y 2} =not=> (R. 1 2)
+ ;; (NotR. 1 2)  =not=> (R. 1 2)
+ (R. 1 2)     =>     (R. 1 2))
+
+;;;; You can use `just` for extended equality.
+;;;; Use `contains` when you don't care about parts of a map or record
+
+(facts
+ (fact "`just` provides extended equality"
+       {:a 1, :b 2, :c "some text"} => (just {:a odd?, :b 2, :c #"text"}))
+ (fact "`contains` ignores unmentioned keys"
+       (R. 1 2) => (contains {:x 1}))
+ (fact "`contains` provides extended equality"
+       (R. 1 2) => (contains {:x odd?})))
+
+;;;; In both of the previous examples, `contains` will ignore the type
+;;;; of the left-hand side. If you want to say specifically that the
+;;;; left-hand side is an R that contains an odd :x, use a combining
+;;;; checker:
+
+(fact
+ (R. 1 2) => (every-checker #(instance? R %)
+                            (contains {:x 1})))
+
+;;;; `has` works with quantifiers and values
+
+(fact "`has` quantifies over values"
+      {:a 1, :b 3} => (has every? odd?)
+      {:a 1, :b 3} => (has some #(= 1 %)))
+
+;;;; Making claims about keys is more awkward
+
+(fact
+ "ways to make claims about keys"
+ (fact "Contains every key -- two ways"
+       (keys {:x 1, :y 1}) => (just #{:x :y})
+       {:x 1, :y 1} => (just {:x anything, :y anything}))
+ (fact "Contains some of the keys -- two ways"
+       (keys {:x 1, :y 1}) => (contains #{:x})
+       {:x 1, :y 1} => (contains {:x anything})))
+
+;;;; Map entries
+;;;; The just and contains right-hand sides can take arrays of pairs
+;;;; (or Java MapEntry objects) instead of a map or record:
+
+(fact
+ "a sequence of key/value pairs is OK on the right-hand side"
+ {:a 1, :b 2} => (just [[:a 1] [:b 2]])
+ (R. 1 nil) => (contains [[:x 1]]))
+
+;;;; ___________________________________________________________________________
+;;;; Checking sets
+
+;;;; Checking the whole set
+
+(fact "`just` provides extended equality for sets"
+      #{3 8 1} => (just odd? 3 even?))
+
+(fact "checking properties of known number of elements"
+      #{1 3 5} => (three-of odd?))
+
+(fact "number irrelevant"
+      #{1 3 5} => (has every? odd?))
+
+;;;; Checking a subset
+
+(fact "subsets of literal values"
+      #{1 2 3} => (contains 3))
+
+(fact "subsets of checkers"
+      #{1 2 3} => (contains odd? even?)) ; **** example has extra right parenthesis.
+
+;;;; ___________________________________________________________________________
+;;;; Combining checkers
+
+;;;; `every-checker` can take any argument that can appear on the
+;;;; right-hand side of a checkable, including values to be compared
+;;;; with ordinary equality.
+
+(fact 5 => (every-checker 5 odd? (roughly 5)))
+
+(fact "aaab" => (every-checker #"a+b" #(= 4 (count %))))
+
+;;;; `some-checker` fails only if all of its constituent checkers
+;;;; fail. If any succeeds, some-checker stops checking and succeeds
+;;;; itself.
+
+(fact 4 =>     (some-checker odd? (roughly 4)))
+(fact 4 =not=> (some-checker odd? (roughly 3)))
+
+;;;; ___________________________________________________________________________
+;;;; Setup and teardown
+
+;;;; Marick: "Testing code that works with mutable state often
+;;;; requires that you change that state before or after a fact or
+;;;; checkable. Midje has two ways to do that, one baroque and
+;;;; deprecated, one simpler and encouraged."
+
+;;;; Here's the simpler approach.
+
+;;; (with-state-changes [(before :facts ...)]
+;;;   (fact ...)
+;;;   (fact ...)
+;;;   ...)
+;;;
+;;; (with-state-changes [(after :facts ...)]
+;;;   (fact ...)
+;;;   (fact ...))
+;;;
+;;; (with-state-changes [(around :facts (... ?form ...))]
+;;;   (fact ...)
+;;;   (fact ...))
+
+;;;; Nesting currently gets things a bit wrong.
+
+;;;; REPL and whole-file support
+;;;; For if you want to test individual facts in the REPL.
+;;;; I think it means "namespace", not "whole file".
+
+;;;; ___________________________________________________________________________
+;;;; Tabular facts
+
+;;;; ___________________________________________________________________________
+;;;; Chatty checkers
+;;;; https://github.com/marick/Midje/wiki/Chatty-checkers
+
+;;;; Chatty checkers provide extra information about a failure.
+
+;;;; There are three ways to create them. Two depend on a checker
+;;;; function having the right "shape". The other is less convenient,
+;;;; but more general.
+
+;;;; (1) `every-checker` and `some-checker`.
+
+;;;; (2) `chatty-checker` converts each top-level function application
+;;;;     in its body into a form that reports its results.
+
+;;;; (3) Adding notes to checker failures
+;;;;     Marick: "Note: this implementation is nicely functional and
+;;;;     all that, but it's actually awkward for the Midje
+;;;;     implementation and prone to error. It may be replaced in
+;;;;     later versions of Midje."
+
+;;;; ___________________________________________________________________________
+;;;; Testing private functions
+
+;;;; Three ways:
+
+;;;; (1) Can use `#'` to get any var.
+;;;;     This is ugly, but only this way works in prerequisites (which
+;;;;     is perhaps an argument for always using this way).  That's
+;;;;     because the other ways copy vars.
+
+;;;  (fact (#'scratch.core/super-secret-function 1) => 6)
+
+;;;; (2) `testable-privates`
+
+;;; (use '[midje.util :only [testable-privates]])
+;;; (testable-privates scratch.core super-secret-function)
+;;; (fact (super-secret-function 4) => 4)
+
+;;;; (3) `expose-testables`
+
+;;; Code under test:
+;;;   (defn- ^{:testable true}
+;;;     not-so-secret-function [n] ...)
+;;; Tests:
+;;;   (use '[midje.util :only [expose-testables]])
+;;;   (expose-testables scratch.core2)
+;;;   (fact (not-so-secret-function 4) => 4)
+
+;;;; ___________________________________________________________________________
+;;;; Top-down
+
+;;;; ____
+;;;; Basics
+
+;;; Note the use of metaconstants (..lump.. etc).
+
+(unfinished lump-pieces decode-piece)
+
+(defn decode-lump [lump]
+  (apply str (map decode-piece (lump-pieces lump))))
+
+(fact
+ (decode-lump ..lump..) => "01"
+ (provided
+  (lump-pieces ..lump..) => [..0-lump.. ..1-lump..]
+  (decode-piece ..0-lump..) => 0
+  (decode-piece ..1-lump..) => 1))
+
+;;;; ____
+;;;; Throwing
+
+(unfinished throw-if-4)
+
+(defn call-throw-if-4 [x]
+  (try (throw-if-4 x)
+       (catch Error
+           e
+         :throw-happened)))
+
+(fact
+ (call-throw-if-4 4) => :throw-happened
+ (provided
+  (throw-if-4 4) =throws=> (Error. "boom!")))
+
+;;;; ____
+;;;; Multiple checkables with pre-requisites -- **** horrible syntax
+
+;;;; **** Did I mention that the /x => y/ syntax is horrible? In Lisp
+;;;;      you want to make good use of forms, for nice indentation and
+;;;;      for simpler editing.
+;;;;      Here you have four separate things that go together but that
+;;;;      aren't together.
+;;;;      (fact a1 => e1 (provided ...) a2 => e2 (provided ...))
+
+(fact
+ "Nasty syntax; don't do this! Have separate facts instead."
+ (call-throw-if-4 4) => :throw-happened
+ (provided
+  (throw-if-4 4) =throws=> (Error. "boom!"))
+ (call-throw-if-4 5) => 5
+ (provided
+  (throw-if-4 5) => 5))
+
+(fact
+ "Nicer"
+ (fact
+  (call-throw-if-4 4) => :throw-happened
+  (provided
+   (throw-if-4 4) =throws=> (Error. "boom!")))
+ (fact
+  (call-throw-if-4 5) => 5
+  (provided
+   (throw-if-4 5) => 5)))
+
+;;;; ____
+;;;; The GPA exercises
+
+(unfinished child-of-wealthy-alumnus?)
+
+(defn gpa-1 [student coursework]
+  (let [total-hours (reduce + (map :credit-hours
+                                   coursework))
+        total-grads (reduce + (map #(* (:credit-hours %) (:grade %))
+                                   coursework))
+        extras (if (child-of-wealthy-alumnus? student) 0.5 0)]
+    (min 5.0
+         (+ (/ total-grads total-hours)
+            extras))))
+
+(fact
+ (let [correct-gpa 3.66
+       tolerance 0.01
+       coursework [{:credit-hours 1, :grade 5}
+                   {:credit-hours 2, :grade 3}]]
+   (fact "without extras"
+         (gpa-1 ..student.. coursework) => (roughly correct-gpa tolerance)
+         (provided (child-of-wealthy-alumnus? ..student..) => false))
+   (fact "with extras"
+         (gpa-1 ..student.. coursework) => (roughly (+ correct-gpa 0.5) tolerance)
+         (provided (child-of-wealthy-alumnus? ..student..) => true)))
+ (let [max-gpa 5.0
+       coursework [{:credit-hours 1, :grade 4.7}]]
+   (fact "max"
+         (gpa-1 ..student.. coursework) => max-gpa
+         (provided (child-of-wealthy-alumnus? ..student..) => true))))
+
+;;;; ____
+
+(defn fair-gpa [coursework]
+  (let [total-hours (reduce + (map :credit-hours
+                                   coursework))
+        total-grads (reduce + (map #(* (:credit-hours %) (:grade %))
+                                   coursework))]
+    (/ total-grads total-hours)))
+
+(defn gpa-2 [student coursework]
+  (let [extras (if (child-of-wealthy-alumnus? student) 0.5 0)]
+    (min 5.0
+         (+ (fair-gpa coursework)
+            extras))))
+
+(fact
+ (let [correct-gpa 3.66
+       tolerance 0.01
+       coursework [{:credit-hours 1, :grade 5}
+                   {:credit-hours 2, :grade 3}]]
+   (fact "fair-gpa"
+         (fair-gpa coursework) => (roughly correct-gpa tolerance))
+   (fact "extras"
+         (fact "without extras"
+               (gpa-2 ..student.. ..coursework..) => (roughly correct-gpa tolerance)
+               (provided (child-of-wealthy-alumnus? ..student..) => false
+                         (fair-gpa ..coursework..) => correct-gpa))
+         (fact "with extras"
+               (gpa-2 ..student.. ..coursework..) => (roughly (+ correct-gpa 0.5) tolerance)
+               (provided (child-of-wealthy-alumnus? ..student..) => true
+                         (fair-gpa ..coursework..) => correct-gpa))
+         (fact "max"
+               (let [max-gpa 5.0]
+                 (fact
+                  (gpa-2 ..student.. ..coursework..) => max-gpa
+                  (provided (child-of-wealthy-alumnus? ..student..) => true
+                            (fair-gpa ..coursework..) => 4.7)))))))
+
+;;;; ____
+;;;; Prerequisites use a variant of extended equality to match
+;;;; arguments
+;;;; https://github.com/marick/Midje/wiki/Describing-one-checkable%27s-prerequisites#prerequisites-use-a-variant-of-extended-equality-to-match-arguments
+
+;; (provided
+;;  (g #"hello.*world") => 12)
+
+;; (provided
+;;  (g (roughly 5.0 0.01)) => 89)
+
+;; (provided
+;;  (g anything) => 89)
+
+;;; Argument matching isn't quite the same as extended equality,
+;;; though. It differs in the handling of functions other than
+;;; predefined checkers. Functions are treated just as values.
+;;; You can use `as-checker`, which means /satisfies?/.
+;;; You can define your own checkers for use in prerequisites.
+;;; (**** I think use of /satisfies?/ everywhere would have been nicer.)
+
+;;;; ____
+;;;; Call counts
+
+(unfinished call-me maybe-call-me)
+
+(defn do-two-calls []
+  (call-me)
+  (call-me)
+  42)
+
+(facts
+ (fact "By default, expect at least one call"
+       (do-two-calls) => 42
+       (provided
+        (call-me) => anything))
+ (fact "Can specify call counts"
+       (do-two-calls) => 42
+       (provided
+        (call-me) => anything :times 2))
+ (fact "Can specify call counts as a sequence of permitted values"
+       (do-two-calls) => 42
+       (provided
+        (call-me) => anything :times [2 4]))
+ (fact "Can specify call counts as a lazy sequence of permitted values"
+       (do-two-calls) => 42
+       (provided
+        (call-me) => anything :times (range 2 5)))
+ (fact "To say this call is optional, use /:times (range)/"
+       (do-two-calls) => 42
+       (provided
+        (call-me) => anything
+        (maybe-call-me) => anything :times (range)))
+ (fact "Can specify call counts using checkers"
+       (do-two-calls) => 42
+       (provided
+        (call-me) => anything :times even?))
+ (fact "To say not called, must specify args (if any) and result.
+        This will be improved later."
+       (do-two-calls) => 42
+       (provided
+        (call-me) => anything
+        (maybe-call-me) => anything :times 0)))
+
+;;;; ____
+;;;; Shorthand for prerequisite chaining
+
+(unfinished happens-first happens-second)
+
+(defn function-under-test [n]
+  (inc (happens-second (happens-first 1 n))))
+
+(fact "Not using prerequisite chaining"
+      (function-under-test 5) => 101
+      (provided
+       (happens-first 1 5) => ..some-result..
+       (happens-second ..some-result..) => 100))
+
+(fact "Using prerequisite chaining"
+      (function-under-test 5) => 101
+      (provided
+       (happens-second (happens-first 1 5)) => 100))
+
+;;;; ____
+;;;; Variant prerequisite arrows
+
+;;;; Streaming values from impure prerequisites
+;;;; `=streams=>`
+
+;;;; Prerequisites that throw exceptions
+;;;; `=throws=>` -- we've seen this already.
+
+;;;; ____
+;;;; Prerequisites and protocols
+
+;;;; Because protocol functions are compiled so they're called by the
+;;;; JVM, not by the Clojure dispatching mechanism, using them in
+;;;; prerequisites requires a little extra work.
+
+;; use midje.open-protocols in addition to midje.sweet
+;;
+;; Use `defrecord-openly`, `deftype-openly`.
+;;
+;; Other protocol functions like reify don't have -openly variants
+;; yet.
+
+;;;; ____
+;;;; Using private functions in prerequisites
+
+;;;; "Earlier, you saw three ways of using private functions in
+;;;; checkables."  But only referring to them via their var works
+;;;; in prerequisites, because the other ways copy vars.
+
+;;;; ____
+;;;; Establishing fact-wide prerequisites
+
+(unfinished fwp-1 fwp-2)
+
+(defn fwp-1+2 [] (+ (fwp-1) (fwp-2)))
+(defn fwp-1*2 [] (* (fwp-1) (fwp-2)))
+
+(fact
+ (prerequisites (fwp-1) => 3
+                (fwp-2) => 4)
+ (fwp-1+2) => 7
+ (fwp-1*2) => 12)
+
+;;;; "Fact-wide prerequisites do not have to be used."
+
+;;;; Nesting overrides as you'd expect.
+
+;;;; "`provided` prerequisites override any from a `prerequisites` form."
+
+;;;; "When more than one prerequisite at the same nesting level match,
+;;;; it's the latest one that's chosen. That allows for "catch all" or
+;;;; default prerequisites."
+
+;;;; "prerequisite expressions have access to lexically-scoped symbols."
+
+;;;; ___________________________________________________________________________
+;;;; Defining checkers for use in prerequisites
+
+;;;; https://github.com/marick/Midje/wiki/Defining-checkers-for-use-in-prerequisites
+
+;;;; ___________________________________________________________________________
+;;;; =expands-to=>
+;;;; The left-hand side is macroexpanded and compared to the right-hand side:
+
+(fact (when true 3) =expands-to=> (if true (do 3)))


do not force re-routing to invitation if URL has invitation code but is for rules, terms, or privacy

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/clojurecup/cc2014-frontend.git/'


add cgenified dubstep example

add cgenified dubstep example

error: pathspec 'test/example/composed_dubstep.clj' did not match any file(s) known to git

--- test/example/composed_dubstep.clj
+++ test/example/composed_dubstep.clj
@@ -0,0 +1,43 @@
+(ns example.composed-dubstep
+  (:use [overtone.live]))
+
+(defcgen kick-drum
+  "basic synthesised kick drum"
+  [bpm {:default 120 :doc "tempo of kick in beats per minute"}
+   pattern {:default [1 0] :doc "sequence pattern of beats"}]
+  (:ar
+   (let [kickenv (decay (t2a (demand (impulse:kr (/ bpm 30)) 0 (dseq pattern INF))) 0.7)
+         kick (* (* kickenv 7) (sin-osc (+ 40 (* kickenv kickenv kickenv 200))))]
+     (clip2 kick 1))))
+
+(defcgen snare-drum
+  "basic synthesised snare drum"
+  [bpm {:default 120 :doc "tempo of snare in beats per minute"}]
+  (:ar
+   (let [snare (* 3 (pink-noise [1 1]) (apply + (* (decay (impulse (/ bpm 240) 0.5) [0.4 2]) [1 0.05])))
+         snare (+ snare (bpf (* 4 snare) 2000))]
+     (clip2 snare 1))))
+
+(defcgen wobble
+  "wobble an input src"
+  [src {:doc "input source"}
+   wobble-factor {:doc "num wobbles per second"}]
+  (:ar
+   (let [sweep (lin-exp (lf-tri wobble-factor) -1 1 40 3000)
+         wob   (lpf src sweep)
+         wob   (* 0.8 (normalizer wob))
+         wob   (+ wob (bpf wob 1500 2))]
+     (+ wob (* 0.2 (g-verb wob 9 0.7 0.7))))))
+
+(definst dubstep [bpm 120 wobble-factor 1 note 50]
+ (let [trig (impulse:kr (/ bpm 120))
+       freq (midicps (lag note 0.25))
+       bass (apply + (saw (* freq [0.99 1.01])))
+       bass (wobble bass wobble-factor)
+       kick (kick-drum bpm :pattern [1 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0])
+       snare (snare-drum bpm)]
+
+   (clip2 (+ bass kick snare) 1)))
+
+;;(dubstep)
+;;(stop)


Starting unit tests for ratings application

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/stuartwakefield/microdocuments-prototype.git/'


add util test and modify some function name in task.clj

error: pathspec 'test/hebo/util_test.clj' did not match any file(s) known to git

--- test/hebo/util_test.clj
+++ test/hebo/util_test.clj
@@ -0,0 +1,19 @@
+(ns hebo.util-test
+  (:use [clojure.test]
+        [clj-time.coerce :only [to-long from-long]]
+        [clj-time.core :exclude [second extend]]
+        [clj-time.format]
+        [hebo.util]))
+
+(deftest granu-test
+  (testing "granu used for same-granu is error"
+    (let [daily-granu (granularity-is :daily)
+          data-timestamp (daily-granu "2013-01-01T23:01:25+0800")
+          input-timestamp (datetime-to-timestamp (from-time-zone (date-time 2013 1 1) (default-time-zone)))]
+       (is (= input-timestamp data-timestamp)))))
+
+
+(deftest get-fine-granu-test
+  (is (= :daily (get-fine-granu :daily :monthly)))
+  (is (= :daily (get-fine-granu :daily :monthly :yearly)))
+  (is (= :hourly (get-fine-granu :daily :monthly :yearly :hourly))))


composite uniqueness tutorial

composite uniqueness tutorial

error: pathspec 'tutorial/composite_unique.clj' did not match any file(s) known to git

--- tutorial/composite_unique.clj
+++ tutorial/composite_unique.clj
@@ -0,0 +1,36 @@
+;   Copyright (c) Cognitect, Inc. All rights reserved.
+;   The use and distribution terms for this software are covered by the
+;   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;   which can be found in the file epl-v10.html at the root of this distribution.
+;   By using this software in any fashion, you are agreeing to be bound by
+;   the terms of this license.
+;   You must not remove this notice, or any other, from this software.
+
+(require
+  '[datomic.client.api :as d]
+  '[datomic.samples.repl :as repl])
+
+(def conn (repl/scratch-db-conn "config.edn"))
+
+(d/transact conn {:tx-data [{:db/ident :room/letter
+                             :db/valueType :db.type/string
+                             :db/cardinality :db.cardinality/one}
+                            {:db/ident :room/number
+                             :db/valueType :db.type/long
+                             :db/cardinality :db.cardinality/one}
+                            {:db/ident :room/number+letter
+                             :db/valueType :db.type/tuple
+                             :db/cardinality :db.cardinality/one
+                             :db/unique :db.unique/value
+                             :db/tupleAttrs [:room/number :room/letter]}]})
+
+(d/transact conn {:tx-data [{:room/number 42 :room/letter "B" :room/number+letter []}]})
+
+(d/q '[:find (pull ?e [*])
+       :in $ ?number
+       :where [?e :room/number ?number]]
+     (d/db conn) 42)
+
+(->
+  (d/transact conn {:tx-data [{:room/number 42 :room/letter "B" :room/number+letter []}]})
+  repl/thrown-data)


Solve Salary with Bonus in clj

Solve Salary with Bonus in clj

error: pathspec 'solutions/uri/1009/1009.clj' did not match any file(s) known to git

--- solutions/uri/1009/1009.clj
+++ solutions/uri/1009/1009.clj
@@ -0,0 +1,9 @@
+(ns main)
+
+(defn main []
+  (let [_ (read-line)
+        a (Double/parseDouble (read-line))
+        b (Double/parseDouble (read-line))]
+    (format "%.2f" (+ a (* b 0.15)))))
+
+(printf "TOTAL = R$ %s%n" (main))


add pre-over-head check which is language (i.e. Italian)-dependent and add comments

--- src/babel/over.cljc
+++ src/babel/over.cljc
@@ -55,6 +55,8 @@
    (check-vals parent child [:head :synsem :pronoun]        [:synsem :pronoun])
    (check-vals parent child [:head :synsem :propernoun]     [:synsem :propernoun])
    (check-vals parent child [:head :synsem :subcat]         [:synsem :subcat])
+   ;; TODO: language-specific rules should be supplied from their respective namespaces.
+   (check-vals parent child [:head :italiano :italiano]     [:italiano :italiano])
   ))

 (defn comp-pre-checks [parent child]
@@ -95,6 +97,8 @@
           result)

         ;; else: attempt to put head under parent failed: provide diagnostics through log/debug messages.
+        ;; Ideally the attempt would always succeed, because calling (moreover-head) is expensive
+        ;; because of the need to copy structures.
         (do
           (if (not (= true head-pre-checks))
             (log/warn (str "moreover-head: pre-check missed: fail-path-between "


Maintain thread bindings when processing messages

This allows fireplace to work as expected. I'm not entirely sure which
binding is required for the exact issue fireplace was having with ids.

However, when communicating in this way across threads, a copy of the
thread-locals highly increases the chance of normal operation in all
cases.

--- sidecar/src/figwheel_sidecar/repl.clj
+++ sidecar/src/figwheel_sidecar/repl.clj
@@ -89,12 +89,11 @@
     ;; we need to print in the same thread as
     ;; the that the repl process was created in
     ;; thank goodness for the go loop!!
-    (reset! (::repl-writers figwheel-server) {:out *out* ::err *err*})
+    (reset! (::repl-writers figwheel-server) (get-thread-bindings))
     (go-loop []
       (when-let [{:keys [stream args]}
                  (<! (:repl-print-chan figwheel-server))]
-        (binding [*out* (:out @(::repl-writers figwheel-server))
-                  *err* (:err @(::repl-writers figwheel-server))]
+        (with-bindings @(::repl-writers figwheel-server)
           (if (= stream :err)
             (binding [*out* *err*]
               (apply println args)
@@ -107,12 +106,12 @@
     (wait-for-connection figwheel-server)
     (Thread/sleep 500)) ;; just to help with setup latencies
   (-evaluate [_ _ _ js]
-    (reset! (::repl-writers figwheel-server) {:out *out* ::err *err*})
+    (reset! (::repl-writers figwheel-server) (get-thread-bindings))
     (wait-for-connection figwheel-server)
     (eval-js figwheel-server js))
       ;; this is not used for figwheel
   (-load [this ns url]
-    (reset! (::repl-writers figwheel-server) {:out *out* ::err *err*})
+    (reset! (::repl-writers figwheel-server) (get-thread-bindings))
     (wait-for-connection figwheel-server)
     (eval-js figwheel-server (slurp url)))
   (-tear-down [_]


Day 14

Day 14

error: pathspec 'src/advent_2018/day_14.cljc' did not match any file(s) known to git

--- src/advent_2018/day_14.cljc
+++ src/advent_2018/day_14.cljc
@@ -0,0 +1,45 @@
+(ns advent-2018.day-14
+  (:require
+   [clojure.string :as string]))
+
+(def digits
+  (merge
+    (zipmap (range 10) (map vector (range 10)))
+    (zipmap (map #(+ % 10) (range 9)) (map #(vector 1 %) (range 9)))))
+
+(defn solve-1 [n]
+  (loop [idx-1 0 idx-2 1 recipes [3 7]]
+    (let [recipe-1 (recipes idx-1)
+          recipe-2 (recipes idx-2)
+          sum      (+ recipe-1 recipe-2)
+          recipes  (apply conj recipes (digits sum))
+          c        (count recipes)]
+      (if (> c (+ n 10))
+        (string/join (subvec recipes n (+ n 10)))
+        (recur (mod (+ idx-1 recipe-1 1) c) (mod (+ idx-2 recipe-2 1) c) recipes)))))
+
+(defn part-1 []
+  (solve-1 825401))
+
+(defn solve-2 [desired]
+  (loop [idx-1 0 idx-2 1 recipes [3 7]]
+    (let [recipe-1 (recipes idx-1)
+          recipe-2 (recipes idx-2)
+          sum      (+ recipe-1 recipe-2)
+          recipes  (apply conj recipes (digits sum))
+          c        (count recipes)]
+      (cond
+        (< c 10)
+        (recur (mod (+ idx-1 recipe-1 1) c) (mod (+ idx-2 recipe-2 1) c) recipes)
+
+        (= desired (subvec recipes (- c (count desired) 1) (dec c)))
+        (- c (count desired) 1)
+
+        (= desired (subvec recipes (- c (count desired))))
+        (- c (count desired))
+
+        :else
+        (recur (mod (+ idx-1 recipe-1 1) c) (mod (+ idx-2 recipe-2 1) c) recipes)))))
+
+(defn part-2 []
+  (solve-2 [8 2 5 4 0 1]))


Add initial chrono dates, need to be reviewed later.

error: pathspec 'src/clj/guangyin/chrono.clj' did not match any file(s) known to git

--- src/clj/guangyin/chrono.clj
+++ src/clj/guangyin/chrono.clj
@@ -0,0 +1,82 @@
+(ns guangyin.chrono
+  (:require [guangyin.internal.fields :as fields]
+            [guangyin.internal.types :refer :all])
+  (:import (java.time.chrono HijrahDate JapaneseDate MinguoDate
+                             ThaiBuddhistDate)))
+
+(defprotocol IHijrahDate
+  (hijrah-date [this] [year month day]))
+
+(extend-protocol IHijrahDate
+  guangyin.internal.types.ObjectWrapper
+  (hijrah-date [this] (hijrah-date @this))
+  clojure.lang.Keyword
+  (hijrah-date [this] (when (= this :now)
+                            (wrap (HijrahDate/now))))
+  java.time.temporal.TemporalAccessor
+  (hijrah-date [this] (wrap (HijrahDate/from this)))
+  java.time.Clock
+  (hijrah-date [this] (wrap (HijrahDate/now this)))
+  java.time.ZoneId
+  (hijrah-date [this] (wrap (HijrahDate/now this)))
+  java.lang.Long
+  (hijrah-date [year month day] (wrap (HijrahDate/of year month day))))
+
+(defprotocol IJapaneseDate
+  (japanese-date [this] [year month day] [era year month day]))
+
+(extend-protocol IJapaneseDate
+  guangyin.internal.types.ObjectWrapper
+  (japanese-date ([this] (japanese-date @this))
+                 ([era year month day] (japanese-date @era year month day)))
+  clojure.lang.Keyword
+  (japanese-date [this] (when (= this :now)
+                              (wrap (JapaneseDate/now))))
+  java.time.temporal.TemporalAccessor
+  (japanese-date [this] (wrap (JapaneseDate/from this)))
+  java.time.chrono.JapaneseEra
+  (japanese-date [era year month day]
+    (wrap (JapaneseDate/of era year month day)))
+  java.time.Clock
+  (japanese-date [this] (wrap (JapaneseDate/now this)))
+  java.time.ZoneId
+  (japanese-date [this] (wrap (JapaneseDate/now this)))
+  java.lang.Long
+  (japanese-date [year month day] (wrap (JapaneseDate/of year month day))))
+
+(defprotocol IMinguoDate
+  (minguo-date [this] [year month day]))
+
+(extend-protocol IMinguoDate
+  guangyin.internal.types.ObjectWrapper
+  (minguo-date [this] (minguo-date @this))
+  clojure.lang.Keyword
+  (minguo-date [this] (when (= this :now)
+                            (wrap (MinguoDate/now))))
+  java.time.temporal.TemporalAccessor
+  (minguo-date [this] (wrap (MinguoDate/from this)))
+  java.time.Clock
+  (minguo-date [this] (wrap (MinguoDate/now this)))
+  java.time.ZoneId
+  (minguo-date [this] (wrap (MinguoDate/now this)))
+  java.lang.Long
+  (minguo-date [year month day] (wrap (MinguoDate/of year month day))))
+
+(defprotocol IThaiBuddhistDate
+  (thai-buddhist-date [this] [year month day]))
+
+(extend-protocol IThaiBuddhistDate
+  guangyin.internal.types.ObjectWrapper
+  (thai-buddhist-date [this] (thai-buddhist-date @this))
+  clojure.lang.Keyword
+  (thai-buddhist-date [this] (when (= this :now)
+                                   (wrap (ThaiBuddhistDate/now))))
+  java.time.temporal.TemporalAccessor
+  (thai-buddhist-date [this] (wrap (ThaiBuddhistDate/from this)))
+  java.time.Clock
+  (thai-buddhist-date [this] (wrap (ThaiBuddhistDate/now this)))
+  java.time.ZoneId
+  (thai-buddhist-date [this] (wrap (ThaiBuddhistDate/now this)))
+  java.lang.Long
+  (thai-buddhist-date [year month day]
+    (wrap (ThaiBuddhistDate/of year month day))))


rev exception string

rev exception string

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/michaelsbradleyjr/transwarp.git/'


Fix #54 Double bootstrapping can mess with core protocol definitions

We simply place a guard in the REPL `-setup` code to only bootstrap
if needed by detecting if `cljs` has been defined.

--- Clojure/src/ambly/repl/jsc.clj
+++ Clojure/src/ambly/repl/jsc.clj
@@ -222,58 +222,59 @@
         (socket endpoint-address (dec endpoint-port)))
       ;; Start dedicated thread to read messages from socket
       (start-reading-messages repl-env opts)
-      ;; compile cljs.core & its dependencies, goog/base.js must be available
-      ;; for bootstrap to load, use new closure/compile as it can handle
-      ;; resources in JARs
-      (let [core-js (closure/compile core
-                      (assoc opts
-                        :output-dir webdav-mount-point
-                        :output-file
-                        (closure/src-file->target-file core)))
-            deps (closure/add-dependencies opts core-js)]
-        ;; output unoptimized code and the deps file
-        ;; for all compiled namespaces
-        (apply closure/output-unoptimized
-          (assoc opts
-            :output-dir webdav-mount-point
-            :output-to (.getPath (io/file output-dir "ambly_repl_deps.js")))
-          deps))
-      ;; Set up CLOSURE_IMPORT_SCRIPT function, injecting path
-      (jsc-eval repl-env
-        (str "CLOSURE_IMPORT_SCRIPT = function(src) {"
-          (form-ambly-require-expr-js
-            (str "'goog" File/separator "' + src"))
-          "return true; };"))
-      ;; bootstrap
-      (jsc-eval repl-env
-        (form-ambly-require-path-js (io/file "goog" "base.js")))
-      ;; load the deps file so we can goog.require cljs.core etc.
-      (jsc-eval repl-env
-        (form-ambly-require-path-js (io/file "ambly_repl_deps.js")))
-      ;; monkey-patch isProvided_ to avoid useless warnings - David
-      (jsc-eval repl-env
-        (str "goog.isProvided_ = function(x) { return false; };"))
-      ;; monkey-patch goog.require, skip all the loaded checks
-      (repl/evaluate-form repl-env env "<cljs repl>"
-        '(set! (.-require js/goog)
-           (fn [name]
-             (js/CLOSURE_IMPORT_SCRIPT
-               (aget (.. js/goog -dependencies_ -nameToPath) name)))))
-      ;; load cljs.core, setup printing
-      (repl/evaluate-form repl-env env "<cljs repl>"
-        '(do
-           (.require js/goog "cljs.core")
-           (set-print-fn! js/out.write)))
-      ;; redef goog.require to track loaded libs
-      (repl/evaluate-form repl-env env "<cljs repl>"
-        '(do
-           (set! *loaded-libs* #{"cljs.core"})
-           (set! (.-require js/goog)
-             (fn [name reload]
-               (when (or (not (contains? *loaded-libs* name)) reload)
-                 (set! *loaded-libs* (conj (or *loaded-libs* #{}) name))
-                 (js/CLOSURE_IMPORT_SCRIPT
-                   (aget (.. js/goog -dependencies_ -nameToPath) name)))))))
+      (when (= "true" (:value (jsc-eval repl-env "typeof cljs === 'undefined'")))
+        ;; compile cljs.core & its dependencies, goog/base.js must be available
+        ;; for bootstrap to load, use new closure/compile as it can handle
+        ;; resources in JARs
+        (let [core-js (closure/compile core
+                        (assoc opts
+                          :output-dir webdav-mount-point
+                          :output-file
+                          (closure/src-file->target-file core)))
+              deps (closure/add-dependencies opts core-js)]
+          ;; output unoptimized code and the deps file
+          ;; for all compiled namespaces
+          (apply closure/output-unoptimized
+            (assoc opts
+              :output-dir webdav-mount-point
+              :output-to (.getPath (io/file output-dir "ambly_repl_deps.js")))
+            deps))
+        ;; Set up CLOSURE_IMPORT_SCRIPT function, injecting path
+        (jsc-eval repl-env
+          (str "CLOSURE_IMPORT_SCRIPT = function(src) {"
+            (form-ambly-require-expr-js
+              (str "'goog" File/separator "' + src"))
+            "return true; };"))
+        ;; bootstrap
+        (jsc-eval repl-env
+          (form-ambly-require-path-js (io/file "goog" "base.js")))
+        ;; load the deps file so we can goog.require cljs.core etc.
+        (jsc-eval repl-env
+          (form-ambly-require-path-js (io/file "ambly_repl_deps.js")))
+        ;; monkey-patch isProvided_ to avoid useless warnings - David
+        (jsc-eval repl-env
+          (str "goog.isProvided_ = function(x) { return false; };"))
+        ;; monkey-patch goog.require, skip all the loaded checks
+        (repl/evaluate-form repl-env env "<cljs repl>"
+          '(set! (.-require js/goog)
+             (fn [name]
+               (js/CLOSURE_IMPORT_SCRIPT
+                 (aget (.. js/goog -dependencies_ -nameToPath) name)))))
+        ;; load cljs.core, setup printing
+        (repl/evaluate-form repl-env env "<cljs repl>"
+          '(do
+             (.require js/goog "cljs.core")
+             (set-print-fn! js/out.write)))
+        ;; redef goog.require to track loaded libs
+        (repl/evaluate-form repl-env env "<cljs repl>"
+          '(do
+             (set! *loaded-libs* #{"cljs.core"})
+             (set! (.-require js/goog)
+               (fn [name reload]
+                 (when (or (not (contains? *loaded-libs* name)) reload)
+                   (set! *loaded-libs* (conj (or *loaded-libs* #{}) name))
+                   (js/CLOSURE_IMPORT_SCRIPT
+                     (aget (.. js/goog -dependencies_ -nameToPath) name))))))))
       {:merge-opts {:output-dir webdav-mount-point}})
     (catch Throwable t
       (tear-down repl-env)


...-loc -> ...-instruct

...-loc -> ...-instruct


Fixing bug in RNG for Nashorn

Fixing bug in RNG for Nashorn

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/xcthulhu/clj-bitauth.git/'


Refactoring to use bytes/fromBits

Refactoring to use bytes/fromBits


sort loops by start time

sort loops by start time

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/wilkerlucio/youtube-looper.git/'


nascent config editor

nascent config editor

git-svn-id: 03a8048b5ee8463be5048a3801110fb50f378627@8895 d0ab736e-dc22-4aeb-8dc9-08def0aa14fd

error: pathspec 'acqEngine/src/org/micromanager/config_editor.clj' did not match any file(s) known to git

--- acqEngine/src/org/micromanager/config_editor.clj
+++ acqEngine/src/org/micromanager/config_editor.clj
@@ -0,0 +1,223 @@
+(ns org.micromanager.config-editor
+  (:import [javax.swing DefaultListModel JFrame JList JPanel JTable
+                        JScrollPane JViewport ListSelectionModel SpringLayout]
+           [javax.swing.event ListSelectionListener]
+           [java.awt Color Dimension])
+  (:use [org.micromanager.mm :only [load-mm core edt get-config]]))
+
+;; swing layout
+
+(defn put-constraint [comp1 edge1 comp2 edge2 dist]
+  (let [edges {:n SpringLayout/NORTH
+               :w SpringLayout/WEST
+               :s SpringLayout/SOUTH
+               :e SpringLayout/EAST}]
+  (.. comp1 getParent getLayout
+            (putConstraint (edges edge1) comp1
+                           dist (edges edge2) comp2))))
+
+(defn put-constraints [comp & args]
+  (let [args (partition 3 args)
+        edges [:n :w :s :e]]
+    (dorun (map #(apply put-constraint comp %1 %2) edges args))))
+
+(defn constrain-to-parent
+  "Distance from edges of parent comp args"
+  [& args]
+  (doseq [[comp & params] (partition 9 args)]
+    (apply put-constraints comp
+           (flatten (map #(cons (.getParent comp) %) (partition 2 params))))))
+
+(defn add-component [parent child & constraints]
+  (.add parent child)
+  (apply constrain-to-parent child constraints))
+
+;; main stuff
+
+(load-mm)
+
+(defn update-list [list data]
+  (let [model (.getModel list)]
+    (.clear model)
+    (doseq [datum data]
+      (.addElement model datum)))
+  list)
+
+(defn groups []
+  (sort (seq (core getAvailableConfigGroups))))
+
+(defn update-group-list [list]
+  (update-list list (sort (seq (core getAvailableConfigGroups)))))
+
+(defn group-list []
+  (update-group-list (JList. (DefaultListModel.))))
+
+(defn presets [group]
+  (when-not (empty? group)
+    (sort (seq (core getAvailableConfigs group)))))
+
+(defn group-data [group]
+  (into (sorted-map) (map #(vector % (get-config group %)) (presets group))))
+
+(defn properties [group-data]
+  (sort (set (apply concat (map keys (vals group-data))))))
+
+(defn property-name [prop-vec]
+  (let [[dev prop] prop-vec]
+    (str dev "-" prop)))
+
+(defn table-data [group-data]
+  (for [property (properties group-data)]
+          (for [preset (keys group-data)]
+            (get-in group-data [preset property] ""))))
+
+(defn into-1d-array
+  ([data]
+    (into-array data))
+  ([type data]
+    (if-not (empty? data)
+      (into-array data)
+      (make-array type 0))))
+
+(defn into-2d-array
+  ([data]
+    (into-array (map into-array data)))
+  ([type data]
+    (if-not (empty? data)
+      (into-array (map #(into-array type %) data))
+      (make-array type 0 0))))
+
+(defn table []
+  (let [table (JTable.)]
+    (doto table
+      )))
+
+(defn scroll-pane [table]
+   (let [sp (JScrollPane. table)]
+    sp))
+
+(defn attach-selection-listener [table f]
+  (-> table .getSelectionModel
+      (.addListSelectionListener
+        (reify ListSelectionListener
+          (valueChanged [this event]
+            (when-not (.getValueIsAdjusting event)
+              (try
+                (f (.getSelectedRow table))
+                (catch Exception e (.printStackTrace e)))))))))
+
+(defn populate-list [list data]
+  (let [model (.getModel list)]
+    (.clear model)
+    (doseq [datum data]
+      (.addElement model datum)))
+  list)
+
+(defn show []
+  (let [f (JFrame. "Micro-Manager Configuration Preset Editor")
+        cp (.getContentPane f)
+        groups-table (table)
+        presets-table (table)
+        preset-names-table (table)
+        groups-sp (scroll-pane groups-table)
+        presets-sp (scroll-pane presets-table)
+        ]
+    (edt
+      (.setAutoResizeMode presets-table JTable/AUTO_RESIZE_OFF)
+      (.. groups-table getSelectionModel (setSelectionMode ListSelectionModel/SINGLE_SELECTION))
+      (.. presets-table getTableHeader (setReorderingAllowed false))
+      (.setRowHeaderView presets-sp preset-names-table)
+      (.. preset-names-table getParent (setPreferredSize (Dimension. 150 100)))
+      ;(.setFixedCellWidth preset-names-list 150)
+      ;(.setFixedCellHeight preset-names-list (.getRowHeight presets-table))
+      (.setBackground preset-names-table (Color. 0xE0 0xE0 0xE0))
+      (doto cp
+        (.setLayout (SpringLayout.))
+        (add-component presets-sp :n 5 :w 155 :s -5 :e -5)
+        (add-component groups-sp :n 5 :w 5 :s -5 :w 150))
+        (.setBounds f 100 100 800 500)
+        (.show f))
+    {:groups-table groups-table
+     :presets-table presets-table
+     :preset-names-table preset-names-table}))
+
+(defn set-table-data [table body header]
+  (.setDataVector
+    (.getModel table)
+    (into-2d-array String body)
+    (into-1d-array String header)))
+
+(defn update-presets-table [components group]
+  (let [preset-names-table (components :preset-names-table)
+        presets-table (components :presets-table)
+        group-data (group-data group)
+        body (table-data group-data)
+        header (keys group-data)
+        prop-names (map list (map property-name (properties group-data)))]
+    (edt (set-table-data presets-table body header)
+         (when-let [column-objects (.getColumns (.getColumnModel presets-table))]
+           (doseq [column (enumeration-seq column-objects)]
+             (.setPreferredWidth column 120)))
+         (set-table-data preset-names-table prop-names (list ""))
+         (.. preset-names-table getColumnModel (getColumn 0) (setMaxWidth 150)))))
+
+(defn update-groups-table [t]
+  (edt (set-table-data t (map list (groups)) (list "Groups"))))
+
+(defn activate-groups-table [components]
+  (attach-selection-listener
+    (components :groups-table)
+    #(update-presets-table components
+                           (try (.getValueAt (components :groups-table) % 0)
+                                (catch Exception _ nil)))))
+
+;; editing groups
+
+(defn add-group [components group]
+  (core defineConfigGroup group)
+  (update-groups-table (:groups-table components))
+  )
+
+(defn rename-group [components group-old group-new]
+  (core renameConfigGroup group-old group-new)
+  (update-groups-table (:groups-table components))
+  )
+
+(defn delete-group [components group]
+  (core deleteConfigGroup group)
+  (update-groups-table (:groups-table components))
+  )
+
+;; editing presets
+
+(defn add-property [group]
+  )
+
+(defn remove-property [group property])
+
+(defn add-preset [components group preset]
+  (core defineConfig group preset)
+  (update-presets-table components group))
+
+(defn rename-preset [components group preset-old preset-new]
+  (core renameConfig group preset-old preset-new)
+  (update-presets-table components group))
+
+(defn delete-preset [components group preset]
+  (core deleteConfig group preset)
+  (update-presets-table components group))
+
+(defn set-preset-value [components group preset property value]
+  ; TODO: make this work.
+  )
+
+;; test/run
+
+(defn start
+  ([]
+    (start nil))
+  ([group]
+    (let [components (show)]
+      (update-groups-table (components :groups-table))
+      (activate-groups-table components)
+      components)))


Refactored JSON parsing function for image API.

- Fixes issue with only getting info from one source
- Is much more readable thanks to threaded "->>" form

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/talexand/kittens-gallery.git/'


Added timing functions for use in a timer component.

error: pathspec 'src/cmr/dev/env/manager/timing.clj' did not match any file(s) known to git

--- src/cmr/dev/env/manager/timing.clj
+++ src/cmr/dev/env/manager/timing.clj
@@ -0,0 +1,38 @@
+(ns cmr.dev.env.manager.timing)
+
+(def times
+  {:min (* 60 1000)
+   :5mins (* 5 60 1000)
+   :15mins (* 15 60 1000)
+   :hr (* 60 60 1000)
+   :6hrs (* 6 60 60 1000)
+   :12hrs (* 12 60 60 1000)
+   :day (* 24 60 60 1000)
+   :week (* 7 24 60 60 1000)})
+
+(defn new-tracker
+  []
+  (zipmap (keys times)
+          (replicate (count times) (System/currentTimeMillis))))
+
+(defn get-interval
+  [times tracker time-key]
+  (- (System/currentTimeMillis)
+     (time-key tracker)
+     (time-key times)))
+
+(defn get-interval-key-pair
+  [times tracker time-key]
+  [time-key (get-interval times tracker time-key)])
+
+(defn intervals
+  [times tracker]
+  (into {} (map (partial get-interval-key-pair times tracker) (keys times))))
+
+(defn get-passed
+  [times tracker time-key]
+  [time-key (pos? (get-interval times tracker time-key))])
+
+(defn passed?
+  [times tracker]
+  (into {} (map (partial get-passed times tracker) (keys times))))


Problem 0062.

Problem 0062.

error: pathspec 'src/project_euler/problem_0062.clj' did not match any file(s) known to git

--- src/project_euler/problem_0062.clj
+++ src/project_euler/problem_0062.clj
@@ -0,0 +1,50 @@
+(ns project-euler.problem_0062)
+
+;; The cube, 41063625 (345^3), can be permuted to produce two other cubes: 56623104 (384^3) and 66430125 (405^3).
+;; In fact, 41063625 is the smallest cube which has exactly three permutations of its digits which are also cube.
+
+;; Find the smallest cube for which exactly five permutations of its digits are cube.
+
+;;-------------------------------------------------------------------------------------------------------
+;; from problem_0030:
+
+(defn digits
+  [n]
+  (loop [n n, ds []]
+    (let [r (rem n 10)
+          q (quot n 10)
+          new-ds (conj ds r)]
+      (if (== q 0)
+        new-ds
+        (recur q new-ds)
+        ))))
+;;-------------------------------------------------------------------------------------------------------
+
+
+(defn cube [x] (* x x x))
+
+
+(defn cubes-by-n-digits
+  ([] (cubes-by-n-digits 10 10000))
+  ([x lim]
+   (lazy-seq
+    (loop [x x, n-digit-cubes nil]
+      (let [c (cube x)]
+        (if (< c lim)
+          (recur (inc x) (conj n-digit-cubes c))
+          (cons n-digit-cubes (cubes-by-n-digits x (* 10 lim)))))))))
+
+(defn n-digits-solution [cubes]
+  (->> (group-by (comp sort vec digits) cubes)
+       (filter (fn [[ds cs]] (== 5 (count cs))))))
+
+(defn solution []
+  (->> (cubes-by-n-digits)
+       (map n-digits-solution)
+       (some seq)
+       (mapcat second)
+       (apply min)
+       ))
+
+;;-> 127035954683
+


substitute sms date formatting

substitute sms date formatting

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/election-notification-works.git/'


Txukundu

Txukundu

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lnmnd/magnet.bez.git/'


Ning now looks more like aleph

Ning now looks more like aleph

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/terrancesnyder/engulf.git/'


add a comment

add a comment

--- test/metabase/api/meta/table_test.clj
+++ test/metabase/api/meta/table_test.clj
@@ -5,6 +5,7 @@
             [metabase.test-data :refer [table->id db-id org-id user->client]]))

 ;; Test GET /api/meta/table?org
+;; These should come back in alphabetical order and include relevant metadata
 (expect [{:description nil, :entity_type nil, :name "CATEGORIES", :rows 75, :entity_name nil, :active true, :id (table->id :categories), :db_id @db-id}
          {:description nil, :entity_type nil, :name "CHECKINS", :rows 1000, :entity_name nil, :active true, :id (table->id :checkins), :db_id @db-id}
          {:description nil, :entity_type nil, :name "USERS", :rows 15, :entity_name nil, :active true, :id (table->id :users), :db_id @db-id}


Convert voting-methods-service-test to response-for

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/turbovote-http-api.git/'


add unit tests for chapter2-3

add unit tests for chapter2-3

error: pathspec 'test/sicp/chapter2_3_test.clj' did not match any file(s) known to git

--- test/sicp/chapter2_3_test.clj
+++ test/sicp/chapter2_3_test.clj
@@ -0,0 +1,22 @@
+(ns sicp.chapter2-3-test
+  (:require [clojure.test :refer :all]
+            [sicp.chapter2-3 :refer :all]))
+
+;;;; 2.3  Symbolic Data
+
+;;; 2.3.1  Quotation
+
+(deftest memq-test
+  (is (false? (memq 'apple '(pear banana prune))))
+  (is (= (memq 'apple '(x (apple sauce) y apple pear)) '(apple pear))))
+
+;; Exercise 2.54
+(deftest equal?-test
+  (is (true? (equal? '(this is a list) '(this is a list))))
+  (is (false? (equal? '(this is a list) '(this (is a) list)))))
+
+;;; 2.3.2  Example: Symbolic Differentiation
+
+;;; 2.3.3  Example: Representing Sets
+
+;;; 2.3.4  Example: Huffman Encoding Trees


New test module utils_test and added various tests into it

error: pathspec 'test/hurvinek/utils_test.clj' did not match any file(s) known to git

--- test/hurvinek/utils_test.clj
+++ test/hurvinek/utils_test.clj
@@ -0,0 +1,68 @@
+;
+;  (C) Copyright 2016  Pavel Tisnovsky
+;
+;  All rights reserved. This program and the accompanying materials
+;  are made available under the terms of the Eclipse Public License v1.0
+;  which accompanies this distribution, and is available at
+;  http://www.eclipse.org/legal/epl-v10.html
+;
+;  Contributors:
+;      Pavel Tisnovsky
+;
+
+(ns hurvinek.utils-test
+  (:require [clojure.test :refer :all]
+            [hurvinek.utils :refer :all]))
+
+;
+; Common functions used by tests.
+;
+
+(defn callable?
+    "Test if given function-name is bound to the real function."
+    [function-name]
+    (clojure.test/function? function-name))
+
+;
+; Tests for various function definitions
+;
+
+(deftest test-third-existence
+    "Check that the hurvinek.utils/third definition exists."
+    (testing "if the hurvinek.utils/third definition exists."
+        (is (callable? 'hurvinek.utils/third))))
+
+
+(deftest test-substring-existence
+    "Check that the hurvinek.utils/substring definition exists."
+    (testing "if the hurvinek.utils/substring definition exists."
+        (is (callable? 'hurvinek.utils/substring))))
+
+
+(deftest test-startsWith-existence
+    "Check that the hurvinek.utils/startsWith definition exists."
+    (testing "if the hurvinek.utils/startsWith definition exists."
+        (is (callable? 'hurvinek.utils/startsWith))))
+
+
+(deftest test-endsWith-existence
+    "Check that the hurvinek.utils/endsWith definition exists."
+    (testing "if the hurvinek.utils/endsWith definition exists."
+        (is (callable? 'hurvinek.utils/endsWith))))
+
+
+(deftest test-contains-existence
+    "Check that the hurvinek.utils/contains definition exists."
+    (testing "if the hurvinek.utils/contains definition exists."
+        (is (callable? 'hurvinek.utils/contains))))
+
+
+(deftest test-replaceAll-existence
+    "Check that the hurvinek.utils/replaceAll definition exists."
+    (testing "if the hurvinek.utils/replaceAll definition exists."
+        (is (callable? 'hurvinek.utils/replaceAll))))
+
+;
+; Tests for behaviour of all functions
+;
+


added outside world interface to structure driven crawler

error: pathspec 'src/crawler/main.clj' did not match any file(s) known to git

--- src/crawler/main.clj
+++ src/crawler/main.clj
@@ -0,0 +1,32 @@
+(ns crawler.main
+  "Run from here"
+  (:require [clojure.tools.cli :as cli]
+            [crawler.crawl :as crawl]
+            [crawler.utils :as utils]
+            [crawler.structure-driven :as structure-driven]))
+
+(defn crawler-options
+  [[nil "--structure-driven" "Use the structure driven crawler"]
+   [nil "--start" "Entry point for the structure driven crawler"]
+   [nil "--example" "Example leaf page url for the structure driven crawler"]])
+
+(defn -main
+  [& args]
+  (let [options (-> args
+                    (cli/parse-opts crawler-options)
+                    :options)]
+    (cond (:structure-driven options)
+          (let [start-url    (-> options :start)
+                example-body (-> options
+                                 :example
+                                 download-with-cookie)
+
+                structure-driven-leaf?     (fn [x]
+                                             (structure-driven/leaf?
+                                              x example-body))]
+            (crawl/sample-sitemap-lookahead start-url
+                                            structure-driven-leaf?
+                                            structure-driven/extractor))
+
+          :else
+          (println "Pick one bruh"))))


[WM SD] remove unused require from vbm-form ns

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/vote-by-mail-works.git/'


fixing up the repl interface a bit

fixing up the repl interface a bit

--- sidecar/src/figwheel_sidecar/system.clj
+++ sidecar/src/figwheel_sidecar/system.clj
@@ -496,7 +496,7 @@
   (if (frepl/in-nrepl-env?)
     (figwheel-cljs-repl* system start-build-id) ;; no build switching
     (loop [build-id start-build-id]
-      (figwheel-cljs-repl* system build-id)
+      (figwheel-cljs-repl* system {:build-id build-id})
       (let [builds (get-in @system [:figwheel-server :builds])]
         (when-let [chosen-build-id
                    (get-build-choice
@@ -507,15 +507,15 @@
   ([system] (cljs-repl* system nil))
   ([system start-build-id]
    (if (frepl/in-nrepl-env?)
-     (figwheel-cljs-repl* system start-build-id)
+     (figwheel-cljs-repl* system {:build-id start-build-id})
      (build-switching-cljs-repl* system start-build-id))))

 ;; takes a FigwheelSystem
 (defn figwheel-cljs-repl
   ([figwheel-system]
-   (figwheel-cljs-repl figwheel-system {}))
-  ([{:keys [system]} repl-options]
-   (figwheel-cljs-repl* system repl-options)))
+   (figwheel-cljs-repl figwheel-system nil))
+  ([{:keys [system]} build-id]
+   (figwheel-cljs-repl* system {:build-id build-id})))

 ;; takes a FigwheelSystem this will not work for nrepl
 (defn build-switching-cljs-repl
@@ -523,9 +523,16 @@
   ([{:keys [system]} start-build-id]
    (build-switching-cljs-repl* system start-build-id)))

+(defn initial-repl-focus-build-id [system]
+  (when-let [build-key (first (all-build-keys system))]
+    (key->id build-key)))
+
 (defn cljs-repl
   ([{:keys [system]}] (cljs-repl* system nil))
-  ([{:keys [system]} start-build-id] (cljs-repl* system start-build-id)))
+  ([{:keys [system]} start-build-id] (cljs-repl* system
+                                                 (or
+                                                  start-build-id
+                                                  (initial-repl-focus-build-id @system)))))

 ;; figwheel starting and stopping helpers


stock info

stock info

error: pathspec 'stock-ticker-demo/src/stock_ticker_demo/price_feed.clj' did not match any file(s) known to git

--- stock-ticker-demo/src/stock_ticker_demo/price_feed.clj
+++ stock-ticker-demo/src/stock_ticker_demo/price_feed.clj
@@ -0,0 +1,14 @@
+(ns stock-ticker-demo.price-feed)
+
+(def stock-map {"YHOO" {:max-price 31.1 :min-price 11.51
+                        :wavelength 90 :starting-point 0.5
+                        :eps 2.15}
+                "APPL" {:max-price 408.38 :min-price 84.11
+                        :wavelength 60 :starting-point 0
+                        :eps 31.25}
+                "GOOG" {:max-price 809.1 :min-price 292.96
+                        :wavelength 50 :starting-point 0.75
+                        :eps 29.31}
+                "AMZN" {:max-price 274.1 :min-price 42.7
+                        :wavelength 45 :starting-point 0.25
+                        :eps 1.15}})


Add WIP yeti command

Add WIP yeti command

error: pathspec 'src/yetibot/core/commands/yeti.clj' did not match any file(s) known to git

--- src/yetibot/core/commands/yeti.clj
+++ src/yetibot/core/commands/yeti.clj
@@ -0,0 +1,11 @@
+(ns yetibot.core.commands.yeti
+  (:require
+    [yetibot.core.hooks :refer [cmd-hook]]))
+
+(defn self-cmd
+  "yeti # show known info about Yetibot"
+  [_]
+  "TODO")
+
+(cmd-hook #"yeti"
+  #"self" self-cmd)


fix require issue.

fix require issue.

--- test/metabase/models/pulse_test.clj
+++ test/metabase/models/pulse_test.clj
@@ -5,7 +5,7 @@
             [metabase.db :refer :all]
             (metabase.models [pulse :refer :all]
                              [pulse-card :refer :all])
-            [metabase.test-data :refer :all]
+            [metabase.test.data :refer :all]
             [metabase.test.data.users :refer :all]
             [metabase.test.util :as tu]))


more clarification

more clarification

--- support/src/figwheel/client/file_reloading.cljs
+++ support/src/figwheel/client/file_reloading.cljs
@@ -59,7 +59,7 @@
        (js/setTimeout #(apply on-jsload [res]) 10))
      (when (not-empty files-not-loaded)
        (.debug js/console "Figwheel: NOT loading files that haven't been required")
-       (.log js/console (pr-str (map :file files-not-loaded)))))))
+       (.log js/console "not required:" (pr-str (map :file files-not-loaded)))))))

 ;; CSS reloading


Added more colors for book cover with a random selection

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/hudren/ebook-novel.git/'


More…

More…

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/physion/ovation-webapi.git/'


fixed issue when building path to markdown files

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/20centaurifux/my-website.git/'


Add elasticsearch helper file

Add elasticsearch helper file

error: pathspec 'src/in/co/sdslabs/slack_lens/lib/es.clj' did not match any file(s) known to git

--- src/in/co/sdslabs/slack_lens/lib/es.clj
+++ src/in/co/sdslabs/slack_lens/lib/es.clj
@@ -0,0 +1,54 @@
+(ns in.co.sdslabs.slack_lens.lib.es
+  (:require [clojurewerkz.elastisch.native :as es]
+            [clojurewerkz.elastisch.native.index :as esi]
+            [clojurewerkz.elastisch.native.document :as esd]
+            [clojure.tools.logging :as log]))
+
+(defn ensure-index!
+  "Returns boolean according to if es index exists or not, if es index is already exists we move on returning true
+   Else we continue and try to create the index, finally we return true if we were successful else we return false
+   indicating our failure"
+  [conn index-name settings mappings]
+  (if (esi/exists? conn index-name)
+    (do
+      (log/info "Index already exists. Moving on") ; Already exists, return true
+      true)
+    (do
+      (log/info "Creating index: " index-name)
+        (esi/create conn index-name :settings settings :mappings mappings) ;Create the index
+        (esi/refresh conn index-name) ; Refresh so we all or on the same page
+        (if (esi/exists? conn index-name) ; Lets check if we have the index now
+          (do
+            (log/info index-name " successfully created.") ; We have the index lets return true
+            true)
+          (do
+            (log/info "Something happened, failed to create.") ; We don't have the index we must return false
+            false))
+        )))
+
+(defn connect-es
+  "Takes options map as parameter and tries to establish connection to the es node
+   Options is a map with the following keys
+    :port Port number where the updator should connect for es [Since this is the
+          native client so in usual cases this will be 9300
+    :url Url of elasticsearch [Locally 127.0.0.1]
+    :clustername Name of the elasticsearch cluster [Usually 'elasticsearch']"
+  [options]
+  (let [{:keys [port url clustername]} options]
+    (try
+      (es/connect [[url port]] {"cluster.name" clustername})
+      (catch Exception e (log/info e)))))
+
+(defn elastic-feed
+  "Creates document with options passed as param and sets it's
+   value as 'response' on an es 'conn', mapping 'mapping' and index 'index-name'
+   These all are required keys in the options params"
+  [{:keys [conn index-name response mapping]}]
+  (esd/create conn index-name mapping response))
+
+(defn elastic-delete
+  "Creates document with options passed as param and sets it's
+   value as 'response' on an es 'conn' and index 'index-name'
+   These all are required keys in the options params"
+  [{:keys [conn index-name response id mapping]}]
+  (esd/delete conn index-name mapping id))


remove unneeded type hint

remove unneeded type hint

--- storm-core/src/clj/backtype/storm/tuple.clj
+++ storm-core/src/clj/backtype/storm/tuple.clj
@@ -21,5 +21,4 @@
   [^List alist]
   (if (nil? alist)
     1
-    (let [^"[Ljava.lang.Object;" array (.toArray alist)] ;; Object[]
-      (Arrays/deepHashCode array))))
+    (Arrays/deepHashCode (.toArray alist))))


Handle cases where sync didn't complete

Handle cases where sync didn't complete

--- src/metabase/driver/query_processor.clj
+++ src/metabase/driver/query_processor.clj
@@ -203,8 +203,16 @@
                      (into {}))]
     (->> column-names
          (map (fn [column-name]
-                (or (columns column-name)                             ; try to get matching column from the map we build earlier
-                    (get-special-column-info query column-name))))))) ; if it's not there then it's a special column like `count`
+                (try
+                  (or (columns column-name)                        ; try to get matching column from the map we build earlier
+                      (get-special-column-info query column-name)) ; if it's not there then it's a special column like `count`
+                  (catch Throwable _                               ; If for some reason column info lookup failed just return empty info map
+                    {:name         column-name                     ; TODO - should we log this ? It shouldn't be happening ideally
+                     :id           nil
+                     :table_id     nil
+                     :description  nil
+                     :base_type    :UnknownField
+                     :special_type nil})))))))

 (defn get-special-column-info