From ec472e2e01b2e65aba06b28f235027842794bb38 Mon Sep 17 00:00:00 2001 From: Sebastian Andersen <5475129+lambdank@users.noreply.github.com> Date: Sun, 16 Jun 2024 14:55:50 +0200 Subject: [PATCH] Created :thread rule and handled idx and :even/:odd --- cljfmt/resources/cljfmt/indents/clojure.clj | 8 ++- cljfmt/src/cljfmt/core.cljc | 52 +++++++++++----- cljfmt/test/cljfmt/core_test.cljc | 69 ++++++++++++--------- 3 files changed, 81 insertions(+), 48 deletions(-) diff --git a/cljfmt/resources/cljfmt/indents/clojure.clj b/cljfmt/resources/cljfmt/indents/clojure.clj index aee9cc56..1279594e 100644 --- a/cljfmt/resources/cljfmt/indents/clojure.clj +++ b/cljfmt/resources/cljfmt/indents/clojure.clj @@ -1,7 +1,8 @@ -{alt! [[:block 0]] +{-> [[:thread] [:block 0]] + alt! [[:block 0]] alt!! [[:block 0]] are [[:block 2]] - as-> [[:block 2]] + as-> [[:thread] [:block 2]] binding [[:block 1]] bound-fn [[:inner 0]] case [[:block 1]] @@ -9,7 +10,7 @@ comment [[:block 0]] cond [[:block 0]] condp [[:block 2]] - cond-> [[:block 1]] + cond-> [[:thread :odd] [:block 1]] cond->> [[:block 1]] def [[:inner 0]] defmacro [[:inner 0]] @@ -50,6 +51,7 @@ ns [[:block 1]] proxy [[:block 2] [:inner 1]] reify [[:inner 0] [:inner 1]] + some-> [[:thread] [:block 0]] struct-map [[:block 1]] testing [[:block 1]] thread [[:block 0]] diff --git a/cljfmt/src/cljfmt/core.cljc b/cljfmt/src/cljfmt/core.cljc index 5586eab9..4d48f161 100644 --- a/cljfmt/src/cljfmt/core.cljc +++ b/cljfmt/src/cljfmt/core.cljc @@ -275,28 +275,39 @@ (symbol? key) (= key sym) (pattern? key) (re-find key (str sym))))) -(defn form-matches-key? [zloc key context] +(defn- form-symbol-matches? [zloc pred context] (let [possible-sym (form-symbol zloc)] - (or (symbol-matches-key? (fully-qualified-symbol possible-sym context) key) - (symbol-matches-key? (remove-namespace possible-sym) key)))) + (or (pred (fully-qualified-symbol possible-sym context)) + (pred (remove-namespace possible-sym))))) + +(defn- form-matches-key? [zloc key context] + (form-symbol-matches? zloc #(symbol-matches-key? % key) context)) (defn- form-matches-thread-macro? [zloc context] - (let [possible-sym (form-symbol zloc) - fully-qualified-sym (fully-qualified-symbol possible-sym context) - sym-without-namespace (remove-namespace possible-sym)] - (some #(or (symbol-matches-key? fully-qualified-sym %) - (symbol-matches-key? sym-without-namespace %)) - #{'-> 'as-> 'some-> 'cond->}))) + (form-symbol-matches? zloc (:threads context) context)) -(defn- first-argument? [zloc] - (= (z/right (z/leftmost zloc)) zloc)) +(defn- get-zipper-position [zloc] + (loop [idx 0 + loop-zloc (z/leftmost zloc)] + (cond + (= zloc loop-zloc) idx + (= loop-zloc (z/rightmost zloc)) nil + :else (recur (inc idx) (z/right loop-zloc))))) (defn- in-thread-macro? [zloc context] - (and (form-matches-thread-macro? zloc context) (not (first-argument? zloc)))) + (when (= zloc (z/root zloc)) + (when-some [idx (form-matches-thread-macro? zloc context)] + (let [position (cond-> (get-zipper-position (z/up zloc)) + (in-thread-macro? (z/up (z/up zloc)) context) inc)] + (cond + (< position 2) false + (= idx :odd) (odd? position) + (= idx :even) (even? position) + :else (<= idx position)))))) (defn- inner-indent [zloc key depth idx context] (let [top (nth (iterate z/up zloc) depth) - adjusted-idx (cond-> idx (in-thread-macro? (z/up top) context) (some-> dec))] + adjusted-idx (cond-> idx (in-thread-macro? zloc context) (some-> dec))] (when (and (form-matches-key? top key context) (or (nil? idx) (index-matches-top-argument? zloc depth adjusted-idx))) (let [zup (z/up zloc)] @@ -317,7 +328,7 @@ (defn- block-indent [zloc key idx context] (when (form-matches-key? zloc key context) - (let [adjusted-idx (cond-> idx (in-thread-macro? (z/up zloc) context) (some-> dec (max 0))) + (let [adjusted-idx (cond-> idx (in-thread-macro? zloc context) (some-> dec (max 0))) zloc-after-idx (some-> zloc (nth-form (inc adjusted-idx)))] (if (and (or (nil? zloc-after-idx) (first-form-in-line? zloc-after-idx)) (> (index-of zloc) adjusted-idx)) @@ -352,6 +363,9 @@ (defmethod indenter-fn :block [sym context [_ idx]] (fn [zloc] (block-indent zloc sym idx context))) +(defmethod indenter-fn :thread [_ _ _] + (constantly nil)) + (defn- make-indenter [[key opts] context] (apply some-fn (map (partial indenter-fn key context) opts))) @@ -388,6 +402,13 @@ (defn- find-namespace [zloc] (some-> zloc root z/down (z/find z/right ns-form?) z/down z/next z/sexpr)) +(defn- get-thread-indents [indents] + (->> indents + (keep (fn [[k v]] + (when-first [[_ idx] (filter (fn [[rule]] (= rule :thread)) v)] + [k (or idx 2)]))) + (into {}))) + (defn indent ([form] (indent form default-indents {})) @@ -400,7 +421,8 @@ sorted-indents (sort-by indent-order indents) context (merge (select-keys opts [:function-arguments-indentation]) {:alias-map alias-map - :ns-name ns-name})] + :ns-name ns-name + :threads (get-thread-indents indents)})] (transform form edit-all should-indent? #(indent-line % sorted-indents context))))) diff --git a/cljfmt/test/cljfmt/core_test.cljc b/cljfmt/test/cljfmt/core_test.cljc index 1ec1b48b..81518260 100644 --- a/cljfmt/test/cljfmt/core_test.cljc +++ b/cljfmt/test/cljfmt/core_test.cljc @@ -692,39 +692,48 @@ ["#:clj {:a :b" ":c :d}"] ["#:clj {:a :b" - " :c :d}"]))) + " :c :d}"]))) (testing "thread first" (is (reformats-to? - ["(-> v" - "(cond->" - "a b" - "c d))"] - ["(-> v" - " (cond->" - " a b" - " c d))"])) - (is (reformats-to? - ["(cond-> v" - "a b" - "c d)"] - ["(cond-> v" - " a b" - " c d)"])) - (is (reformats-to? - ["(-> v" - "(cond-> a b" - "c d))"] - ["(-> v" - " (cond-> a b" - " c d))"])) - (is (reformats-to? - ["(-> (cond-> a" - "odd? inc)" - "inc)"] - ["(-> (cond-> a" - " odd? inc)" - " inc)"])))) + ["(-> v" + "(cond-> a b" + "c d))"] + ["(-> v" + " (cond-> a b" + " c d))"])) + (is (reformats-to? + ["(cond-> v" + "a b" + "c d)"] + ["(cond-> v" + " a b" + " c d)"])) + (is (reformats-to? + ["(-> v" + "(cond-> a b" + "c d))"] + ["(-> v" + " (cond-> a b" + " c d))"])) + (is (reformats-to? + ["(-> (cond-> a" + "odd? inc)" + "inc)"] + ["(-> (cond-> a" + " odd? inc)" + " inc)"])) + (is (reformats-to? + ["(cond-> a" + "(cond-> 1 + odd? inc) + (cond-> a b + c d))"] + ["(cond-> a" + " (cond-> 1" + " odd? inc)" + " (cond-> a b" + " c d))"])))) (deftest test-remove-multiple-non-indenting-spaces (let [opts {:remove-multiple-non-indenting-spaces? true}]