(ns blocks.store.replica-test
  (:require
    (blocks.store
      [memory :refer [memory-store]]
      [replica :refer [replica-store]]
      [tests :refer [test-block-store]])
    [clojure.test :refer :all]))

; TODO: test that writes actually populate all backing stores.
; TODO: test that removing blocks from one store still returns all blocks.
; TODO: test that listing provides merged block list.

(deftest ^:integration test-replica-store
  (let [store (replica-store [(memory-store) (memory-store)])]
    (test-block-store
      "replica-store" store
      :max-size 1024
      :blocks 25)))

(ns blocks.store.replica-test
  (:require
    [blocks.core :as block]
    (blocks.store
      [memory :refer [memory-store]]
      [replica :refer [replica-store]]
      [tests :refer [test-block-store]])
    [clojure.test :refer :all]))

(deftest replica-behavior
  (let [replica-1 (memory-store)
        replica-2 (memory-store)
        store (replica-store [replica-1 replica-2])
        a (block/read! "foo bar baz")
        b (block/read! "abracadabra")
        c (block/read! "123 xyz")]
    (block/put! store a)
    (block/put! store b)
    (block/put! store c)
    (is (= 3 (count (block/list replica-1))))
    (is (every? (partial block/get replica-1)
                (map :id [a b c]))
        "all blocks are stored in replica-1")
    (is (= 3 (count (block/list replica-2))))
    (is (every? (partial block/get replica-2)
                (map :id [a b c]))
        "all blocks are stored in replica-2")
    (is (= 3 (count (block/list store))))
    (block/delete! replica-1 (:id a))
    (block/delete! replica-2 (:id c))
    (is (= 3 (count (block/list store)))
        "replica lists all available blocks")))

(deftest ^:integration test-replica-store
  (let [store (replica-store [(memory-store) (memory-store)])]
    (test-block-store
      "replica-store" store
      :max-size 1024
      :blocks 25)))

Add tests for replication behavior.

Add tests for replication behavior.


(ns example.one-bar-sequencer
  (:use overtone.live))

(def metro (metronome 128))

; Our bar is a map of beat to instruments to play

(def bar {0   [kick]
          0.5 [c-hat]
          1   [kick snare]
          1.5 [c-hat]
          2   [kick]
          2.5 [c-hat]
          3   [kick snare]
          3.5 [c-hat]})

; For every tick of the metronome, we loop through all our beats
; and find the apropriate one my taking the metronome tick mod 4.
; Then we play all the instruments for that beat.

(defn player
  [tick]
  (dorun
    (for [k (keys bar)]
      (let [beat (Math/floor k)
            offset (- k beat)]
           (if (= 0 (mod (- tick beat) 4))
               (let [instruments (bar k)]
                    (dorun
                      (for [instrument instruments]
                         (at (metro (+ offset tick)) (instrument))))))))))

(ns example.one-bar-sequencer
  (:use [overtone.live]
        [overtone.inst drum]))

(def metro (metronome 128))

; Our bar is a map of beat to instruments to play

(def bar {0   [kick]
          0.5 [c-hat]
          1   [kick snare]
          1.5 [c-hat]
          2   [kick]
          2.5 [c-hat]
          3   [kick snare]
          3.5 [c-hat]})

; For every tick of the metronome, we loop through all our beats
; and find the apropriate one my taking the metronome tick mod 4.
; Then we play all the instruments for that beat.

(defn player
  [tick]
  (dorun
    (for [k (keys bar)]
      (let [beat (Math/floor k)
            offset (- k beat)]
           (if (= 0 (mod (- tick beat) 4))
               (let [instruments (bar k)]
                    (dorun
                      (for [instrument instruments]
                        (at (metro (+ offset tick)) (instrument))))))))))

;; define a run fn which will call our player fn for each beat and will schedule
;; itself to be called just before the next beat

