This is a handy bit of code I've written more than once. I thought I'd throw it in here so I can refer back to it later. Basically, it lets you read a config file to produce a Clojure map. The config files themselves can contain one or more forms, each of which can be either a map or a list. Maps are simply merged. Lists correspond to invocations of extension points, which in turn produces a map, which is merged along with everything else.
Consider the following files:
names.edn
{:first-name "Craig"
:middle-name "Bert"}
;; Comments are ignored - cool!
{:last-name "Andera"
:middle-name "Alan"} ; Later entries override earlier ones
addresses.edn
{:real-world {:city "Fairfax" :state "VA"}
:email "[email protected]"}
craig.edn
(include "names.edn")
(include "addresses.edn")
{:favorites {:colors [:red :black]}}
Calling (read-config "/path/to/craig.edn")
would produce the following map:
{:first-name "Craig"
:last-name "Andera"
:middle-name "Alan"}
:real-world {:city "Fairfax" :state "VA"}
:email "[email protected]"
:favorites {:colors [:red :black]}}
Note that you can use relative or absolute pathnames in the (include ...
calls, and they'll be resolved relative to the file they appear in
This is simpler (and passes every test case I've thought of to throw at it)