summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjetil Orbekk <kj@orbekk.com>2021-07-07 17:25:50 -0400
committerKjetil Orbekk <kj@orbekk.com>2021-07-07 17:25:50 -0400
commitfe12fe16fa5f8bddece8cab225a9bc4a332cfffd (patch)
tree57b42bb51d26497a839bb4050775528325e37c73
parent8f75d757356ed386899fe6fffa422311532e38aa (diff)
more clojure
-rw-r--r--clojure/src/csvtool/core.clj132
1 files changed, 42 insertions, 90 deletions
diff --git a/clojure/src/csvtool/core.clj b/clojure/src/csvtool/core.clj
index 8a061c8..8654f3a 100644
--- a/clojure/src/csvtool/core.clj
+++ b/clojure/src/csvtool/core.clj
@@ -9,39 +9,25 @@
(->> (zipmap keys row)
(#(dissoc % :ignore))))
-;; (defn my-read []
-;; (with-open [reader (io/reader "in-file.csv")]
-;; (doall
-;; (map handle-record (csv/read-csv reader)))))
-
-;; (defn my-write []
-;; (with-open [writer (io/writer "out-file.csv")]
-;; (csv/write-csv writer
-;; [["abc" "def"]
-;; ["ghi" "jkl"]])))
-
-(defmacro wrap-matcher
- ([] identity)
-
- ([body]
- `(fn [~'record]
- (let [~'get #(get ~'record %)
- ~'set #(assoc ~'record %1 %2)]
- ~body)))
-
- ([expr & next]
- `(fn [record#]
- ((wrap-matcher ~@next) ((wrap-matcher ~expr) record#)))))
-
-(defn record-action [name & rest]
+(defn record-action [expr & rest]
+ (let [actions
+ {:set (fn [keyword value & rest]
+ (fn [record]
+ [(assoc record keyword value) rest]))
+ :mod (fn [keyword modf & rest]
+ (fn [record]
+ [(update record keyword modf) rest]))}]
+ (if (fn? expr)
+ (fn [record] [(expr record) rest])
+ (apply (get actions expr) rest))))
+
+(defn record-actions [& exprs]
(fn [record]
- (let [actions {:set (fn [keyword value]
- (assoc record keyword value))
- :mod (fn [keyword modf]
- (update record keyword modf))}]
- (if (fn? name)
- (name record)
- (apply (get actions name) rest)))))
+ (let [[next-record rest] ((apply record-action exprs) record)
+ next-action (if (empty? rest)
+ identity
+ (apply record-actions rest))]
+ (next-action next-record))))
(defn record-test [keyword pred]
(fn [record]
@@ -49,17 +35,11 @@
(pred (get record keyword))
nil)))
-(defn matches [keyword pattern]
- (fn [record]
- (re-matches pattern (get record keyword))))
-
-(def always (constantly true))
-
(defmacro mk-rule
[test & actions]
`(fn [record#]
(if (~test record#)
- ((~record-action ~@actions) record#)
+ ((~record-actions ~@actions) record#)
record#)))
(defmacro mk-chain
@@ -77,63 +57,35 @@
[name & rules]
`(def ~name (mk-chain ~@rules)))
+(def always (constantly true))
+
+(defn matches [keyword pattern]
+ (fn [record]
+ (and (contains? record keyword)
+ (re-matches pattern (get record keyword)))))
+
+(defn matches-any [keyword & patterns]
+ (fn [record]
+ (let [v (get record keyword)]
+ (some (fn [pattern] (re-matches pattern v)) patterns))))
+
+(defchain dining
+ [(matches-any :desc
+ #"(?i)chipotle.*"
+ #"(?i)tappo- location.*")
+ :set :account2 "expenses:dining"])
+
(defchain default
- ;; Set default account
[always :set :account2 "expenses:unknown"]
+ [always dining]
+
[(matches :desc #"(?i)key food.*")
- :set :desc "Key Foods"]
+ :set :desc "Key Foods"
+ :set :account2 "expenses:groceries"]
[(matches :desc #"(?i)google \*cloud")
- :set :account2 "expenses:services"]
- )
-
-;; (defmacro matches
-;; [keyword pattern]
-;; `(wrap-matcher
-;; (let [v# (~'get ~keyword)]
-;; (and v# (re-matches ~pattern (~'get ~keyword))))))
-
-;; (defmacro defchain
-;; ([] identity)
-
-;; ([[pred & arg]]
-;; (let [expr2
-;; (if (= :do (first arg))
-;; `((wrap-matcher ~@(rest arg)))
-;; arg)]
-;; `(fn [record#]
-;; (if (~pred record#)
-;; (~@expr2 record#)
-;; record#))))
-
-;; ([x & next]
-;; `(fn [record#]
-;; ((defchain ~@next)
-;; ((defchain ~x) record#)))))
-
-;; (def always (constantly true))
-
-;; (def other-rules
-;; (defchain
-;; [(matches :desc #"Amazon.com.*")
-;; :do (set :desc "Amazon purchase")]))
-
-;; (def my-rules
-;; (defchain
-;; [always :do (set :account2 "expenses:unknown")]
-
-;; [(matches :desc #"(?i)key food.*")
-;; :do
-;; (set :desc "Key Foods")
-;; (set :account2 "expenses:groceries")]
-
-;; [(matches :desc #"(?i)google \*cloud")
-;; :do
-;; (set :desc "Google Cloud")
-;; (set :account2 "expenses:services")]
-
-;; [always other-rules]))
+ :set :account2 "expenses:services"])
(defn handle-record [row]
(let [record (mk-mapping row :date :postdate :desc :category :type :amount :memo)]