(defn run
  [m]
  (let [beat (m)]
    (player beat)
    (apply-at (m (inc beat))  #'run [m])))

;; make beats!
(run metro)

;; stop
(stop)

Fix up one bar sequencer

Fix up one bar sequencer


; Copyright 2009 Howard M. Lewis Ship
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;   http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
; implied. See the License for the specific language governing permissions
; and limitations under the License.

(ns cascade.utils)

(defmacro lcond
	"A reimplementation of Clojure's cond, with the addition of a special :let
	keyword that injects an implicit let into the logic."
	[& clauses]
	(when clauses
		(if (= 1 (count clauses))
			(throw (IllegalArgumentException. "lcond requires an even number of forms")))
			(let
				[tst (first clauses)
				 expr (second clauses)
				 rst (next (next clauses))]
				 (if (= tst :let)
				 	`(let [~@expr] (lcond ~@rst))
				 	`(if ~tst ~expr (lcond ~@rst))))))

; Copyright 2009 Howard M. Lewis Ship
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;   http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
; implied. See the License for the specific language governing permissions
; and limitations under the License.

(ns cascade.utils
	(:use
		(clojure.contrib pprint macro-utils)))

(defmacro lcond
	"A reimplementation of Clojure's cond, with the addition of a special :let
	keyword that injects an implicit let into the logic."
	[& clauses]
	(when clauses
		(if (= 1 (count clauses))
			(throw (IllegalArgumentException. "lcond requires an even number of forms")))
			(let
				[tst (first clauses)
				 expr (second clauses)
				 rst (next (next clauses))]
				 (if (= tst :let)
				 	`(let [~@expr] (lcond ~@rst))
				 	`(if ~tst ~expr (lcond ~@rst))))))

(defmacro debug-form
	"Expands all macros in a form, recursively, and prints the result. Returns nil."
	[form]
	`(pprint (mexpand-all '~form)))

Add debug-form macro, which expands and pretty-prints an unevaluated form.


;; This is usefull to display the functions, ask the user for the
;; input parameters, and then execute them, presenting the result to
;; the user.
;; Intended to expose the functions in a Browser, but it could be
;; anything else: command line, rich client, ...
;;
(ns fnx.meta.expose
  "Get the public functions of a namespace"
  (:use [midje.sweet]))

;;
;; * First we load the ns with `require`
;; * Then we get the public functions (read from bottom to top):
;; * We want only functions, not the other vars: We can spot them because they have an `:arglists` in their meta.
;; * Don't really know why, but we need to `ns-resolve` the symbols(?)
;; * Get the public vars with `ns-publics`
;;
(defn ns-public-fn
  "Given a ns symbol, returns all the public fns of this ns."
  [ns] (do (require ns)
           (filter #(:arglists (meta %))
                   (map #(ns-resolve ns %)
                        (keys (ns-publics (find-ns ns)))))))

(fact "ns-public-fn"
      (second (ns-public-fn 'fnx.meta.example)) => (resolve 'fnx.meta.example/hello-noir))

(fact "ns-public-fn: listing functions and calling them (it's more an example of usage than a true test)"
      (map (fn [f] (apply f
                         (range 0 (count (first (:arglists (meta f)))))))
           (ns-public-fn 'fnx.meta.example)) => ["arg=0", "Hello noir" "args=0,1"])

;; This is usefull to display the functions, ask the user for the
;; input parameters, and then execute them, presenting the result to
;; the user.
;; Intended to expose the functions in a Browser, but it could be
;; anything else: command line, rich client, ...
;;
(ns fnx.meta.expose
  "Get the public functions of a namespace"
  (:use [midje.sweet]))

;;
;; * First we load the ns with `require`
;; * Then we get the public functions (read from bottom to top):
;; * We want only functions, not the other vars: We can spot them because they have an `:arglists` in their meta.
;; * Get the public vars with `ns-publics`
;;
(defn ns-public-fn
  "Given a ns symbol, returns all the public fns of this ns."
  [ns] (do (require ns)
           (filter #(:arglists (meta %))
                   (vals (ns-publics (find-ns ns))))))

(fact "ns-public-fn"
      (second (ns-public-fn 'fnx.meta.example)) => (resolve 'fnx.meta.example/hello-noir))

(fact "ns-public-fn: listing functions and calling them (it's more an example of usage than a true test)"
      (map (fn [f] (apply f
                         (range 0 (count (first (:arglists (meta f)))))))
           (ns-public-fn 'fnx.meta.example)) => ["arg=0", "Hello noir" "args=0,1"])

Simplify so that we do not need to map the ns-resolve methods.


(ns vinculum.main
  (:require [vinculum.core :as core]))

(core/main)

(ns vinculum.main
  (:require [vinculum.core :as core]))

(js/console.log "Starting production mode CLJS!")
(core/main)

Make sure it warns when running production-mode code.


(ns pfrt.main
  (:require [pfrt.pf :refer [packet-filter]]
            [pfrt.web :refer [web-server]]
            [pfrt.core.app :as app]
            [pfrt.settings :as settings])
  (:gen-class))

;; Global var, only used for store
;; a global app instance when this is
;; used from REPL.
(def main-app nil)

;; System private constructor with
;; clear and explicit dependency injection
;; on each app components.
(defn- make-app []
  (let [config    (settings/cfg)
        pf        (packet-filter config)
        webserver (web-server config pf)]
    (-> (app/->App [pf webserver])
        (assoc :config config)
        (app/init))))

;; Start function that should
;; only be used from REPL.
(defn start []
  (alter-var-root #'main-app
    (constantly (make-app)))
  (start main-app))

;; Stop function that should
;; only be used from REPL.
(defn stop []
  (app/stop main-app))

;; Main entry point
(defn -main
  [& args]
  (let [app-instance (make-app)]
    (app/start app-instance)
    (println "Application started.")))

(ns pfrt.main
  (:require [pfrt.pf :refer [packet-filter]]
            [pfrt.web :refer [web-server]]
            [pfrt.core.app :as app]
            [pfrt.settings :as settings])
  (:gen-class))

;; Global var, only used for store
;; a global app instance when this is
;; used from REPL.
(def main-app nil)

;; System private constructor with
;; clear and explicit dependency injection
;; on each app components.
(defn- make-app []
  (let [config    (settings/cfg)
        pf        (packet-filter config)
        webserver (web-server config pf)]
    (-> (app/->App [pf webserver])
        (assoc :config config)
        (app/init))))

;; Start function that should
;; only be used from REPL.
(defn start []
  (alter-var-root #'main-app
    (constantly (make-app)))
  (start main-app))

;; Stop function that should
;; only be used from REPL.
(defn stop []
  (app/stop main-app))

;; Helper function that executes
;; stop and start.
(defn restart []
  (start)
  (stop))

;; Main entry point
(defn -main
  [& args]
  (let [app-instance (make-app)]
    (app/start app-instance)
    (println "Application started.")))

Add repl restart function helper.

Add repl restart function helper.


(ns cglossa.core
  (:require [reagent.core :as reagent :refer [atom]]
            [plumbing.core :as plumbing :refer [map-vals]]
            [cglossa.centre :as centre]))

(def state {:showing-results false})

(def data {:categories ["ku" "hest"]
           :users      ["per" "kari"]})

(defonce app-state (into {} (map-vals atom state)))
(defonce app-data (into {} (map-vals atom data)))

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

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

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

(defn ^:export main []
  (reagent/render-component
    (fn []
      [app app-state app-data])
    (. js/document (getElementById "app"))))

(ns cglossa.core
  (:require [reagent.core :as reagent :refer [atom]]
            [plumbing.core :as plumbing :refer [map-vals]]
            [cglossa.centre :as centre]))

(def state {:showing-results false})

(def data {:categories ["ku" "hest"]
           :users      ["per" "kari"]})

(defonce app-state (into {} (map-vals atom state)))
(defonce app-data (into {} (map-vals atom data)))

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

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

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

(defn ^:export main []
  (reagent/render-component
    (fn []
      [app app-state app-data])
    (. js/document (getElementById "app"))))

Rename to header and footer

Rename to header and footer


(ns ^{:doc "When this library is loaded, create a logger named
'events' and send all application-specific events to it.

To view log messages in the browser console, add a call
to `(log/console-output)` to this namespace or evaluate this from the
REPL.

For more information see library.logging."}
  one.repmax.logging
  (:require [one.dispatch :as dispatch]
            [one.logging :as log]))

(def ^{:doc "The logger that receives all application-specific events."}
  logger (log/get-logger "events"))

(dispatch/react-to (constantly true)
                   (fn [t d] (log/info logger (str (pr-str t) " - " (pr-str d)))))

;; log to the console
(log/start-display (log/console-output))

(ns ^{:doc "When this library is loaded, create a logger named 'events'.

           See comments at end of file for example usage.

           For more information see one.logging."}
  one.repmax.logging
  (:require [one.dispatch :as dispatch]
            [one.logging :as log]))

(def ^{:doc "The logger that receives all application-specific events."}
  logger (log/get-logger "events"))

(defn log!
  "Create a new reaction that will react to ALL events and log them to the
  given logger.

  WARNING: For events that have a large amount of data (which is the case for
  most :model-change events in One Rep Max), sending these events to the logger
  has a significant negative performance impact on the application. You are
  recommended to log events ONLY For debugging purposes."
  [logger]
  (dispatch/react-to (constantly true)
                     (fn [t d] (log/info logger (str (pr-str t) " - " (pr-str d))))))

(comment

  ;; register a reaction that will react to ALL events and log them to the 'events' logger
  (def logging-reaction (log! logger))

  ;; send the the log output to the console
  (log/start-display (log/console-output))

  ;; stop logging events
  (dispatch/delete-reaction logging-reaction)

  ;; change the logging level
  (log/set-level logger :fine)

  )

Allow enabling/disabling of logger in running app

Loading the one.repmax.logging namespace no longer automatically creates
a reaction for logging events. Logging :model-change events has a hugely
negative impact on performance (e.g., filtering the exercise list is
about 2 orders of magnitude slower when :model-change events are being
sent to the logger). To avoid this performance hit, logging is disabled
by default; it can be enabled on demand when needed.


(defproject ring/ring-jetty-adapter "1.9.1"
  :description "Ring Jetty adapter."
  :url "https://github.com/ring-clojure/ring"
  :scm {:dir ".."}
  :license {:name "The MIT License"
            :url "http://opensource.org/licenses/MIT"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [ring/ring-core "1.9.1"]
                 [ring/ring-servlet "1.9.1"]
                 [org.eclipse.jetty/jetty-server "9.4.36.v20210114"]]
  :aliases {"test-all" ["with-profile" "default:+1.8:+1.9:+1.10" "test"]}
  :profiles
  {:dev  {:dependencies [[clj-http "3.10.0"]
                         [less-awful-ssl "1.0.6"]]
          :jvm-opts ["-Dorg.eclipse.jetty.server.HttpChannelState.DEFAULT_TIMEOUT=500"]}
   :1.8  {:dependencies [[org.clojure/clojure "1.8.0"]]}
   :1.9  {:dependencies [[org.clojure/clojure "1.9.0"]]}
   :1.10 {:dependencies [[org.clojure/clojure "1.10.2"]]}})

(defproject ring/ring-jetty-adapter "1.9.1"
  :description "Ring Jetty adapter."
  :url "https://github.com/ring-clojure/ring"
  :scm {:dir ".."}
  :license {:name "The MIT License"
            :url "http://opensource.org/licenses/MIT"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [ring/ring-core "1.9.1"]
                 [ring/ring-servlet "1.9.1"]
                 [org.eclipse.jetty/jetty-server "9.4.38.v20210224"]]
  :aliases {"test-all" ["with-profile" "default:+1.8:+1.9:+1.10" "test"]}
  :profiles
  {:dev  {:dependencies [[clj-http "3.10.0"]
                         [less-awful-ssl "1.0.6"]]
          :jvm-opts ["-Dorg.eclipse.jetty.server.HttpChannelState.DEFAULT_TIMEOUT=500"]}
   :1.8  {:dependencies [[org.clojure/clojure "1.8.0"]]}
   :1.9  {:dependencies [[org.clojure/clojure "1.9.0"]]}
   :1.10 {:dependencies [[org.clojure/clojure "1.10.2"]]}})

Update Jetty dependency to 9.4.38

Update Jetty dependency to 9.4.38

Fixes #433.

See: https://snyk.io/vuln/SNYK-JAVA-ORGECLIPSEJETTY-1080611


(ns structural-typing.validators
  "Validators. These differ from Bouncer validators in that (1) they default to optional, and
   (2) the messages include the failing value."
  (:require [bouncer.validators :as v]))

(defmacro defoptional [name doc message-format & body]
  `(do
     (v/defvalidator ~name {:optional true
                            :default-message-format ~message-format} ~@body)
     (alter-meta! (var ~name) assoc :doc ~doc)))

(v/defvalidator ^{:doc "Fails if key is missing or its value is `nil`."} required
  {:default-message-format "%s must be present and non-nil"}
  [v]
  (not (nil? v)))

(defoptional number
  "Validates against optional `number?`"
  "%s is `%s`, which is not a number"
  [maybe-a-number]
  (number? maybe-a-number))

(ns structural-typing.validators
  "Validators. These differ from Bouncer validators in that (1) they default to optional, and
   (2) the messages include the failing value."
  (:require [bouncer.validators :as v]))

(defmacro defoptional
  "Define a validator for an optional argument.

       (defoptional number
         \"Validates against optional `number?`\" ; doc string
         \"%s is `%s`, which is not a number\"
         [maybe-a-number]
         (number? maybe-a-number))
"
  [name doc message-format arglist & body]
  `(do
     (v/defvalidator ~name {:optional true
                            :default-message-format ~message-format} ~arglist ~@body)
     (alter-meta! (var ~name) assoc :doc ~doc
                                    :arglists (list '~arglist))))

(v/defvalidator ^{:doc "Fails if key is missing or its value is `nil`."} required
  {:default-message-format "%s must be present and non-nil"}
  [v]
  (not (nil? v)))

(defoptional number
  "Validates against optional `number?`"
  "%s is `%s`, which is not a number"
  [maybe-a-number]
  (number? maybe-a-number))

Make validator arglists available to codox


(ns arachnida.core)

(require '[clojure.java.jdbc :as jdbc])

(require '[clojure.pprint     :as pprint])

(require '[hozumi.rm-rf       :as rm-rf])

(require '[ring.adapter.jetty      :as jetty])
(require '[ring.middleware.params  :as http-params])
(require '[ring.util.response      :as http-response])
(require '[ring.middleware.cookies :as cookies])

(require '[hiccup.page :as page])
(require '[hiccup.form :as form])

(require '[arachnida.db-spec       :as db-spec])
(require '[arachnida.db-interface  :as db-interface])
(require '[arachnida.git-data-fetcher  :as git-data-fetcher])

(defn -main
    [& args]
    (git-data-fetcher/process))

(ns arachnida.core)

(require '[clojure.tools.cli      :as cli])

(require '[clojure.java.jdbc :as jdbc])

(require '[clojure.pprint     :as pprint])

(require '[hozumi.rm-rf       :as rm-rf])

(require '[ring.adapter.jetty      :as jetty])
(require '[ring.middleware.params  :as http-params])
(require '[ring.util.response      :as http-response])
(require '[ring.middleware.cookies :as cookies])

(require '[hiccup.page :as page])
(require '[hiccup.form :as form])

(require '[arachnida.db-spec       :as db-spec])
(require '[arachnida.db-interface  :as db-interface])
(require '[arachnida.git-data-fetcher  :as git-data-fetcher])

(def cli-options
  [["-h" "--help"    "help"                   :id :help]
   ["-g" "--git"     "fetch GIT statistic"    :id :git]
   ["-s" "--server"  "run as HTTP server"     :id :server]])

(defn show-help
    []
    (println "Usage:")
    (println "-h" "--help      help")
    (println "-g" "--git       fetch GIT statistic")
    (println "-s" "--server    run as HTTP server"))

(defn show-error
    []
    (println "Unknown command line option!")
    (show-help))

(defn start-server
    []
    )

(defn -main
    [& args]
    (let [all-options           (cli/parse-opts args cli-options)
          options               (all-options :options)
          show-help?            (options :help)
          git?                  (options :git)
          server?               (options :server)]
        (cond show-help? (show-help)
              git?       (git-data-fetcher/process)
              server?    (start-server)
              :else      (show-error))))

Support for handling basic CLI options: -h, -g, -s etc.


(ns {{namespace}}
  (:require [play-clj.core :refer :all])
  (:import [com.badlogic.gdx.graphics Color]
           [com.badlogic.gdx.graphics.g2d BitmapFont]
           [com.badlogic.gdx.scenes.scene2d.ui Label Label$LabelStyle]))

(defscreen main-screen
  :on-show
  (fn [screen entities]
    (update! screen :renderer (stage))
    (conj entities (label "Hello world!" (color :white))))
  :on-render
  (fn [screen entities]
    (clear!)
    (draw! screen entities)
    entities))

(defgame {{app-name}}
  :on-create
  (fn [this]
    (set-screen! this main-screen)))

(ns {{namespace}}
  (:require [play-clj.core :refer :all]))

(defscreen main-screen
  :on-show
  (fn [screen entities]
    (update! screen :renderer (stage))
    (conj entities (label "Hello world!" (color :white))))
  :on-render
  (fn [screen entities]
    (clear!)
    (draw! screen entities)))

(defgame {{app-name}}
  :on-create
  (fn [this]
    (set-screen! this main-screen)))

Remove unnecessary imports from clojure game template


(ns exploud.numel
  (:require [cemerick.url :refer [url]]
            [cheshire.core :as json]
            [environ.core :refer [env]]
            [exploud.http :as http]))

(def timeout
  "The number of milliseconds we'll wait for a response."
  10000)

(def poke-numel-url
  "The base URL for Numel in poke"
  (url (env :service-numel-poke-url)))

(def prod-numel-url
  "The base URL for Numel in prod"
  (url (env :service-numel-prod-url)))

(defn application-registrations-url
  [environment application]
  (if (= "prod" (name environment))
    (str (url prod-numel-url "1.x" "registration" application))
    (str (url poke-numel-url "1.x" "registration" application))))

(defn application-registrations
  [environment application]
  (let [url (application-registrations-url environment application)
        {:keys [body status] :as response} (http/simple-get url {:socket-timeout timeout})]
    (if (= 200 status)
      (json/parse-string body true)
      (throw (ex-info "Unexpected response" {:type ::unexpected-response :response response})))))

(ns exploud.numel
  (:require [cemerick.url :refer [url]]
            [cheshire.core :as json]
            [environ.core :refer [env]]
            [exploud.http :as http]))

(def timeout
  "The number of milliseconds we'll wait for a response."
  10000)

(def poke-numel-url
  "The base URL for Numel in poke"
  (url (env :service-numel-poke-url)))

(def prod-numel-url
  "The base URL for Numel in prod"
  (url (env :service-numel-prod-url)))

(defn application-registrations-url
  [environment application]
  (if (= "prod" (name environment))
    (str (url prod-numel-url "1.x" "registration" application))
    (str (url poke-numel-url "1.x" "registration" application))))

(defn application-registrations
  [environment application]
  (let [url (application-registrations-url environment application)
        {:keys [body status] :as response} (http/simple-get url {:socket-timeout timeout})]
    (cond (= 200 status) (json/parse-string body true)
          (= 404 status) nil
          :else (throw (ex-info "Unexpected response" {:type ::unexpected-response :response response})))))

Handle 404 when getting Numel registrations


(ns theatralia.t-core
  (:require [midje.sweet :refer :all]
            [clojure.test.check :as tc]
            [clojure.test.check.generators :as gen]
            [clojure.test.check.properties :as prop]
            [theatralia.core :refer [first-element]]))

;; Credits: http://zotskolf.nl/2014/11/10/testcheckbasics.html
(def prop-first-element-returns-first-element
  (prop/for-all [fst gen/simple-type
                 v (gen/vector gen/simple-type)]
    (= fst (first-element (cons fst v) :default))))

(facts "about `first-element`"
  (fact "it normally returns the first element"
    (first-element [1 2 3] :default) => 1
    (first-element '(1 2 3) :default) => 1
    (tc/quick-check 100 prop-first-element-returns-first-element)
        => (just {:result true :num-tests 100 :seed anything}))

  ;; I'm a little unsure how Clojure types map onto the Lisp I'm used to.
  (fact "default value is returned for empty sequences"
    (first-element [] :default) => :default
    (first-element '() :default) => :default
    (first-element nil :default) => :default
    (first-element (filter even? [1 3 5]) :default) => :default))

(ns theatralia.t-core
  (:require [midje.sweet :refer :all]
            [clojure.test.check :as tc]
            [clojure.test.check.generators :as gen]
            [clojure.test.check.properties :as prop]
            [theatralia.core :refer [first-element]]))

;;; Credits: http://zotskolf.nl/2014/11/10/testcheckbasics.html

(defn quick-check [times]
  (fn [prop]
    ((just {:result true :num-tests times :seed anything})
     (tc/quick-check times prop))))

(facts "about `first-element`"
  (fact "it normally returns the first element"
    (first-element [1 2 3] :default) => 1
    (first-element '(1 2 3) :default) => 1)

  (fact "it returns the first element for lots of vectors"
    (prop/for-all [fst gen/simple-type
                   v (gen/vector gen/simple-type)]
      (= fst (first-element (cons fst v) :default)))
      => (quick-check 100))

  ;; I'm a little unsure how Clojure types map onto the Lisp I'm used to.
  (fact "default value is returned for empty sequences"
    (first-element [] :default) => :default
    (first-element '() :default) => :default
    (first-element nil :default) => :default
    (first-element (filter even? [1 3 5]) :default) => :default))

Add Midje checker for cooperation with test.check

I'm not yet sure where to put it, though. Does test support code belong
in src or test?


(defproject fleetdb "0.2.0-RC1"
  :description "A schema-free database optimized for agile development."
  :url "http://github.com/mmcgrana/fleetdb"
  :source-path "src/clj"
  :java-source-path "src/jvm/"
  :javac-fork "true"
  :dependencies [[org.clojure/clojure "1.1.0"]
                 [org.clojure/clojure-contrib "1.1.0"]
                 [clj-stacktrace "0.1.0"]
                 [net.sf.jopt-simple/jopt-simple "3.2"]
                 [clj-json "0.2.0"]]
  :dev-dependencies [[org.clojars.mmcgrana/lein-clojars "0.5.0"]
                     [org.clojars.mmcgrana/lein-javac "0.1.0"]
                     [clj-unit "0.1.0"]]
  :namespaces [fleetdb.server])

(defproject fleetdb "0.2.0-RC1"
  :description "A schema-free database optimized for agile development."
  :url "http://github.com/mmcgrana/fleetdb"
  :source-path "src/clj"
  :java-source-path "src/jvm/"
  :javac-fork "true"
  :dependencies [[org.clojure/clojure "1.1.0"]
                 [org.clojure/clojure-contrib "1.1.0"]
                 [clj-stacktrace "0.1.2"]
                 [net.sf.jopt-simple/jopt-simple "3.2"]
                 [clj-json "0.2.0"]]
  :dev-dependencies [[org.clojars.mmcgrana/lein-clojars "0.5.0"]
                     [org.clojars.mmcgrana/lein-javac "0.1.0"]
                     [clj-unit "0.1.0"]]
  :namespaces [fleetdb.server])

Use most recent clj-stacktrace version.

Use most recent clj-stacktrace version.


(defproject onyx-app/lein-template "0.9.7.0-alpha8"
  :description "Onyx Leiningen application template"
  :url "https://github.com/onyx-platform/onyx-template"
  :license {:name "MIT License"
            :url "http://choosealicense.com/licenses/mit/#"}
  :repositories {"snapshots" {:url "https://clojars.org/repo"
                              :username :env
                              :password :env
                              :sign-releases false}
                 "releases" {:url "https://clojars.org/repo"
                             :username :env
                             :password :env
                             :sign-releases false}}
  :plugins [[lein-set-version "0.4.1"]]
  :profiles {:dev {:plugins [[lein-set-version "0.4.1"]
                             [lein-update-dependency "0.1.2"]
                             [lein-pprint "1.1.1"]]}}
  :eval-in-leiningen true)

(defproject onyx-app/lein-template "0.9.7.0-SNAPSHOT"
  :description "Onyx Leiningen application template"
  :url "https://github.com/onyx-platform/onyx-template"
  :license {:name "MIT License"
            :url "http://choosealicense.com/licenses/mit/#"}
  :repositories {"snapshots" {:url "https://clojars.org/repo"
                              :username :env
                              :password :env
                              :sign-releases false}
                 "releases" {:url "https://clojars.org/repo"
                             :username :env
                             :password :env
                             :sign-releases false}}
  :plugins [[lein-set-version "0.4.1"]]
  :profiles {:dev {:plugins [[lein-set-version "0.4.1"]
                             [lein-update-dependency "0.1.2"]
                             [lein-pprint "1.1.1"]]}}
  :eval-in-leiningen true)

Prepare for next release cycle.

Prepare for next release cycle.


(defproject io.aviso/rook "0.1.10-SNAPSHOT"
  :description "Ruby on Rails-style resource mapping for Clojure/Compojure web apps"
  :url "https://github.com/AvisoNovate/rook"
  :license {:name "Apache Sofware License 2.0"
            :url  "http://www.apache.org/licenses/LICENSE-2.0.html"}
  :profiles {:dev
              {:dependencies [[ring-mock "0.1.5"]
                              [io.aviso/pretty "0.1.11"]
                              [clj-http "0.9.1"]
                              [speclj "3.0.2"]
                              [log4j "1.2.17"]]}}
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [org.clojure/core.async "0.1.278.0-76b25b-alpha"]
                 [org.clojure/tools.logging "0.2.6"]
                 [ring "1.3.0"]
                 [medley "0.4.0"]
                 [ring-middleware-format "0.3.2"]
                 [prismatic/schema "0.2.3"]]
  :plugins [[speclj "3.0.2"]]
  :test-paths ["spec"]
  :codox {:src-dir-uri               "https://github.com/AvisoNovate/rook/blob/master/"
          :src-linenum-anchor-prefix "L"
          :defaults                  {:doc/format :markdown}})

(defproject io.aviso/rook "0.1.10-SNAPSHOT"
  :description "Ruby on Rails-style resource mapping for Clojure/Compojure web apps"
  :url "https://github.com/AvisoNovate/rook"
  :license {:name "Apache Sofware License 2.0"
            :url  "http://www.apache.org/licenses/LICENSE-2.0.html"}
  :profiles {:dev
              {:dependencies [[ring-mock "0.1.5"]
                              [io.aviso/pretty "0.1.11"]
                              [clj-http "0.9.1"]
                              [speclj "3.0.2"]
                              [log4j "1.2.17"]]}}
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [org.clojure/core.async "0.1.303.0-886421-alpha"]
                 [org.clojure/tools.logging "0.2.6"]
                 [ring "1.3.0"]
                 [medley "0.4.0"]
                 [ring-middleware-format "0.3.2"]
                 [prismatic/schema "0.2.3"]]
  :plugins [[speclj "3.0.2"]]
  :test-paths ["spec"]
  :codox {:src-dir-uri               "https://github.com/AvisoNovate/rook/blob/master/"
          :src-linenum-anchor-prefix "L"
          :defaults                  {:doc/format :markdown}})

Update to latest version of core.async

Update to latest version of core.async


(defproject statuses "1.0.0-SNAPSHOT"
  :description "Statuses app for innoQ"
  :url "https://github.com/innoq/statuses"
  :license {:name "Apache License, Version 2.0"
            :url "http://www.apache.org/licenses/LICENSE-2.0"
            :distribution :repo
            :comments "A business-friendly OSS license"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [ring "1.3.2"]
                 [compojure "1.3.3"]
                 [clj-time "0.9.0"]
                 [org.clojure/data.json "0.2.6"]
                 [org.clojure/tools.cli "0.3.3"]]
  :pedantic? :abort
  :plugins [[jonase/eastwood "0.2.0"]]
  :profiles {:dev {:dependencies [[ring-mock "0.1.5"]]}
             :uberjar {:aot [statuses.server]}}
  :main statuses.server
  :aliases {"lint" "eastwood"}
  :eastwood {:exclude-linters [:constant-test]})

(defproject statuses "1.0.0-SNAPSHOT"
  :description "Statuses app for innoQ"
  :url "https://github.com/innoq/statuses"
  :license {:name "Apache License, Version 2.0"
            :url "http://www.apache.org/licenses/LICENSE-2.0"
            :distribution :repo
            :comments "A business-friendly OSS license"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [ring "1.4.0"]
                 [compojure "1.3.3"]
                 [clj-time "0.9.0"]
                 [org.clojure/data.json "0.2.6"]
                 [org.clojure/tools.cli "0.3.3"]]
  :pedantic? :abort
  :plugins [[jonase/eastwood "0.2.0"]]
  :profiles {:dev {:dependencies [[ring-mock "0.1.5"]]}
             :uberjar {:aot [statuses.server]}}
  :main statuses.server
  :aliases {"lint" "eastwood"}
  :eastwood {:exclude-linters [:constant-test]})

Update ring from 1.3.2 to 1.4.0

Update ring from 1.3.2 to 1.4.0


(defproject foreclojure "1.2.0"
  :description "4clojure - a website for lisp beginners"
  :dependencies [[clojure "1.2.1"]
                 [clojure-contrib "1.2.0"]
                 [compojure "0.6.2"]
                 [hiccup "0.2.4"]
                 [clojail "0.4.0-SNAPSHOT"]
                 [sandbar "0.4.0-SNAPSHOT"]
                 [org.clojars.christophermaier/congomongo "0.1.4-SNAPSHOT"]
                 [org.jasypt/jasypt "1.7"]
                 [useful "0.7.0-beta1"]
                 [amalloy/ring-gzip-middleware "[0.1.0,)"]
                 [clj-github "1.0.1"]
                 [ring "0.3.7"]
                 [clj-config "0.1.0"]
                 [incanter/incanter-core "1.2.3"]
                 [incanter/incanter-charts "1.2.3"]
                 [org.apache.commons/commons-email "1.2"]]
  :dev-dependencies [[lein-ring "0.4.5"]
                     [swank-clojure "1.2.1"]
                     [midje "1.1.1"]]
  :main foreclojure.core
  :ring {:handler foreclojure.core/app
         :init foreclojure.mongo/prepare-mongo})

(defproject foreclojure "1.3.0"
  :description "4clojure - a website for lisp beginners"
  :dependencies [[clojure "1.2.1"]
                 [clojure-contrib "1.2.0"]
                 [compojure "0.6.2"]
                 [hiccup "0.2.4"]
                 [clojail "0.4.0-SNAPSHOT"]
                 [sandbar "0.4.0-SNAPSHOT"]
                 [org.clojars.christophermaier/congomongo "0.1.4-SNAPSHOT"]
                 [org.jasypt/jasypt "1.7"]
                 [useful "0.7.0-beta1"]
                 [amalloy/ring-gzip-middleware "[0.1.0,)"]
                 [clj-github "1.0.1"]
                 [ring "0.3.7"]
                 [clj-config "0.1.0"]
                 [incanter/incanter-core "1.2.3"]
                 [incanter/incanter-charts "1.2.3"]
                 [org.apache.commons/commons-email "1.2"]]
  :dev-dependencies [[lein-ring "0.4.5"]
                     [swank-clojure "1.2.1"]
                     [midje "1.1.1"]]
  :main foreclojure.core
  :ring {:handler foreclojure.core/app
         :init foreclojure.mongo/prepare-mongo})

Set version number for 1.3.0

Set version number for 1.3.0


{:user {:plugins [[cider/cider-nrepl "0.10.0-SNAPSHOT"]
                  [refactor-nrepl "1.2.0-SNAPSHOT"]]
        :dependencies [[org.clojure/tools.nrepl "0.2.12"]]}}

{:user {:plugins [[cider/cider-nrepl "0.11.0-SNAPSHOT"]
                  [refactor-nrepl "1.2.0-SNAPSHOT"]]
        :dependencies [[org.clojure/tools.nrepl "0.2.12"]]}}

Update cider-nrepl version to v0.11.0-SNAPSHOT


(ns re-frame.core
  (:require
    [re-frame.handlers   :as handlers]
    [re-frame.subs       :as subs]
    [re-frame.middleware :as middleware]))

;; --  API  -------

(def register-handler handlers/register)
(def dispatch         handlers/dispatch)
(def dispatch-sync    handlers/dispatch-sync)

(def register-sub  subs/register)
(def subscribe     subs/subscribe)

(def pure        middleware/pure)
(def debug       middleware/debug)
(def undoable    middleware/undoable)
(def path        middleware/path)
(def validate    middleware/validate)
(def trim-v      middleware/trim-v)
; (def log-events  middleware/log-events)

;; --  Convienience  -------

;; virtually ever handler will be pure, make it easy
(defn register-pure-handler
  ([id handler]
    (register-handler id pure handler))
  ([id middleware handler]
    (register-handler id [pure middleware] handler)))

(ns re-frame.core
  (:require
    [re-frame.handlers   :as handlers]
    [re-frame.subs       :as subs]
    [re-frame.middleware :as middleware]))

;; --  API  -------

(def register-handler handlers/register)
(def dispatch         handlers/dispatch)
(def dispatch-sync    handlers/dispatch-sync)

(def register-sub  subs/register)
(def subscribe     subs/subscribe)

(def noop        middleware/noop)
(def pure        middleware/pure)
(def debug       middleware/debug)
(def undoable    middleware/undoable)
(def path        middleware/path)
(def validate    middleware/validate)
(def trim-v      middleware/trim-v)
; (def log-events  middleware/log-events)

;; --  Convienience  -------

;; virtually ever handler will be pure, make it easy
(defn register-pure-handler
  ([id handler]
    (register-handler id pure handler))
  ([id middleware handler]
    (register-handler id [pure middleware] handler)))

(defn comp-middleware
  "Given a vector of middleware, filter out any nils, and use comp to compose.
  v can  be vectors of vectors and will be flattended before use.
  For convienience, if v turns out to already be a function, just return it."
  [v]
  (if (ifn? v)     ;; noop if v is a fucntion
    v
    (do
      (assert  (or (vector? v) (list v))
               (str "re-frame:  compose expects a vector, got: " v))
      (let [v (remove nil? (flatten v))]
        (cond
          (empty? v)       noop
          (= 1 (count v))  (first v)
          :else            (apply comp v))))))

Add new API - a noop middleware - a comp-middleware


(ns todo-repl.core
    #_(:load "/todo-repl/date-parsing")
    (:require [todo-repl.date-parsing :as dp])
    #_(:use todo-repl.date-parsing))

(defn new-task [name due-by due-after context url]
  {:name name
   :due-after due-after
   :due-by due-by
   :context context
   :url url
   :status :incomplete
   :created (str (java.util.Date.))
   })

(defn new-task-better [{:keys [name due-after due-by context url]
                   :or {due-by "never"
                        due-after nil
                        context nil
                        url [{:label "" :url ""}] }}]
  (new-task name
            (dp/nl-to-date due-by)
            (dp/nl-to-date due-after)
            context
            url))

(defn add-new-task-to [new-task tasks]
  (cons (new-task-better new-task) tasks))

(defn filter-tasks [filter-attrib val tasks]
  (filter #(= val (filter-attrib %)) tasks))

(defn complete-task [& xs]
  (map #(assoc % :status :complete)) xs)

(ns todo-repl.core
    #_(:load "/todo-repl/date-parsing")
    (:require [todo-repl.date-parsing :as dp])
    #_(:use todo-repl.date-parsing))

(defn new-task [name due due-after context url]
  {:name name
   :due-after due-after
   :due due
   :context context
   :url url
   :status :incomplete
   :created (str (java.util.Date.))
   })

(defn new-task-better [{:keys [name due-after due context url]
                   :or {due "never"
                        due-after nil
                        context nil
                        url [{:label "" :url ""}] }}]
  (new-task name
            (dp/nl-to-date due)
            (dp/nl-to-date due-after)
            context
            url))

(defn add-new-task-to [new-task tasks]
  (cons (new-task-better new-task) tasks))

(defn filter-tasks [filter-attrib val tasks]
  (filter #(= val (filter-attrib %)) tasks))

(defn complete-task [& xs]
  (map #(assoc % :status :complete)) xs)

Change tasks :due-by to :due.

Change tasks :due-by to :due.


(defn square [x] (* x x))

(meditations
  "One may know what they seek by knowing what they do not seek"
  (= [__ __ __] (let [not-a-symbol? (complement symbol?)]
                  (map not-a-symbol? [:a 'b "c"])))

  "Praise and 'complement' may help you separate the wheat from the chaff"
  (= [:wheat "wheat" 'wheat]
       (let [not-nil? ___]
         (filter not-nil? [nil :wheat nil "wheat" nil 'wheat nil])))

  "Partial functions allow procrastination"
  (= 20 (let [multiply-by-5 (partial * 5)]
          (___ __)))

  "Don't forget: first things first"
  (= [__ __ __ __]
       (let [ab-adder (partial concat [:a :b])]
         (ab-adder [__ __])))

  "Functions can join forces as one 'composed' function"
  (= 25 (let [inc-and-square (comp square inc)]
          (inc-and-square __)))

  "Have a go on a double dec-er"
  (= __ (let [double-dec (comp dec dec)]
          (double-dec 10)))

  "Be careful about the order in which you mix your functions"
  (= 99 (let [square-and-dec ___]
          (square-and-dec 10))))

(defn square [x] (* x x))

(meditations
  "One may know what they seek by knowing what they do not seek"
  (= [true false true] (let [not-a-symbol? (complement symbol?)]
                  (map not-a-symbol? [:a 'b "c"])))

  "Praise and 'complement' may help you separate the wheat from the chaff"
  (= [:wheat "wheat" 'wheat]
       (let [not-nil? (complement nil?)]
         (filter not-nil? [nil :wheat nil "wheat" nil 'wheat nil])))

  "Partial functions allow procrastination"
  (= 20 (let [multiply-by-5 (partial * 5)]
          (multiply-by-5 4)))

  "Don't forget: first things first"
  (= [:a :b :c :d]
       (let [ab-adder (partial concat [:a :b])]
         (ab-adder [:c :d])))

  "Functions can join forces as one 'composed' function"
  (= 25 (let [inc-and-square (comp square inc)]
          (inc-and-square 4)))

  "Have a go on a double dec-er"
  (= 8 (let [double-dec (comp dec dec)]
          (double-dec 10)))

  "Be careful about the order in which you mix your functions"
  (= 99 (let [square-and-dec (comp dec square)]
          (square-and-dec 10))))

Complete creating functions koans test

Complete creating functions koans test


(ns clj-beautify.core
  (:require [clj-beautify.file-handler :as f]
            [clj-beautify.beautify :refer [format-clj]])
  (:gen-class))

(defn format-file
  "Given a file page and a valid mode (`clj`|`edn`) open and use
  `clojure.tools.reader/read-string` to transform the file to a literal so that
  if can be formatted by `clojure.pprint/write`. It then writes back to the same
  file with a formatted string."
  [filename mode]
  (let [input   (f/read-file filename)
        output  (format-clj input mode)]
    (f/write-file filename output)))

(defn -main
  "Entry point of the command line program that takes a file path (or directory)
  and mode (clj|edn). Formats all files to specified mode and rewrites the
  original files."
  [& args]
  (let [arg-cnt (count args)]
    (when (< 2 arg-cnt)
      (throw (Exception. (str "Invalid number of arguements. Expected 2 but "
                              "found " arg-cnt))))
    ;; TODO: do something with the valid args
    (doseq [file (f/list-files (nth args 1))]
      (format-file file (nth args 0)))))

(ns clj-beautify.core
  (:require [clj-beautify.file-handler :as f]
            [clj-beautify.beautify :refer [format-clj]])
  (:gen-class))

(defn format-string
  "Just a function wrapper arond format-clj"
  [input mode]
  (format-clj input mode))

(defn format-file
  "Given a file page and a valid mode (`clj`|`edn`) open and use
  `clojure.tools.reader/read-string` to transform the file to a literal so that
  if can be formatted by `clojure.pprint/write`. It then writes back to the same
  file with a formatted string."
  [filename mode]
  (let [input   (f/read-file filename)
        output  (format-string input mode)]
    (f/write-file filename output)))

(defn -main
  "Entry point of the command line program that takes a file path (or directory)
  and mode (clj|edn). Formats all files to specified mode and rewrites the
  original files."
  [& args]
  (let [arg-cnt (count args)]
    (when (< 2 arg-cnt)
      (throw (Exception. (str "Invalid number of arguements. Expected 2 but "
                              "found " arg-cnt))))
    ;; TODO: do something with the valid args
    (doseq [file (f/list-files (nth args 1))]
      (format-file file (nth args 0)))))

Create a function wrapper for a cleanly exposed API.


(ns app.components.snippet-list
  (:require [om.next :as om :refer-macros [defui]]
            [om.dom :as dom]
            [app.components.snippet :refer [snippet]]))

(defn sort-snippets [snippets]
  (sort-by :uuid
           (fn [id1 id2] (instance? om.tempid/TempId id1))
           snippets))

(defui SnippetList
  Object
  (render [this]
    (let [{:keys [snippets]} (om/props this)
          {:keys [toggle-fn create-fn edit-fn delete-fn update-fn save-fn]}
          (om/get-computed this)]
      (dom/div #js {:className "snippet-list"}
        (dom/h2 #js {:className "snippet-list-title"}
          (dom/span #js {:className "snippet-list-title-text"} "Snippets")
          (dom/span #js {:className "snippet-list-title-buttons"}
            (dom/button #js {:className "snippet-list-title-button"
                             :onClick #(when create-fn (create-fn))}
              "+ Create")))
        (for [sn (sort-snippets (reverse snippets))]
          (snippet (om/computed sn {:toggle-fn toggle-fn
                                    :edit-fn edit-fn
                                    :delete-fn delete-fn
                                    :update-fn update-fn
                                    :save-fn save-fn})))))))

(def snippet-list (om/factory SnippetList))

(ns app.components.snippet-list
  (:require [om.next :as om :refer-macros [defui]]
            [om.dom :as dom]
            [app.components.snippet :refer [snippet]]))

(defn sort-snippets [snippets]
  (sort-by :uuid
           (fn [id1 id2] (instance? om.tempid/TempId id1))
           snippets))

(defui SnippetList
  Object
  (render [this]
    (let [{:keys [snippets]} (om/props this)
          {:keys [toggle-fn create-fn edit-fn delete-fn update-fn save-fn]}
          (om/get-computed this)]
      (dom/div #js {:className "snippet-list"}
        (dom/h2 #js {:className "snippet-list-title"}
          (dom/span #js {:className "snippet-list-title-text"} "Snippets")
          (dom/span #js {:className "snippet-list-title-buttons"}
            (dom/button #js {:className "snippet-list-title-button"
                             :onClick #(when create-fn (create-fn))}
              "+ Create")))
        (for [sn (sort-snippets snippets)]
          (snippet (om/computed sn {:toggle-fn toggle-fn
                                    :edit-fn edit-fn
                                    :delete-fn delete-fn
                                    :update-fn update-fn
                                    :save-fn save-fn})))))))

(def snippet-list (om/factory SnippetList))

Fix sorting snippets so that the most recent shows up at the top


(ns lambdacd.state.protocols
  "Defines protocols that need to be implemented by a state component")

(defprotocol StepResultUpdateConsumer
  "Components implementing this protocol can update the state of the pipeline"
  (consume-step-result-update [self build-number step-id step-result]
    "Tells the component to update the result of a particular step. Is called on every update so it needs to handle lots of requests"))

(defprotocol PipelineStructureConsumer
  "Components implementing this protocol can set the structure a pipeline had for a particular build"
  (consume-pipeline-structure [self build-number pipeline-structure-representation]
    "Tells the component to update the structure of a particular build."))

(defprotocol NextBuildNumberSource
  "Components implementing this protocol provide the LambdaCD execution engine with new build numbers"
  (next-build-number [self]
    "Returns the build number for the next build. Must be comparable and greater than all existing build numbers")) ; TODO: is build number an int?

(defprotocol QueryAllBuildNumbersSource
  "Components implementing this protocol can supply a list of all build numbers present in the datastore"
  (all-build-numbers [self]
    "Returns a sorted list of build numbers present in the datastore"))

(defprotocol QueryStepResultsSource
  "Components implementing this protocol can supply steps results of a build"
  (get-step-results [self build-number]
    "Returns a map of step-id to step results"))

(defprotocol PipelineStructureSource
  "Components implementing this protocol can supply the structure of the pipeline for a particular build"
  (get-pipeline-structure [self build-number]
    "Returns a map describing the pipeline of for a particular build"))

(ns lambdacd.state.protocols
  "Defines protocols that need to be implemented by a state component")

(defprotocol StepResultUpdateConsumer
  "Components implementing this protocol can update the state of the pipeline"
  (consume-step-result-update [self build-number step-id step-result]
    "Tells the component to update the result of a particular step. Is called on every update so it needs to handle lots of requests"))

(defprotocol PipelineStructureConsumer
  "Components implementing this protocol can set the structure a pipeline had for a particular build"
  (consume-pipeline-structure [self build-number pipeline-structure-representation]
    "Tells the component to update the structure of a particular build."))

(defprotocol NextBuildNumberSource
  "Components implementing this protocol provide the LambdaCD execution engine with new build numbers"
  (next-build-number [self]
    "Returns the build number for the next build. Must be an integer and greater than all existing build numbers"))

(defprotocol QueryAllBuildNumbersSource
  "Components implementing this protocol can supply a list of all build numbers present in the datastore"
  (all-build-numbers [self]
    "Returns a sorted list of build numbers present in the datastore"))

(defprotocol QueryStepResultsSource
  "Components implementing this protocol can supply steps results of a build"
  (get-step-results [self build-number]
    "Returns a map of step-id to step results"))

(defprotocol PipelineStructureSource
  "Components implementing this protocol can supply the structure of the pipeline for a particular build"
  (get-pipeline-structure [self build-number]
    "Returns a map describing the pipeline of for a particular build"))

Clarify protocol documentation: LambdaCD expects build numbers to be integers


(ns ^:figwheel-always potoo.core
  (:require [reagent.core :as r]
            [ajax.core :refer [GET POST]]))

(defonce app-state
  (r/atom {:potoos []}))

(defn potoo [p]
  (let [{:keys [text name date]} p]
    [:li
     [:span (str text ", " name ", " date)]]))

(defn potoo-list []
  (fn []
    (GET "/api/potoos" {:keywords? true
                        :response-format :json
                        :handler #(swap! app-state assoc :potoos %)})
    [:div
     [:h1 "Potooooooos!"]
     [:ul
      (for [p (:potoos @app-state)]
        ^{:key p} [potoo p])]]))

(defn ^:export run []
  (r/render
    [potoo-list]
    (js/document.getElementById "app")))

(run)

;; demo

(comment
  (defn cp [text]
    (let [name "Mr. Meeseeks"
          date (str (js/Date.))
          potoo {:key "zxc" :text text :name name :date date}]
      (swap! app-state update-in [:potoos] conj potoo))))

(ns ^:figwheel-always potoo.core
  (:require [reagent.core :as r]
            [ajax.core :refer [GET POST]]))

(defonce app-state
  (r/atom {:potoos []}))

(defn potoo [p]
  (let [{:keys [text name date]} p]
    [:li
     [:span (str text ", " name ", " date)]]))

(defn potoo-list []
  [:div
   [:h1 "Potooooooos!"]
   [:ul
    (for [p (:potoos @app-state)]
      ^{:key p} [potoo p])]])

(def potoo-list-initial
  (with-meta potoo-list
    {:get-initial-state
     (fn [_]
       (GET "/api/potoos" {:keywords? true
                           :response-format :json
                           :handler #(swap! app-state assoc :potoos %)}))}))

(defn ^:export run []
  (r/render
    [potoo-list-initial]
    (js/document.getElementById "app")))

(run)

;; demo

(comment
  (defn cp [text]
    (let [name "Mr. Meeseeks"
          date (str (js/Date.))
          potoo {:key "zxc" :text text :name name :date date}]
      (swap! app-state update-in [:potoos] conj potoo))))

Use react's get-initial-state for potoo list


(ns noir-app.init
  (:require [immutant.web :as web]
            [immutant.util :as util]
            [noir.server :as server]
            [lobos.config]))

(server/load-views-ns 'noir-app.views)
(web/start "/" (server/gen-handler {:mode :dev :ns 'noir-app}))

(ns noir-app.init
  (:require [immutant.web :as web]
            [immutant.util :as util]
            [noir.server :as server]
            [lobos.config]))

;; Use this once the new bultitude and noir 1.3.0 are released
;(server/load-views-ns 'noir-app.views)
(server/load-views (util/app-relative "src/noir_app/views"))
(web/start "/" (server/gen-handler {:mode :dev :ns 'noir-app}))

Use load-views until a new noir is released.


(ns detritus.types)

(defn atom? [x]
  (instance? clojure.lang.Atom x))

(ns detritus.types)

;; Concrete type predicates
;;--------------------------------------------------------------------
(defn atom? [x]
  (instance? clojure.lang.Atom x))

(defn map-entry? [x]
  (or (instance? clojure.lang.MapEntry x)
      (and (vector? x)
           (= 2 (count x)))))

(defn lazy-seq? [x]
  (instance? clojure.lang.LazySeq x))

(defn pattern? [x]
  (instance? java.util.regex.Pattern x))

(defn uuid? [x]
  (instance? java.util.UUID x))

(defn boolean? [x]
  (instance? java.lang.Boolean x))

(defn long? [x]
  (instance? java.lang.Long x))

(defn int? [x]
  (instance? java.lang.Integer x))

(defn big-int? [x]
  (or (instance? java.math.BigInteger x)
      (instance? clojure.lang.BigInt x)))

;; Interface predicates
;;--------------------------------------------------------------------
(defn ref? [x]
  (instance? clojure.lang.IRef x))

(defn deref? [x]
  (instance? clojure.lang.IDeref x))

(defn named? [x]
  (instance? clojure.lang.Named))

(defn throwable? [x]
  (instance? java.lang.Throwable x))

(defn seqable? [x]
  (or (instance? clojure.lang.ISeq x)
      (instance? clojure.lang.Seqable x)
      (instance? Iterable x)
      (instance? CharSequence x)
      (instance? java.util.Map x)
      (nil? x)
      (.. x getClass isArray)))

Add a plethora of type predicates

Add a plethora of type predicates


(ns om-tut.core
  (:require [om.core :as om :include-macros true]
            [om.dom :as dom :include-macros true]))

(enable-console-print!)

(println "A new developer message. Pay attention, dev guy!")

;; define your app data so that it doesn't get over-written on reload

(defonce app-state (atom {:list ["Lion" "Zebra" "Buffalo" "Antelope"]}))

(om/root
 (fn [data owner]
   (om/component
    (apply dom/ul #js {:className "animals"}
           (map (fn [text] (dom/li nil text)) (:list data)))))
 app-state
 {:target (. js/document (getElementById "app0"))})

(defn on-js-reload []
  ;; optionally touch your app-state to force rerendering depending on
  ;; your application
  ;; (swap! app-state update-in [:__figwheel_counter] inc)
)

(ns om-tut.core
  (:require [om.core :as om :include-macros true]
            [om.dom :as dom :include-macros true]))

(enable-console-print!)

(println "A new developer message. Pay attention, dev guy!")

;; define your app data so that it doesn't get over-written on reload

(defonce app-state (atom {:list ["Lion" "Zebra" "Buffalo" "Antelope"]}))

(defn stripe [text background-color]
  (let [st #js {:backgroundColor background-color}]
    (dom/li #js {:style st} text)))

(om/root
 (fn [data owner]
   (om/component
    (apply dom/ul #js {:className "animals"}
           (map stripe (:list data) (cycle ["#ff0" "#fff"])))))

 app-state
 {:target (. js/document (getElementById "app0"))})

(defn on-js-reload []
  ;; optionally touch your app-state to force rerendering depending on
  ;; your application
  ;; (swap! app-state update-in [:__figwheel_counter] inc)
)

Implement code for "Life without a..."

Implement code for "Life without a..."

Write the code for the "Life without a templating language" section.
This section demonstrates using functional programming to implement
features that templating languages might provide.


(defproject org.onyxplatform/onyx-metrics "0.8.0.3-SNAPSHOT"
  :description "Instrument Onyx workflows"
  :url "https://github.com/MichaelDrogalis/onyx"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :repositories {"snapshots" {:url "https://clojars.org/repo"
                              :username :env
                              :password :env
                              :sign-releases false}
                 "releases" {:url "https://clojars.org/repo"
                             :username :env
                             :password :env
                             :sign-releases false}}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [interval-metrics "1.0.0"]
                 [stylefruits/gniazdo "0.4.0"]]
  :java-opts ^:replace ["-server" "-Xmx3g"]
  :global-vars  {*warn-on-reflection* true
                 *assert* false
                 *unchecked-math* :warn-on-boxed}
  :profiles {:dev {:dependencies [^{:voom {:repo "git@github.com:onyx-platform/onyx.git" :branch "master"}}
                                  [org.onyxplatform/onyx "0.8.0.1"]
                                  [riemann-clojure-client "0.4.1"]]
                   :plugins [[lein-set-version "0.4.1"]
                             [lein-update-dependency "0.1.2"]
                             [lein-pprint "1.1.1"]]}})

(defproject org.onyxplatform/onyx-metrics "0.8.0.3-SNAPSHOT"
  :description "Instrument Onyx workflows"
  :url "https://github.com/MichaelDrogalis/onyx"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :repositories {"snapshots" {:url "https://clojars.org/repo"
                              :username :env
                              :password :env
                              :sign-releases false}
                 "releases" {:url "https://clojars.org/repo"
                             :username :env
                             :password :env
                             :sign-releases false}}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [interval-metrics "1.0.0"]
                 [stylefruits/gniazdo "0.4.0"]]
  :java-opts ^:replace ["-server" "-Xmx3g"]
  :global-vars  {*warn-on-reflection* true
                 *assert* false
                 *unchecked-math* :warn-on-boxed}
  :profiles {:dev {:dependencies [^{:voom {:repo "git@github.com:onyx-platform/onyx.git" :branch "master"}}
                                  [org.onyxplatform/onyx "0.8.0"]
                                  [riemann-clojure-client "0.4.1"]]
                   :plugins [[lein-set-version "0.4.1"]
                             [lein-update-dependency "0.1.2"]
                             [lein-pprint "1.1.1"]]}})

Revert onyx dependency back to release version


(defproject tttclj "0.0.1-SNAPSHOT"
  :description "Cool new project to do things and stuff"
  :dependencies [[org.clojure/clojure "1.4.0"]
                 [http-kit "2.1.16"]
                 [compojure "1.1.8"]]
  :profiles {:dev {:dependencies [[midje "1.5.0"]]}}
  :main tttclj.web)

(defproject tttclj "0.0.1-SNAPSHOT"
  :description "Cool new project to do things and stuff"
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [org.clojure/clojurescript "0.0-2227"]
                 [http-kit "2.1.16"]
                 [compojure "1.1.8"]]
  :profiles {:dev {:dependencies [[midje "1.5.0"]]
                   :plugins [[lein-cljsbuild "1.0.3"]]
                   :cljsbuild {:builds [{:source-paths ["src"]
                                         :compiler {:output-to "target/classes/public/app.js"
                                                    :optimizations :whitespace
                                                    :pretty-print true}}]}}}
  :main tttclj.web)

Upgrade Clojure & add ClojureScript

Upgrade Clojure & add ClojureScript


(defproject org.onyxplatform/onyx-metrics "0.8.0.2"
  :description "Instrument Onyx workflows"
  :url "https://github.com/MichaelDrogalis/onyx"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :repositories {"snapshots" {:url "https://clojars.org/repo"
                              :username :env
                              :password :env
                              :sign-releases false}
                 "releases" {:url "https://clojars.org/repo"
                             :username :env
                             :password :env
                             :sign-releases false}}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [interval-metrics "1.0.0"]
                 [stylefruits/gniazdo "0.4.0"]]
  :java-opts ^:replace ["-server" "-Xmx3g"]
  :global-vars  {*warn-on-reflection* true
                 *assert* false
                 *unchecked-math* :warn-on-boxed}
  :profiles {:dev {:dependencies [^{:voom {:repo "git@github.com:onyx-platform/onyx.git" :branch "master"}}
                                  [org.onyxplatform/onyx "0.8.0.1"]
                                  [riemann-clojure-client "0.4.1"]]
                   :plugins [[lein-set-version "0.4.1"]
                             [lein-update-dependency "0.1.2"]
                             [lein-pprint "1.1.1"]]}})

(defproject org.onyxplatform/onyx-metrics "0.8.0.3-SNAPSHOT"
  :description "Instrument Onyx workflows"
  :url "https://github.com/MichaelDrogalis/onyx"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :repositories {"snapshots" {:url "https://clojars.org/repo"
                              :username :env
                              :password :env
                              :sign-releases false}
                 "releases" {:url "https://clojars.org/repo"
                             :username :env
                             :password :env
                             :sign-releases false}}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [interval-metrics "1.0.0"]
                 [stylefruits/gniazdo "0.4.0"]]
  :java-opts ^:replace ["-server" "-Xmx3g"]
  :global-vars  {*warn-on-reflection* true
                 *assert* false
                 *unchecked-math* :warn-on-boxed}
  :profiles {:dev {:dependencies [^{:voom {:repo "git@github.com:onyx-platform/onyx.git" :branch "master"}}
                                  [org.onyxplatform/onyx "0.8.0.1"]
                                  [riemann-clojure-client "0.4.1"]]
                   :plugins [[lein-set-version "0.4.1"]
                             [lein-update-dependency "0.1.2"]
                             [lein-pprint "1.1.1"]]}})

Prepare for next release cycle.

Prepare for next release cycle.


(ns puppeteer.domain.entity.message)

(defrecord Field
  [title value short?])

(defrecord Attachment
  [text color fields])

(defrecord Message
  [channel-id user-id text timestamp attachments for-me?])

(ns puppeteer.domain.entity.message)

(defrecord Field
  [title value short?])

(defrecord Attachment
  [text color fields])

(defrecord Message
  [channel-id user-id text timestamp attachments for-me? from-me?])

Add from-me? key to Message

Add from-me? key to Message


(ns lt.objs.notifos
  (:require [lt.object :as object]
            [lt.objs.statusbar :as statusbar]
            [lt.objs.command :as cmd]
            [lt.util.js :refer [wait]]
            [crate.binding :refer [map-bound bound deref?]])
  (:require-macros [lt.macros :refer [behavior defui]]))

(def standard-timeout 10000)

(defn working [msg]
  (when msg
    (set-msg! msg))
  (statusbar/loader-inc))

(defn done-working
  ([]
   (statusbar/loader-dec))
  ([msg]
   (set-msg! msg)
   (statusbar/loader-dec)))

(defn msg* [m opts]
  (let [m (if (string? m)
            m
            (pr-str m))]
    (object/merge! statusbar/statusbar-loader (merge {:message m :class ""} opts))))

(defn set-msg! [msg opts]
  (msg* msg opts)
  (js/clearTimeout cur-timeout)
  (set! cur-timeout (wait standard-timeout #(msg* ""))))

(cmd/command {:command :reset-working
              :desc "Statusbar: Reset working indicator"
              :exec (fn []
                      (statusbar/loader-set 0)
                      )})

(ns lt.objs.notifos
  (:require [lt.object :as object]
            [lt.objs.statusbar :as statusbar]
            [lt.objs.command :as cmd]
            [lt.util.js :refer [wait]]
            [crate.binding :refer [map-bound bound deref?]])
  (:require-macros [lt.macros :refer [behavior defui]]))

(def standard-timeout 10000)

(defn working [msg]
  (when msg
    (set-msg! msg))
  (statusbar/loader-inc))

(defn done-working
  ([]
   (statusbar/loader-dec))
  ([msg]
   (set-msg! msg)
   (statusbar/loader-dec)))

(defn msg* [m & [opts]]
  (let [m (if (string? m)
            m
            (pr-str m))]
    (object/merge! statusbar/statusbar-loader (merge {:message m :class ""} opts))))

(defn set-msg! [msg opts]
  (msg* msg opts)
  (js/clearTimeout cur-timeout)
  (set! cur-timeout (wait standard-timeout #(msg* ""))))

(cmd/command {:command :reset-working
              :desc "Statusbar: Reset working indicator"
              :exec (fn []
                      (statusbar/loader-set 0)
                      )})

Make msg* opts argument optional

Make msg* opts argument optional

To avoid compiler warnings, change the opts argument of notifos/msg* into an optional one.


(ns route-ccrs.core
  (:require [clojure.tools.logging :as log]
            [route-ccrs.active-routes :as ar]
            [route-ccrs.route-ccr :as ccr]))

(defn calculate-and-record-ccrs!  [sys]
  (let [c {:connection (:db sys)}]
    (log/info "CCR calculation started")
    (->> (into [] ar/transduce-routes (ar/active-routes {} c))
         (map
           (fn [[r o]]
             (ccr/ccr-entry-updates
               r
               (ccr/get-last-known-ccr r c)
               (ccr/select-current-ccr (:db sys) o))))
         (filter seq)
         (reduce
           (fn [c u]
             (let [t (-> u second first)
                   tc (get c t 0)]
               (ccr/update! (:db sys) u)
               (assoc c t (inc tc))))
           {})
         (log/info "calculation complete, updated:"))))

(ns route-ccrs.core
  (:require [clojure.tools.logging :as log]
            [route-ccrs.active-routes :as ar]
            [route-ccrs.route-ccr :as ccr]))

(defmacro with-db-connection
  ^{:private true}
  [sys & body]
  `(let [~'db (:db ~sys)
         ~'c {:connection ~'db}]
     ~@body))

(defn- route-update [sys [route-id operations]]
  (with-db-connection sys
    (ccr/ccr-entry-updates
      route-id
      (ccr/get-last-known-ccr route-id c)
      (ccr/select-current-ccr db operations))))

(defn- reduce-to-updates [sys routes]
  (reduce
    (fn [u route]
      (let [ru (route-update sys route)]
        (if (seq ru)
          (conj u ru)
          u)))
    []
    routes))

(defn- apply-updates! [sys updates]
  (with-db-connection sys
    (reduce
      (fn [totals route-update]
        (let [update-type (-> route-update second first)]
          (ccr/update! db route-update)
          (update-in totals [update-type] #(inc (or % 0)))))
      {}
      updates)))

(defn calculate-and-record-ccrs!  [sys]
  (with-db-connection sys
    (log/info "CCR calculation started")
    (->> (into [] ar/transduce-routes (ar/active-routes {} c))
         (reduce-to-updates sys)
         (apply-updates! sys)
         (log/info "calculation complete, updated:"))))

Break calculate-and-record-ccrs! into discrete functions

For ease of understanding and modification


(ns servisne-info.tasks
  (:use [raven-clj.core :only [capture]]
        [raven-clj.interfaces :only [stacktrace]])
  (:require [environ.core :refer [env]]
            [overtone.at-at :as at-at]
            [taoensso.timbre :as timbre]))

(defmacro deftask [task-name & body]
  `(fn []
     (try
       (do
         (timbre/info ~task-name " starting...")
         ~@body
         (timbre/info ~task-name " done."))
       (catch Exception e#
         (capture (env :sentry-dsn)
                  (-> {:message (.getMessage e#)}
                      (stacktrace e#)))))))

(def tasks-pool (at-at/mk-pool :cpu-count 1))
(def default-period 3600)
(def periodic-tasks (atom []))

(defn add-periodic-task [task]
  (swap! periodic-tasks conj task))

(defn schedule-periodic-tasks []
  (doseq [task @periodic-tasks]
    (at-at/every default-period task tasks-pool :initial-delay (/ default-period 10))))

(ns servisne-info.tasks
  (:use [raven-clj.core :only [capture]]
        [raven-clj.interfaces :only [stacktrace]])
  (:require [environ.core :refer [env]]
            [overtone.at-at :as at-at]
            [taoensso.timbre :as timbre]))

(defmacro deftask [task-name & body]
  `(fn []
     (try
       (do
         (timbre/info ~task-name " starting...")
         ~@body
         (timbre/info ~task-name " done."))
       (catch Exception e#
         (capture (env :sentry-dsn)
                  (-> {:message (.getMessage e#)}
                      (stacktrace e#)))))))

(def tasks-pool (at-at/mk-pool :cpu-count 1))
(def default-period (* 60 60 1000)) ; one hour
(def periodic-tasks (atom []))

(defn add-periodic-task [task]
  (swap! periodic-tasks conj task))

(defn schedule-periodic-tasks []
  (doseq [task @periodic-tasks]
    (at-at/every default-period task tasks-pool :initial-delay (/ default-period 10))))

Set task period to one hour

Set task period to one hour


(ns leiningen.pallet-release.core)

(defn deep-merge
  "Recursively merge maps."
  [& ms]
  (letfn [(f [a b]
            (if (and (map? a) (map? b))
              (deep-merge a b)
              b))]
    (apply merge-with f ms)))

(defn fail
  "Fail with the given message, msg."
  [msg]
  (throw (ex-info msg {:exit-code 1})))

(defn fail-on-error
  "Fail on a shell error"
  [exit]
  (when (and exit (pos? exit))
    (fail "Shell command failed")))

(def push-repo-fmt
  "https://pbors:${GH_TOKEN}@github.com%s.git")

(defn repo-coordinates
  [{:keys [url] :as project}]
  (when-not (or url (-> project :pallet-release :url))
    (fail "No :url available in project.clj"))
  (if-let [release-url (-> project :pallet-release :url)]
    release-url
    (let [u (java.net.URL. url)]
      (if (= "github.com" (.getHost u))
        (format push-repo-fmt (.getPath u))
        (fail (str "Don't know how to create a pushable git url from"
                   url))))))

(defn release-config
  "Return a pallet release configuration map"
  [project]
  {:url (repo-coordinates project)
   :branch (or (-> project :pallet-release :branch)
               "master")})

(ns leiningen.pallet-release.core)

(defn deep-merge
  "Recursively merge maps."
  [& ms]
  (letfn [(f [a b]
            (if (and (map? a) (map? b))
              (deep-merge a b)
              b))]
    (apply merge-with f ms)))

(defn fail
  "Fail with the given message, msg."
  [msg]
  (throw (ex-info msg {:exit-code 1})))

(defn fail-on-error
  "Fail on a shell error"
  [exit]
  (when (and exit (pos? exit))
    (fail "Shell command failed")))

(def push-repo-fmt
  "https://pbors:${GH_TOKEN}@github.com%s.git")

(defn repo-coordinates
  [{:keys [url] :as project}]
  (when-not (or url (-> project :pallet-release :url))
    (fail "No :url available in project.clj"))
  (if-let [release-url (-> project :pallet-release :url)]
    release-url
    (let [u (java.net.URL. url)]
      (if (= "github.com" (.getHost u))
        (format push-repo-fmt (.getPath u))
        (fail (str "Don't know how to create a pushable git url from "
                   url))))))

(defn release-config
  "Return a pallet release configuration map"
  [project]
  {:url (repo-coordinates project)
   :branch (or (-> project :pallet-release :branch)
               "master")})

Add space to unknown repo format message


(ns cruncher.moves.main
  (:require [cruncher.moves.data :as data]))

(defn get-name
  "Return move object from moves-database by the move id."
  [id]
  (:name (get data/all id)))

(defn get-move
  "Return complete move by its id"
  [id]
  (get data/all id))

Add fn to return complete move object

Add fn to return complete move object


; An attempt to use in-place array mutation in Clojure
; Highly non-idiomatic. Should not be used. EXPERIMENTAL.
; Also it is ridiculously slow. Does anyone know why?

(defn generatePermutations [a n]
  (if (zero? n)
    (println (apply str a))
    (doseq [i (range 0 (inc n))]
      (generatePermutations a (dec n))
      (let [j (if (even? n) i 0) oldn (aget a n) oldj (aget a j)]
        (aset a n oldj) (aset a j oldn)))))

(if (not= (count *command-line-args*) 1)
  (do
    (println "Exactly one argument is required")
    (System/exit 1))
  (let [word (-> *command-line-args* first vec to-array)]
    (time (generatePermutations word (dec (count word))))))

; An attempt to use in-place array mutation in Clojure
; Highly non-idiomatic. Should not be used. EXPERIMENTAL.
; Also it is ridiculously slow. Does anyone know why?

(defn generatePermutations [^chars a n]
  (if (zero? n)
    ();(println (apply str a))
    (doseq [i (range 0 (inc n))]
      (generatePermutations a (dec n))
      (let [j (if (even? n) i 0) oldn (aget a n) oldj (aget a j)]
        (aset-char a n oldj) (aset-char a j oldn)))))

(if (not= (count *command-line-args*) 1)
  (do
    (println "Exactly one argument is required")
    (System/exit 1))
  (let [word (-> *command-line-args* first vec char-array)]
    (time (generatePermutations word (dec (count word))))))

Use char arrays and type hints

Use char arrays and type hints


(ns comic-reader.pages.sites
  (:require [comic-reader.session :as session]
            [reagent.core :as reagent :refer [atom]]
            [secretary.core :refer [dispatch!]]))

(defn manga-site [site-data]
  ^{:key (:id site-data)} [:li (:name site-data)])

(defn site-list [sites]
  [:div
   [:h1 "Comic Sources"]
   [:ul (map manga-site sites)]])

(ns comic-reader.pages.sites
  (:require [comic-reader.session :as session]
            [reagent.core :as reagent :refer [atom]]
            [secretary.core :refer [dispatch!]]))

(defn manga-site [site-data]
  ^{:key (:id site-data)}
  [:li
   [:input {:type "button"
            :value (:name site-data)
            :on-click #(.log js/console
                        (str "You clicked the "
                             (:id site-data)
                             " button!"))}]])

(defn site-list [sites]
  [:div
   [:h1 "Comic Sources"]
   [:ul (map manga-site sites)]])

Make the site components contain a button


(ns workflo.macros.spec-test
  (:require #?(:cljs [cljs.test :refer-macros [deftest is]]
               :clj  [clojure.test :refer [deftest is]])
            #?(:cljs [cljs.spec :as s]
               :clj  [clojure.spec :as s])
            #?(:cljs [cljs.spec.test :as st]
               :clj  [clojure.spec.test :as st])
            [workflo.macros.view]
            [workflo.macros.query]
            [workflo.macros.query.util]
            [workflo.macros.command]
            [workflo.macros.command.util]))

#?(:cljs (deftest test-specs
           (doseq [v (s/speced-vars)]
             (println "  Testing" v)
             (let [result (st/check-var v :num-tests 10 :max-size 10)]
               (println "  >" result)
               (and (is (map? result))
                    (is (true? (:result result))))))))

#?(:clj (deftest test-specs
          (doseq [s (st/testable-syms)]
            (println "  Testing" s)
            (let [result (first (st/test s {:clojure.spec.test.check/opts
                                            {:num-tests 10}}))]
              (and (is (map? result))
                   (is (true? (:result result))))))))

(ns workflo.macros.spec-test
  (:require #?(:cljs [cljs.test :refer-macros [deftest is]]
               :clj  [clojure.test :refer [deftest is]])
            #?(:cljs [cljs.spec :as s]
               :clj  [clojure.spec :as s])
            #?(:cljs [cljs.spec.test :as st]
               :clj  [clojure.spec.test :as st])
            [workflo.macros.view]
            [workflo.macros.query]
            [workflo.macros.query.util]
            [workflo.macros.command]
            [workflo.macros.command.util]))

#?(:cljs (deftest test-specs
           (doseq [v (s/speced-vars)]
             (println "  Testing" v)
             (when-not (= #'workflo.macros.query/parse-subquery v)
               (let [result (st/check-var v :num-tests 10 :max-size 10)]
                 (println "  >" result)
                 (and (is (map? result))
                      (is (true? (:result result)))))))))

#?(:clj (deftest test-specs
          (doseq [s (st/testable-syms)]
            (println "  Testing" s)
            (let [result (first (st/test s {:clojure.spec.test.check/opts
                                            {:num-tests 10}}))]
              (and (is (map? result))
                   (is (true? (:result result))))))))

