Spoiler: I created my own configuration language maml.dev
Here will be a list of all the markup languages/configuration languages I found on the internet, and the things I don’t like about them.
YAML
- - 1
- 2
- - 3
- 4YAML 1.2 is better than YAML 1.0. But still, the YAML specification is monstrous, and I don’t understand how people trying to implement it aren’t going crazy. YAML has a lot of features.
xml
-
R&D Handbook
n/a
The era of XML is in the past. I remember the hype about XML, how it was supposed to be a universal format, and people built a lot of things around it. But now it is dead.
JSON
String,
JSON is good and JSON wins. It is a universal, data-interchange format for web and applications. That’s why I based my MAML on top of JSON. I fixed things inside the JSON that were a bit annoying for me.
TOML
[[servers.web]]
name = "frontend"
ip = "192.168.1.10"
[[servers]]
region = "eu-central"
[[servers.web]]
name = "backend"
ip = "192.168.1.11"I don’t understand why [table] is more readable, and I don’t understand [[array of tables]] Bad. and lack of null,
JSON5
String,
Too many unnecessary features. Object key-value pairs are still disorganized. No difference between integers and floats.
HJSON
String,
Unquoted strings and three different types of comments. Multi-line strings with significant indentation.
JSONH
{
// use #, // or /**/ comments
keys: without quotes,
isn\'t:
name
}JSONH is similar to HJSON but different.
RJSON
{
shopping-list: [ milk butter /* don't forget the beer */ beer ]
a\ space : t\:em item\ with\ spaces
}Strings without quotation marks, but only if they do not contain spaces or commas. No specification.
JSONC
{
/*
This is a multi-line comment
that spans multiple lines
*/
"name": "Jane Doe",
"age": 25,
}There are a lot of implementations and differences in the implementation of JSON with comments. For example, it has trailing commas. There are still duplicate keys allowed, there are still no integer, dislocated key-value objects.
hcl
service "aws_ami" "ubuntu" {
most_recent = true
instance_type = var.instance_type != "" ? var.instance_type : "t3.micro"
}I don’t like to nest with service "http" "web_proxy" or ability to specify service multiple times in different parts of the file.
pkl
class Bird {
name: String
hidden taxonomy: Taxonomy
}
pigeon: Bird = new {
name = "Common wood pigeon"
taxonomy {
species = "Columba palumbus"
}
}This is not a markup language. It is a full-fledged programming language. I would honestly just use TypeScript instead.
Ron
GameConfig( // optional struct name
window_size: (800, 600),
key_bindings: {
"up": Up,
"down": Down,
"left": Left,
"right": Right,
},
)Highly rust-centric.
edn
#:demo{:id #uuid "de305d54-75b4-431b-adb2-eb6b9e546014"
:ts #inst "2025-11-04T09:00:00Z"
:nums [1 2 3 4/2 5.5M]
:set #{:a :b :c}
:rx #"[A-Z]+"
:q #queue ["x" "y"]
:tag #user{:name "Zed"}}I think Clojure developers like it. I am not one of them.
HOCON
include required("foo.conf")
a : [ 1, 2 ] [ 3, 4 ]
data-center-east = ${data-center-generic} { name = "east" }
{ foo include : 42 }Lots of features. Is it some kind of programming language? And it seems to be focused on just one project.
nestedtext
default repository: home
report style: tree
compact format: {repo}: {size:{fmt}}. Last back up: {last_create:ddd, MMM DD}.
date format: D MMMM YYYY
size format: .2bYAML version with strings only. But I want boolean!
kdl
author "Alex Monad" email=alex@example.com active=#true
scripts {
message """
hello
world
"""
}KDL is very close to XML with properties on nodes. But I like data structures like JSON. It is easy to understand them. Also, I don’t like key indentation on multi-line strings.
SDLang
// Trailing semicolons are optional
prop true;
anotherprod on; author "Peter Parker"
this-is.1_valid$Tag-Name
renderer:options "invisible"
physics:options "nocollide"
title \
"Some title"they have true And falsewhy are you adding on And offBy default, integers are 32 bits long. suffix 10L Required for 64-bits.
Signal
import "math"
piPlusOne: math.Pi + 1
"quoted field names": {
"four^four": math.Pow(4, 4)
}I would just use TypeScript instead of this programming language. Lots of features; The specificity is huge.
Descend
let makeUser = \(user : Text) ->
let home = "/home/${user}"
let privateKey = "${home}/.ssh/id_ed25519"
let publicKey = "${privateKey}.pub"
in { home, privateKey, publicKey }
{- Add another user to this list -}
in [ makeUser "bill"
, makeUser "jane"
]Again, it is a programming language. So I assume only one implementation of Dhall exists?
Jsonnet
local my_function(x, y=10) = x + y;
{
person1: {
name: "Alice",
welcome: "Hello " + self.name + "!",
},
person2: self.person1 { name: "Bob" },
len: [
std.length('hello'),
std.length([1, 2, 3]),
]
}Well, it is a type of programming language with dynamic types. But there are lots of good programming languages, so I don’t know why there is a need to use it.
Out
let conf = {
name = "NiCl",
version = "0.0.1$",
description = "My cool app!"
} in
let SemanticVersion = fun label value =>
let pattern = "^\\d{1,2}\\.\\d{1,2}(\\.\\d{1,2})?$" in
if std.string.is_match pattern value then
value
else
let msg = "invalid version number" in
std.contract.blame_with_message msg label
in
let AppSchema = {
name | String,
version | SemanticVersion,
description | String,
} in
conf | AppSchemaGood programming language. Not a markup language.
starlark
def fizz_buzz(n):
"""Print Fizz Buzz numbers from 1 to n."""
for i in range(1, n + 1):
s = ""
if i % 3 == 0:
s += "Fizz"
if i % 5 == 0:
s += "Buzz"
print(s if s else i)
fizz_buzz(20)Starlark is a programming language. The lack of porting/reimplementing Starlark in another programming language is good.
ucg
let tuple = {
inner = {
field = "value",
},
list = [1, 2] + [3],
"quoted field" = "quoted value",
};This is just an implementation of a language. Not portable to other languages.
ucl
.include "${CURDIR}/path.conf"
.macro_name(param={key=value}) "something";
section "blah" "foo" {
key = value;
}Ok. Implementation of configuration language. No specification. No other implementation.
confetti
probe-device eth0 eth1
user * {
login anonymous
password "${ENV:ANONPASS}"
machine 167.89.14.1
proxy {
try-ports 582 583 584
}
}Nice logo! But other than that, I found it difficult to understand what is happening in this example. What about escaping into the stars?
ziggy
{
.name = "ziggy",
.version = @v("1.0.0"),
.license = @spdx("MIT"),
.dependencies = {
"react": "next",
"leftpad": "^1.0.0",
},
.repository = Git {
// "type" is now the struct name
.url = "https://github.com",
},
.description =
\\# Ziggy
\\
\\A Data Serialization Language.
,
}I really like the idea of separating structures and maps. But this is just an implementation of one tool. No specification. And I don’t like zig-style multiline strings.
HUML
website::
ports:: 80, 443
enabled: true
factor: 3.14
props:: mime_type: "text/html", encoding: "gzip"
tags::
- "markup"
- "webpage"
- "schema"Good idea to make YAML less ugly. But it’s still a YAML, with the same problems and significant indentation.
MAML
{
project: "MAML"
tags: [
"minimal"
"readable"
]
# A simple nested object
spec: {
version: 1
author: "Anton Medvedev"
}
# Array of objects
examples: [
{
name: "JSON", born: 2001
}
{
name: "MAML", born: 2025
}
]
notes: """
This is a multiline raw strings.
Keeps formatting as-is.
"""
}
So, I decided to create a specification for my language. And I wanted a unique name, not something like JSON. I wanted a good name and strict specificity. There are trade-offs in all languages. MAML too.
