From 8f75d757356ed386899fe6fffa422311532e38aa Mon Sep 17 00:00:00 2001 From: Kjetil Orbekk Date: Wed, 7 Jul 2021 08:20:17 -0400 Subject: redo-matchers --- clojure/src/csvtool/core.clj | 153 +++++++++++++++++++++++++++++-------------- 1 file changed, 104 insertions(+), 49 deletions(-) (limited to 'clojure/src') 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] -- cgit v1.2.3