minor improvements to the documentation and state handling.

--- src/quiescent_model/state.cljs
+++ src/quiescent_model/state.cljs
@@ -1,7 +1,9 @@
 (ns quiescent-model.state
   (:require [quiescent-model.events :as evt]))

-(defn root-scope [app-state-atom]
+(defn root-scope
+  "Creates a root scope for a top-level component"
+  [app-state-atom]
   {
    :app-state-atom  app-state-atom
    :scope           []
@@ -9,10 +11,15 @@
    }
   )

-(defn find-first [pred coll] (first (filter pred coll)) )
+(defn find-first
+  "Helper function returning (first (filter pred coll))"
+  [pred coll]
+  (first (filter pred coll)) )

 (defn data-path
-  "Corrects actual internal path to account for the inclusion of vectors as data structures."
+  "Converts a conceptual data path to an associative path usable by get-in.
+  The abstract internal path may include vectors as data structures which
+  are instructions to look up items in a list by a key."
   [context]
   (let [state @(:app-state-atom context)
         path-seq (:scope context)
@@ -30,7 +37,7 @@
                     (if index
                       (conj real-path vector-key index)
                       (do
-                        (cljs.pprint/pprint "ERROR: NO ITEM FOUND AT DATA PATH ")
+                        (.log js/console "ERROR: NO ITEM FOUND AT DATA PATH ")
                         (cljs.pprint/pprint path-seq)
                         real-path
                         )
@@ -41,13 +48,20 @@
               )
             [] path-seq)))

-(defn context-data [context]
+(defn context-data
+  "Get the data from the application state that is represented by an
+  abstract context"
+  [context]
   (let [state-atom (:app-state-atom context)
         path (data-path context)
         ]
     (get-in @state-atom path)))

-(defn update-in-context [context op]
+(defn update-in-context
+  "Update the data represented by the context in the real application
+  state using the supplied operation (this operation is like swap!, but
+  you don't have to know where the data is actually stored)."
+  [context op]
   (let [state-atom (:app-state-atom context)
         path (data-path context)
         ]
@@ -72,3 +86,11 @@
                                  (update-in-context context operation))
   )

+(defn context-op-builder
+  "Creates an application-state operation builder based on the given
+  context. In other words: returns a function that takes
+  a function that can evolve the context data. This function, when called,
+  returns a function that can do that operation in the larger context
+  of the application state."
+  [context]
+  (fn [op & triggers] (path-operator context op triggers)))


commiting core.cljs, still experimenting

--- src/saved_for_reddit/core.cljs
+++ src/saved_for_reddit/core.cljs
@@ -3,18 +3,19 @@
             [cljs-http.client :as http]
             [cljs.core.async :refer [<!]]
             [cemerick.url :as url]
-            [saved-for-reddit.reddit-api :refer [authorize]])
+            [clojure.walk :refer [keywordize-keys]]
+            [saved-for-reddit.reddit-api :refer [gen-auth-url authorize]])
   (:require-macros [cljs.core.async.macros :refer [go]]))

 (enable-console-print!)

 (println "This text is printed from src/saved-for-reddit/core.cljs. Go ahead and edit it and see reloading in action.")

-(println (:query (url/url (-> js/window .-location .-href))))
 ;; define your app data so that it doesn't get over-written on reload
+(def app-state (r/atom {:username ""
+                        :code ""}))

-
-(def app-state (r/atom {:username ""}))
+(def error-msg (r/atom ""))

 (defn set-app-state-field [field value]
   (swap! app-state update-in [field] #(str value))
@@ -71,8 +72,25 @@
               :on-click authorize}]
      [:div {:id "status"}]]))

+(defn error-html []
+  [:div [:h1 "Error"]
+   [:pre @error-msg]])

