I posted related taxonomy here:
(1) Stringly typed: .ini, YAML
(2) Typed Data: JSON, XML to some extent, SDLang
(3) Programmable configuration: HCL, Cue, Jsonnet, Nix expressions, BCL, Starlark, Oil
SDLang looks really similar to HCL too, except HCL is programmable:
Very important: With categories 1 and 2, people add template languages like Go templates on top to solve the programmability problem, which we don’t want!!! We don’t want to move typed data back to the stringly typed realm!
I’m still undecided whether ordering is a good thing or isn’t as good as it may seem to be.
In soupault I went for TOML because it’s generally the least annoying to write by hand, of all widely used configuration languages.
The moment when ordering issues came into play was when I wanted to add a way to sequence HTML processing steps so that the output of one widget/plugin can become the input of another. If TOML was ordered, I would have likely used its “natural” ordering because it would be easy to do.
However, it would make the user re-arrange chunks of the config to change the ordering. I went for an option after = "some-widget", but then I realized that if I need topological sort anyway now, I can as well allow multiple dependencies, like after = ["some-widget", "another-widget"]. That does have a potential for making messy dependency graphs, but at least it’s explicit (and there’s a way to see the computed order in the debug log). An ordered format could lead to messy and implicit dependencies. What I’ve done is explicit at least.
after = "some-widget"
after = ["some-widget", "another-widget"]
Tree Notation can support named or unnamed, ordered or unordered, and all combinations thereof.
It is a great lower level notation to build higher configuration languages on top of.