浏览代码

applied code formatting

Brandon Wong 3 周之前
父节点
当前提交
46abed816b

+ 3 - 5
frontend/src/cljs/microtables_frontend/core.cljs

@@ -1,12 +1,10 @@
 (ns microtables-frontend.core
   (:require
-   [reagent.core :as reagent]
-   [re-frame.core :as re-frame]
+   [microtables-frontend.config :as config]
    [microtables-frontend.events :as events]
    [microtables-frontend.views :as views]
-   [microtables-frontend.config :as config]))
-
-
+   [re-frame.core :as re-frame]
+   [reagent.core :as reagent]))
 
 (defn dev-setup []
   (when config/debug?

+ 1 - 2
frontend/src/cljs/microtables_frontend/db.cljs

@@ -1,8 +1,7 @@
 (ns microtables-frontend.db)
 
 (def default-db
-  {
-   :controls nil
+  {:controls nil
    ;TODO: add "start" and "end" corners as selection
    :position {:cursor nil
               :selection nil #_{:start {:col "A" :row 5}

+ 42 - 45
frontend/src/cljs/microtables_frontend/events.cljs

@@ -1,72 +1,69 @@
 (ns microtables-frontend.events
   (:require
-   [re-frame.core :as re-frame]
    [microtables-frontend.db :as db]
-   [microtables-frontend.utils :as utils]))
-
-
-
+   [microtables-frontend.utils :as utils]
+   [re-frame.core :as re-frame]))
 
 (re-frame/reg-event-db
  ::initialize-db
  (fn [_ _]
    (println "initializing db")
    (-> db/default-db
-       (update-in [:table-data] #(utils/walk-modify-data % (fn [c r datum] (if (= (first (:value datum)) "=") (assoc datum :dirty true) datum))))
+       (update-in [:table-data] #(utils/walk-modify-data
+                                  %
+                                  (fn [_c _r datum]
+                                    (if (= (first (:value datum)) "=")
+                                      (assoc datum :dirty true)
+                                      datum))))
        (update-in [:table-data] utils/create-all-references)
        (update-in [:table-data] utils/create-all-back-references)
        (update-in [:table-data] utils/evaluate-all))))
 
-
 (re-frame/reg-event-db
-  ::movement-enter-cell
-  (fn [db [_ c r]]
-    (println "::movement-enter-cell" c r)
-    (assoc-in db [:position :cursor] {:col c :row r})))
-
-
+ ::movement-enter-cell
+ (fn [db [_ c r]]
+   (println "::movement-enter-cell" c r)
+   (assoc-in db [:position :cursor] {:col c :row r})))
 
 (re-frame/reg-event-db
-  ::movement-leave-cell
-  (fn [db [_ c r]]
-    (println "::movement-leave-cell" c r)
-    (-> db
-        (assoc-in [:position :cursor] nil)
-        (assoc-in [:position :selection] nil)
-        (update-in [:table-data] #(utils/reset-references % c r))
-        (update-in [:table-data] #(utils/evaluate-from-cell % c r)))))
-
+ ::movement-leave-cell
+ (fn [db [_ c r]]
+   (println "::movement-leave-cell" c r)
+   (-> db
+       (assoc-in [:position :cursor] nil)
+       (assoc-in [:position :selection] nil)
+       (update-in [:table-data] #(utils/reset-references % c r))
+       (update-in [:table-data] #(utils/evaluate-from-cell % c r)))))
 
 (re-frame/reg-event-db
-  ::edit-cell-value
-  (fn [db [_ c r value]]
-    (println "::edit-cell-value" c r value)
-    (update-in db [:table-data] #(utils/change-datum-value % c r value))))
+ ::edit-cell-value
+ (fn [db [_ c r value]]
+   (println "::edit-cell-value" c r value)
+   (update-in db [:table-data] #(utils/change-datum-value % c r value))))
 
 ; handle pressing enter (move to the next cell down)
 ; tab is taken care of natively, and is good enough
 (re-frame/reg-event-fx
-  ::press-enter-in-cell
-  (fn [{:keys [db]} [_ c r]]
-    (let [max-row? (= (utils/highest-row (:table-data db)) r)
-          max-col? (= (utils/highest-col (:table-data db)) c)
-          new-col (if max-row?
-                    (if max-col?
-                      "A"
-                      (utils/next-letter c))
-                    c)
-          new-row (if max-row?
-                    1
-                    (inc r))]
-      (println "::press-enter-in-cell" c r)
-      {:focus-on-cell [new-col new-row]})))
+ ::press-enter-in-cell
+ (fn [{:keys [db]} [_ c r]]
+   (let [max-row? (= (utils/highest-row (:table-data db)) r)
+         max-col? (= (utils/highest-col (:table-data db)) c)
+         new-col (if max-row?
+                   (if max-col?
+                     "A"
+                     (utils/next-letter c))
+                   c)
+         new-row (if max-row?
+                   1
+                   (inc r))]
+     (println "::press-enter-in-cell" c r)
+     {:focus-on-cell [new-col new-row]})))
 
 (re-frame/reg-fx
-  :focus-on-cell
-  (fn [[c r]]
-    (println "fx for :press-enter" c r)
-    (.focus (.getElementById js/document (str c r)))))
-
+ :focus-on-cell
+ (fn [[c r]]
+   (println "fx for :press-enter" c r)
+   (.focus (.getElementById js/document (str c r)))))
 
 (re-frame/reg-event-db
  ::set-controls-state

+ 16 - 16
frontend/src/cljs/microtables_frontend/subs.cljs

@@ -1,13 +1,13 @@
 (ns microtables-frontend.subs
   (:require
-   [re-frame.core :as re-frame]
-   [microtables-frontend.utils :as utils]))
+   [microtables-frontend.utils :as utils]
+   [re-frame.core :as re-frame]))
 
 (re-frame/reg-sub
  ::controls-state
  (fn [db]
-  (println "reporting state of controls")
-  (:controls db)))
+   (println "reporting state of controls")
+   (:controls db)))
 
 (defn highlight-cells
   "Modify all cells in data (set :view to :highlighted) that are within the given range."
@@ -27,17 +27,17 @@
 
 ;TODO: insert other display mode data? ("value": formula (cursor), "display" (default): evaluated, "highlighted": in a selection (just a class?))
 (re-frame/reg-sub
-  ::table-data
-  (fn [db]
-    (println "returning table data")
-    (let [data (:table-data db)
-          cursor (get-in db [:position :cursor])
-          selection (get-in db [:position :selection])
-          highlighted (if selection
-                        (highlight-cells data selection)
-                        data)]
-      (if cursor
-        (assoc-in highlighted [(:col cursor) (:row cursor) :view] :value)
-        highlighted))))
+ ::table-data
+ (fn [db]
+   (println "returning table data")
+   (let [data (:table-data db)
+         cursor (get-in db [:position :cursor])
+         selection (get-in db [:position :selection])
+         highlighted (if selection
+                       (highlight-cells data selection)
+                       data)]
+     (if cursor
+       (assoc-in highlighted [(:col cursor) (:row cursor) :view] :value)
+       highlighted))))
 
 

+ 75 - 54
frontend/src/cljs/microtables_frontend/utils.cljs

@@ -1,25 +1,33 @@
 (ns microtables-frontend.utils
   (:require
-   ["mathjs" :as mathjs]))
+   ["mathjs" :as mathjs]
+   [clojure.set :refer [intersection]]
+   [clojure.string :as string]))
 
 ; to add an npm package to shadow-cljs:
 ; https://clojureverse.org/t/guide-on-how-to-use-import-npm-modules-packages-in-clojurescript/2298
 ; https://shadow-cljs.github.io/docs/UsersGuide.html#npm
 
-
 (defn highest-col
   "Return the highest column (letter) for which there is a non-empty cell"
   [data]
   ; choose the "max" (alphabetical order) value among the longest keys
-  (apply max (val (apply max-key key (group-by #(.-length %) (keys data))))))
+  (->> data
+       keys
+       (group-by #(.-length %))
+       (apply max-key key)
+       val
+       (apply max)))
 
 (defn highest-row
   "Return the highest row (number) for which there is a non-empty cell"
   [data]
   ; get all the row keys from all the column objects (and flatten), then pick the max
-  (apply max (flatten (map keys (vals data)))))
-
-
+  (->> data
+       vals
+       (map keys)
+       flatten
+       (apply max)))
 
 (defn increment-letter-code [s]
   (let [l (last s)]
@@ -28,13 +36,15 @@
       (= l 90) (conj (increment-letter-code (subvec s 0 (dec (count s)))) 65)
       :else (conj (subvec s 0 (dec (count s))) (inc l)))))
 
-
 (defn next-letter [lc]
-  (apply str (map char (increment-letter-code (mapv #(.charCodeAt % 0) lc)))))
-
-
-(def col-letters (iterate next-letter "A"))
+  (->> lc
+       (mapv #(.charCodeAt % 0))
+       increment-letter-code
+       (map char)
+       (apply str)))
 
+(def col-letters
+  (iterate next-letter "A"))
 
 (defn order-two-cols
   "Accepts two column names (letters) and returns them in order."
@@ -52,8 +62,8 @@
         start-row (min row1 row2)
         end-row (max row1 row2)]
     (for [col (take-while #(not= (next-letter end-col) %) (iterate next-letter start-col))
-             row (range start-row (inc end-row))]
-         {:col col :row row})))
+          row (range start-row (inc end-row))]
+      {:col col :row row})))
 
 ; the order goes top to bottom, then left to right - that makes the most sense to me
 ; I don't know why a different order would be important, or even in what situation order is important at all
@@ -69,17 +79,19 @@
 (def range->commalist
   "Converts a range in \"A1:B2\" notation to a comma-separated list of cells: \"A1,A2,B1,B2\"."
   (memoize (fn [range-string]
-            (let [cell-list (parse-range range-string)
-                  strings (map #(str (:col %) (:row %)) cell-list)]
-             (str "(" (clojure.string/join "," strings) ")")))))
+             (let [cell-list (parse-range range-string)
+                   strings (map #(str (:col %) (:row %)) cell-list)]
+               (str "(" (string/join "," strings) ")")))))
 
 (def replace-ranges-in-expression
   "Receives an expression string, and replaces all ranges in colon notation (\"A1:B2\") into a comma-separated list of cells (\"A1,A2,B1,B2\")."
   (memoize (fn [expression]
-             (clojure.string/replace expression #"\(\s*[A-Z]+[0-9]+\s*:\s*[A-Z]+[0-9]+\s*\)" range->commalist))))
+             (string/replace expression #"\(\s*[A-Z]+[0-9]+\s*:\s*[A-Z]+[0-9]+\s*\)" range->commalist))))
 
 (defn formula?
-  "Determines if a value is a fomula. If it is, it returns it (without the leading equals sign. If not, it returns nil."
+  "Determines if a value is a fomula.
+  If it is, it returns it (without the leading equals sign).
+  If not, it returns nil."
   [value]
   (if (= (first value) "=")
     (subs value 1)
@@ -92,7 +104,6 @@
                                   (map #(.toUpperCase %) $)
                                   (filter #(re-matches #"[A-Z]+[0-9]+" %) $)))))
 
-
 (def str->rc (memoize (fn [s]
                         (let [c (re-find #"^[A-Z]+" s)
                               r (.parseInt js/window (re-find #"[0-9]+$" s))]
@@ -124,6 +135,7 @@
     (let [target (first refs)
           de-notified (update-in data [(:col target) (:row target) :inbound] (partial filter #(not= % origin)))]
       (recur de-notified origin (rest refs)))))
+
 (defn notify-references
   "Update references in all cells referenced by this cell"
   [data origin refs]
@@ -132,38 +144,45 @@
     (let [target (first refs)
           notified (update-in data [(:col target) (:row target) :inbound] conj origin)]
       (recur notified origin (rest refs)))))
+
 (defn create-all-references
-  "Starting from a clean slate, add in all references. This wipes any references that may have been present."
+  "Starting from a clean slate, add in all references.
+  This wipes any references that may have been present."
   [data]
   (reduce-kv
-    (fn [columns c curr-column]
-      (assoc columns c (reduce-kv
-                         (fn [rows r datum]
-                           (assoc rows r (add-references (dissoc (dissoc datum :refs) :inbound))))
-                         {}
-                         curr-column)))
-    {}
-    data))
+   (fn [columns c curr-column]
+     (assoc columns c (reduce-kv
+                       (fn [rows r datum]
+                         (assoc rows r (add-references (dissoc (dissoc datum :refs) :inbound))))
+                       {}
+                       curr-column)))
+   {}
+   data))
 
 ;TODO: re-write create-all-references to use walk-modify-data instead
 (defn walk-modify-data
   "Walks through the data map and updates each datum by applying f (a function accepting col, row, datum)."
   [data f]
   (reduce-kv
-    (fn [columns c curr-column]
-      (assoc columns c (reduce-kv
-                         (fn [rows r datum]
-                           (assoc rows r (f c r datum)))
-                         {}
-                         curr-column)))
-    {}
-    data))
-
+   (fn [columns c curr-column]
+     (assoc columns c (reduce-kv
+                       (fn [rows r datum]
+                         (assoc rows r (f c r datum)))
+                       {}
+                       curr-column)))
+   {}
+   data))
 
 (defn walk-get-refs
   "Walks through the data map and returns a list of :col/:row maps for each cell which satisfies the predicate (a function accepting col, row, datum)."
   [data pred]
-  (reduce-kv (fn [l c column] (concat l (map (fn [[r _]] {:col c :row r}) (filter (fn [[r datum]] (pred c r datum)) column)))) '() data))
+  (reduce-kv (fn [l c column]
+               (->> column
+                    (filter (fn [[r datum]] (pred c r datum)))
+                    (map (fn [[r _]] {:col c :row r}))
+                    (concat l)))
+             '()
+             data))
 
 ; proposed alternative (the beginning of one) to walk-get-refs
 ;(defn col-map? [m] (and (map? m) (every? #(and (string? %) (re-matches #"[A-Z]+" %)) (keys m))))
@@ -183,7 +202,8 @@
         (recur updated-one (rest formulas))))))
 
 (defn set-dirty-flags
-  "Sets the target cell to \"dirty\" and recursively repeat with its back-references all the way up. Returns the new data set."
+  "Sets the target cell to \"dirty\" and recursively repeat with its back-references all the way up.
+  Returns the new data set."
   ([data c r]
    (set-dirty-flags data (list {:col c :row r})))
   ([data queue]
@@ -199,7 +219,6 @@
                new-queue (concat (rest queue) (:inbound datum))]
            (recur new-data new-queue)))))))
 
-
 (defn change-datum-value
   "Modify the value of a datum in the table, and update all applicable references"
   [data c r value]
@@ -224,28 +243,29 @@
 (defn remove-valueless-range-elements
   "Remove nil values specifically from ranges (to solve issues with some functions like average)."
   [variables var-list]
-  (let [l (clojure.string/split (clojure.string/replace (first var-list) #"[()]" "") #",")
+  (let [l (string/split (string/replace (first var-list) #"[()]" "") #",")
         has-values (filter #(not (nil? (variables %))) l)]
-    (str "(" (clojure.string/join "," has-values) ")")))
-
-
+    (str "(" (string/join "," has-values) ")")))
 
 (defn preprocess-expression
   "Handle range cases, rename certain functions (to work with math.js), prepare expression and variables for processing."
   [expression variables]
-  (let [renamed-expression (clojure.string/replace expression #"\baverage\(" "mean(")
-        new-expression (clojure.string/replace renamed-expression #"\(([A-Z]+[0-9]+,)*[A-Z]+[0-9]+\)" (partial remove-valueless-range-elements variables))
+  (let [renamed-expression (string/replace expression #"\baverage\(" "mean(")
+        new-expression (string/replace renamed-expression
+                                       #"\(([A-Z]+[0-9]+,)*[A-Z]+[0-9]+\)"
+                                       (partial remove-valueless-range-elements variables))
         new-variables (reduce-kv #(assoc %1 %2 (if (nil? %3) "0" %3)) {} variables)]
     (println "PREPROCESS" {:expression new-expression :variables new-variables})
     {:expression new-expression
      :variables new-variables}))
 
-
 (def evaluate-expression
-  "Convert (via mathjs) an expression string to a final answer (also a string).  A map of variables must also be provided. If there is an error, it will return :calc-error."
+  "Convert (via mathjs) an expression string to a final answer (also a string).
+  A map of variables must also be provided. If there is an error, it will return :calc-error."
   (memoize (fn [expression variables]
              (let [range-replaced (replace-ranges-in-expression expression)
-                   {ready-expression :expression ready-variables :variables} (preprocess-expression range-replaced variables)]
+                   {ready-expression :expression
+                    ready-variables :variables} (preprocess-expression range-replaced variables)]
                (try
                  (.evaluate mathjs ready-expression (clj->js ready-variables))
                  (catch js/Error e
@@ -264,14 +284,15 @@
          current {:col c :row r}
          this-and-above (conj ancest current)
          inbound (:inbound datum)
-         found-repeat (not (empty? (clojure.set/intersection this-and-above (set inbound))))]
+         found-repeat (not (empty? (intersection this-and-above (set inbound))))]
      (if found-repeat
        :cycle-error
        (some #(find-cycle data (:col %) (:row %) this-and-above) inbound)))))
 
-
 (defn gather-variables-and-evaluate-cell
-  "Assumes that all the cell's immediate references have been resolved. Collects the final values from them, then evaluates the current cell's expression. Returns the new data map."
+  "Assumes that all the cell's immediate references have been resolved.
+  Collects the final values from them, then evaluates the current cell's expression.
+  Returns the new data map."
   [data c r]
   (let [datum (dissoc (dissoc (get-in data [c r]) :dirty) :display) ; get rid of the dirty flag right away (it must be included with the returned data to have effect)
         refs (:refs datum)
@@ -302,7 +323,6 @@
                   new-datum (assoc datum :display evaluated-value)]
               (assoc-in data [c r] new-datum)))))
 
-
 ; THE NEW EVALUATE FUNCTION
 ; - check for cycles in the back references, starting from the target cell (if any, use another function to mark it and its back references with :cycle-error and remove :dirty)
 ; - if any of the forward references are dirty, mark the cell (and recurse up) with an error (and set a TODO to think about this further)
@@ -341,7 +361,8 @@
 
 ;TODO: does this need a cycle check?
 (defn evaluate-all
-  "Evaluates all cells marked as \"dirty\". Generally reserved for the initialization."
+  "Evaluates all cells marked as \"dirty\".
+  Generally reserved for the initialization."
   ([data]
    (evaluate-all data (walk-get-refs data #(:dirty %3))))
   ([data queue]

+ 7 - 9
frontend/src/cljs/microtables_frontend/views.cljs

@@ -1,10 +1,9 @@
 (ns microtables-frontend.views
   (:require
-   [re-frame.core :as re-frame]
-   [microtables-frontend.subs :as subs]
    [microtables-frontend.events :as events]
-   [microtables-frontend.utils :as utils]))
-
+   [microtables-frontend.subs :as subs]
+   [microtables-frontend.utils :as utils]
+   [re-frame.core :as re-frame]))
 
 ;; TABLE COMPONENTS
 
@@ -31,8 +30,8 @@
 (defn header-row [cols]
   ^{:key "header"} [:tr
                     (cons
-                      ^{:key "corner"} [:th]
-                      (map (fn [c] ^{:key (str "col-head-" c)} [:th c]) cols))])
+                     ^{:key "corner"} [:th]
+                     (map (fn [c] ^{:key (str "col-head-" c)} [:th c]) cols))])
 
 (defn sheet [data]
   [:table
@@ -44,9 +43,8 @@
           maxcol "Z";(utils/highest-col data)
           cols (take-while (partial not= (utils/next-letter maxcol)) utils/col-letters)]
       (cons
-        (header-row cols)
-        (map #(row % cols data) (range 1 (inc maxrow)))))]])
-
+       (header-row cols)
+       (map #(row % cols data) (range 1 (inc maxrow)))))]])
 
 (defn extend-range
   []