-(r/render-component [login-html] (.getElementById js/document "app"))
+(defn init []
+  (println "Initiazlizing...")
+  (let [query-vars (keywordize-keys (:query (url/url (-> js/window .-location .-href))))
+        code (:code query-vars)
+        error (:error query-vars)]
+    (if (nil? error)
+      (if (nil? code)
+        (set! (.-location js/window) (gen-auth-url))
+        (r/render-component [login-html] (.getElementById js/document "app")))
+      (let [] ;; handling error
+        (swap! error-msg #(str error))
+        (r/render-component [error-html] (.getElementById js/document "app"))))))
+
+;; initialize the HTML page in unobtrusive way
+(set! (.-onload js/window) init)

 ;; (defonce app-state (atom {:text "Hello world!"}))


updated template parsing logic

updated template parsing logic

--- src/selmer/template_parser.clj
+++ src/selmer/template_parser.clj
@@ -12,19 +12,17 @@

 (defn handle-includes
   "parse any included templates and splice them in replacing the include tags"
-  [template]
+  [template]
   (let [buf (StringBuilder.)]
     (with-open [rdr (reader (StringReader. template))]
     (loop [ch (read-char rdr)]
       (when ch
         (if (= *tag-open* ch)
-          (let [tag-str (read-tag-content rdr)]
-            (println tag-str)
-            (if (re-matches #"\{\%\s*include.*" tag-str)
-              (do
-                (println "got include" (.replaceAll (get-tag-name #"include" tag-str) "\"" ""))
-                (find-template-dependencies (.replaceAll (get-tag-name #"include" tag-str) "\"" "")))
-              (.append buf tag-str)))
+          (let [tag-str (read-tag-content rdr)]
+            (.append buf
+              (if (re-matches #"\{\%\s*include.*" tag-str)
+                (preprocess-template (.replaceAll (get-tag-name #"include" tag-str) "\"" ""))
+              tag-str)))
           (.append buf ch))
         (recur (read-char rdr))))
     (.toString buf))))
@@ -120,10 +118,13 @@
           (read-char rdr))
         templates))))

-#_(let [template "templates/inheritance/inherit-c.html"
-        templates (find-template-dependencies template)
-        blocks (find-blocks template templates {})]
-    (-> template
+(defn preprocess-template [filename]
+  (let [templates (find-template-dependencies filename)
+        blocks (find-blocks filename templates {})]
+    (-> filename
         (find-root templates)
         (fill-blocks blocks)
-        handle-includes))
+        handle-includes)))
+
+#_(preprocess-template "templates/inheritance/inherit-c.html")
+


fixed loading nested blocks

fixed loading nested blocks

--- src/selmer/template_parser.clj
+++ src/selmer/template_parser.clj
@@ -4,7 +4,7 @@
             [clojure.string :refer [split trim]])
   (:import java.io.StringReader))

-(declare preprocess-template)
+(declare consume-block preprocess-template)

 (defn get-tag-params [tag-id block-str]
   (-> block-str (split tag-id) second (split #"%") first trim))
@@ -29,24 +29,35 @@
   (let [template (get-tag-params #"extends" tag-str)]
     (.substring template 1 (dec (.length template)))))

-(defn consume-block [rdr & [^StringBuilder buf]]
-  (loop [ch (read-char rdr)
-         blocks-to-close 1]
+(defn consume-block [rdr & [^StringBuilder buf blocks]]
+  (loop [blocks-to-close 1
+         ch (read-char rdr)]
     (when (and (pos? blocks-to-close) ch)
       (if (= *tag-open* ch)
-        (let [content (read-tag-content rdr)]
-          (when buf (.append buf content))
-          (recur (read-char rdr)
-                 (long
-                   (cond
-                     (re-matches #"\{\%\s*block.*" content)
-                     (inc blocks-to-close)
-                     (re-matches #"\{\%\s*endblock.*" content)
-                     (dec blocks-to-close)
-                     :else blocks-to-close))))
+        (let [tag-str (read-tag-content rdr)
+              block? (re-matches #"\{\%\s*block.*" tag-str)
+              block-name (if block? (get-tag-params #"block" tag-str))
+              existing-block (if block-name (get blocks block-name))]
+          (when (and buf (not existing-block)) (.append buf tag-str))
+          (recur
+            (long
+              (cond
+                existing-block
+                (do
+                  (consume-block rdr)
+                  (consume-block (StringReader. existing-block) buf (dissoc blocks block-name))
+                  blocks-to-close)
+
+                block?
+                (inc blocks-to-close)
+
+                (re-matches #"\{\%\s*endblock.*" tag-str)
+                (dec blocks-to-close)
+                :else blocks-to-close))
+            (read-char rdr)))
         (do
           (when buf (.append buf ch))
-          (recur (read-char rdr) blocks-to-close))))))
+          (recur blocks-to-close (read-char rdr)))))))

 (defn read-block [rdr block-tag blocks]
   (let [block-name (get-tag-params #"block" block-tag)]
@@ -55,7 +66,7 @@
       (assoc blocks block-name
              (->buf [buf]
                     (.append buf block-tag)
-                    (consume-block rdr buf))))))
+                    (consume-block rdr buf blocks))))))

 (defn process-block [rdr buf block-tag blocks]
   (let [block-name (get-tag-params #"block" block-tag)]
@@ -114,4 +125,4 @@
   (-> (read-template template {}) insert-includes))

 #_(preprocess-template "templates/inheritance/inherit-c.html")
-#_(println (preprocess-template "templates/inheritance/inherit-c.html"))
+#_(println "\n----------\n" (preprocess-template "templates/inheritance/inherit-c.html"))


update copyright year on main page

update copyright year on main page

--- src/sierpinski_sieve/core.cljs
+++ src/sierpinski_sieve/core.cljs
@@ -57,7 +57,7 @@
      (slider "Size" :size size {:type "range" :min 100 :max 1200 :step 100})
      (slider "Modulus" :modulus modulus {:type "range" :min 2 :max 32 :step 1})
      [:p
-      "© 2017-2021 Charles L.G. Comstock "
+      "© 2017-2022 Charles L.G. Comstock "
       [:a {:href "https://github.com/dgtized/sierpinski-sieve"} "(github)"]]]))

 (defn paint-canvas []


remove unnecessary reverse

remove unnecessary reverse

--- src/sierpinski_sieve/core.cljs
+++ src/sierpinski_sieve/core.cljs
@@ -37,7 +37,7 @@
         (set! (.-fillStyle ctx) "black")
         (.fillRect ctx 0 0 size size)
         (set! (.-fillStyle ctx) "white")
-        (doseq [[y row] (reverse (map-indexed vector sieve))]
+        (doseq [[y row] (map-indexed vector sieve)]
           (paint-row ctx y row size))))))

 (defn render-canvas [size]


bootstrap load fix

bootstrap load fix

--- src/main/shadow/bootstrap.cljs
+++ src/main/shadow/bootstrap.cljs
@@ -19,10 +19,6 @@
   (xhr/chan :GET path nil {:body-only true
                            :transform transit-read}))

-(defn txt-load [path]
-  (xhr/chan :GET path nil {:body-only true
-                           :transform identity}))
-
 (defonce empty-result-helper
   (doto (async/chan)
     (async/close!)))
@@ -36,8 +32,7 @@
 ;; names that where provided by the "app"
 (defn set-loaded [namespaces]
   (let [loaded (into #{} (map symbol) namespaces)]
-    (swap! loaded-ref set/union loaded)
-    (swap! cljs/*loaded* set/union loaded)))
+    (swap! loaded-ref set/union loaded)))

 (defonce index-ref (atom nil))

@@ -133,6 +128,12 @@
         compile-state
         @compile-state-ref

+        things-already-loaded
+        (->> deps-to-load-with-macros
+             (filter #(set/superset? @loaded-ref (:provides %)))
+             (map :provides)
+             (reduce set/union))
+
         js-files-to-load
         (->> deps-to-load-with-macros
              (remove #(set/superset? @loaded-ref (:provides %)))
@@ -161,6 +162,11 @@

         loader
         (BulkLoader. (into-array uris))]
+
+    ;; this is transfered to cljs/*loaded* here to delay it as much as possible
+    ;; the JS may already be loaded but the analyzer data may be missing
+    ;; this way cljs.js is forced to ask first
+    (swap! cljs/*loaded* set/union things-already-loaded)

     ;; may sometimes not need to load anything?
     (if (empty? load-info)


DM FIX: Temporarily remove es translations for usability testing

--- src/objective8/translation.clj
+++ src/objective8/translation.clj
@@ -3,40 +3,42 @@
             [taoensso.tower :as tower]))

 ;;TODO move translations to external files
+
+(declare spanish-translations)

 (def translation-config
   {:dictionary {:en { :base {:header-logo-text "Objective[8]"
                              :header-logo-title "Go to home page"
                              :project-status! "ALPHA: We are still testing, find out more"
                              :browsehappy! "You are using an outdated browser. Please upgrade your browser to improve your experience."}
-                      :navigation-global {:sign-in-text "Sign in"
-                                          :sign-in-title "Go to sign in"
-                                          :sign-out-text "Sign out"
-                                          :sign-out-title "Go to sign out"
-                                          :profile-text "Profile"
-                                          :profile-title "Go to user profile"}
-                      :share-widget {:title "Share this page:"
-                                     :facebook-title "Share on Facebook..."
-                                     :facebook-text "Share on Facebook"
-                                     :google-plus-title "Plus one this page on Google"
-                                     :google-plus-text "Google +1"
-                                     :twitter-title "Share this page on Twitter"
-                                     :twitter-text "Tweet"
-                                     :linkedin-title "Share this page on LinkedIn"
-                                     :linkedin-text "Share on LinkedIn"
-                                     :reddit-title "Submit this page to Reddit"
-                                     :reddit-text "Submit to Reddit"
-                                     :url-label "URL to share"
-                                     :url-title "The link to this page"}
-                      :error-404 {:doc-title "Error 404 | Objective[8]"
-                             :doc-description "Sorry the page you requested can't be found."
-                             :page-title "Sorry the page you requested can't be found."
-                             :page-intro "The page you were trying to reach at this address doesn't seem to exist. This is usually the result of a bad or outdated link. We apologise for any inconvenience."
-                             :page-content! "
What can I do now?

Please return to the home page.

To report an issue visit our github issues page.

" }
+                     :navigation-global {:sign-in-text "Sign in"
+                                         :sign-in-title "Go to sign in"
+                                         :sign-out-text "Sign out"
+                                         :sign-out-title "Go to sign out"
+                                         :profile-text "Profile"
+                                         :profile-title "Go to user profile"}
+                     :share-widget {:title "Share this page:"
+                                    :facebook-title "Share on Facebook..."
+                                    :facebook-text "Share on Facebook"
+                                    :google-plus-title "Plus one this page on Google"
+                                    :google-plus-text "Google +1"
+                                    :twitter-title "Share this page on Twitter"
+                                    :twitter-text "Tweet"
+                                    :linkedin-title "Share this page on LinkedIn"
+                                    :linkedin-text "Share on LinkedIn"
+                                    :reddit-title "Submit this page to Reddit"
+                                    :reddit-text "Submit to Reddit"
+                                    :url-label "URL to share"
+                                    :url-title "The link to this page"}
+                     :error-404 {:doc-title "Error 404 | Objective[8]"
+                                 :doc-description "Sorry the page you requested can't be found."
+                                 :page-title "Sorry the page you requested can't be found."
+                                 :page-intro "The page you were trying to reach at this address doesn't seem to exist. This is usually the result of a bad or outdated link. We apologise for any inconvenience."
+                                 :page-content! "
What can I do now?

Please return to the home page.

To report an issue visit our github issues page.

" }
                      :notifications {:drafting-has-started "Drafting has started on this objective!"
                                      :drafting-started-helper-text "This means that you can no longer ask or answer questions, comment, or invite new writers.  However, you can follow and contribute to the drafting progress "
                                      :go-to-drafting "here."}
-                      :index {:doc-title "Objective[8]"
+                     :index {:doc-title "Objective[8]"
                              :doc-description ""
                              :index-welcome "Collaborative policy making for democratic organisations."
                              :index-intro "Gather community opinion, generate ideas, share, discuss, vote and collaborate with experts to draft new policy."
@@ -164,7 +166,7 @@
                                            :sign-in-to-accept "Sign in to accept"
                                            :accept "Accept"
                                            :decline "Decline"}
-                      :invitation-banner {:message "Respond to your invitation to help draft policy"}
+                     :invitation-banner {:message "Respond to your invitation to help draft policy"}
                      :candidate-list {:doc-title "Candidate policy writers | Objective[8]"
                                       :doc-description "Candidate policy writers..."
                                       :page-intro "Writers work with each other and the community to draft policy."
@@ -188,183 +190,189 @@
                                :not-well-formed "Username must be 1-16 characters in length, containing only letters and numbers"
                                :email-label "Email"
                                :email-title "Add your email title"
-                               :button "Create account"}}
-
-                :es {:base {:header-logo-text "Objective[8]"
-                            :header-logo-title "Inicio"
-                            :project-status! "Spanish(ALPHA: We are still in development and testing, find out more)"
-                            :browsehappy! "Por favor actualiza tu navegador para que tengas una mejor experiencia."}
-                     :navigation-global {:sign-in-text "Entrar"
-                                         :sign-in-title "Iniciar sesión"
-                                         :sign-out-text "Salir"
-                                         :sign-out-title "Cerrar sesión"
-                                         :profile-text "Perfil"
-                                         :profile-title "Perfil"}
-                     :share-widget {:title "Compartir"
-                                     :facebook-title "Compartir en Facebook"
-                                     :facebook-text "Compartir en Facebook"
-                                     :google-plus-title "Compartir en Google+"
-                                     :google-plus-text "Compartir en Google+"
-                                     :twitter-title "Compartir en Twitter"
-                                     :twitter-text "Compartir en Twitter"
-                                     :linkedin-title "Compartir en LinkedIn"
-                                     :linkedin-text "Compartir en LinkedIn"
-                                     :reddit-title "Compartir en Reddit"
-                                     :reddit-text "Compartir en Reddit"
-                                     :url-label "Comparte el link"
-                                     :url-title "Comparte el link"}
-                     :error-404 {:doc-title "Spanish(Error 404 | Objective[8])"
-                             :doc-description "Spanish(Sorry the page you requested can't be found.)"
-                             :page-title "Spanish(Sorry the page you requested can't be found.)"
-                             :page-intro "Spanish(The page you were trying to reach at this address doesn't seem to exist. This is usually the result of a bad or outdated link. We apologise for any inconvenience.)"
-                             :page-content! "
What can I do now?

Please return to the home page.

To report an issue visit our github issues page.

" }
-                     :notifications {:drafting-has-started "Spanish(...)"
-                                     :drafting-started-helper-text "Spanish(...)"
-                                     :go-to-drafting "Spanish(...)"}
-                     :index {:doc-title "Objective[8]"
-                             :doc-description ""
-                             :index-welcome "Politicos colaborando con organizaciones democráticas"
-                             :index-intro "Recolectar la opinion de la comunidad, generar ideas, compartir, discutir, votar y colaborar con expertos para redactar nuevas politicas."
-                             :index-get-started "Objetivo"
-                             :index-get-started-title "Objetivo"
-                             :index-learn-more "Más información"
-                             :index-learn-more-title "Más información"}
-                     :sign-in {:doc-title "Entrar | Objective[8]"
-                               :doc-description "Entrar"
-                               :page-title "Spanish(Sign in or Sign up)"
-                               :twitter-sign-in-btn "Entra con Twitter"
-                               :twitter-sign-in-title "Entra con Twitter"
-                               :reassurance "Spanish(We will never post to Twitter without your permission.)"}
-                     :project-status {:doc-title "Spanish(Project status | Objective [8])"
-                                      :doc-description ""
-                                      :page-title "Spanish(Alpha phase)"
-                                      :page-intro "Spanish(We are developing and designing Objective[8] in the open. This allows the tool evolve as you use it, as you give feedback, and as the developers update and add content.)"
-                                      :page-content! "Spanish(
It is important to note that during this time data may be removed or destroyed as part of our process. Any of the views and data expressed here is to be used for example purposes only and does not accurately represent the real views of users.

How to get involved

This project is open source and we are inviting people to collaborate with us to build a better tool. For developers and you can find the code on github at https://github.com/ThoughtWorksInc/objective8. We will also be adding details for upcoming usability sessions shortly.

Have you got an idea?

We are really interested in user feedback and are currently inviting people to leave comments our github issues page.
)" }
-                     :learn-more {:doc-title "Spanish(Learn more) | Objective[8]"
-                                  :doc-description ""
-                                  :page-title "Spanish(...)"
-                                  :sub-title "Spanish(...)"
-                                  :page-intro "Spanish(...)"
-                                  :get-started-button-title "Spanish(...)"
-                                  :get-started-button-text "Spanish(...)"
-                                  :page-content! "Spanish(...)"}
-                     :objective-nav {:title "Spanish(Navigation for)"
-                                     :details "Spanish(Details)"
-                                     :questions "Spanish(Questions)"
-                                     :writers "Spanish(Writers)"}
-                     :objective-list {:doc-title "Spanish(Objectives | Objective[8])"
-                                      :doc-description ""
-                                      :page-title "Spanish(Objectives)"
-                                      :create-button-title "Spanish(Create an objective)"
-                                      :create-button-text "Spanish(Create an objective)"
-                                      :please "Spanish(Please)"
-                                      :sign-in "Spanish(sign in)"
-                                      :to "Spanish(to create an objective.)"
-                                      :subtitle "Spanish(Recently created objectives)"
-                                      :drafting-begins "Spanish(Drafting begins on)"
-                                      :objectives-intro-text "Spanish(...)"}
-                     :objective-create {:doc-title "Crea un objetivo | Objective[8]"
-                                        :doc-description "Crea un objetivo"
-                                        :page-title "Crea un objetivo"
-                                        :page-intro "Spanish(...)"
-                                        :headline-label "Spanish(...)"
-                                        :headline-title "3 carateres mínimo, 120 carateres máximo"
-                                        :headline-prompt "Spanish(...)"
-                                        :headline-placeholder "Spanish(...)"
-                                        :goals-label "Meta"
-                                        :goals-prompt "Spanish(...)"
-                                        :goals-title "50 carateres mínimo, 200 carateres máximo"
-                                        :goals-placeholder "Spanish(...)"
-                                        :background-label "Spanish(...)"
-                                        :background-prompt "Spanish(...)"
-                                        :background-title "Escribe una descripcion máximo de 1000 caracteres."
-                                        :end-date-label "Spanish(...)"
-                                        :end-date-prompt "Spanish(...)"
-                                        :drafting-not-yet-implemented "Spanish(...)"
-                                        :end-date-title "Por favor escribe la fecha de vencimiento"
-                                        :end-date-placeholder "yyyy-mm-dd"
-                                        :submit "Crear"}
-                     :objective-view {:doc-title "Objetivo | Objective[8]"
-                                      :doc-description ""
-                                      :background-label "Spanish(Background)"
-                                      :goals-label "Meta"
-                                      :end-date-label "Fecha de vencimiento"
-                                      :created-message "Tu objetivo ha sido creado"}
-                    :comment-view {:created-message "Tu comentario ha sido creado"
-                                   :comment-title "Comentarios"
-                                   :no-comments "Spanish(There are no comments yet.)"}
-                    :comment-create {:comment-label "Spanish(Your comment)"
-                                     :comment-title "Los comentarios son máximo de 500 caracteres."
-                                     :post-button "Spanish(Add comment)"}
-                     :comment-sign-in {:please "Spanish(Please)"
-                                       :sign-in "Spanish(sign in)"
-                                       :to "Spanish(to start commenting.)"}
-                     :question-list {:questions-about "Spanish(Questions about)"
-                                     :page-intro "Spanish(...)"
-                                     :question-list-heading "Spanish(...)"
-                                     :no-questions "Spanish(There are no questions yet.)" }
-                     :question-create {:question-label "Spanish(Question)"
-                                       :question-title "Spanish(Questions are a maximum length of 500 characters)"
-                                       :post-button "Spanish(Add)"}
-                    :question-view {:added-message "Spanish(Your question has been added!)"
-                                    :added-answer-message "Spanish(Your answer has been added!)"}
-                     :question-sign-in {:please "Spanish(Please)"
-                                        :sign-in "Spanish(sign in)"
-                                        :to "Spanish(to ask a question.)" }
-                     :answer-view   {:created-message "Spanish(Your answer has been posted!)"
-                                     :answer-title "Spanish(Answers)"
-                                     :no-answers "Spanish(No one has answered this question yet.)"}
-                     :answer-create {:answer-label "Spanish(Your answer)"
-                                     :answer-title "Spanish(Answers are a maximum length of 500 characters)"
-                                     :post-button "Spanish(Post your answer)"}
-                     :answer-sign-in {:please "Spanish(Please)"
-                                      :sign-in "Spanish(sign in)"
-                                      :to "Spanish(to answer this question.)"}
-                     :invitation {:doc-title "Spanish(...)"
-                                  :doc-description "Spanish(...)"
-                                  :page-title "Spanish(...)"
-                                  :page-intro "Spanish(...)"
-                                  :writer-name-label "Spanish(...)"
-                                  :writer-name-title "Spanish(...)"
-                                  :reason-label "Spanish(...)"
-                                  :reason-title "Spanish(...)"
-                                  :submit "Spanish(...)"}
-                     :invitation-response {:doc-title "Spanish(...)"
-                                           :doc-description "Spanish(...)"
-                                           :page-title "Spanish(...)"
-                                           :page-intro "Spanish(...)"
-                                           :for-objective-text "Spanish(...)"
-                                           :rsvp-text "Spanish(...)"
-                                           :sign-in-to-accept "Spanish(...)"
-                                           :accept "Spanish(...)"
-                                           :decline "Spanish(...)"}
-                     :invitation-sign-in {:please "Spanish(...)"
-                                              :sign-in "Spanish(...)"
-                                              :to "Spanish(...)"}
-                     :invitation-banner {:message "Spanish(...)"}
-                     :candidate-list {:page-intro "Spanish(...)"
-                                      :candidate-list-heading "Spanish(...)"
-                                      :no-candidates "Spanish(...)"}
-                     :current-draft {:page-intro "Spanish(...)"
-                                     :no-drafts "Spanish(...)"}
-                     :edit-draft {:doc-title "Spanish(...)"
-                                  :doc-description "Spanish(...)"
-                                  :preview "Spanish(...)"
-                                  :submit "Spanish(...)"}
-                     :sign-up {:doc-title "Perfil | Objective[8]"
-                               :doc-description ""
-                               :page-title ""
-                               :welcome  "Tu correo electrónico nos permitira informarte cuando recivas respuestas a tus comentarios, objetivos y votos."
-                               :username-label ""
-                               :username-title ""
-                               :not-unique ""
-                               :not-well-formed ""
-                               :email-label  "Correo electrónico"
-                               :email-title  "Escribe tu cuenta de correo electrónico"
-                               :button ""}}}
+                               :button "Create account"}}}
+
+   :es spanish-translations
+
    :dev-mode? false
    :fallback-locale :en
    :log-missing-translations-function (fn [{:keys [locale ks scope]}]
                                         (log/warn (str "Missing translations! " locale ks scope)))})

+
+(def spanish-translations {}
+  #_{:es {:base {:header-logo-text "Objective[8]"
+                  :header-logo-title "Inicio"
+                  :project-status! "Spanish(ALPHA: We are still in development and testing, find out more)"
+                  :browsehappy! "Por favor actualiza tu navegador para que tengas una mejor experiencia."}
+           :navigation-global {:sign-in-text "Entrar"
+                               :sign-in-title "Iniciar sesión"
+                               :sign-out-text "Salir"
+                               :sign-out-title "Cerrar sesión"
+                               :profile-text "Perfil"
+                               :profile-title "Perfil"}
+           :share-widget {:title "Compartir"
+                          :facebook-title "Compartir en Facebook"
+                          :facebook-text "Compartir en Facebook"
+                          :google-plus-title "Compartir en Google+"
+                          :google-plus-text "Compartir en Google+"
+                          :twitter-title "Compartir en Twitter"
+                          :twitter-text "Compartir en Twitter"
+                          :linkedin-title "Compartir en LinkedIn"
+                          :linkedin-text "Compartir en LinkedIn"
+                          :reddit-title "Compartir en Reddit"
+                          :reddit-text "Compartir en Reddit"
+                          :url-label "Comparte el link"
+                          :url-title "Comparte el link"}
+           :error-404 {:doc-title "Spanish(Error 404 | Objective[8])"
+                       :doc-description "Spanish(Sorry the page you requested can't be found.)"
+                       :page-title "Spanish(Sorry the page you requested can't be found.)"
+                       :page-intro "Spanish(The page you were trying to reach at this address doesn't seem to exist. This is usually the result of a bad or outdated link. We apologise for any inconvenience.)"
+                       :page-content! "
What can I do now?

Please return to the home page.

To report an issue visit our github issues page.

" }
+           :notifications {:drafting-has-started "Spanish(...)"
+                           :drafting-started-helper-text "Spanish(...)"
+                           :go-to-drafting "Spanish(...)"}
+           :index {:doc-title "Objective[8]"
+                   :doc-description ""
+                   :index-welcome "Politicos colaborando con organizaciones democráticas"
+                   :index-intro "Recolectar la opinion de la comunidad, generar ideas, compartir, discutir, votar y colaborar con expertos para redactar nuevas politicas."
+                   :index-get-started "Objetivo"
+                   :index-get-started-title "Objetivo"
+                   :index-learn-more "Más información"
+                   :index-learn-more-title "Más información"}
+           :sign-in {:doc-title "Entrar | Objective[8]"
+                     :doc-description "Entrar"
+                     :page-title "Spanish(Sign in or Sign up)"
+                     :twitter-sign-in-btn "Entra con Twitter"
+                     :twitter-sign-in-title "Entra con Twitter"
+                     :reassurance "Spanish(We will never post to Twitter without your permission.)"}
+           :project-status {:doc-title "Spanish(Project status | Objective [8])"
+                            :doc-description ""
+                            :page-title "Spanish(Alpha phase)"
+                            :page-intro "Spanish(We are developing and designing Objective[8] in the open. This allows the tool evolve as you use it, as you give feedback, and as the developers update and add content.)"
+                            :page-content! "Spanish(
It is important to note that during this time data may be removed or destroyed as part of our process. Any of the views and data expressed here is to be used for example purposes only and does not accurately represent the real views of users.

How to get involved

This project is open source and we are inviting people to collaborate with us to build a better tool. For developers and you can find the code on github at https://github.com/ThoughtWorksInc/objective8. We will also be adding details for upcoming usability sessions shortly.

Have you got an idea?

We are really interested in user feedback and are currently inviting people to leave comments our github issues page.
)" }
+           :learn-more {:doc-title "Spanish(Learn more) | Objective[8]"
+                        :doc-description ""
+                        :page-title "Spanish(...)"
+                        :sub-title "Spanish(...)"
+                        :page-intro "Spanish(...)"
+                        :get-started-button-title "Spanish(...)"
+                        :get-started-button-text "Spanish(...)"
+                        :page-content! "Spanish(...)"}
+           :objective-nav {:title "Spanish(Navigation for)"
+                           :details "Spanish(Details)"
+                           :questions "Spanish(Questions)"
+                           :writers "Spanish(Writers)"}
+           :objective-list {:doc-title "Spanish(Objectives | Objective[8])"
+                            :doc-description ""
+                            :page-title "Spanish(Objectives)"
+                            :create-button-title "Spanish(Create an objective)"
+                            :create-button-text "Spanish(Create an objective)"
+                            :please "Spanish(Please)"
+                            :sign-in "Spanish(sign in)"
+                            :to "Spanish(to create an objective.)"
+                            :subtitle "Spanish(Recently created objectives)"
+                            :drafting-begins "Spanish(Drafting begins on)"
+                            :objectives-intro-text "Spanish(...)"}
+           :objective-create {:doc-title "Crea un objetivo | Objective[8]"
+                              :doc-description "Crea un objetivo"
+                              :page-title "Crea un objetivo"
+                              :page-intro "Spanish(...)"
+                              :headline-label "Spanish(...)"
+                              :headline-title "3 carateres mínimo, 120 carateres máximo"
+                              :headline-prompt "Spanish(...)"
+                              :headline-placeholder "Spanish(...)"
+                              :goals-label "Meta"
+                              :goals-prompt "Spanish(...)"
+                              :goals-title "50 carateres mínimo, 200 carateres máximo"
+                              :goals-placeholder "Spanish(...)"
+                              :background-label "Spanish(...)"
+                              :background-prompt "Spanish(...)"
+                              :background-title "Escribe una descripcion máximo de 1000 caracteres."
+                              :end-date-label "Spanish(...)"
+                              :end-date-prompt "Spanish(...)"
+                              :drafting-not-yet-implemented "Spanish(...)"
+                              :end-date-title "Por favor escribe la fecha de vencimiento"
+                              :end-date-placeholder "yyyy-mm-dd"
+                              :submit "Crear"}
+           :objective-view {:doc-title "Objetivo | Objective[8]"
+                            :doc-description ""
+                            :background-label "Spanish(Background)"
+                            :goals-label "Meta"
+                            :end-date-label "Fecha de vencimiento"
+                            :created-message "Tu objetivo ha sido creado"}
+           :comment-view {:created-message "Tu comentario ha sido creado"
+                          :comment-title "Comentarios"
+                          :no-comments "Spanish(There are no comments yet.)"}
+           :comment-create {:comment-label "Spanish(Your comment)"
+                            :comment-title "Los comentarios son máximo de 500 caracteres."
+                            :post-button "Spanish(Add comment)"}
+           :comment-sign-in {:please "Spanish(Please)"
+                             :sign-in "Spanish(sign in)"
+                             :to "Spanish(to start commenting.)"}
+           :question-list {:questions-about "Spanish(Questions about)"
+                           :page-intro "Spanish(...)"
+                           :question-list-heading "Spanish(...)"
+                           :no-questions "Spanish(There are no questions yet.)" }
+           :question-create {:question-label "Spanish(Question)"
+                             :question-title "Spanish(Questions are a maximum length of 500 characters)"
+                             :post-button "Spanish(Add)"}
+           :question-view {:added-message "Spanish(Your question has been added!)"
+                           :added-answer-message "Spanish(Your answer has been added!)"}
+           :question-sign-in {:please "Spanish(Please)"
+                              :sign-in "Spanish(sign in)"
+                              :to "Spanish(to ask a question.)" }
+           :answer-view   {:created-message "Spanish(Your answer has been posted!)"
+                           :answer-title "Spanish(Answers)"
+                           :no-answers "Spanish(No one has answered this question yet.)"}
+           :answer-create {:answer-label "Spanish(Your answer)"
+                           :answer-title "Spanish(Answers are a maximum length of 500 characters)"
+                           :post-button "Spanish(Post your answer)"}
+           :answer-sign-in {:please "Spanish(Please)"
+                            :sign-in "Spanish(sign in)"
+                            :to "Spanish(to answer this question.)"}
+           :invitation {:doc-title "Spanish(...)"
+                        :doc-description "Spanish(...)"
+                        :page-title "Spanish(...)"
+                        :page-intro "Spanish(...)"
+                        :writer-name-label "Spanish(...)"
+                        :writer-name-title "Spanish(...)"
+                        :reason-label "Spanish(...)"
+                        :reason-title "Spanish(...)"
+                        :submit "Spanish(...)"}
+           :invitation-response {:doc-title "Spanish(...)"
+                                 :doc-description "Spanish(...)"
+                                 :page-title "Spanish(...)"
+                                 :page-intro "Spanish(...)"
+                                 :for-objective-text "Spanish(...)"
+                                 :rsvp-text "Spanish(...)"
+                                 :sign-in-to-accept "Spanish(...)"
+                                 :accept "Spanish(...)"
+                                 :decline "Spanish(...)"}
+           :invitation-sign-in {:please "Spanish(...)"
+                                :sign-in "Spanish(...)"
+                                :to "Spanish(...)"}
+           :invitation-banner {:message "Spanish(...)"}
+           :candidate-list {:page-intro "Spanish(...)"
+                            :candidate-list-heading "Spanish(...)"
+                            :no-candidates "Spanish(...)"}
+           :current-draft {:page-intro "Spanish(...)"
+                           :no-drafts "Spanish(...)"}
+           :edit-draft {:doc-title "Spanish(...)"
+                        :doc-description "Spanish(...)"
+                        :preview "Spanish(...)"
+                        :submit "Spanish(...)"}
+           :sign-up {:doc-title "Perfil | Objective[8]"
+                     :doc-description ""
+                     :page-title ""
+                     :welcome  "Tu correo electrónico nos permitira informarte cuando recivas respuestas a tus comentarios, objetivos y votos."
+                     :username-label ""
+                     :username-title ""
+                     :not-unique ""
+                     :not-well-formed ""
+                     :email-label  "Correo electrónico"
+                     :email-title  "Escribe tu cuenta de correo electrónico"
+                     :button ""}}})
+
+
 (def t (tower/make-t translation-config))


update when video id changes

update when video id changes

--- src/oc/storage/api/entries.clj
+++ src/oc/storage/api/entries.clj
@@ -171,7 +171,8 @@
         (let [remaining-entries (entry-res/list-all-entries-by-board conn (:uuid old-board))]
           (board-res/maybe-delete-draft-board conn org old-board remaining-entries user)))
       (timbre/info "Updated entry for:" entry-for)
-      (handle-video-data conn updated-result)
+      (when (not= (:video-id updated-entry) (:video-id entry))
+        (handle-video-data conn updated-result))
       (notification/send-trigger! (notification/->trigger :update org board {:old entry :new updated-result} user nil))
       {:updated-entry (assoc updated-result :board-name (:name board))})


Updated component API to allow for connection extraction.

--- src/dragon/components/core.clj
+++ src/dragon/components/core.clj
@@ -20,3 +20,7 @@
   ""
   [system]
   (get-in system (concat [:event] dataflow-keys)))
+
+(defn get-db-conn
+  [system]
+  (get-in system [:db :conn]))


CMR-1380: Do not perform the database migrations in parallel.

--- metadata-db-app/src/migrations/013_add_granule_ur_to_granule_tables.clj
+++ metadata-db-app/src/migrations/013_add_granule_ur_to_granule_tables.clj
@@ -3,7 +3,7 @@
   (:require [config.mdb-migrate-helper :as h]))

 (defn up
-  "Migrates the database up to version 14."
+  "Migrates the database up to version 13."
   []
   (println "migrations.013-add-granule-ur-to-granule-tables up...")

@@ -12,16 +12,14 @@
   (doseq [t (h/get-granule-tablenames)]
     (h/sql (format "alter table %s add granule_ur VARCHAR(250)" t)))

-  ;; Populate the granule_ur column. Perform the updates in parallel to reduce the time of the
-  ;; overall migration
-  (doall (pmap (fn [t]
-                 (h/sql (format "update %s set granule_ur = native_id" t))
-                 (h/sql (format "alter table %s modify granule_ur NOT NULL" t))
-                 (h/sql (format "CREATE INDEX idx_%s_ur ON %s(granule_ur)" t t)))
-               (h/get-granule-tablenames))))
+  ;; Populate the granule_ur column and create an index simultaneous with ongoing ingest.
+  (doseq [t (h/get-granule-tablenames)]
+    (h/sql (format "update %s set granule_ur = native_id" t))
+    (h/sql (format "alter table %s modify granule_ur NOT NULL" t))
+    (h/sql (format "CREATE INDEX idx_%s_ur ON %s(granule_ur)" t t))))

 (defn down
-  "Migrates the database down from version 14."
+  "Migrates the database down from version 13."
   []
   (println "migrations.013-add-granule-ur-to-granule-tables down.")
   (doseq [t (h/get-granule-tablenames)]


Generate the Readme as well

Generate the Readme as well

--- src/leiningen/new/figwheel.clj
+++ src/leiningen/new/figwheel.clj
@@ -46,6 +46,7 @@
                 :reagent? (reagent? opts)}]
       (main/info "Generating fresh 'lein new' figwheel project.")
       (->files data
+               ["README.md" (render "README.md" data)]
                ["project.clj" (render "project.clj" data)]
                ["src/{{sanitized}}/core.cljs" (render "core.cljs" data)]
                ["resources/public/index.html" (render "index.html" data)]


Fix fn name.

Fix fn name.

--- src/leiningen/new/onyx_app.clj
+++ src/leiningen/new/onyx_app.clj
@@ -4,7 +4,7 @@

 (def render (renderer "onyx-app"))

-(defn onyx
+(defn onyx-app
   "Creates a new Onyx application template"
   [name]
   (let [path (name-to-path name)


change both w and h at the same time

change both w and h at the same time

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

--- plugins/SlideExplorer2/src/slide_explorer/canvas.clj
+++ plugins/SlideExplorer2/src/slide_explorer/canvas.clj
@@ -147,7 +147,9 @@
 (defn demo-animation [reference]
   (dotimes [i 200]
   (Thread/sleep 10)
-  (swap! reference assoc-in [0 :params :w] (+ i 100))
-  (swap! reference assoc-in [0 :params :h] (+ i 100))
-  ))
+  (swap! reference (fn [data]
+                     (-> data
+                         (assoc-in [0 :params :w] (+ i 100))
+                         (assoc-in [0 :params :h] (+ i 100)))
+                     ))))


added dire

added dire

--- src/babel/italiano/lexicon.clj
+++ src/babel/italiano/lexicon.clj
@@ -815,6 +815,19 @@
                             :sem {:pred :paint}}
                    :italiano {:passato "dipinto"}}

+      "dire"
+      (let [shared-part-of-dire
+              {:synsem {:cat :verb}
+               :italiano {:italiano "dicere"
+                          :drop-e false
+                          :passato "detto"
+                          :future-stem "dir"
+                          :present {:2plur "dite"}}]
+            [(merge shared-part-of-dire
+                    {:synsem {:pred :say}})
+             (merge shared-part-of-dire
+                    {:synsem {:pred :tell}})])
+
       "divertirsi" (let [subject-semantics (ref {:human true})
                          subject-agr (ref :top)]
                      {:synsem {:cat :verb


Fix unit/conversion-rate

Fix unit/conversion-rate

--- src/bakyeono/litedocx/unit.clj
+++ src/bakyeono/litedocx/unit.clj
@@ -54,7 +54,7 @@
 (defn conversion-rate
   "Returns conversion rate for 'from' unit -> 'to' unit."
   [from to]
-  (let [sym (symbol (str to "-per-" from))]
+  (let [sym (symbol (str "bakyeono.litedocx.unit/" to "-per-" from))]
     (cond (resolve sym) (eval sym)
           (= from to) 1
           true (throw (Exception. (str "Unsupported unit conversion: "


if we scroll on did-update, don't also need will-receive-props

--- src/braid/ui/views/thread.cljs
+++ src/braid/ui/views/thread.cljs
@@ -56,8 +56,6 @@
       {:display-name "thread"

        :component-did-mount scroll-to-bottom!
-
-       :component-will-receive-props scroll-to-bottom!

        :component-did-update scroll-to-bottom!


Cleans up ABT code.

Cleans up ABT code.

--- src/clj/game/cards-agendas.clj
+++ src/clj/game/cards-agendas.clj
@@ -27,15 +27,13 @@
                            (when (< n i)
                              (resolve-ability state side (abt (inc n) i) card nil)))})]
      {:optional {:prompt "Look at the top 3 cards of R&D?"
-                 :yes-ability {:effect (req (let [n (count (filter #(= (:type %) "ICE")
-                                                                   (take 3 (:deck corp))))]
-                                              (resolve-ability
-                                               state side
-                                               {:msg "look at the top 3 cards of R&D"
-                                                :effect (req (doseq [c (take 3 (:deck corp))]
-                                                               (move state side c :play-area))
-                                                             (resolve-ability state side (abt 1 n) card nil))}
-                                               card nil)))}}})
+                 :yes-ability {:effect (req (let [n (count (filter #(= (:type %) "ICE") (take 3 (:deck corp))))]
+                                              (resolve-ability state side
+                                                               {:msg "look at the top 3 cards of R&D"
+                                                                :effect (req (doseq [c (take 3 (:deck corp))]
+                                                                               (move state side c :play-area))
+                                                                             (resolve-ability state side (abt 1 n) card nil))}
+                                                               card nil)))}}})

    "Ancestral Imager"
    {:events {:jack-out {:msg "do 1 net damage" :effect (effect (damage :net 1))}}}


add simplemde to assets list

add simplemde to assets list

--- src/clj/salava/core/layout.clj
+++ src/clj/salava/core/layout.clj
@@ -18,12 +18,14 @@
   ["/assets/bootstrap/css/bootstrap.min.css"
    "/assets/bootstrap/css/bootstrap-theme.min.css"
    "/assets/font-awesome/css/font-awesome.min.css"
-   "/css/rateit/rateit.css"])
+   "/css/rateit/rateit.css"
+   "/css/simplemde.min.css"])

 (def asset-js
   ["/assets/jquery/jquery.min.js"
    "/assets/bootstrap/js/bootstrap.min.js"
-   "/js/ckeditor/ckeditor.js"])
+   "/js/ckeditor/ckeditor.js"
+   "/js/simplemde.min.js"])

 (defn with-version [ctx resource-name]


Enable subscene source

Enable subscene source

--- src/clj/subman/parser/core.clj
+++ src/clj/subman/parser/core.clj
@@ -15,7 +15,7 @@
 (def sources (atom [addicted-source
                     podnapisi-source
                     opensubtitles-source
-                    ;subscene-source
+                    subscene-source
                     notabenoid-source
                     uksubtitles-source]))


fixed clojuredocs update - seems I lost the listen statement during the merge (?)

--- src/clj_ns_browser/browser.clj
+++ src/clj_ns_browser/browser.clj
@@ -312,6 +312,8 @@
       :action (fn [event] (swap! (id :browse-btn-atom) not)))
     (listen (id :edit-btn)
       :action (fn [event] (swap! (id :edit-btn-atom) not)))
+    (listen (id :update-clojuredocs-btn)
+      :action (fn [event] (swap! (id :update-clojuredocs-btn-atom) not)))
     (listen (id :clojuredocs-offline-rb)
       :action (fn [event] (swap! (id :clojuredocs-offline-rb-atom) not)))
     (listen (id :clojuredocs-online-rb)
@@ -574,11 +576,11 @@
     (b/bind
       (id :update-clojuredocs-btn-atom)
       (b/transform (fn [& o]
-        (invoke-later
+        (future
           (let [f (str (System/getProperty "user.home") "/.clojuredocs-snapshot.txt")]
             (spit f (slurp
         "https://raw.github.com/jafingerhut/cd-client/develop/snapshots/clojuredocs-snapshot-latest.txt"))
-            (alert (str "Locally cached copy of ClojureDocs updated at:" \newline f)))))))
+            (invoke-soon (alert (str "Locally cached copy of ClojureDocs updated at:" \newline f))))))))
     ;;
     ;; inspect-btn pressed =>
     ;; If var is selected and its value is a collection, create inspector.
@@ -597,6 +599,13 @@
     )) ; end of bind-all

+(defn set-font-handler! [root f]
+  (let [id (partial select-id root)]
+    (config! (id :doc-ta) :font {:name f :size (.getSize (config (id :doc-ta) :font))})
+    (config! (id :doc-tf) :font {:name f :style :bold :size (.getSize (config (id :doc-tf) :font))})
+    (config! (id :ns-lb) :font {:name f :size (.getSize (config (id :ns-lb) :font))})
+    (config! (id :vars-lb) :font {:name f :size (.getSize (config (id :vars-lb) :font))})
+    ))

 ;;seesaw.core/toggle-full-screen! (locks up computer!!! don't use)
 ;;(seesaw.dev/show-options) and (seesaw.dev/show-events)
@@ -604,8 +613,7 @@
   "Built menu for given browser-root-frame.
   Note that each frame has its own menu, which will be active when frame is in-focus."
   [root]
-  (let [;;root (frame :id :fake-root)
-        id (partial select-id root)]
+  (let [id (partial select-id root)]

     ;; built-up menu-bar
     (let [main-menu (menubar :id :main-menu)
@@ -617,7 +625,16 @@
           clojuredocs-menu (menu :text "ClojureDocs" :id :clojuredocs-menu)
           window-menu (menu :text "Window" :id :window-menu)
           help-menu (menu :text "Help"  :id :help-menu)
-
+
+          font-menu (menu :text "Font"  :id :font-menu)
+          ;;(config! (id :doc-ta) :font "Menlo")
+          ;;(config! (id :doc-ta) :font "Monospaced")
+          ;;(config! (id :doc-ta) :font "Inconsolata")
+          font-btn-group (button-group)
+          font-Monospaced-rb (radio-menu-item :text "Monospaced" :id :font-Monospaced-rb :group font-btn-group)
+          font-Menlo-rb (radio-menu-item :text "Menlo" :id :font-Menlo-rb :group font-btn-group)
+          font-Inconsolata-rb (radio-menu-item :text "Inconsolata" :id :font-Inconsolata-rb :group font-btn-group)
+
           update-clojuredocs (menu-item :text "ClojureDocs Update local repo" :id :update-clojuredocs-btn)
           clojuredocs-access-btn-group (button-group)
           clojuredocs-online-rb (radio-menu-item :text "ClojureDocs Online" :id :clojuredocs-online-rb :group clojuredocs-access-btn-group)
@@ -638,13 +655,18 @@

       (config! vars-menu :items ["Trace" "Unmap"])

-      (config! window-menu :items [(id :zoom-in-action) (id :zoom-out-action) "-------------"
+      (config! font-Monospaced-rb :listen [:action (fn [e] (set-font-handler! root "Monospaced"))] :selected? true)
+      (config! font-Menlo-rb :listen [:action (fn [e] (set-font-handler! root "Menlo"))])
+      (config! font-Inconsolata-rb :listen [:action (fn [e] (set-font-handler! root "Inconsolata"))])
+      (config! font-menu :items [font-Monospaced-rb  font-Menlo-rb font-Inconsolata-rb])
+
+      (config! window-menu :items [(id :zoom-in-action) (id :zoom-out-action) font-menu :separator
         (id :bring-all-windows-to-front-action) (id :cycle-through-windows-action)])

       (config! help-menu :items [(id :go-github-action) (id :go-clojure.org-action) (id :go-clojuredocs-action) (id :go-cheatsheet-action) (id :go-jira-action) (id :go-about-action)])
-      (config! docs-menu :items [update-clojuredocs "-------------"
+      (config! docs-menu :items [update-clojuredocs :separator
                                  clojuredocs-online-rb clojuredocs-offline-rb
-                                 "-------------"])
+                                 :separator])
       )))

 ;; init and browser-window management


Modify the algorithm of linear index

Modify the algorithm of linear index

--- src/cljam/bam_index/writer.clj
+++ src/cljam/bam_index/writer.clj
@@ -98,13 +98,11 @@
        (map (partial zipmap [:bin :chunks]))))

 (defn- init-linear-index []
-  {:index (gen-vec max-lidx-size 0)
-   :largest-seen -1})
+  {})

 (defn- update-linear-index
   [linear-index aln]
-  (let [{:keys [index largest-seen]} linear-index
-        {:keys [beg]} (:chunk (:meta aln))
+  (let [{:keys [beg]} (:chunk (:meta aln))
         aln-beg (:pos aln)
         aln-end (dec (+ aln-beg (cgr/count-ref (:cigar aln))))
         win-beg (if (zero? aln-end)
@@ -113,28 +111,31 @@
         win-end (if (zero? aln-end)
                   win-beg
                   (pos->lidx-offset aln-end))]
-    (assoc linear-index
-      :index (loop [i win-beg, lidx* index]
-               (if (<= i win-end)
-                 (let [l (nth lidx* i)]
-                   (recur (inc i) (if (or (zero? l) (< beg l))
-                                    (assoc lidx* i beg)
-                                    lidx*)))
-                 lidx*))
-      :largest-seen (max win-end largest-seen))))
+    (loop [i win-beg, lidx* linear-index]
+      (if (<= i win-end)
+        (recur (inc i) (update-in lidx* [i] (fn [l]
+                                              (if l (min l beg) beg))))
+        lidx*))))
+
+(defn- complement-linear-index
+  "([1 10] [3 30]) -> ([0 0] [1 10] [2 10] [3 30])"
+  [linear-index]
+  (loop [[f & r] (if (zero? (ffirst linear-index))
+                   linear-index
+                   (conj linear-index [0 0]))
+         ret []]
+    (if (seq r)
+      (recur r (apply conj ret (map #(conj (vector %) (second f)) (range (first f) (ffirst r)))))
+      (conj ret f))))
+

 (defn- finish-linear-index
-  "Optimizes the linear index for safety. This seems unnecessary, but samtools
-  does this process."
   [linear-index]
-  (let [{lidx :index, largest-lidx-seen :largest-seen} linear-index]
-    (loop [i 0, lidx* [], last-non-zero 0]
-      (if (<= i largest-lidx-seen)
-        (let [l (long (nth lidx i))]
-          (if (zero? l)
-            (recur (inc i) (conj lidx* last-non-zero) last-non-zero)
-            (recur (inc i) (conj lidx* l) l)))
-        lidx*))))
+  (->> linear-index
+       (seq)
+       (sort-by first)
+       (complement-linear-index)
+       (map second)))

 (defn- init-index-status []
   {:meta-data    (init-meta-data)
@@ -220,17 +221,9 @@
   [bin-map1 bin-map2]
   (merge-with merge-chunks bin-map1 bin-map2))

-;;; slow ...
 (defn- merge-lidx
   [lidx1 lidx2]
-  {:index (vec (map (fn [l1 l2]
-                      (cond
-                        (zero? l1) l2
-                        (zero? l2) l1
-                        :else (min l1 l2)))
-                    (:index lidx1) (:index lidx2))) ; OPTIMIZE
-   :largest-seen (max (:largest-seen lidx1) (:largest-seen lidx2))})
-
+  (merge-with min lidx1 lidx2))

 (defn merge-index
   [idx1 idx2]
@@ -254,7 +247,6 @@
        (make-index* refs)
        (finish-index refs)))

- ; TODO: Parallelize
 (defn make-index1
   [refs alns]
   (->> (partition-all 1000 alns)


Fix a bug that 2bit reader incorrectly reads small n

--- src/cljam/io/twobit/reader.clj
+++ src/cljam/io/twobit/reader.clj
@@ -114,8 +114,8 @@
            (if (<= 1 ref-pos len)
              (.put cb (.charAt ^String (twobit-to-str (+ (aget ba ba-pos) 128)) bit-pos))
              (.put cb \N))))
+       (replace-ambs! cb ambs start' end')
        (when mask? (mask! cb masks start' end'))
-       (replace-ambs! cb ambs start' end')
        (.rewind cb)
        (.toString cb)))))


whitespace

whitespace

--- src/cljs/greffe/doc_comps.cljs
+++ src/cljs/greffe/doc_comps.cljs
@@ -95,7 +95,7 @@
            (when (:editText state)
              (dom/textarea #js {:value (:editContent state)
                                 :cols "50" :rows "3"
-                             :onChange
+                                :onChange
                                 (fn [ev]
                                   (let [new-val (-> ev .-target .-value)]
                                     (om/set-state! owner :editContent new-val)


Add google maps integration

Add google maps integration

--- src/cljs/sloth/views/text.cljs
+++ src/cljs/sloth/views/text.cljs
@@ -140,6 +140,26 @@
                  [:iframe (assoc iframe-attrs :src src)])
                default-value)
       default-value)))
+
+(defmethod convert-http-url :www.google.es
+  [url]
+  (let [uri (Uri. url)
+        path (.getPath uri)
+        splitted-path (filter (complement empty?) (str/split path "/"))
+        url-category (keyword (first splitted-path))]
+
+    (.log js/console "--- MAPA ---")
+    (.log js/console (str url-caterogy))
+    (if (= url-category :maps)
+      (let [embed-url (str "https://maps.googleapis.com/maps/api/staticmap?")
+            additional-attrs (str "&zoom=15&size=600x300")
+            coords (str/join "," (subvec (str/split (nth (str/split uri "@") 1) ",") 0 2))
+            coords-attr (str "center=" coords)
+            mark-attr (str "&markers=color:red|label:A|" coords)
+            maps-static-url (str embed-url coords-attr mark-attr additional-attrs)]
+        (.log js/console "--- DE VERDAD ---")
+        (make-image-message maps-static-url))
+      (make-external-link url))))

 (defmethod convert-http-url :default
   [url]


Correctly handle castling moves in book.

--- src/clojure/clj_chess/book.clj
+++ src/clojure/clj_chess/book.clj
@@ -437,9 +437,15 @@
         f (Square/make ff fr)
         t (Square/make tf tr)]
     (assoc entry :move
-           (if (= p 0)
+           (cond
+             (and (= (b/piece-type (b/piece-on board f)) b/king)
+                  (not= 1 (Math/abs (- t f))))
+             (Move/makeCastle f t)
+
+             (= p 0)
              (Move/make f t)
-             (Move/makePromotion f t p)))))
+
+             :else (Move/makePromotion f t p)))))

 (defn find-book-entries
   "Returns a list of all book entries for the given input board, read from


Added :binding-invalidated lifecycle callback.

--- src/clojure/freactive/dom.cljs
+++ src/clojure/freactive/dom.cljs
@@ -116,13 +116,13 @@
                               (dispose-node child-key state)))))))

 (defn- remove-dom-node [dom-node]
-  (time
-    (let [state (aget element-state-lookup dom-node)]
-      (dispose-node dom-node state)
-      (when-let [parent (.-parentNode dom-node)]
-        (.removeChild parent dom-node)
-        (when state
-          (js-delete (.-parent-state state) state))))))
+  ;(println "removing dom node")
+  (let [state (aget element-state-lookup dom-node)]
+    (dispose-node dom-node state)
+    (when-let [parent (.-parentNode dom-node)]
+      (.removeChild parent dom-node)
+      (when state
+        (js-delete (.-parent-state state) state)))))

 (defn remove! [x]
   (if (dom-node? x)
@@ -240,26 +240,26 @@
   (when-let [[add-watch* remove-watch*] (r/get-add-remove-watch* ref)]
     (let [attr-state #js {:disposed false}
           key [element attr-name]
-          f (fn on-value-ref-invalidated
-              ([]
-               (on-value-ref-invalidated key ref))
-              ([key ref _ _]
-               (on-value-ref-invalidated key ref))
-              ([key ref]
-               (remove-watch* ref key)
-               (queue-animation
-                 (fn [_]
-                   (when-not (.-disposed attr-state)
-                     (add-watch* ref key on-value-ref-invalidated)
-                     (set-fn (non-reactively @ref)))))))]
+          invalidate
+          (fn on-value-ref-invalidated
+            ([]
+             (on-value-ref-invalidated key ref))
+            ([key ref _ _]
+             (on-value-ref-invalidated key ref))
+            ([key ref]
+             (remove-watch* ref key)
+             (queue-animation
+               (fn [_]
+                 (when-not (.-disposed attr-state)
+                   (add-watch* ref key on-value-ref-invalidated)
+                   (set-fn (non-reactively @ref)))))))]
       (register-with-parent-state node-state
                                   (str "-" state-prefix "." attr-name) attr-state)
-      (add-watch* ref key f)))
+      (add-watch* ref key invalidate)))
   (set-fn @ref))

 (defn- bind-style-prop! [element attr-name attr-value node-state]
   (let [setter (fn [v]
-                 ;(println "setting style" element attr-name v)
                  (set-style-prop! element attr-name v))]
     (if (satisfies? cljs.core/IDeref attr-value)
       (bind-attr* setter element "style" attr-name attr-value node-state)
@@ -513,8 +513,13 @@
         (set! (.-parent-state state) parent-state)
         (register-with-parent-state parent-state (get-node-id new-elem) state)))))

-(defn- replace-node-completly [parent new-elem-spec cur-dom-node]
-  (let [new-elem (build-element new-elem-spec)]
+(defn- replace-node-completely [parent new-elem-spec cur-dom-node top-level]
+  (let [new-elem
+        (if top-level
+          (do
+            ;(println "build")
+            (build-element new-elem-spec))
+          (build-element new-elem-spec))]
     (register-element-with-parent parent new-elem)
     (.replaceChild parent new-elem cur-dom-node)
     (dispose-node cur-dom-node)
@@ -546,24 +551,28 @@
         ;;vdom (normalize-virtual-element vdom)
         ]
     (if (keyword-identical? (first vdom) (first cur-vdom))
-      (let [old-attrs? (second cur-vdom)
-            new-attrs? (second vdom)
-            new-attrs (when (map? new-attrs?) new-attrs?)]
-        (replace-attrs! cur-dom-node
-                        (when (map? old-attrs?) old-attrs?)
-                        new-attrs)
-        (when-not top-level
-          (dispose-child-state (get-element-state cur-dom-node) "-reactive"))
-        (reset-element-spec! cur-dom-node vdom)
-        (let [new-children (if new-attrs (nnext vdom) (next vdom))
-              dangling-child (try-diff-subseq cur-dom-node (.-firstChild cur-dom-node) new-children)]
-          (loop [cur-child dangling-child]
-            (when cur-child
-              (let [next-sib (.-nextSibling cur-child)]
-                (.removeChild cur-dom-node cur-child)
-                (recur next-sib)))))
-        cur-dom-node)
-      (replace-node-completly parent vdom cur-dom-node))))
+      (do
+        ;(println "diff hit" (first vdom))
+        (let [old-attrs? (second cur-vdom)
+              new-attrs? (second vdom)
+              new-attrs (when (map? new-attrs?) new-attrs?)]
+          (replace-attrs! cur-dom-node
+                          (when (map? old-attrs?) old-attrs?)
+                          new-attrs)
+          (when-not top-level
+            (dispose-child-state (get-element-state cur-dom-node) "-reactive"))
+          (reset-element-spec! cur-dom-node vdom)
+          (let [new-children (if new-attrs (nnext vdom) (next vdom))
+                dangling-child (try-diff-subseq cur-dom-node (.-firstChild cur-dom-node) new-children)]
+            (loop [cur-child dangling-child]
+              (when cur-child
+                (let [next-sib (.-nextSibling cur-child)]
+                  (.removeChild cur-dom-node cur-child)
+                  (recur next-sib)))))
+          cur-dom-node))
+      (do
+        ;(println "build hit" (first vdom) (first cur-vdom))
+        (replace-node-completely parent vdom cur-dom-node top-level)))))

 (defn- replace-child [parent new-elem-spec cur-dom-node top-level]
   (let [new-virtual-dom (get-virtual-dom new-elem-spec)]
@@ -582,12 +591,7 @@
               (try-diff parent new-virtual-dom cur-dom-node top-level)))
           (try-diff parent new-virtual-dom cur-dom-node top-level))

-        (if top-level
-          (do
-            (println "starting full replace")
-            (time
-              (replace-node-completly parent new-elem-spec cur-dom-node))))
-        (replace-node-completly parent new-elem-spec cur-dom-node)))))
+        (replace-node-completely parent new-elem-spec cur-dom-node top-level)))))

 (defn- insert-child [parent vdom before]
   (let [new-elem (build-element vdom)]
@@ -666,6 +670,8 @@
   (if-let [[add-watch* remove-watch*] (r/get-add-remove-watch* child-ref)]
     (let [id (new-reactive-id)
           state (ReactiveElement. id parent nil false false false nil  nil)
+
+          ref-meta (meta ref)

           get-new-elem (fn []
                          (set! (.-dirty state) false)
@@ -716,13 +722,23 @@
                (set! (.-dirty state) true)
                (when-not (.-updating state)
                  (set! (.-updating state) true)
-                 (queue-animation animate)))))]
+                 (queue-animation animate)))))
+
+          binding-invalidated (:binding-invalidated ref-meta)
+
+          invalidate (if binding-invalidated
+                       (fn binding-invalidated-wrapper
+                         ([key child-ref _ _] (binding-invalidated-wrapper key child-ref))
+                         ([key child-ref]
+                          (when (binding-invalidated (.-cur-element state) child-ref)
+                            (invalidate key child-ref))))
+                       invalidate)]
       (set! (.-animate state) animate)
       (set! (.-invalidate state) invalidate)
       (when-let [binding-disposed (get (meta child-ref) :binding-disposed)]
         (set! (.-disposed-callback state) binding-disposed))
       (when-let [parent-state (get-element-state parent)]
-        (register-with-parent-state parent-state (str "-reactive" id) state))
+        (register-with-parent-state parent-state id state))
       (when-let [binding-initialized (get (meta child-ref)
                                           :binding-initialized)]
         (binding-initialized))


Alphabot can now take latitude and longitude on command line for queries that make use of geographic location.

--- Alphabot/src/alphabot/core.clj
+++ Alphabot/src/alphabot/core.clj
@@ -83,12 +83,12 @@
             (extract-didyoumeans xmldoc)
 )))

-(defn make-query-url [query appid]
-    (str "http://api.wolframalpha.com/v2/query?input=" (url-encode query) "&appid=" (url-encode appid)))
+(defn make-query-url [query appid latlong]
+    (str "http://api.wolframalpha.com/v2/query?input=" (url-encode query) "&appid=" (url-encode appid) "&latlong=" (url-encode latlong)))

-(defn ask-wolfram [query appid]
+(defn ask-wolfram [query appid latlong]
     (let [
-        query-url (make-query-url query appid)
+        query-url (make-query-url query appid latlong)
         response-xml (clojure.xml/parse query-url)
         result (get-results response-xml query)
         ]
@@ -112,9 +112,9 @@
             "Free: " (to-mb free) " MiB")))

 (def alpha-command "!alpha ")
-(defn on-message [{:keys [nick channel message irc]} wolfram-appid]
+(defn on-message [{:keys [nick channel message irc]} wolfram-appid latlong]
     (if (.startsWith message alpha-command)
-        (let [results (ask-wolfram (.substring message (count alpha-command)) wolfram-appid)]
+        (let [results (ask-wolfram (.substring message (count alpha-command)) wolfram-appid latlong)]
             (doseq [line results]
                 (send-message irc channel line))))
     (if (.startsWith message "!memory")
@@ -126,21 +126,22 @@
     [& args]
     (with-command-line
         args
-        "Arguments: -channel #mychannel -nick botnick -server irc.server.com -appname wolfram-app-name -appid wolfram-app-id"
+        "Arguments: -channel #mychannel -nick botnick -server irc.server.com -appname wolfram-app-name -appid wolfram-app-id -latlong <latitude>,<longitude>"
         [
             [channel c "IRC Channel to join." "#alphabottest"]
             [nick n "Bot's IRC nick." "alphabot"]
             [server s "IRC server address." "localhost"]
             [appid i "Application ID for Wolfram Alpha API." ""]
+            [latlong l "Latitude and longitude for queries requiring location (i.e 40.42,-3.71)." ""]
         ]
         (do
-            (println channel nick server appid)
+            (println channel nick server appid latlong)
             (connect
                 (create-irc {
                     :name nick
                     :server server
                     :fnmap {
-                        :on-message #(on-message % appid)
+                        :on-message #(on-message % appid latlong)
                     }
                 })
                 :channels [channel])


Fix NamespaceOfFile

Fix NamespaceOfFile

--- src/de/kotka/gorilla/nails.clj
+++ src/de/kotka/gorilla/nails.clj
@@ -91,20 +91,19 @@
                  *in*)
         eof    (Object.)
         of-interest '#{in-ns ns clojure.core/in-ns clojure.core/ns}
-        in-seq (repeatedly #(read in false eof))]
-    (let [candidate
-          (drop-while #(and (not= % eof)
-                            (or (not (instance? clojure.lang.ISeq %))
-                                (not (contains? of-interest (first %)))))
-                      in-seq)]
-      (when (not= candidate eof)
-        (let [candidate (first candidate)]
-          (cond
-            ('#{ns clojure.core/ns} (first candidate))
-            (println (second candidate))
-
-            ('#{in-ns clojure.core/in-ns} (first candidate))
-            (println (second (second candidate)))))))))
+        in-seq (repeatedly #(read in false eof))
+        candidate (first
+                    (drop-while #(and (not= % eof)
+                                      (or (not (instance? clojure.lang.ISeq %))
+                                          (not (contains? of-interest
+                                                          (first %)))))
+                                in-seq))]
+    (println
+      (cond
+        (= candidate eof)                                "user"
+        ('#{ns clojure.core/ns} (first candidate))       (second candidate)
+        ('#{in-ns clojure.core/in-ns} (first candidate)) (second (second candidate))
+        :else                                            (println "user")))))

 (defnail NamespaceInfo
   "Usage: ng de.kotka.gorilla.nails.NamespaceInfo [--] namespace ..."


Add devcards for eden

Add devcards for eden

--- src/devcards/discuss/eden.cljs
+++ src/devcards/discuss/eden.cljs
@@ -1,6 +1,34 @@
 (ns devcards.discuss.eden
   (:require [devcards.core :as dc :refer-macros [defcard defcard-om-next om-next-root]]
-            [discuss.eden.views :as eviews]))
+            [sablono.core :as html :refer-macros [html]]
+            [discuss.eden.views :as eviews]
+            [discuss.components.options :as options]
+            [discuss.parser :as parser]
+            [discuss.views :as views]
+            [discuss.communication.auth :as auth]
+            [discuss.utils.common :as lib]
+            [devcards.discuss.utils :as utils]))

-(defcard add-new-eden-argument
+(defcard-om-next connection-browser
+  options/ConnectionBrowser
+  parser/reconciler)
+
+(defcard buttons
+  (html [:div
+         (utils/button #(auth/login "Christian" "iamgroot") "Login as Christian")
+         (utils/button #(lib/last-api! "/town-has-to-cut-spending/justify/37/agree?history=/attitude/37") "Set :api/last-url")]))
+
+(defcard-om-next new-eden-argument
+  eviews/EDENArgumentForm
+  parser/reconciler)
+
+(defcard-om-next overview-menu
+  eviews/OverviewMenu
+  parser/reconciler)
+
+#_(defcard add-new-eden-argument
   (eviews/eden-argument-form {:click-fn (fn [] (println "clicked"))}))
+
+(defcard-om-next main-view
+  views/MainView
+  parser/reconciler)


Better function to render breadcrumb

Better function to render breadcrumb

--- src/hurvinek/html_renderer.clj
+++ src/hurvinek/html_renderer.clj
@@ -53,15 +53,18 @@

 (defn render-breadcrumb
     "Render the breadcumb at the top of page."
-    [url-prefix
-     first-link first-name
-     chapter-id chapter-name
-     group-id group-name]
-    [:ol {:class "breadcrumb"}
-         [:li [:a {:href url-prefix} "Hurvinek"]]
-         (if first-link
-             [:li [:a {:href first-link} first-name]])
-         ])
+    (   [url-prefix]
+        [:ol {:class "breadcrumb"}
+             [:li [:a {:href url-prefix} "Hurvinek"]]])
+    (   [url-prefix first-link first-name]
+        [:ol {:class "breadcrumb"}
+             [:li [:a {:href url-prefix} "Hurvinek"]]
+             [:li [:a {:href first-link} first-name]]])
+    (   [url-prefix first-link first-name second-link second-name]
+        [:ol {:class "breadcrumb"}
+             [:li [:a {:href url-prefix} "Hurvinek"]]
+             [:li [:a {:href first-link} first-name]]
+             [:li [:a {:href second-link} second-name]]]))

 (defn render-front-page
     "Render front page of this application."
@@ -71,7 +74,7 @@
         [:body
             [:div {:class "container"}
                 (render-navigation-bar-section url-prefix title)
-                (render-breadcrumb url-prefix nil nil nil nil nil nil)
+                (render-breadcrumb url-prefix)
                 [:div {:class "container-fluid"}
                     [:h1 "Main menu"]
                     [:table {:class "table table-hover"}
@@ -94,7 +97,7 @@
         [:body
             [:div {:class "container"}
                 (render-navigation-bar-section url-prefix title)
-                (render-breadcrumb url-prefix "select-product" "Product list" nil nil nil nil)
+                (render-breadcrumb url-prefix "select-product" "Product list")
                 [:div {:class "container-fluid"}
                     [:h2 "Product list"]
                     [:table {:class "table table-hover"}


Add a no-op gate implementation

Add a no-op gate implementation

--- src/main/audio_utils/gate.cljs
+++ src/main/audio_utils/gate.cljs
@@ -1,28 +1,83 @@
 (ns audio-utils.gate
   (:require [audio-utils.ring-buffer :as rb]
             [audio-utils.rms-buffer :as rms]
-            [audio-utils.util :refer [db->amplitude time->samples]]))
+            [audio-utils.util :refer [aatom aderef areset! aswap!
+                                      db->amplitude time->samples]]))

-(defprotocol IGate)
+(defprotocol IGate
+  (connect-source [this source])
+  (connect-destination [this destination])
+  (disconnect [this]))
+
+;;sample-rate        (.-sampleRate ctx)
+;;threshold'         (db->amplitude threshold)
+;;rms-samples        (max 1 (time->samples rms-window sample-rate))
+;;rms-buffers        (aatom [])
+;;hold-samples       (time->samples hold sample-rate)
+;;look-ahead-samples (max 1 (time->samples look-ahead sample-rate))
+;;look-ahead-buffer  (rb/ring-buffer look-ahead-samples)
+
+(defrecord Gate [config node rms-buffers]
+  IGate
+  (connect-source [this source]
+    (let [sample-rate (.-sampleRate (:ctx config))
+          rms-window  (:rms-window config)
+          rms-samples (max 1 (time->samples rms-window sample-rate))]
+      (areset! rms-buffers
+               (into [] (repeat (.-channelCount source)
+                                (rms/rms-buffer rms-samples)))))
+    (.connect source node))
+
+  (connect-destination [this destination]
+    (.connect node destination))
+
+  (disconnect [this]
+    (.disconnect node))
+
+  Object
+  (generate-output-sample [this channel sample]
+    sample)
+
+  (process-audio [this event]
+    (let [input-buffer  (.-inputBuffer event)
+          output-buffer (.-outputBuffer event)
+          n-channels    (.-numberOfChannels output-buffer)]
+      (dotimes [channel n-channels]
+        (let [input-data  (.. input-buffer  (getChannelData channel))
+              output-data (.. output-buffer (getChannelData channel))]
+          (dotimes [n (.-length input-data)]
+            (let [input-sample  (aget input-data n)
+                  output-sample (.generate-output-sample this channel
+                                                         input-sample)]
+              (aset output-data n output-sample))))))))

 (defn default-trigger
   [gate state])

 (defn gate
-  [{:keys [audio-ctx size threshold look-ahead hold rms-window trigger]
-    :or   {size       8192
-           threshold  -32.0
-           look-ahead 0.5
-           hold       0.1
-           rms-window 0.1
-           trigger    default-trigger}}]
-  (let [processor          (.createScriptProcessor audio-ctx size 1 1)
-        sample-rate        (.-sampleRate audio-ctx)
-        threshold'         (db->amplitude threshold)
-        rms-samples        (time->samples rms-window sample-rate)
-        hold-samples       (time->samples hold sample-rate)
-        look-ahead-samples (time->samples look-ahead sample-rate)
-        rms-buffer         (rms/rms-buffer rms-samples)
-        look-ahead-buffer  (rb/ring-buffer look-ahead-samples)]
-    (specify! processor
-      IGate)))
+  [{:keys [ctx
+           buffer-size
+           threshold
+           look-ahead
+           hold
+           rms-window
+           trigger]
+    :or   {buffer-size 4096
+           threshold   -32.0
+           look-ahead  500
+           hold        100
+           rms-window  100
+           trigger     default-trigger}}]
+  (let [node   (.createScriptProcessor ctx buffer-size 1 1)
+        config {:ctx        ctx
+                :threshold  threshold
+                :look-ahead look-ahead
+                :hold       hold
+                :rms-window rms-window
+                :trigger    trigger}
+        gate   (map->Gate {:config      config
+                           :node        node
+                           :rms-buffers (aatom [])})]
+    (set! (.-onaudioprocess node)
+          #(.process-audio gate %))
+    gate))


Draft of some work for #10 Parses JSC stack into a Clojure map

--- Clojure/src/ambly/repl/jsc.clj
+++ Clojure/src/ambly/repl/jsc.clj
@@ -1,5 +1,6 @@
 (ns ambly.repl.jsc
-  (:require [clojure.java.io :as io]
+  (:require [clojure.string :as string]
+            [clojure.java.io :as io]
             [cljs.analyzer :as ana]
             [cljs.compiler :as comp]
             [cljs.repl :as repl]
@@ -37,15 +38,42 @@
                (.append sb (char c))
                (recur sb (.read in)))))))

+(defn stack-line->frame
+  "Parses a stack line into a frame representation, returning nil
+  if parse failed."
+  [stack-line]
+  (let [[function file line column]
+        (rest (re-matches #"(.*)@file://(.*):([0-9]+):([0-9]+)"
+                     stack-line))]
+    (if (and function file line column)
+      {:function function
+       :file     file
+       :line (Long/parseLong line)
+       :column (Long/parseLong column)})))
+
+(defn process-exception
+  "Process a JSC stack representation, optionally parsing it into
+  stack frames if normalize? is true."
+  [normalize? stack]
+  (merge {:stack stack}
+         (when normalize?
+           {:frames (remove nil?
+                            (map stack-line->frame
+                                 (rest (string/split-lines stack))))})))
+
 (defn jsc-eval
   "Evaluate a JavaScript string in the JSC REPL process."
   [repl-env js]
   (let [{:keys [in out]} @(:socket repl-env)]
     (write out js)
     (let [result (json/read-str
-                   (read-response in) :key-fn keyword)]
-      {:status (keyword (:status result))
-       :value  (:value result)})))
+                   (read-response in) :key-fn keyword)
+          status (keyword (:status result))
+          value (:value result)]
+      {:status status
+       :value (if (= :exception status)
+                (process-exception true value)              ; TODO determine when to normalize based on REPL flag
+                value)})))

 (defn load-javascript
   "Load a Closure JavaScript file into the JSC REPL process."
@@ -165,4 +193,4 @@
      :cache-analysis true
      :source-map true})

-  )+  )


Update build.boot

Update build.boot

--- examples/blog/build.boot
+++ examples/blog/build.boot
@@ -1,7 +1,7 @@
 (set-env!
   :source-paths #{"src"}
   :resource-paths #{"resources"}
-  :dependencies '[[perun "0.4.1-SNAPSHOT"]
+  :dependencies '[[perun "0.4.2-SNAPSHOT"]
                   [hiccup "1.0.5"]
                   [pandeiro/boot-http "0.6.3-SNAPSHOT"]])


Adapt `exit` for use with p5js

Adapt `exit` for use with p5js

--- src/cljc/quil/core.cljc
+++ src/cljc/quil/core.cljc
@@ -1532,7 +1532,8 @@
   completed (or after setup completes if called during the setup
   method). "
   []
-  (.exit (ap/current-applet)))
+  #?(:clj (.exit (ap/current-applet))
+     :cljs (.remove (ap/current-applet))))

 (defn
   ^{:requires-bindings false


* src/cljs/cljs/core.cljs: fix typo

* src/cljs/cljs/core.cljs: fix typo

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -2654,7 +2654,7 @@

 (defn get-in
   "Returns the value in a nested associative structure,
-  where ks is a sequence of ke(ys. Returns nil if the key is not present,
+  where ks is a sequence of keys. Returns nil if the key is not present,
   or the not-found value if supplied."
   {:added "1.2"
    :static true}


Merging in test for truthiness

Merging in test for truthiness

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -1811,6 +1811,104 @@
   (pr-with-opts obj (pr-opts))
   (newline (pr-opts)))

+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Reference Types ;;;;;;;;;;;;;;;;
+
+(deftype Atom [state meta validator]
+  IEquiv
+  (-equiv [o other] (identical? o other))
+
+  IDeref
+  (-deref [_] state)
+
+  IMeta
+  (-meta [_] meta))
+
+(defn atom
+  "Creates and returns an Atom with an initial value of x and zero or
+  more options (in any order):
+
+  :meta metadata-map
+
+  :validator validate-fn
+
+  If metadata-map is supplied, it will be come the metadata on the
+  atom. validate-fn must be nil or a side-effect-free fn of one
+  argument, which will be passed the intended new state on any state
+  change. If the new state is unacceptable, the validate-fn should
+  return false or throw an exception."
+  ([x] (Atom. x nil nil))
+  ([x & {:keys [meta validator]}] (Atom. x meta validator)))
+
+(defn reset!
+  "Sets the value of atom to newval without regard for the
+  current value. Returns newval."
+  [a newval]
+  (when-let [v (.validator a)]
+    (when-not (v newval)
+      (throw "Validator rejected reference state")))
+  (set! a.state newval))
+
+(defn swap!
+  "Atomically swaps the value of atom to be:
+  (apply f current-value-of-atom args). Note that f may be called
+  multiple times, and thus should be free of side effects.  Returns
+  the value that was swapped in."
+  ([a f]
+     (reset! a (f (.state a))))
+  ([a f & args]
+     (reset! a (apply f (.state a) args))))
+
+(defn compare-and-set!
+  "Atomically sets the value of atom to newval if and only if the
+  current value of the atom is identical to oldval. Returns true if
+  set happened, else false."
+  [a oldval newval]
+  (if (= a.state oldval)
+    (do (reset! a newval) true)
+    false))
+
+;; generic to all refs
+;; (but currently hard-coded to atom!)
+
+(defn deref
+  [o]
+  (-deref o))
+
+(defn set-validator!
+  "Sets the validator-fn for a var/ref/agent/atom. validator-fn must be nil or a
+  side-effect-free fn of one argument, which will be passed the intended
+  new state on any state change. If the new state is unacceptable, the
+  validator-fn should return false or throw an exception. If the current state (root
+  value if var) is not acceptable to the new validator, an exception
+  will be thrown and the validator will not be changed."
+  [iref val]
+  (set! iref.validator val))
+
+(defn get-validator
+  "Gets the validator-fn for a var/ref/agent/atom."
+  [iref]
+  (.validator iref))
+
+(defn alter-meta!
+  "Atomically sets the metadata for a namespace/var/ref/agent/atom to be:
+
+  (apply f its-current-meta args)
+
+  f must be free of side-effects"
+  [iref f & args]
+  (set! iref.meta (apply f (.meta iref) args)))
+
+(defn reset-meta!
+  "Atomically resets the metadata for a namespace/var/ref/agent/atom"
+  [iref m]
+  (set! iref.meta m))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Fixtures ;;;;;;;;;;;;;;;;
+
+(def fixture1 1)
+(def fixture2 2)
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Tests ;;;;;;;;;;;;;;;;

 (defn test-stuff []
@@ -1851,7 +1949,7 @@
                       (-reduce "abcd" jumble))))
   (assert (= "cafrogbd" (let
                             [jumble (fn [a b] (str (apply str (reverse (str a))) b))]
-                        (-reduce "abcd" jumble "frog"))))
+                          (-reduce "abcd" jumble "frog"))))
   (assert (= [0 0 1 0 1]
                [(bit-and 1 0)
                 (bit-and 0 0)
@@ -1907,5 +2005,18 @@
               (false? true)
               (true? undefined)
               (false? undefined)]))
+  (assert (= 1 (try 1)))
+  (let [a (atom 0)]
+    (assert (= 0 (deref a)))
+    (assert (= 1 (swap! a inc)))
+    (assert (= false (compare-and-set! a 0 42)))
+    (assert (= true (compare-and-set! a 1 7)))
+    (assert (nil? (meta a)))
+    (assert (nil? (get-validator a))))
+  (let [a (atom [1] :validator coll? :meta {:a 1})]
+    (assert (= coll? (get-validator a)))
+    (assert (= {:a 1} (meta a)))
+    (alter-meta! a assoc :b 2)
+    (assert (= {:a 1 :b 2} (meta a))))
   :ok
 )


cleanup int-rotate-left and imul. implement basic murmur ops, results match Clojure

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -403,22 +403,63 @@

 ;; http://developer.classpath.org/doc/java/lang/Integer-source.html
 (defn ^number int-rotate-left [x n]
-  (cljs.core/bit-or
-    (cljs.core/bit-shift-left x n)
-    (cljs.core/unsigned-bit-shift-right x (- n))))
+  (bit-or
+    (bit-shift-left x n)
+    (unsigned-bit-shift-right x (- n))))

 ;; http://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
 (if (exists? Math/imul)
   (defn ^number imul [a b] (js/Math.imul a b))
   (defn ^number imul [a b]
-    (let [ah (cljs.core/bit-and (cljs.core/unsigned-bit-shift-right a 16) 0xffff)
-          al (cljs.core/bit-and a 0xffff)
-          bh (cljs.core/bit-and (cljs.core/unsigned-bit-shift-right b 16) 0xffff)
-          bl (cljs.core/bit-and b 0xffff)]
-      (cljs.core/bit-or
+    (let [ah (bit-and (unsigned-bit-shift-right a 16) 0xffff)
+          al (bit-and a 0xffff)
+          bh (bit-and (unsigned-bit-shift-right b 16) 0xffff)
+          bl (bit-and b 0xffff)]
+      (bit-or
         (+ (* al bl)
-           (cljs.core/unsigned-bit-shift-right
-             (cljs.core/bit-shift-left (+ (* ah bl) (* al bh)) 16) 0)) 0))))
+           (unsigned-bit-shift-right
+             (bit-shift-left (+ (* ah bl) (* al bh)) 16) 0)) 0))))
+
+;; http://smhasher.googlecode.com/svn/trunk/MurmurHash3.cpp
+(def m3-seed 0)
+(def m3-C1 0xcc9e2d51)
+(def m3-C2 0x1b873593)
+
+(defn ^number m3-mix-K1 [k1]
+  (-> k1 (imul m3-C1) (int-rotate-left 15) (imul m3-C2)))
+
+(defn ^number m3-mix-H1 [h1 k1]
+  (-> h1 (bit-xor k1) (int-rotate-left 13) (imul 5) (+ 0xe6546b64)))
+
+(defn ^number m3-fmix [h1 len]
+  (as-> h1 h1
+    (bit-xor h1 len)
+    (bit-xor h1 (unsigned-bit-shift-right h1 16))
+    (imul h1 0x85ebca6b)
+    (bit-xor h1 (unsigned-bit-shift-right h1 13))
+    (imul h1 0xc2b2ae35)
+    (bit-xor h1 (unsigned-bit-shift-right h1 16))))
+
+(defn ^number m3-hash-int [in]
+  (if (zero? in)
+    in
+    (let [k1 (m3-mix-K1 in)
+          h1 (m3-mix-H1 m3-seed k1)]
+      (m3-fmix h1 4))))
+
+(defn ^number m3-hash-unencoded-chars [in]
+  (let [h1 (loop [i 1 h1 m3-seed]
+             (if (< i (alength in))
+               (recur (+ i 2)
+                 (m3-mix-H1 h1
+                   (m3-mix-K1
+                     (bit-or (.charCodeAt in (dec i))
+                       (bit-shift-left (.charCodeAt in i) 16)))))
+               h1))
+        h1 (if (== (bit-and (alength in) 1) 1)
+             (bit-xor h1 (m3-mix-K1 (.charCodeAt in (dec (alength in)))))
+             h1)]
+    (m3-fmix h1 (imul 2 (alength in)))))

 ;;;;;;;;;;;;;;;;;;; symbols ;;;;;;;;;;;;;;;


Cleanup

Cleanup

--- src/graphql_clj/validator/rules/variables_in_allowed_position.clj
+++ src/graphql_clj/validator/rules/variables_in_allowed_position.clj
@@ -22,7 +22,7 @@
 (defn- effective-type
   "If a variable definition has a default value, it's effectively non-null."
   [variable-type {:keys [default-value]}]
-  (if (and default-value (not (s/valid? #nu/tapd variable-type nil)))
+  (if (and default-value (not (s/valid? variable-type nil)))
     (spec/add-required (namespace variable-type) (name variable-type))
     variable-type))


(rest [1]) returns emptly list. Fixes #59

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -309,8 +309,7 @@
   "Returns a possibly empty seq of the items after the first. Calls seq on its
   argument."
   [coll]
-  (when coll
-    (-rest (seq coll))))
+  (-rest (seq coll)))

 (defn next
   "Returns a seq of the items after the first. Calls seq on its
@@ -2321,6 +2320,8 @@
   (assert (not (= {:a :b :c nil} {:a :b :d nil})))
   (assert (= (list 3 2 1) [3 2 1]))
   (assert (= [3 2 1] (seq (array 3 2 1))))
+  (assert (= () (rest nil)))
+  (assert (= () (rest [1])))
   (assert (= {"x" "y"} (meta ^{"x" "y"} [])))
   (assert (= {:a :b} (dissoc {:a :b :c :d} :c)))
   (assert (= (hash-map :foo 5)


fix -swap! invokes in swap!

fix -swap! invokes in swap!

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -7141,19 +7141,19 @@
   ([a f]
      (if (instance? Atom a)
        (reset! a (f (.-state a)))
-       (-swap! a (deref a))))
+       (-swap! a f)))
   ([a f x]
      (if (instance? Atom a)
        (reset! a (f (.-state a) x))
-       (-swap! a (f (deref a) x))))
+       (-swap! a f x)))
   ([a f x y]
      (if (instance? Atom a)
        (reset! a (f (.-state a) x y))
-       (-swap! a (f (deref a) x y))))
+       (-swap! a f x y)))
   ([a f x y & more]
      (if (instance? Atom a)
        (reset! a (apply f (.-state a) x y more))
-       (-swap! a (f (deref a) x y more)))))
+       (-swap! a f x y more))))

 (defn compare-and-set!
   "Atomically sets the value of atom to newval if and only if the


Remove native-font hints as Processing 3 dropped support for it and suggests to use createFont() instead.

--- src/cljx/quil/core.cljx
+++ src/cljx/quil/core.cljx
@@ -51,8 +51,7 @@
  color-modes (:rgb :hsb)
  image-formats (:rgb :argb :alpha)
  ellipse-modes (:center :radius :corner :corners)
- hint-options (:enable-native-fonts :disable-native-fonts
-               :enable-depth-test :disable-depth-test
+ hint-options (:enable-depth-test :disable-depth-test
                :enable-depth-sort :disable-depth-sort
                :enable-depth-mask :disable-depth-mask
                :enable-opengl-errors :disable-opengl-errors


instr-control/set-params-at (:set) now logs at info level instead of debug level

--- src/overtime/instr_control.clj
+++ src/overtime/instr_control.clj
@@ -37,11 +37,11 @@

 (defn set-params
-  [type key & params]
-  (log/debug "Set params for" type key "to" params)
+  [type key log-level & params]
+  (log/logp log-level "Set params for" type key "to" params)
   (apply ot/ctl (synth-instance type key) params))

-(defn set-params-at [time & params] (apply-by time (ot/at time (apply set-params params))))
+(defn set-params-at [time type key & params] (apply-by time (ot/at time (apply set-params type key :info params))))

 (defn- get-delta-vals
   [start-val num-steps f]
@@ -59,7 +59,7 @@
         vals-times (map vector vals times)]
     (log/debug "Vals:" vals)
     (log/debug "Times:" times)
-    (doseq [[val time] vals-times] (ot/at time (set-params type key param-key val)))
+    (doseq [[val time] vals-times] (ot/at time (set-params type key :debug param-key val)))
     [synth vals-times]))

 (defn set-param-over-time-at [time & params] (apply-by time (apply set-param-over-time params)))


Whitespace.

Whitespace.

--- src/overtunes/songs/at_all.clj
+++ src/overtunes/songs/at_all.clj
@@ -10,7 +10,6 @@

 (defn after [timing offset] #(timing (+ offset %)))
 (defn tempo [timing factor] #(timing (/ % factor)))
-
 (defn ground [note] (+ 60 note))

 (def note# (comp sampled-piano ground))