KSON proudly claims "no whitespace sensitivity", which means "misleading indentation" is back. And it's pretty light on syntax, so there are going to be plenty of mistakes made here.
I actually prefer a syntax that is whitespace-sensitive, but should not give meaning to whitespace. That is, the whitespace should not perform a semantic duty, but should be required to be correct.
This is roughly equivalent to saying that a linter can transform the AST of the language into a canonical representation, and the syntax will be rejected unless it matches the canonical representation (modulo things like comments or whitespace-for-clarity).
This sounds like a stricter version of KSON's current warnings for misleading indentation... maybe KSON should have an opt-in feature for this. Thanks for the idea!
Hmmm that's interesting. KSON actually shows a warning when there's misleading indentation, exactly to prevent this sort of thing! It seems like the detection logic only considers indents after a new line, so it doesn't complain in this case. I just opened an issue to see if things can be tightened up a bit (https://github.com/kson-org/kson/issues/221).
To see misleading indentation warnings in action, you can try the following snippet in the playground (https://kson.org/playground/) and will properly get a warning:
ports:
- 80
- 8000
- 10000
- 12000
- 14000
Next to that, note that KSON already has an autoformatter, which also helps prevent misleading indentation in files.
Configuration files need to be powerful programming languages (in terms of expressiveness) while being restricted (in terms of network and I/O and non-determinism). We need to aim very high for configuration languages especially when we treat them like user interfaces. Look at Cue (https://cuelang.org/), Starlark or Dhall (https://dhall-lang.org/) for inspiration, not JSON, unless your configuration file is almost always written programmatically.
Any configuration language that doesn't support strict/user/explicit types is worthless (ahem jsonnet).
The idea of configuring something but not actually having any sort of assurances that what you're configuring is correct is maddening. Building software with nothing but hopes and dreams.
JSON5 is good enough that it works for frontend devs, backend, qa, firmware, data science, chemists, optical engineers, and the hardware team, in my org at least. Interns pick up on it quickly.
The comment option gives enough space for devs to explain new options flags and objects included to those familiar enough to be using it.
This is why Caddy has config adapters: bring any config file language you like, and Caddy will run it. It's built-into the binary and just takes a command line flag to switch languages: https://caddyserver.com/docs/config-adapters
This makes it difficult to configure Caddy in anything except the native Caddyfile language due to a lack of thorough documentation. It's an interesting idea, but configuring Caddy with a yaml config that someone prior deemed a great idea was quite painful.
Curiously, LLMs have made it a lot easier. One step away from an English adapter that routes through an LLM to generate the config.
KSON looks interesting. Where I work we did a metadata type project in Pkl recently, which is somewhat similar. Unfortunately, developments on the tooling front for Pkl have taken an extremely very long time. Not sure the the tooling/LSPs are anywhere close to what the language offers yet.
I like the language embedding feature in KSON - we would use that. Have you thought about having functions and variables? That is something you get in Pkl and Dhall which are useful.
This sounds like the kind of question for Daniel himself to chime in, since he has the best overview of the language's design and vision. He's not super active on HN, but I'll give him a heads up! Otherwise feel free to join our Zulip (https://kson-org.zulipchat.com) and we can chat over there.
From the application point of view, recently I'm converging on this: define data structures for your config. Ensure it can be deserialized from json and toml. (In Rust this is easy to do with Serde; in Python with Pydantic or dataclasses.) Users can start simple and write toml by hand. If you prefer KSON, sure, write KSON and render to json. If config is UI, I think the structure of the data, and names of fields and values, matter much more than the syntax. (E.g. `timeout = 300` is meaningless regardless of syntax; `timeout_ms = 300` or `timeout = "300 ms"` are self-documenting.)
When the configuration grows complex, and you feel the need to abstract and generate things, switch to a configuration language like Cue or RCL, and render to json. The application doesn't need to force a format onto the user!
the duration one in particular bugs me. I work on a dynamic configuration system and i was super happy when we added proper duration support. we took the approach of storing in iso duration format as a string. so myconfig = `5s` then you get a duration object and can call myconfig.in_millis. so much better imo.
I like where their head is at here, especially the "superset of JSON" part. Some of the things I'm not _in love_ with like the %% ending blocks or how maybe a bit of significant whitespace might make things a bit less misleading with indentation as others have said, but overall I think I like this better than YAML.
With all the code syntax highlighting support as a feature, I feel it will become tempting to put code in configuration files (which some of their examples show). That just feels wrong. Code should go in code files/modules/libraries, not mixed with configuration files. If your configuration starts to become code, maybe you need to rethink your software architecture. Or perhaps KSON proves that principle to be too rigid and inferior, and leads to more intelligible, manageable software. I guess we'll have to see.
- The key-value pair. Maybe some section marker (INI,..). Easy to sed.
- The command kind. Where the file contains the same command that can be used in other place (vim, mg, sway). More suited to TUI and bigger applications.
I think the post is hurt by the desire to sort of… “have a theory” or take a new stance. The configuration file is obviously not a user interface, it is data. It is data that is typically edited with a text editor. The text editor is the UI. The post doesn’t really justify the idea of calling the configuration file, rather than the program used to edit it, the UI. Instead it focuses on a better standard for the data.
The advancement of standards that make the data easier to handle inside the text editor is great, though! Maybe the slightly confusing (I dare say confused) blog title will help spread the idea of kson, regardless.
Edit: another idea, one that is so obvious that nobody would write a blog post about it, is that configuring your program is part of the UX.
yes but to validate it you need dynamic runtime logic and therefore a live server with all the I/O glue code that entails. i.e., static types alone cannot render your tax forms
That’s why 90% of each iOS update is just another menu or a reorganization of menus and why there are 3 different ways to access the same info/menus on iOS.
Or you just use YAML. It's a configuration language for your software, you control which parser you use which can be YAML 1.2, you can use the safe loader which can't run untrusted code, and you're parsing the values into your language's types so any type confusion will be instantly caught.
I agree that it's not perfect but worse is better and familiar is a massive win over making your users look up a new file format or set their editor up for it. If you truly hate YAML that's fine, there's plenty of other familiar formats: INI, toml, JSON.
YamlScript (YS) adds more programmatic expressiveness to YAML.
It extends an executable Clojure runtime (non-jvm, like Babaskha).
Created by YAML inventor/maintainer
I'm just so tired of writing bash scripts inside the YAML. I want to be able to lint and test whatever goes into my pipelines and actions. Not fight shitty DX on top of whatever Azure spits out when it fails.
This is entirely understandable, and entirely the fault of whoever thought bash scripts belong in configuration files. If you’re trying to stuff a tiger into a desk drawer, the natural consequences are hardly the fault of the desk drawer.
But it's the situation we're in now. It's what you see in the docs and what my colleagues write as well. I entirely agree that scripting into a markup language doesn't make sense yet the inertia is there and I wish there was some way out.
Can't tell if asked honestly. Because that's how most platforms handle their pipelines. Terraform or Bicep let you use a declarative language for your platform. Everything else is calling cli commands or scripts from pipelines, written in YAML.
Invariably, ppl will write inline scripts instead of actual scripts in their own files. There are also some SDKs for most of these operations that would let you do it in code but they are not always 100% the same as the CLI, some options are different, etc.
KSON proudly claims "no whitespace sensitivity", which means "misleading indentation" is back. And it's pretty light on syntax, so there are going to be plenty of mistakes made here.
Here is an example I made in a few minutes:
Guess how it parses? answer:I actually prefer a syntax that is whitespace-sensitive, but should not give meaning to whitespace. That is, the whitespace should not perform a semantic duty, but should be required to be correct.
This is roughly equivalent to saying that a linter can transform the AST of the language into a canonical representation, and the syntax will be rejected unless it matches the canonical representation (modulo things like comments or whitespace-for-clarity).
This sounds like a stricter version of KSON's current warnings for misleading indentation... maybe KSON should have an opt-in feature for this. Thanks for the idea!
Hmmm that's interesting. KSON actually shows a warning when there's misleading indentation, exactly to prevent this sort of thing! It seems like the detection logic only considers indents after a new line, so it doesn't complain in this case. I just opened an issue to see if things can be tightened up a bit (https://github.com/kson-org/kson/issues/221).
To see misleading indentation warnings in action, you can try the following snippet in the playground (https://kson.org/playground/) and will properly get a warning:
Next to that, note that KSON already has an autoformatter, which also helps prevent misleading indentation in files.Assuming this takes off, there would be a prettier-plugin that corrects any weird formatting.
When I think about it, any language should come with a strict, non-configurable built-in formatter anyways.
> any language should come with a strict, non-configurable built-in formatter
Would that be on the language, or the IDEs that support it? Seems out of scope to the language itself, but maybe I'm misunderstanding.
Configuration files need to be powerful programming languages (in terms of expressiveness) while being restricted (in terms of network and I/O and non-determinism). We need to aim very high for configuration languages especially when we treat them like user interfaces. Look at Cue (https://cuelang.org/), Starlark or Dhall (https://dhall-lang.org/) for inspiration, not JSON, unless your configuration file is almost always written programmatically.
Or Jsonnet (https://jsonnet.org), if you do like JSON but want less quoting.
Any configuration language that doesn't support strict/user/explicit types is worthless (ahem jsonnet).
The idea of configuring something but not actually having any sort of assurances that what you're configuring is correct is maddening. Building software with nothing but hopes and dreams.
expressiveness unfortunately usually means that while you can read the output value, you lose the ability to modify it programmatically...
JSON5 is good enough that it works for frontend devs, backend, qa, firmware, data science, chemists, optical engineers, and the hardware team, in my org at least. Interns pick up on it quickly.
The comment option gives enough space for devs to explain new options flags and objects included to those familiar enough to be using it.
For customer facing configurations we build a UI.
In the kitchen sink example (https://json5.org/), they say:
> "backwardsCompatible": "with JSON",
But in that same example, they have a comment like this:
> // comments
Wouldn't that make it not compatible with JSON?
It's confusing.
From what I understand, it's "backwards-compatible" with JSON because valid JSON is also valid JSON5.
But it's not "forwards-compatible" precisely because of comments etc.
Your existing JSON < 5 will work with json5, not the other way around
It’s a superset of JSON. I guess they mean it’s backwards compatible in terms of reading existing JSONs?
This is why Caddy has config adapters: bring any config file language you like, and Caddy will run it. It's built-into the binary and just takes a command line flag to switch languages: https://caddyserver.com/docs/config-adapters
This makes it difficult to configure Caddy in anything except the native Caddyfile language due to a lack of thorough documentation. It's an interesting idea, but configuring Caddy with a yaml config that someone prior deemed a great idea was quite painful.
Curiously, LLMs have made it a lot easier. One step away from an English adapter that routes through an LLM to generate the config.
KSON looks interesting. Where I work we did a metadata type project in Pkl recently, which is somewhat similar. Unfortunately, developments on the tooling front for Pkl have taken an extremely very long time. Not sure the the tooling/LSPs are anywhere close to what the language offers yet.
I like the language embedding feature in KSON - we would use that. Have you thought about having functions and variables? That is something you get in Pkl and Dhall which are useful.
Thanks for the kind words :)
This sounds like the kind of question for Daniel himself to chime in, since he has the best overview of the language's design and vision. He's not super active on HN, but I'll give him a heads up! Otherwise feel free to join our Zulip (https://kson-org.zulipchat.com) and we can chat over there.
From the application point of view, recently I'm converging on this: define data structures for your config. Ensure it can be deserialized from json and toml. (In Rust this is easy to do with Serde; in Python with Pydantic or dataclasses.) Users can start simple and write toml by hand. If you prefer KSON, sure, write KSON and render to json. If config is UI, I think the structure of the data, and names of fields and values, matter much more than the syntax. (E.g. `timeout = 300` is meaningless regardless of syntax; `timeout_ms = 300` or `timeout = "300 ms"` are self-documenting.)
When the configuration grows complex, and you feel the need to abstract and generate things, switch to a configuration language like Cue or RCL, and render to json. The application doesn't need to force a format onto the user!
the duration one in particular bugs me. I work on a dynamic configuration system and i was super happy when we added proper duration support. we took the approach of storing in iso duration format as a string. so myconfig = `5s` then you get a duration object and can call myconfig.in_millis. so much better imo.
I like this take! Have you used Cue or RCL yourself? How was the experience?
I like where their head is at here, especially the "superset of JSON" part. Some of the things I'm not _in love_ with like the %% ending blocks or how maybe a bit of significant whitespace might make things a bit less misleading with indentation as others have said, but overall I think I like this better than YAML.
With all the code syntax highlighting support as a feature, I feel it will become tempting to put code in configuration files (which some of their examples show). That just feels wrong. Code should go in code files/modules/libraries, not mixed with configuration files. If your configuration starts to become code, maybe you need to rethink your software architecture. Or perhaps KSON proves that principle to be too rigid and inferior, and leads to more intelligible, manageable software. I guess we'll have to see.
There’s two configuration that I like:
- The key-value pair. Maybe some section marker (INI,..). Easy to sed.
- The command kind. Where the file contains the same command that can be used in other place (vim, mg, sway). More suited to TUI and bigger applications.
With these two, include statement are nice.
KSON looks neat.
I think the post is hurt by the desire to sort of… “have a theory” or take a new stance. The configuration file is obviously not a user interface, it is data. It is data that is typically edited with a text editor. The text editor is the UI. The post doesn’t really justify the idea of calling the configuration file, rather than the program used to edit it, the UI. Instead it focuses on a better standard for the data.
The advancement of standards that make the data easier to handle inside the text editor is great, though! Maybe the slightly confusing (I dare say confused) blog title will help spread the idea of kson, regardless.
Edit: another idea, one that is so obvious that nobody would write a blog post about it, is that configuring your program is part of the UX.
While I agree with the general idea, 2 minutes of looking at KSON was enough for me. If this is UI, it’s an ugly one.
I’ll stick to JSON. When JSON isn’t enough it usually means the schema needs an update.
yes but to validate it you need dynamic runtime logic and therefore a live server with all the I/O glue code that entails. i.e., static types alone cannot render your tax forms
Yes all user interfaces are a key/value list.
That’s why 90% of each iOS update is just another menu or a reorganization of menus and why there are 3 different ways to access the same info/menus on iOS.
Or you just use YAML. It's a configuration language for your software, you control which parser you use which can be YAML 1.2, you can use the safe loader which can't run untrusted code, and you're parsing the values into your language's types so any type confusion will be instantly caught.
I agree that it's not perfect but worse is better and familiar is a massive win over making your users look up a new file format or set their editor up for it. If you truly hate YAML that's fine, there's plenty of other familiar formats: INI, toml, JSON.
YamlScript (YS) adds more programmatic expressiveness to YAML. It extends an executable Clojure runtime (non-jvm, like Babaskha). Created by YAML inventor/maintainer
https://yamlscript.org/
I'm just so tired of writing bash scripts inside the YAML. I want to be able to lint and test whatever goes into my pipelines and actions. Not fight shitty DX on top of whatever Azure spits out when it fails.
This is entirely understandable, and entirely the fault of whoever thought bash scripts belong in configuration files. If you’re trying to stuff a tiger into a desk drawer, the natural consequences are hardly the fault of the desk drawer.
But it's the situation we're in now. It's what you see in the docs and what my colleagues write as well. I entirely agree that scripting into a markup language doesn't make sense yet the inertia is there and I wish there was some way out.
> I'm just so tired of writing bash scripts inside the YAML.
Why would you be doing that?
Can't tell if asked honestly. Because that's how most platforms handle their pipelines. Terraform or Bicep let you use a declarative language for your platform. Everything else is calling cli commands or scripts from pipelines, written in YAML.
I suppose I am confused by what you mean with, "writing bash scripts".
Like, are you _literally_ scripting in the value of an item or are you just equating that they are similar?
Literal being:
get_number_of_lines:
Something like this: https://learn.microsoft.com/en-us/azure/devops/pipelines/tas...
Invariably, ppl will write inline scripts instead of actual scripts in their own files. There are also some SDKs for most of these operations that would let you do it in code but they are not always 100% the same as the CLI, some options are different, etc.
Anecdote: I am still of the opinion that in most (~99%)[1] of the situations people are in "YAML Hell" because they put themselves in "YAML Hell".
1: I pulled that out of my butt, there's no factual data to it.