Anonymous avatar Anonymous committed 3187487

First import

Comments (0)

Files changed (8)

+-*- markdown -*-
+
+# Changes and TODO
+
+## 0.1 / 2010-Sep-04 (GMT+5:30)
+
+- Load view templates from classpath and directory
+- Populate view templates with attribute values
+- Render view templates as java.lang.String
+- Transform keyword-keys/value map to string-keys/value map
+-*- markdown -*-
+
+# Clj-StringTemplate
+
+Clj-StringTemplate is a simple wrapper around the StringTemplate
+library. The supported operations are:
+
+* Load view template from classpath
+* Load view template from directory
+* Populate view template with attribute/values
+* Render view template as java.lang.String
+
+
+## Usage
+
+FIXME: Maven/Leiningen dependency details are here: FIXME
+
+Examples for usage can be found in the tutorial below:
+
+
+## Building/Installation
+
+You will need Maven 2 to build from sources. Execute the following:
+
+    $ mvn clean package  # packages up a JAR in "target" dir
+    $ mvn install        # to install to your local Maven repo
+    $ mvn clojure:gendoc # generate Clojure API documentation
+
+
+## License
+
+Copyright (C) 2010 Shantanu Kumar (kumar.shantanu at gmail dot com)
+
+Distributed under the Apache 2 License.
+
+
+# Tutorial
+
+Clj-StringTemplate can be used by including the following in your
+namespace:
+
+    (ns example.app
+      (:use org.bituf.clj-stringtemplate))
+
+
+## Load view template from classpath
+
+    (get-view-from-classpath "hello")
+
+The snippet above will look for the file called <i>hello.st</i> at the
+top level in classpath, and will return the view template.
+
+    (get-view-from-classpath "foo/hello")
+
+The above snippet will look for the file called <i>hello.st</i> under
+the package <i>foo</i> at the top level in classpath, and will return
+the view template.
+
+    (get-view-from-classpath "foo/bar/hello")
+
+The above snippet will do the same as the earlier one, but under the
+package <i>foo.bar</i>.
+
+
+## Load view template from directory
+
+    (get-view-from-dir "hello" "/home/joe/templates")
+
+The above snippet will look for the file
+<i>/home/joe/templates/hello.st</i> and will return the view template.
+
+    (get-view-from-dir "foo/hello" "/home/joe/templates")
+
+The above snippet will look for the file
+<i>/home/joe/templates/foo/hello.st</i> and will return the view
+template.
+
+    (get-view-from-dir "foo/bar/hello" "/home/joe/templates")
+
+The above snippet will look for the file
+<i>/home/joe/templates/foo/bar/hello.st</i> and will return the view
+template.
+
+
+## Populate view template with attribute/values
+
+    (let [view (get-view-from-classpath "hello")]
+      (fill-view! view "name" "Henry")
+      ...)
+
+The snippet above sets value for the attribute "name" in the view
+template.
+
+    (let [view (get-view-from-classpath "hello")]
+      (fill-view! view "names" ["Henry" "Neal" "Rama"])
+      ...)
+
+The snippet above sets a multi-value (essentially a List) for the
+attribute "names" in the view template.
+
+    (let [view (get-view-from-classpath "hello")]
+      (fill-view! view {"names" ["Henry" "Neal" "Rama"]
+                        "title" "List of names"} )
+      ...)
+
+The snippet above sets the corresponding values for the
+attributes "names" and "title" in the view template.
+
+
+## Render view template as <i>java.lang.String</i>
+
+    (let [view   (get-view-from-classpath "hello")
+          filled (fill-view! view "name" "Henry")]
+      (println (render-view filled)))
+
+
+## Transform keyword-key/value map to string-key/value map
+
+    (kv-to-sv {:a 10 :b 20 :c 30})
+
+The snippet above will produce the output {"a" 10 "b" 20 "c" 30}. Such
+transformations may be useful to convert typical Clojure maps to a
+format suitable for StringTemplate view templates.
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.bituf</groupId>
+  <artifactId>clj-stringtemplate</artifactId>
+  <packaging>jar</packaging>
+  <version>0.1-SNAPSHOT</version>
+  <name>clj-stringtemplate</name>
+  <description>Clj-Stringtemplate is a Clojure wrapper for the StringTemplate Java library</description>
+  <url>http://code.google.com/p/bitumenframework/</url>
+  <repositories>
+    <repository>
+      <id>build.clojure.org</id>
+      <url>http://build.clojure.org/snapshots/</url>
+      <snapshots>
+        <enabled>true</enabled>
+      </snapshots>
+    </repository>
+    <repository>
+      <id>clojars.org</id>
+      <url>http://clojars.org/repo</url>
+    </repository>
+  </repositories>
+  <dependencies>
+    <dependency>
+      <groupId>org.clojure</groupId>
+      <artifactId>clojure</artifactId>
+      <version>1.2.0</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>org.clojure</groupId>
+      <artifactId>clojure-contrib</artifactId>
+      <version>1.2.0</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>org.antlr</groupId>
+      <artifactId>stringtemplate</artifactId>
+      <version>3.2</version>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>com.theoryinpractise</groupId>
+        <artifactId>clojure-maven-plugin</artifactId>
+        <version>1.3.3</version>
+        <executions>
+          <execution>
+            <id>compile</id>
+            <phase>compile</phase>
+            <goals>
+              <goal>compile</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>test-compile</id>
+            <phase>test-compile</phase>
+            <goals>
+              <goal>testCompile</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>test</id>
+            <phase>test</phase>
+            <goals>
+              <goal>test</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <clojureOptions>-Dbasedir=${basedir}</clojureOptions>
+          <compileDeclaredNamespaceOnly>true</compileDeclaredNamespaceOnly>
+          <sourceDirectories>
+            <sourceDirectory>src/main/clj</sourceDirectory>
+          </sourceDirectories>
+          <testSourceDirectories>
+            <testSourceDirectory>src/test/clj</testSourceDirectory>
+          </testSourceDirectories>
+          <testScript>${basedir}/src/test/script/runtests.clj</testScript>
+        </configuration>
+        
+      </plugin>
+    </plugins>
+  </build>
+</project>

