From dddf0a504d88a9cc80b78e57b4b50d66fc0ac000 Mon Sep 17 00:00:00 2001 From: Nick Juszczak Date: Wed, 21 Feb 2024 17:33:21 -0600 Subject: [PATCH] add :extra-configs option, pull in additional :extra-indents Allows pulling in :extra-indents from other configs. extra-configs are respected in order listed, so later configs overwrite earlier ones. :extra-indents in the base config override everything, allowing users to overrule indents pulled in that they don't agree with. :extra-configs file paths are expected to be relative to the base config. --- .gitignore | 2 ++ README.md | 10 +++++++ cljfmt/project.clj | 3 +- cljfmt/src/cljfmt/config.clj | 28 +++++++++++++++++++ cljfmt/test/cljfmt/config_test.clj | 25 ++++++++++++++++- cljfmt/test_resources/config_test/cljfmt.edn | 4 +++ .../config_test/empty-cljfmt.edn | 1 + .../config_test/extra1-cljfmt.edn | 11 ++++++++ .../config_test/extra2-cljfmt.edn | 7 +++++ .../config_test/recursive-cljfmt.edn | 1 + 10 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 cljfmt/test_resources/config_test/cljfmt.edn create mode 100644 cljfmt/test_resources/config_test/empty-cljfmt.edn create mode 100644 cljfmt/test_resources/config_test/extra1-cljfmt.edn create mode 100644 cljfmt/test_resources/config_test/extra2-cljfmt.edn create mode 100644 cljfmt/test_resources/config_test/recursive-cljfmt.edn diff --git a/.gitignore b/.gitignore index 4c40234..a01a3da 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ pom.xml.asc .nrepl-port reports .cpcache +.clj-kondo +.lsp diff --git a/README.md b/README.md index 00031eb..34b154f 100644 --- a/README.md +++ b/README.md @@ -284,6 +284,16 @@ In order to load the standard configuration file from Leiningen, add the Paths can also be passed as command line arguments. If the path is `-`, then the input is STDIN, and the output STDOUT. +* `:extra-configs` - + additional config files that will also be imported and merged into + the base configuration. Is not recursive, so `:extra-configs` in + imported configs will not be respected. + + File paths are expected to be relative paths from the base config file. + + Only certain keys from other configs will be respected: + * `:extra-indents` + ## License Copyright © 2023 James Reeves diff --git a/cljfmt/project.clj b/cljfmt/project.clj index f9c0be7..77d7d7e 100644 --- a/cljfmt/project.clj +++ b/cljfmt/project.clj @@ -44,4 +44,5 @@ :opts ["--static" "--libc=musl" "-H:CCompilerOption=-Wl,-z,stack-size=2097152"]}} - :provided {:dependencies [[org.clojure/clojurescript "1.11.60"]]}}) + :provided {:dependencies [[org.clojure/clojurescript "1.11.60"]]} + :dev {:resource-paths ["test_resources"]}}) diff --git a/cljfmt/src/cljfmt/config.clj b/cljfmt/src/cljfmt/config.clj index dfcb60a..3ef766e 100644 --- a/cljfmt/src/cljfmt/config.clj +++ b/cljfmt/src/cljfmt/config.clj @@ -59,6 +59,33 @@ (defn- directory? [path] (some-> path io/file .getAbsoluteFile .isDirectory)) +(def ^:private extra-config-respected-keys [:extra-indents]) + +(defn- merge-keys + [init coll ks] + (reduce (fn [acc k] + (update acc k merge (get coll k))) + init ks)) + +(defn- merge-extra-configs + [path config] + (let [base-dir (-> path io/file ((fn [^java.io.File f] (.getParent f))))] + ;; extra-configs later in the list override earlier ones. + (loop [confs (mapv #(io/file base-dir %) (:extra-configs config)) + econf {}] + (if (empty? confs) + ;; A little confusing but: We're merging the base config's + ;; values into the extra-configs, and then back into the base + ;; config, so we allow the base config to have the final say. + (merge config (merge-keys econf config extra-config-respected-keys)) + (let [;; Only merging select values from other configs. + xtra (-> confs first read-config + (select-keys extra-config-respected-keys))] + (recur (rest confs) ;;(merge econf xtra) + (reduce-kv (fn [acc k v] + (update acc k merge v)) + econf xtra))))))) + (defn load-config "Load a configuration merged with a map of sensible defaults. May take an path to a config file, or to a directory to search. If no argument @@ -70,4 +97,5 @@ path)] (->> (some-> path read-config) (merge default-config) + (merge-extra-configs path) (convert-legacy-keys))))) diff --git a/cljfmt/test/cljfmt/config_test.clj b/cljfmt/test/cljfmt/config_test.clj index 323c299..37f351e 100644 --- a/cljfmt/test/cljfmt/config_test.clj +++ b/cljfmt/test/cljfmt/config_test.clj @@ -1,6 +1,7 @@ (ns cljfmt.config-test (:require [cljfmt.config :as config] - [clojure.test :refer [deftest is]])) + [clojure.test :refer [deftest is testing]] + [clojure.java.io :as io])) (deftest test-convert-legacy-keys (is (= {:indents {'foo [[:inner 0]]}} @@ -8,3 +9,25 @@ (is (= {:extra-indents {'foo [[:inner 0]]}} (config/convert-legacy-keys {:legacy/merge-indents? true :indents {'foo [[:inner 0]]}})))) + +(deftest test-load-config-extra-configs + (testing ":extra-configs allows you to import :extra-indents" + (is (= (config/load-config (io/resource "config_test/empty-cljfmt.edn")) + (-> (config/load-config (io/resource "config_test/cljfmt.edn")) + (dissoc :extra-configs) + (assoc :extra-indents {}))) + (str "should only differ by `:extra-indents` (via :extra-configs)." + " All other keys are ignored.")) + (is (= '{;; exists only in base config `test_resources/cljfmt.edn` + com.unrelated/a [[:inner 0]] + com.foo/a [[:inner 0]], + ;; exists only in `test_resources/extra1-cljfmt.edn` + com.foo/b [[:inner 1]], + ;; overwritten in `test_resources/extra2-cljfmt.edn` + com.foo/c [[:inner 2]], + com.foo/d [[:inner 2]], + ;; exists only in `test_resources/extra2-cljfmt.edn` + com.foo/e [[:inner 2]]} + (:extra-indents (config/load-config (io/resource "config_test/cljfmt.edn")))) + (str "should respect :extra-configs in order (later is higher-prio)," + " with base highest prio.")))) diff --git a/cljfmt/test_resources/config_test/cljfmt.edn b/cljfmt/test_resources/config_test/cljfmt.edn new file mode 100644 index 0000000..3e8b67c --- /dev/null +++ b/cljfmt/test_resources/config_test/cljfmt.edn @@ -0,0 +1,4 @@ +{:extra-indents {com.foo/a [[:inner 0]] + com.unrelated/a [[:inner 0]]} + :extra-configs ["extra1-cljfmt.edn" + "extra2-cljfmt.edn"]} diff --git a/cljfmt/test_resources/config_test/empty-cljfmt.edn b/cljfmt/test_resources/config_test/empty-cljfmt.edn new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/cljfmt/test_resources/config_test/empty-cljfmt.edn @@ -0,0 +1 @@ +{} diff --git a/cljfmt/test_resources/config_test/extra1-cljfmt.edn b/cljfmt/test_resources/config_test/extra1-cljfmt.edn new file mode 100644 index 0000000..75a6430 --- /dev/null +++ b/cljfmt/test_resources/config_test/extra1-cljfmt.edn @@ -0,0 +1,11 @@ +{:parallel? true + :paths ["x"] + :sort-ns-references? true + :extra-indents {;; exists in base + com.foo/a [[:inner 1]] + ;; not included in later config + com.foo/b [[:inner 1]] + ;; overridden in later configs + com.foo/c [[:inner 1]] + com.foo/d [[:inner 1]]} + :extra-configs []} diff --git a/cljfmt/test_resources/config_test/extra2-cljfmt.edn b/cljfmt/test_resources/config_test/extra2-cljfmt.edn new file mode 100644 index 0000000..c884570 --- /dev/null +++ b/cljfmt/test_resources/config_test/extra2-cljfmt.edn @@ -0,0 +1,7 @@ +{:parallel? false + :paths ["y"] + :sort-ns-references? false + :extra-indents {com.foo/c [[:inner 2]] + com.foo/d [[:inner 2]] + com.foo/e [[:inner 2]]} + :extra-configs []} diff --git a/cljfmt/test_resources/config_test/recursive-cljfmt.edn b/cljfmt/test_resources/config_test/recursive-cljfmt.edn new file mode 100644 index 0000000..6141de2 --- /dev/null +++ b/cljfmt/test_resources/config_test/recursive-cljfmt.edn @@ -0,0 +1 @@ +{:extra-configs ["config.edn"]}