summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjetil Orbekk <kj@orbekk.com>2021-07-07 08:20:17 -0400
committerKjetil Orbekk <kj@orbekk.com>2021-07-07 08:20:17 -0400
commit8f75d757356ed386899fe6fffa422311532e38aa (patch)
treeb975068e8e2662d5003c8825a6535a875fdb7c44
parentcac05c040cfa42440f73eea2c1e4c645a40c9363 (diff)
redo-matchers
-rw-r--r--clojure/src/csvtool/core.clj153
1 files changed, 104 insertions, 49 deletions
diff --git a/clojure/src/csvtool/core.clj b/clojure/src/csvtool/core.clj
index a881ad8..8a061c8 100644
--- a/clojure/src/csvtool/core.clj
+++ b/clojure/src/csvtool/core.clj
@@ -9,16 +9,16 @@
(->> (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-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"]])))
+;; (defn my-write []
+;; (with-open [writer (io/writer "out-file.csv")]
+;; (csv/write-csv writer
+;; [["abc" "def"]
+;; ["ghi" "jkl"]])))
(defmacro wrap-matcher
([] identity)
@@ -33,56 +33,111 @@
`(fn [record#]
((wrap-matcher ~@next) ((wrap-matcher ~expr) record#)))))
-(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#)))))
+(defn record-action [name & rest]
+ (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)))))
+
+(defn record-test [keyword pred]
+ (fn [record]
+ (if (contains? record keyword)
+ (pred (get record keyword))
+ nil)))
+
+(defn matches [keyword pattern]
+ (fn [record]
+ (re-matches pattern (get record keyword))))
(def always (constantly true))
-(def other-rules
- (defchain
- [(matches :desc #"Amazon.com.*")
- :do (set :desc "Amazon purchase")]))
+(defmacro mk-rule
+ [test & actions]
+ `(fn [record#]
+ (if (~test record#)
+ ((~record-action ~@actions) record#)
+ record#)))
-(def my-rules
- (defchain
- [always :do (set :account2 "expenses:unknown")]
+(defmacro mk-chain
+ ([] identity)
- [(matches :desc #"(?i)key food.*")
- :do
- (set :desc "Key Foods")
- (set :account2 "expenses:groceries")]
+ ([rule]
+ `(mk-rule ~@rule))
- [(matches :desc #"(?i)google \*cloud")
- :do
- (set :desc "Google Cloud")
- (set :account2 "expenses:services")]
+ ([rule & next]
+ `(fn [record#]
+ ((mk-chain ~@next)
+ ((mk-chain ~rule) record#)))))
- [always other-rules]))
+(defmacro defchain
+ [name & rules]
+ `(def ~name (mk-chain ~@rules)))
+
+(defchain default
+ ;; Set default account
+ [always :set :account2 "expenses:unknown"]
+
+ [(matches :desc #"(?i)key food.*")
+ :set :desc "Key Foods"]
+
+ [(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]))
(defn handle-record [row]
(let [record (mk-mapping row :date :postdate :desc :category :type :amount :memo)]
- (my-rules record)
+ (default record)
))
(defn process-file [path]