Skip to content

Commit

Permalink
add :extra-configs option, pull in additional :extra-indents
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
juszczakn authored and Nick committed Mar 3, 2024
1 parent f3ba8d4 commit a9570e9
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ pom.xml.asc
.nrepl-port
reports
.cpcache
.clj-kondo
.lsp
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion cljfmt/project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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"]}})
46 changes: 43 additions & 3 deletions cljfmt/src/cljfmt/config.clj
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,48 @@
(defn- directory? [path]
(some-> path io/file .getAbsoluteFile .isDirectory))

(defn- deep-merge
"Recursively merges maps together. If all the maps supplied have nested maps
under the same keys, these nested maps are merged. Otherwise the value is
overwritten, as in `clojure.core/merge`."
{:arglists '([& maps])
:added "1.1.0"}
([])
([a] a)
([a b]
(when (or a b)
(letfn [(merge-entry [m e]
(let [k (key e)
v' (val e)]
(if (contains? m k)
(assoc m k (let [v (get m k)]
(if (and (map? v) (map? v'))
(deep-merge v v')
v')))
(assoc m k v'))))]
(reduce merge-entry (or a {}) (seq b)))))
([a b & more]
(reduce deep-merge (or a {}) (cons b more))))

(defn- load-extra-configs
"Load any :extra-configs specified in the base config file.
Notes:
* Not recursive.
* Only select keys are merged (`:extra-indents`)."
[path]
(let [conf (read-config path)
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 conf))
econf {}]
(if (empty? confs)
(->> (deep-merge econf conf)
(merge default-config)
(convert-legacy-keys))
(let [;; Only merging select values from other configs.
xtra (-> confs first read-config (select-keys [:extra-indents]))]
(recur (rest confs) (deep-merge 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
Expand All @@ -68,6 +110,4 @@
(let [path (if (directory? path)
(find-config-file path)
path)]
(->> (some-> path read-config)
(merge default-config)
(convert-legacy-keys)))))
(load-extra-configs path))))
24 changes: 23 additions & 1 deletion cljfmt/test/cljfmt/config_test.clj
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
(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])
(:import (java.io File)))

(deftest test-convert-legacy-keys
(is (= {:indents {'foo [[:inner 0]]}}
(config/convert-legacy-keys {:indents {'foo [[:inner 0]]}})))
(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 "empty-cljfmt.edn"))
(-> (config/load-config (io/resource "cljfmt.edn"))
(dissoc :extra-configs)
(assoc :extra-indents {})))
"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 "cljfmt.edn"))))
"should respect :extra-configs in order (later is higher-prio), with base highest prio.")))
4 changes: 4 additions & 0 deletions cljfmt/test_resources/cljfmt.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{:extra-indents {com.foo/a [[:inner 0]]
com.unrelated/a [[:inner 0]]}
:extra-configs ["extra1-cljfmt.edn"
"extra2-cljfmt.edn"]}
1 change: 1 addition & 0 deletions cljfmt/test_resources/empty-cljfmt.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
11 changes: 11 additions & 0 deletions cljfmt/test_resources/extra1-cljfmt.edn
Original file line number Diff line number Diff line change
@@ -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 []}
7 changes: 7 additions & 0 deletions cljfmt/test_resources/extra2-cljfmt.edn
Original file line number Diff line number Diff line change
@@ -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 []}
1 change: 1 addition & 0 deletions cljfmt/test_resources/recursive-cljfmt.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{:extra-configs ["config.edn"]}

0 comments on commit a9570e9

Please sign in to comment.