From e2394850069240b71342ac7f4b9a41cba069bba2 Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Sun, 16 Dec 2012 19:35:34 +0700 Subject: [PATCH 1/9] Bump dependency (Timbre 1.2.0) --- project.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.clj b/project.clj index 70d97bc..28ceb4d 100644 --- a/project.clj +++ b/project.clj @@ -3,7 +3,7 @@ :url "https://github.com/ptaoussanis/tower" :license {:name "Eclipse Public License"} :dependencies [[org.clojure/clojure "1.3.0"] - [com.taoensso/timbre "1.0.0"]] + [com.taoensso/timbre "1.2.0"]] :profiles {:1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]} :1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]} :1.5 {:dependencies [[org.clojure/clojure "1.5.0-alpha3"]]} From 95896bc5675e453c79c1ba1ee7bb8929765d40b5 Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Fri, 16 Nov 2012 20:47:37 +0700 Subject: [PATCH 2/9] More helpful dictionary error messages --- src/taoensso/tower.clj | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/taoensso/tower.clj b/src/taoensso/tower.clj index 2ac735c..420592d 100644 --- a/src/taoensso/tower.clj +++ b/src/taoensso/tower.clj @@ -306,13 +306,17 @@ read-string (set-config! [:dictionary])) ;; For automatic dictionary reloading: - (set-config! [:dict-res-name] resource-name)))) + (set-config! [:dict-res-name] resource-name) + (catch Exception _ + (throw (Exception. (str "Failed to load dictionary from resource: " + resource-name))))))) (defn- compile-map-path "[:locale :ns1 ... :nsN unscoped-key translation] => {:locale {:ns1.<...>.nsN/unscoped-key (f translation decorator)}}" [path] - {:pre [(seq path) (>= (count path) 3)]} + (when-not (and (seq path) (>= (count path) 3)) + (throw (Exception. "Failed to compile dictionary: malformed"))) (let [path (vec path) locale-name (first path) translation (peek path) From 7d98d473d32e423377522847afa98bb99d8dd4ed Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Wed, 21 Nov 2012 23:27:02 +0700 Subject: [PATCH 3/9] Fix _x_ markdown --- src/taoensso/tower/utils.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/taoensso/tower/utils.clj b/src/taoensso/tower/utils.clj index 5110c71..cd22a91 100644 --- a/src/taoensso/tower/utils.clj +++ b/src/taoensso/tower/utils.clj @@ -53,7 +53,7 @@ (str/replace #"\\\*" "*") ; Unescape \*s (str/replace #"(?$1") - (str/replace #"(?$1") + (str/replace #"(?$1") (str/replace #"\\\_" "_") ; Unescape \_s (str/replace #"(?$1") From d8d71c082eabd24bff272eb9259dc71e3b42d546 Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Fri, 30 Nov 2012 17:53:34 +0700 Subject: [PATCH 4/9] Fix `inline-markdown->html` em tag --- src/taoensso/tower/utils.clj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/taoensso/tower/utils.clj b/src/taoensso/tower/utils.clj index cd22a91..4108a63 100644 --- a/src/taoensso/tower/utils.clj +++ b/src/taoensso/tower/utils.clj @@ -40,7 +40,7 @@ (defn inline-markdown->html "Uses regex to parse given markdown string into HTML. Doesn't do any escaping. **x** => x - *x* => x + *x* => x __x__ => x _x_ => x ~~x~~ => x @@ -49,11 +49,11 @@ (-> (apply str strs) ;; Unescaped X is (?$1") - (str/replace #"(?$1") + (str/replace #"(?$1") (str/replace #"\\\*" "*") ; Unescape \*s (str/replace #"(?$1") - (str/replace #"(?$1") + (str/replace #"(?$1") (str/replace #"\\\_" "_") ; Unescape \_s (str/replace #"(?$1") From a221275f48906865b4b65b615ca757cef8ef6b1a Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Thu, 6 Dec 2012 16:41:43 +0700 Subject: [PATCH 5/9] Update contact details (taoensso.com) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 305d998..62167f0 100644 --- a/README.md +++ b/README.md @@ -199,7 +199,7 @@ CDS (Clojure Documentation Site) is a contributor-friendly community project aim ## Contact & Contribution -Reach me (Peter Taoussanis) at *ptaoussanis at gmail.com* for questions/comments/suggestions/whatever. I'm very open to ideas if you have any! I'm also on Twitter: [@ptaoussanis](https://twitter.com/#!/ptaoussanis). +Reach me (Peter Taoussanis) at [taoensso.com](https://www.taoensso.com) for questions/comments/suggestions/whatever. I'm very open to ideas if you have any! I'm also on Twitter: [@ptaoussanis](https://twitter.com/#!/ptaoussanis). ## License From 798a889953dc98095c9fc8f22598cf81274f716a Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Fri, 28 Dec 2012 14:12:03 +0700 Subject: [PATCH 6/9] Fix `config` docstring --- project.clj | 5 +++-- src/taoensso/tower.clj | 17 ++++++++--------- src/taoensso/tower/utils.clj | 13 +++++++++++-- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/project.clj b/project.clj index 28ceb4d..d07e214 100644 --- a/project.clj +++ b/project.clj @@ -2,8 +2,9 @@ :description "Clojure internationalization & translation library" :url "https://github.com/ptaoussanis/tower" :license {:name "Eclipse Public License"} - :dependencies [[org.clojure/clojure "1.3.0"] - [com.taoensso/timbre "1.2.0"]] + :dependencies [[org.clojure/clojure "1.3.0"] + [org.clojure/tools.macro "0.1.1"] + [com.taoensso/timbre "1.2.0"]] :profiles {:1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]} :1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]} :1.5 {:dependencies [[org.clojure/clojure "1.5.0-alpha3"]]} diff --git a/src/taoensso/tower.clj b/src/taoensso/tower.clj index 420592d..62d54ec 100644 --- a/src/taoensso/tower.clj +++ b/src/taoensso/tower.clj @@ -13,18 +13,17 @@ (declare compiled-dictionary) -(defonce config - ^{:doc - "This map atom controls everything about the way Tower operates. +(utils/defonce* config + "This map atom controls everything about the way Tower operates. - To enable translations, :dictionary should be a map of form - {:locale {:ns1 ... {:nsN {:key text}}}}}. + To enable translations, :dictionary should be a map of form + {:locale {:ns1 ... {:nsN {:key text}}}}}. - :default-locale controls fallback locale for `with-locale` and `t`. - :dev-mode? controls `t` automatic dictionary reloading and default - `log-missing-translation!-fn` behaviour. + :default-locale controls fallback locale for `with-locale` and `t`. + :dev-mode? controls `t` automatic dictionary reloading and default + `log-missing-translation!-fn` behaviour. - See source code for details."} + See source code for details." (atom {:dev-mode? true :default-locale :en diff --git a/src/taoensso/tower/utils.clj b/src/taoensso/tower/utils.clj index 4108a63..3f31fd8 100644 --- a/src/taoensso/tower/utils.clj +++ b/src/taoensso/tower/utils.clj @@ -1,9 +1,18 @@ (ns taoensso.tower.utils {:author "Peter Taoussanis"} - (:require [clojure.string :as str] - [clojure.java.io :as io]) + (:require [clojure.string :as str] + [clojure.java.io :as io] + [clojure.tools.macro :as macro]) (:import [java.io File])) +(defmacro defonce* + "Like `clojure.core/defonce` but supports optional docstring and attributes + map for name symbol." + {:arglists '([name expr])} + [name & sigs] + (let [[name [expr]] (macro/name-with-attributes name sigs)] + `(clojure.core/defonce ~name ~expr))) + (defn leaf-paths "Takes a nested map and squashes it into a sequence of paths to leaf nodes. Based on 'flatten-tree' by James Reaves on Google Groups. From 89139165411328276ce1fafe357fbb17b98354e1 Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Thu, 3 Jan 2013 21:13:23 +0700 Subject: [PATCH 7/9] Update `utils/file-resources-modified?` --- src/taoensso/tower.clj | 2 +- src/taoensso/tower/utils.clj | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/taoensso/tower.clj b/src/taoensso/tower.clj index 62d54ec..02ee5e8 100644 --- a/src/taoensso/tower.clj +++ b/src/taoensso/tower.clj @@ -423,7 +423,7 @@ ;; Automatic dictionary reloading (when (and dev-mode? dict-res-name - (utils/file-resource-modified? dict-res-name)) + (utils/file-resources-modified? dict-res-name)) (load-dictionary-from-map-resource! dict-res-name)) (let [;; :ns1.<...>.nsM.nsA.<...>/nsN = :ns1.<...>.nsN/key diff --git a/src/taoensso/tower/utils.clj b/src/taoensso/tower/utils.clj index 3f31fd8..f2b936e 100644 --- a/src/taoensso/tower/utils.clj +++ b/src/taoensso/tower/utils.clj @@ -109,19 +109,22 @@ file doesn't exist." [resource-name] (when-let [^File file (try (->> resource-name io/resource io/file) - (catch Exception _ nil))] + (catch Exception _))] (.lastModified file))) -(def file-resource-modified? - "Returns true iff the file backing given named resource has changed since this - function was last called." - (let [;; {file1 time1, file2 time2, ...} - previous-times (atom {})] - (fn [resource-name] - (let [time (file-resource-last-modified resource-name)] - (if-not (= time (get @previous-times resource-name)) - (do (swap! previous-times assoc resource-name time) true) - false))))) +(def file-resources-modified? + "Returns true iff any files backing the given group of named resources + have changed since this function was last called." + (let [;; {#{file1A file1B ...#} (time1A time1A ...), + ;; #{file2A file2B ...#} (time2A time2B ...), ...} + group-times (atom {})] + (fn [& resource-names] + (let [file-group (into (sorted-set) resource-names) + file-times (map file-resource-last-modified file-group) + last-file-times (get @group-times file-group)] + (when-not (= file-times last-file-times) + (swap! group-times assoc file-group file-times) + (boolean last-file-times)))))) (defn parse-http-accept-header "Parses HTTP Accept header and returns sequence of [choice weight] pairs From e23c6bcb3ffdcfa0214429dadbb8b817795890f0 Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Fri, 4 Jan 2013 14:52:25 +0700 Subject: [PATCH 8/9] Add `merge-config!` --- src/taoensso/tower.clj | 7 +++++-- src/taoensso/tower/utils.clj | 22 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/taoensso/tower.clj b/src/taoensso/tower.clj index 02ee5e8..ed1d7d3 100644 --- a/src/taoensso/tower.clj +++ b/src/taoensso/tower.clj @@ -23,7 +23,9 @@ :dev-mode? controls `t` automatic dictionary reloading and default `log-missing-translation!-fn` behaviour. - See source code for details." + See source code for details. + See `set-config!`, `merge-config!` for convenient config/dictionary + editing." (atom {:dev-mode? true :default-locale :en @@ -47,7 +49,8 @@ (timbre/warn "Missing translation" k-or-ks "for" locale) (timbre/debug "Missing translation" k-or-ks "for" locale)))})) -(defn set-config! [[k & ks] val] (swap! config assoc-in (cons k ks) val)) +(defn set-config! [[k & ks] val] (swap! config assoc-in (cons k ks) val)) +(defn merge-config! [& maps] (apply swap! config utils/deep-merge maps)) ;;;; Locales (big L for the Java object) diff --git a/src/taoensso/tower/utils.clj b/src/taoensso/tower/utils.clj index f2b936e..2db8c74 100644 --- a/src/taoensso/tower/utils.clj +++ b/src/taoensso/tower/utils.clj @@ -142,4 +142,24 @@ (parse-http-accept-header "en-GB") (parse-http-accept-header "en-GB,en;q=0.8,en-US;q=0.6") (parse-http-accept-header "en-GB , en; q=0.8, en-US; q=0.6") - (parse-http-accept-header "a,")) \ No newline at end of file + (parse-http-accept-header "a,")) + +(defn deep-merge-with ; From clojure.contrib.map-utils + "Like `merge-with` but merges maps recursively, applying the given fn + only when there's a non-map at a particular level. + + (deepmerge-with + {:a {:b {:c 1 :d {:x 1 :y 2}} :e 3} :f 4} + {:a {:b {:c 2 :d {:z 9} :z 3} :e 100}}) + => {:a {:b {:z 3, :c 3, :d {:z 9, :x 1, :y 2}}, :e 103}, :f 4}" + [f & maps] + (apply + (fn m [& maps] + (if (every? map? maps) + (apply merge-with m maps) + (apply f maps))) + maps)) + +(def deep-merge (partial deep-merge-with (fn [x y] y))) + +(comment (deep-merge {:a {:b {:c {:d :D :e :E}}}} + {:a {:b {:g :G :c {:c {:f :F}}}}})) \ No newline at end of file From 4177f58417349d323aa7b7975c0db4dde35b7169 Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Fri, 4 Jan 2013 15:09:20 +0700 Subject: [PATCH 9/9] Bump version (minor) --- README.md | 6 +++--- project.clj | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 62167f0..d5c5c6d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Current [semantic](http://semver.org/) version: ```clojure -[com.taoensso/tower "1.0.0"] +[com.taoensso/tower "1.1.0"] ``` # Tower, a Clojure internationalization & translation library @@ -27,7 +27,7 @@ Tower is an attempt to present a **simple, idiomatic internationalization and lo Depend on Tower in your `project.clj`: ```clojure -[com.taoensso/tower "1.0.0"] +[com.taoensso/tower "1.1.0"] ``` and `require` the library: @@ -203,4 +203,4 @@ Reach me (Peter Taoussanis) at [taoensso.com](https://www.taoensso.com) for ques ## License -Copyright © 2012 Peter Taoussanis. Distributed under the [Eclipse Public License](http://www.eclipse.org/legal/epl-v10.html), the same as Clojure. \ No newline at end of file +Copyright © 2012 Peter Taoussanis. Distributed under the [Eclipse Public License](http://www.eclipse.org/legal/epl-v10.html), the same as Clojure. diff --git a/project.clj b/project.clj index d07e214..d027b79 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject com.taoensso/tower "1.0.0" +(defproject com.taoensso/tower "1.1.0" :description "Clojure internationalization & translation library" :url "https://github.com/ptaoussanis/tower" :license {:name "Eclipse Public License"}