Exclude random test of parse-subquery from being executed in CLJS


(defproject leancloud.data.json "0.1.0-RC2"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.6.0"]]
  :java-source-paths ["src/jvm"]
  :source-paths ["src/clj"]
  :jvm-opts ["-Xmx1g" "-server" "-XX:MaxPermSize=256m" "-XX:+UseConcMarkSweepGC" "-XX:+UseCMSCompactAtFullCollection" "-Dclojure.compiler.elide-meta='[:doc :added]'"]
  :profiles {:dev {:dependencies [[criterium "0.4.3"]
                                  [clj-tuple "0.1.6"]
                                  [org.clojure/data.json "0.2.5"]]}})

(defproject leancloud.data.json "0.1.0-RC3"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.6.0"]]
  :java-source-paths ["src/jvm"]
  :source-paths ["src/clj"]
  :javac-options ["-target" "1.7" "-source" "1.7"]
  :jvm-opts ["-Xmx1g" "-server" "-XX:MaxPermSize=256m" "-XX:+UseConcMarkSweepGC" "-XX:+UseCMSCompactAtFullCollection" "-Dclojure.compiler.elide-meta='[:doc :added]'"]
  :profiles {:dev {:dependencies [[criterium "0.4.3"]
                                  [clj-tuple "0.1.6"]
                                  [org.clojure/data.json "0.2.5"]]}})

