Browse files

Initial commit. Warning: Ugly code.

  • Loading branch information...
0 parents commit 18e51f0ccf82b97554d399679131dc4f422f1ff9 MayDaniel committed Jun 17, 2010
Showing with 96 additions and 0 deletions.
  1. +33 −0 README.markdown
  2. +6 −0 project.clj
  3. +51 −0 src/clj_ini/core.clj
  4. +6 −0 test/clj_ini/core_test.clj
33 README.markdown
@@ -0,0 +1,33 @@
+# Clj-Ini
+
+Another small, superficial read/write key/val configuration utility.
+
+## Usage
+
+- '#' is the prefix for commented lines.
+- `read-map` ignores lines that; are comments, of which every element is whitespace, are empty, or do not include '='.
+- Key/values can not be multiline.
+- Comment metadata is always stored at the top of a file.
+- `:comments` may be a collection of strings, or a string, depending on whether multi-lines or single-lines are wanted, respectively.
+- Written files should not contain multiple keys of the same name.
+
+* `(write-map)` - Writes key/values to a file, in a readable format, with comments metadata accepted.
+* `(read-map)` - Reads the key/values back into a Clojure data structure.
+
+### Example
+
+ (write-map "foo.bar" (with-meta
+ {:a 1 :b 2 :c 3}
+ {:comments ["Comment, line 1" "Comment, line 2"]}))
+
+### Results
+
+File: [foo.bar](http://github.com/maydaniel/blob/master/foo.bar)
+
+## Installation
+
+- Leiningen.
+
+## License
+
+Clj-Ini is licensed under the Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
6 project.clj
@@ -0,0 +1,6 @@
+(defproject clj-ini "0.1.0-SNAPSHOT"
+ :description "Another small, superficial read/write key/val configuration utility."
+ :dependencies [[org.clojure/clojure "1.1.0"]
+ [org.clojure/clojure-contrib "1.1.0"]]
+ :dev-dependencies [[swank-clojure "1.2.1"]]
+ :namespaces :all)
51 src/clj_ini/core.clj
@@ -0,0 +1,51 @@
+(ns clj-ini.core
+ (:use [clojure.contrib.str-utils2 :only [split]]
+ [clojure.contrib.duck-streams :only [read-lines append-spit spit]]
+ [clojure.contrib.seq-utils :only [includes? partition-all]])
+ (:import [java.io File]))
+
+;; Ignores lines that: have the prefix '#' (comment lines), contain only whitespace, are empty, do not include '='
+;; Currently does not allow a key/value to be multiline.
+;; Comment metadata can be a collection of strings or a string, depending on multiline or singleline
+
+(defn read-map [file]
+ (when-not (.exists (File. file)) (.createNewFile (File. file)))
+ (if-not (empty? (read-lines file))
+ (do
+ (let [lines (remove #(or
+ (every? (partial = \space) %)
+ (some (partial = (first %)) [\# nil])
+ (not (includes? % \=))) (read-lines file)) file-str
+ (if-not (empty? lines) (->> lines
+ (interpose \space)
+ (apply str)
+ (remove #(= \= %))
+ (apply str)
+ (.replaceAll #" " " ")
+ (split #" ")
+ (partition-all 2)) {})]
+ (cond (-> file-str last count even?)
+ (reduce merge (map #(hash-map (-> % first read-string keyword)
+ (-> % second read-string)) file-str))
+ (-> file-str last count odd?)
+ (throw (Exception. "Exception in parsing. An uneven number of key/vals in the file."))
+ (-> file-str empty?) {}))) {}))
+
+(defn write-map [file map]
+ (if-let [comments (:comments (meta map))]
+ (do
+ (spit file "")
+ (if-not (sequential? comments)
+ (spit file (str "#" \space comments \newline \newline))
+ (do
+ (doseq [x comments]
+ (append-spit file (str "#" \space x \newline)))
+ (append-spit file \newline))))
+ (let [comments (filter #(= (first %) \#) (read-lines file))]
+ (when-not (empty? comments)
+ (spit file "")
+ (doseq [x comments]
+ (append-spit file (str x \newline)))
+ (append-spit file \newline))))
+ (doseq [kv (merge (read-map file) map)]
+ (append-spit file (str (key kv) " = " (val kv) \newline))))
6 test/clj_ini/core_test.clj
@@ -0,0 +1,6 @@
+(ns clj-ini.core-test
+ (:use [clj-ini.core] :reload-all)
+ (:use [clojure.test]))
+
+(deftest replace-me ;; FIXME: write
+ (is false))

0 comments on commit 18e51f0

Please sign in to comment.