src/main/clj/org/bituf/clj_stringtemplate.clj

+(ns org.bituf.clj-stringtemplate
+  (:import org.antlr.stringtemplate.StringTemplateGroup)
+  (:import org.antlr.stringtemplate.StringTemplate))
+
+(defn get-view-from-classpath "Return the view template from classpath"
+  [^String view-name]
+  (let [st-group (StringTemplateGroup. "default")]
+    (.getInstanceOf st-group view-name)))
+
+(defn get-view-from-dir "Return the view template from specified directory"
+  [^String view-name ^String root-dir]
+  (let [st-group (StringTemplateGroup. "default" root-dir)]
+    (.getInstanceOf st-group view-name)))
+
+(defn fill-view! "Fill view template with key/value pairs"
+  ;;;
+  ;; Fill template with key and value
+  ([^StringTemplate template k v]
+    (.setAttribute template k v)
+    template)
+  ;;;
+  ;; Fill template with key/value from map
+  ([^StringTemplate template ^Map kv-map]
+    (.setAttributes template kv-map)
+    template))
+
+(defn render-view "Return rendered view for the template"
+  [^StringTemplate template]
+  (.toString template))
+
+(defn kv-to-sv
+  "Transforms keyword-value map {:a 10 :b 20 :c 30}
+   to string-value map {\"a\" 10 \"b\" 20 \"c\" 30}"
+  [mp]
+  (let [m (into {} mp)
+        k (keys m)
+        v (vals m)]
+    (zipmap (map #(if (keyword? %) (name %) (str %)) k) v)))

src/test/clj/hello.st

+hello $who$!

src/test/clj/org/bituf/test_clj_stringtemplate.clj

+(ns org.bituf.test-clj-stringtemplate
+  (:use org.bituf.clj-stringtemplate)
+  (:use clojure.test))
+
+
+(def who "Miguel")
+(def names ["Eugenia" "Matt" "Derek"])
+
+(defn not-nil? "Tells whether an object is not-nil" [obj] (not (nil? obj)))
+
+(defn fail "Fails a test, with message" [msg] (println msg) (is false))
+
+(defmacro fail-on-exception [& body]
+  `(try ~@body
+    (catch Exception ~'nee
+      (.printStackTrace ~'nee)
+      (fail (.getMessage ~'nee)))))
+
+(defmacro now-testing [label & body]
+  (println "Now testing: " label)
+  `(testing ~label ~@body))
+
+
+(deftest test-get-view-from-classpath
+  (now-testing "Load view from classpath"
+    (fail-on-exception
+      (let [hello (get-view-from-classpath "hello")
+            foo   (get-view-from-classpath "st/foo")]
+        (is (not-nil? hello))
+        (is (not-nil? foo))))))
+
+
+(deftest test-get-view-from-dir
+  (now-testing "Load view from directory"
+    (fail-on-exception
+      (let [hello (get-view-from-dir "hello"  "src/test/clj")
+            foo   (get-view-from-dir "st/foo" "src/test/clj")]
+        (is (not-nil? hello))
+        (is (not-nil? foo))))))
+
+
+(deftest test-populate-attr-values-in-view
+  (now-testing "Populate attribute key-values in view"
+    (fail-on-exception
+      (let [hello (get-view-from-classpath "hello")
+            _ (fill-view! hello "who" who)
+            foo   (get-view-from-classpath "st/foo")
+            _ (fill-view! foo "names" names)]
+        (is (not-nil? hello))
+        (is (not-nil? foo)))))
+  (now-testing "Populate attribute key/value map in view"
+    (fail-on-exception
+      (let [hello (get-view-from-classpath "hello")
+            _ (fill-view! hello {"who" who})
+            foo   (get-view-from-classpath "st/foo")
+            _ (fill-view! foo {"names" names})]
+        (is (not-nil? hello))
+        (is (not-nil? foo))))))
+
+
+(deftest test-render-view
+  (now-testing "Render view"
+    (fail-on-exception
+      (let [hello (get-view-from-classpath "hello")
+            _ (fill-view! hello "who" who)
+            hello-r (render-view hello)
+            foo   (get-view-from-classpath "st/foo")
+            _ (fill-view! foo "names" names)
+            foo-r (render-view foo)]
+        (is (= hello-r (str "hello " who "!")))
+        (is (= foo-r (apply str "foobar "
+                       (interpose "\n" (map #(str "baz " % "\n") names)))))))))
+
+(deftest test-kv-to-sv
+  (now-testing "Transform Keyword-key/Value map to String-key/value map"
+    (is (= {"a" 10 "b" 20 "c" 30}
+          (kv-to-sv {:a 10 :b 20 :c 30})))
+    (is (= {"a" 10 "b" 20 "c" 30}
+          (kv-to-sv {:a 10 "b" 20 :c 30})))))
+
+(defn test-ns-hook []
+  (test-get-view-from-classpath)
+  (test-get-view-from-dir)
+  (test-populate-attr-values-in-view)
+  (test-render-view)
+  (test-kv-to-sv))

src/test/clj/st/foo.st

+foobar $names: { each |
+baz $each$
+}; separator="\n"$

src/test/script/runtests.clj

+(ns runtests
+  (:use org.bituf.test-clj-stringtemplate)
+  (:use clojure.test))
+
+
+(run-tests
+  'org.bituf.test-clj-stringtemplate)
+
+;(binding [org.bituf.sqlrat.entity/*show-sql* true
+;          org.bituf.sqlrat.entity/*show-sql-results* true]
+;  (run-tests
+;    'org.bituf.sqlrat.test.dbblog))
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.