Set compile target to 1.7

Set compile target to 1.7


(defproject onyx-app/lein-template "0.9.7.0-alpha1"
  :description "Onyx Leiningen application template"
  :url "https://github.com/onyx-platform/onyx-template"
  :license {:name "MIT License"
            :url "http://choosealicense.com/licenses/mit/#"}
  :repositories {"snapshots" {:url "https://clojars.org/repo"
                              :username :env
                              :password :env
                              :sign-releases false}
                 "releases" {:url "https://clojars.org/repo"
                             :username :env
                             :password :env
                             :sign-releases false}}
  :plugins [[lein-set-version "0.4.1"]]
  :profiles {:dev {:plugins [[lein-set-version "0.4.1"]
                             [lein-update-dependency "0.1.2"]
                             [lein-pprint "1.1.1"]]}}
  :eval-in-leiningen true)

(defproject onyx-app/lein-template "0.9.7.0-SNAPSHOT"
  :description "Onyx Leiningen application template"
  :url "https://github.com/onyx-platform/onyx-template"
  :license {:name "MIT License"
            :url "http://choosealicense.com/licenses/mit/#"}
  :repositories {"snapshots" {:url "https://clojars.org/repo"
                              :username :env
                              :password :env
                              :sign-releases false}
                 "releases" {:url "https://clojars.org/repo"
                             :username :env
                             :password :env
                             :sign-releases false}}
  :plugins [[lein-set-version "0.4.1"]]
  :profiles {:dev {:plugins [[lein-set-version "0.4.1"]
                             [lein-update-dependency "0.1.2"]
                             [lein-pprint "1.1.1"]]}}
  :eval-in-leiningen true)

