diff --git a/README.md b/README.md index e0f0838..6d16e80 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ Java and .NET applications. Take a look at YourKit's leading software products: Simply add - [stencil "0.4.0"] + [stencil "0.5.0"] to the `:dependencies` key of your project.clj. @@ -170,6 +170,12 @@ it as soon as possible. ## Recently +* Released version 0.5.0. + - Removed the dependency on slingshot, in favor of Clojure's built-in + ex-info. ex-info was added in Clojure 1.4, so Stencil versions higher + than 0.5.0 will require Clojure 1.4 or later. Thanks to + [Ryan Wilson](https://github.com/rwilson). + * Released version 0.4.0. - Lambdas that have `:stencil/pass-render` true in their metadata will be called with the render function as an explicit arg, in diff --git a/project.clj b/project.clj index c13afbe..f61bfc6 100644 --- a/project.clj +++ b/project.clj @@ -1,20 +1,16 @@ -(defproject stencil "0.4.0" +(defproject stencil "0.5.0" :description "Mustache in Clojure" :url "https://github.com/davidsantiago/stencil" :dependencies [[org.clojure/clojure "1.6.0"] [scout "0.1.0"] [quoin "0.1.2"] - [slingshot "0.10.3"] [org.clojure/core.cache "0.6.3"]] :profiles {:dev {:dependencies [[org.clojure/data.json "0.1.2"]]} :cacheless-test - {:dependencies ^:replace [[org.clojure/clojure "1.3.0"] + {:dependencies ^:replace [[org.clojure/clojure "1.4.0"] [scout "0.1.0"] [quoin "0.1.2"] - [slingshot "0.10.3"] [org.clojure/data.json "0.1.2"]]} - :clj1.2 {:dependencies [[org.clojure/clojure "1.2.1"]]} - :clj1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]} :clj1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]} :clj1.5 {:dependencies [[org.clojure/clojure "1.5.1"]]}} :aliases {"all" ["with-profile" "dev:dev,clj1.4:dev,clj1.5"] diff --git a/src/stencil/loader.clj b/src/stencil/loader.clj index 47a3e8c..9a0c681 100644 --- a/src/stencil/loader.clj +++ b/src/stencil/loader.clj @@ -1,7 +1,6 @@ (ns stencil.loader (:refer-clojure :exclude [load]) (:use [clojure.java.io :only [resource]] - [slingshot.slingshot :only [throw+]] [stencil.parser :exclude [partial]] [stencil.ast :exclude [partial]] [quoin.text :as qtext] @@ -18,21 +17,24 @@ (def ^{:private true} no-core-cache-msg "Could not load core.cache. To use Stencil without core.cache, you must first use set-cache to provide a map(-like object) to use as a cache, and consult the readme to make sure you fully understand the ramifications of running Stencil this way.") +(defn- no-core-cache-ex [] + (Exception. no-core-cache-msg)) + (deftype CoreCacheUnavailableStub_SeeReadme [] clojure.lang.ILookup - (valAt [this key] (throw+ no-core-cache-msg)) - (valAt [this key notFound] (throw+ no-core-cache-msg)) + (valAt [this key] (throw (no-core-cache-ex))) + (valAt [this key notFound] (throw (no-core-cache-ex))) clojure.lang.IPersistentCollection - (count [this] (throw+ no-core-cache-msg)) - (cons [this o] (throw+ no-core-cache-msg)) - (empty [this] (throw+ no-core-cache-msg)) - (equiv [this o] (throw+ no-core-cache-msg)) + (count [this] (throw (no-core-cache-ex))) + (cons [this o] (throw (no-core-cache-ex))) + (empty [this] (throw (no-core-cache-ex))) + (equiv [this o] (throw (no-core-cache-ex))) clojure.lang.Seqable - (seq [this] (throw+ no-core-cache-msg)) + (seq [this] (throw (no-core-cache-ex))) clojure.lang.Associative - (containsKey [this key] (throw+ no-core-cache-msg)) - (entryAt [this key] (throw+ no-core-cache-msg)) - (assoc [this key val] (throw+ no-core-cache-msg))) + (containsKey [this key] (throw (no-core-cache-ex))) + (entryAt [this key] (throw (no-core-cache-ex))) + (assoc [this key val] (throw (no-core-cache-ex)))) ;; The dynamic template store just maps a template name to its source code. (def ^{:private true} dynamic-template-store (atom {})) diff --git a/src/stencil/parser.clj b/src/stencil/parser.clj index f196f3b..2e55249 100644 --- a/src/stencil/parser.clj +++ b/src/stencil/parser.clj @@ -6,8 +6,7 @@ (:import java.util.regex.Pattern scout.core.Scanner) (:use [stencil ast re-utils utils] - clojure.pprint - [slingshot.slingshot :only [throw+]])) + clojure.pprint)) ;; ;; Settings and defaults. @@ -56,7 +55,7 @@ numbers, the row and column." [s idx] (if (> idx (count s)) - (throw+ java.lang.IndexOutOfBoundsException)) + (throw (java.lang.IndexOutOfBoundsException. (str "At index " idx)))) (loop [lines 0 last-line-start 0 ;; Index in string of the last line beginning seen. i 0] @@ -207,17 +206,17 @@ {:keys [scanner output state]} p] ;; First, let's analyze the results and throw any errors necessary. (cond (empty? tag-content) - (throw+ {:type :illegal-tag-content - :tag-content tag-content - :scanner tag-content-scanner} - (str "Illegal content in tag: " tag-content - " at " (format-location tag-content-scanner))) + (throw (ex-info (str "Illegal content in tag: " tag-content + " at " (format-location tag-content-scanner)) + {:type :illegal-tag-content + :tag-content tag-content + :scanner tag-content-scanner})) (nil? (:match close-scanner)) - (throw+ {:type :unclosed-tag - :tag-content tag-content - :scanner close-scanner} - (str "Unclosed tag: " tag-content - " at " (format-location close-scanner)))) + (throw (ex-info (str "Unclosed tag: " tag-content + " at " (format-location close-scanner)) + {:type :unclosed-tag + :tag-content tag-content + :scanner close-scanner}))) (case sigil (\{ \&) (parser scanner (zip/append-child output @@ -255,13 +254,13 @@ state) \/ (let [top-section (zip/node output)] ;; Do consistency checks... (if (not= (:name top-section) (parse-tag-name tag-content)) - (throw+ {:type :mismatched-closing-tag - :tag-content tag-content - :scanner tag-content-scanner} - (str "Attempt to close section out of order: " - tag-content - " at " - (format-location tag-content-scanner))) + (throw (ex-info (str "Attempt to close section out of order: " + tag-content + " at " + (format-location tag-content-scanner)) + {:type :mismatched-closing-tag + :tag-content tag-content + :scanner tag-content-scanner})) ;; Going to close it by moving up the zipper tree, but first ;; we need to store the source code between the tags so that ;; it can be used in a lambda. @@ -301,13 +300,13 @@ (drop 1 (re-matches #"([\S|[^=]]+)\s+([\S|[^=]]+)" tag-content))] (if (or (nil? tag-open) (nil? tag-close)) - (throw+ {:type :invalid-set-delimiters-tag - :tag-content tag-content - :scanner tag-content-scanner} - (str "Invalid set delimiters command: " - tag-content - " at " - (format-location tag-content-scanner))) + (throw (ex-info (str "Invalid set delimiters command: " + tag-content + " at " + (format-location tag-content-scanner)) + {:type :invalid-set-delimiters-tag + :tag-content tag-content + :scanner tag-content-scanner})) (parser scanner output (assoc state :tag-open tag-open @@ -334,11 +333,11 @@ ;; If we can go up from the zipper's current loc, then there is an ;; unclosed tag, so raise an error. (if (zip/up output) - (throw+ {:type :unclosed-tag - :scanner s} - (str "Unclosed section: " - (second (zip/node output)) - " at " (format-location s))) + (throw (ex-info (str "Unclosed section: " + (second (zip/node output)) + " at " (format-location s)) + {:type :unclosed-tag + :scanner s})) (zip/root output))) ;; If we are in tag-position, read a tag. (tag-position? s (:state p))