Prepare for next release cycle.

Prepare for next release cycle.


;(defproject cli4clj "1.0.0"
(defproject cli4clj "1.0.1-SNAPSHOT"
  :description "Create simple interactive CLIs for Clojure applications."
  :url "https://github.com/ruedigergad/cli4clj"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [clj-assorted-utils "1.11.0"]
                 [jline/jline "2.13"]]
  :global-vars {*warn-on-reflection* true}
  :html5-docs-docs-dir "ghpages/doc"
  :html5-docs-ns-includes #"^cli4clj.*"
  :html5-docs-repository-url "https://github.com/ruedigergad/cli4clj/blob/master"
  :test2junit-output-dir "ghpages/test-results"
  :test2junit-run-ant true
  :main cli4clj.example
  :plugins [[lein-cloverage "1.0.2"] [test2junit "1.1.3"] [lein-html5-docs "3.0.3"]])

;(defproject cli4clj "1.0.0"
(defproject cli4clj "1.0.1-SNAPSHOT"
  :description "Create simple interactive CLIs for Clojure applications."
  :url "https://github.com/ruedigergad/cli4clj"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [clj-assorted-utils "1.11.0"]
                 [jline/jline "2.13"]]
  :global-vars {*warn-on-reflection* true}
  :html5-docs-docs-dir "ghpages/doc"
  :html5-docs-ns-includes #"^cli4clj.*"
  :html5-docs-repository-url "https://github.com/ruedigergad/cli4clj/blob/master"
  :test2junit-output-dir "ghpages/test-results"
  :test2junit-run-ant true
  :main cli4clj.example
  :plugins [[lein-cloverage "1.0.2"] [test2junit "1.1.3"] [lein-html5-docs "3.0.3"]]
  :profiles  {:repl  {:dependencies  [[jonase/eastwood "0.2.2" :exclusions  [org.clojure/clojure]]]}}
)

Add eastwood as repl dependency.

Add eastwood as repl dependency.


(defproject madouc "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.8.0"]
                 [ring/ring-core "1.5.1"]
                 [ring-logger "0.7.7"]
                 [ring-logger-timbre "0.7.5"]
                 [com.taoensso/timbre "4.8.0"]
                 [com.fzakaria/slf4j-timbre "0.3.4"]
                 [environ "1.1.0"]
                 [org.immutant/web "2.1.6"
                  :exclusions [ch.qos.logback/logback-classic]]]
  :main madouc.core
  :profiles {:dev {:plugins [[lein-environ "1.1.0"]]}
             :uberjar {:aot :all}})

(defproject madouc "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.8.0"]
                 [ring/ring-core "1.5.1"]
                 [ring-logger "0.7.7"]
                 [ring-logger-timbre "0.7.5"]
                 [com.taoensso/timbre "4.8.0"]
                 [com.fzakaria/slf4j-timbre "0.3.4"]
                 [compojure "1.5.2"]
                 [metosin/compojure-api "1.1.10"]
                 [environ "1.1.0"]
                 [org.immutant/web "2.1.6"
                  :exclusions [ch.qos.logback/logback-classic]]]
  :main madouc.core
  :profiles {:dev {:plugins [[lein-environ "1.1.0"]]}
             :uberjar {:aot :all}})

Add compojure and compojure-api dependencies


(defproject io.aviso/rook "0.1.8-SNAPSHOT"
  :description "Ruby on Rails-style resource mapping for Clojure/Compojure web apps"
  :url "https://github.com/AvisoNovate/rook"
  :license {:name "Apache Sofware License 2.0"
            :url  "http://www.apache.org/licenses/LICENSE-2.0.html"}
  ;; Normally we don't AOT compile; only when tracking down reflection warnings.
  :profiles {:reflection-warnings {:aot         :all
                                   :global-vars {*warn-on-reflection* true}}
             :dev {:dependencies [[ring-mock "0.1.5"]
                                  [io.aviso/pretty "0.1.10"]
                                  [speclj "2.9.1"]
                                  [log4j "1.2.17"]]}}
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [org.clojure/core.async "0.1.267.0-0d7780-alpha"]
                 [org.clojure/tools.logging "0.2.6"]
                 [ring-middleware-format "0.3.2"]
                 [prismatic/schema "0.2.1"]
                 [compojure "1.1.6"]]
  :plugins [[test2junit "1.0.1"]
            [speclj "2.9.1"]]
  :test-paths ["spec"])

(defproject io.aviso/rook "0.1.8-SNAPSHOT"
  :description "Ruby on Rails-style resource mapping for Clojure/Compojure web apps"
  :url "https://github.com/AvisoNovate/rook"
  :license {:name "Apache Sofware License 2.0"
            :url  "http://www.apache.org/licenses/LICENSE-2.0.html"}
  ;; Normally we don't AOT compile; only when tracking down reflection warnings.
  :profiles {:reflection-warnings {:aot         :all
                                   :global-vars {*warn-on-reflection* true}}
             :dev {:dependencies [[ring-mock "0.1.5"]
                                  [io.aviso/pretty "0.1.10"]
                                  [speclj "2.5.0"]
                                  [log4j "1.2.17"]]}}
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [org.clojure/core.async "0.1.267.0-0d7780-alpha"]
                 [org.clojure/tools.logging "0.2.6"]
                 [ring-middleware-format "0.3.2"]
                 [prismatic/schema "0.2.1"]
                 [compojure "1.1.6"]]
  :plugins [[speclj "2.5.0"]]
  :test-paths ["spec"])

Revert to speclj 2.5.0 since later versions don't seem to catch assertions correctly inside should-throw


(defproject funcool/futura "0.2.0-SNAPSHOT"
  :description "A basic building blocks for async programming."
  :url "https://github.com/funcool/futura"
  :license {:name "BSD (2 Clause)"
            :url "http://opensource.org/licenses/BSD-2-Clause"}
  :dependencies [[org.clojure/clojure "1.7.0-beta3" :scope "provided"]
                 [cats "0.4.0"]
                 [manifold "0.1.0"]
                 [org.clojure/core.async "0.1.346.0-17112a-alpha"]
                 [org.reactivestreams/reactive-streams "1.0.0"]]
  :deploy-repositories {"releases" :clojars
                        "snapshots" :clojars}
  :source-paths ["src"]
  :test-paths ["test"]
  :jar-exclusions [#"\.swp|\.swo|user.clj"]
  :javac-options ["-target" "1.8" "-source" "1.8" "-Xlint:-options"]
  :profiles {:dev {:codeina {:sources ["src"]
                             :language :clojure
                             :output-dir "doc/api"}
                   :plugins [[funcool/codeina "0.1.0-SNAPSHOT"
                              :exclusions [org.clojure/clojure]]]}})

(defproject funcool/futura "0.2.0-SNAPSHOT"
  :description "A basic building blocks for async programming."
  :url "https://github.com/funcool/futura"
  :license {:name "BSD (2 Clause)"
            :url "http://opensource.org/licenses/BSD-2-Clause"}
  :dependencies [[org.clojure/clojure "1.7.0-RC1" :scope "provided"]
                 [cats "0.4.0"]
                 [manifold "0.1.0"]
                 [org.clojure/core.async "0.1.346.0-17112a-alpha"]
                 [org.reactivestreams/reactive-streams "1.0.0"]]
  :deploy-repositories {"releases" :clojars
                        "snapshots" :clojars}
  :source-paths ["src"]
  :test-paths ["test"]
  :jar-exclusions [#"\.swp|\.swo|user.clj"]
  :javac-options ["-target" "1.8" "-source" "1.8" "-Xlint:-options"]
  :profiles {:dev {:codeina {:sources ["src"]
                             :language :clojure
                             :output-dir "doc/api"}
                   :plugins [[funcool/codeina "0.1.0-SNAPSHOT"
                              :exclusions [org.clojure/clojure]]]}})

Update clojure version to 1.7.0 rc1

Update clojure version to 1.7.0 rc1


(defproject uruk "0.3.9"
  :description "Clojure wrapper of MarkLogic XML Content Connector For Java (XCC/J)"
  :url "https://github.com/daveliepmann/uruk"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.8.0"]
                 [com.marklogic/marklogic-xcc "9.0.1"]
                 ;; required but not included by MarkLogic (e.g. for ContentFactory):
                 [com.fasterxml.jackson.core/jackson-databind "2.6.3"]
                 [org.clojure/data.json "0.2.6"]
                 [org.clojure/data.xml "0.1.0-beta2"]
                 [slingshot "0.12.2"]]
  :checksum :warn ;; TODO remove this workaround -- MarkLogic's Maven repo doesn't have checksums?
  :repositories [["MarkLogic-releases" "http://developer.marklogic.com/maven2"]])

(defproject uruk "0.3.10"
  :description "Clojure wrapper of MarkLogic XML Content Connector For Java (XCC/J)"
  :url "https://github.com/daveliepmann/uruk"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.9.0"]
                 [com.marklogic/marklogic-xcc "9.0.3"]
                 ;; required but not included by MarkLogic (e.g. for ContentFactory):
                 [com.fasterxml.jackson.core/jackson-databind "2.9.3"]
                 [org.clojure/data.json "0.2.6"]
                 [org.clojure/data.xml "0.1.0-beta2"]
                 [slingshot "0.12.2"]]
  :checksum :warn ;; TODO remove this workaround -- MarkLogic's Maven repo doesn't have checksums?
  :repositories [["MarkLogic-releases" "http://developer.marklogic.com/maven2"]])

Bump version to 0.3.10 and update dependencies


(defproject suricatta "0.2.0-SNAPSHOT"
  :description "High level sql toolkit for clojure (backed by jooq library)"
  :url "https://github.com/niwibe/suricatta"

  :license {:name "BSD (2-Clause)"
            :url "http://opensource.org/licenses/BSD-2-Clause"}

  :profiles {:dev {:dependencies [[postgresql "9.3-1102.jdbc41"]
                                  [com.h2database/h2 "1.3.176"]
                                  [cheshire "5.3.1"]]
                   ;; :global-vars {*warn-on-reflection* true}
                   }}
  :java-source-paths ["src/java"]
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [org.jooq/jooq "3.5.0"]
                 [clojure.jdbc "0.3.2"]
                 [cats "0.2.0" :exclusions [org.clojure/clojure]]
                 [org.clojure/core.async "0.1.346.0-17112a-alpha"]])

(defproject suricatta "0.2.0-SNAPSHOT"
  :description "High level sql toolkit for clojure (backed by jooq library)"
  :url "https://github.com/niwibe/suricatta"

  :license {:name "BSD (2-Clause)"
            :url "http://opensource.org/licenses/BSD-2-Clause"}

  :profiles {:dev {:dependencies [[postgresql "9.3-1102.jdbc41"]
                                  [com.h2database/h2 "1.3.176"]
                                  [cheshire "5.3.1"]]
                   ;; :global-vars {*warn-on-reflection* true}
                   }}
  :java-source-paths ["src/java"]
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [org.jooq/jooq "3.5.1"]
                 [clojure.jdbc "0.3.2"]
                 [cats "0.2.0" :exclusions [org.clojure/clojure]]
                 [org.clojure/core.async "0.1.346.0-17112a-alpha"]])

Update jooq version to 3.5.1

Update jooq version to 3.5.1


(defproject buddy/buddy-sign "2.0.0"
  :description "High level message signing for Clojure"
  :url "https://github.com/funcool/buddy-sign"
  :license {:name "Apache 2.0"
            :url "http://www.apache.org/licenses/LICENSE-2.0"}
  :dependencies [[org.clojure/clojure "1.9.0-alpha17" :scope "provided"]
                 [com.taoensso/nippy "2.13.0" :scope "provided"]
                 [org.clojure/test.check "0.9.0" :scope "test"]
                 [buddy/buddy-core "1.3.0"]
                 [cheshire "5.7.1"]]
  :source-paths ["src"]
  :javac-options ["-target" "1.7" "-source" "1.7" "-Xlint:-options"]
  :test-paths ["test"])

(defproject buddy/buddy-sign "2.0.0"
  :description "High level message signing for Clojure"
  :url "https://github.com/funcool/buddy-sign"
  :license {:name "Apache 2.0"
            :url "http://www.apache.org/licenses/LICENSE-2.0"}
  :dependencies [[org.clojure/clojure "1.9.0-alpha17" :scope "provided"]
                 [com.taoensso/nippy "2.13.0" :scope "provided"]
                 [org.clojure/test.check "0.9.0" :scope "test"]
                 [buddy/buddy-core "1.3.0"]
                 [cheshire "5.8.0"]]
  :source-paths ["src"]
  :javac-options ["-target" "1.7" "-source" "1.7" "-Xlint:-options"]
  :test-paths ["test"])

Update cheshire dependency to 5.8.0

Update cheshire dependency to 5.8.0


(def classifier-version "0.2.3")

(defproject puppetlabs.packages/pe-classifier "0.2.4-SNAPSHOT"
  :description "Release artifacts for classifier"
  :pedantic? :abort
  :dependencies [[puppetlabs/classifier ~classifier-version]]

  :uberjar-name "classifier-release.jar"

  :repositories [["releases" "http://nexus.delivery.puppetlabs.net/content/repositories/releases/"]
                 ["snapshots" "http://nexus.delivery.puppetlabs.net/content/repositories/snapshots/"]]

  :main puppetlabs.trapperkeeper.main

  :ezbake {:user "pe-classifier"
           :group "pe-classifier"
           :build-type "pe"})

(defproject puppetlabs.packages/pe-classifier "0.2.4-SNAPSHOT"
  :description "Release artifacts for classifier"
  :pedantic? :abort
  :dependencies [[puppetlabs/classifier "0.2.3"]]

  :uberjar-name "classifier-release.jar"

  :repositories [["releases" "http://nexus.delivery.puppetlabs.net/content/repositories/releases/"]
                 ["snapshots" "http://nexus.delivery.puppetlabs.net/content/repositories/snapshots/"]]

  :main puppetlabs.trapperkeeper.main

  :ezbake {:user "pe-classifier"
           :group "pe-classifier"
           :build-type "pe"})

Remove version templating from classifier.clj that doesn't work

Using a variable in the defproject macro does not work, so this commit
replaces it with a literal string.


(hash-map

  :layout
  (layout/geodesic
    :radius 3.688
    :pixel-spacing 0.02
    :strut-pixels
    [48 64 64 64]
    :strip-struts
    [[0 6 12 10]
     [2 8 18 16]
     [4 9 17 19]
     [3 7 11 13]
     [1 5 14 15]])

  #_
  (layout/star
    :radius 3.688         ; 12.1'
    :pixel-spacing 0.02   ; 2 cm
    :strip-pixels 240
    :strips 6)

  :event-handler
  (-> state/update-mode
      handler/mode-selector
      (handler/autocycle-modes
        (comp #{:button/press :button/repeat} :type)))

  :web-options
  {:port 8080
   :min-threads 2
   :max-threads 5
   :max-queued 25}

  :modes
  {:rainbow
   (mode/rainbow)

   :strobe
   (mode/strobe
     [(color/rgb 1 0 0)
      (color/rgb 0 1 0)
      (color/rgb 0 0 1)])

   :lantern
   (mode/lantern 0.5)}

  :playlist
  [:rainbow
   :strobe
   :lantern])

(hash-map

  :layout
  #_
  (layout/geodesic
    :radius 3.688
    :pixel-spacing 0.02
    :strut-pixels
    [48 64 64 64]
    :strip-struts
    [[0 6 12 10]
     [2 8 18 16]
     [4 9 17 19]
     [3 7 11 13]
     [1 5 14 15]])

  (layout/star
    :radius 3.688         ; 12.1'
    :pixel-spacing 0.02   ; 2 cm
    :strip-pixels 240
    :strips 6)

  :event-handler
  (-> state/update-mode
      handler/mode-selector
      (handler/autocycle-modes
        (comp #{:button/press :button/repeat} :type)))

  :web-options
  {:port 8080
   :min-threads 2
   :max-threads 5
   :max-queued 25}

  :modes
  {:rainbow
   (mode/rainbow)

   :strobe
   (mode/strobe
     [(color/rgb 1 0 0)
      (color/rgb 0 1 0)
      (color/rgb 0 0 1)])

   :lantern
   (mode/lantern 0.5)}

  :playlist
  [:rainbow
   :strobe
   :lantern])

Switch back to star layout until geodesic stuff is figured out.