As an open-source project, emilk/eon has picked up 174 stars on GitHub (Rust). A simple and friendly config format
Snapshot summary built from the project's own GitHub metadata — there's no written TopGit review yet. The page will update automatically when a full review is published.
WHY NO REVIEW YET
TopGit writes full reviews for the most-starred, most-requested repositories. This page is a snapshot until then — see the READ ME tab for the original README in full.
This repository contains the definition of Eon, a simple config format designed for human editing.
Eon uses the .eon file ending.
Eon is aimed to be a replacement for Toml and Yaml.
This repository also contains a Rust crate eon for using Eon with serde, and a eonfmt binary for formatting Eon files.
Sections:
Overview
Design goals
Why another config format?
Performance
Roadmap
Eon specification
Overview
// Comment
string: "Hello Eon!"
list: [1, 2, 3]
map: {
boolean: true
literal_string: 'Can contain \ and "quotes"'
}
any_map: {
42: "This key is an integer"
[]: "This key is an empty list"
}
hex: 0xdead_beef
special_numbers: [+inf, -inf, +nan]
// Strings come in four flavors:
basic_strings: [
"I'm a string."
"I contain \"quotes\"."
"Newline:\nUnicode: \u{262E} (☮)"
]
multiline_basic_strings: [
"""\
It was the best of strings.
It was the worst of strings."""
// The above is equivalent to:
"It was the best of strings.\n\t\tIt was the worst of strings."
]
literal_strings: {
// What you see is what you get:
windows_path: 'C:\System32\foo.dll'
quotes: 'I use "quotes" in this string'
regex: '[+\-0-9\.][0-9a-zA-Z\.+\-_]*'
}
multiline_literal_strings: {
python: '''
# The first newline is ignored, but everything else is kept
def main():
print('Hello world!')
'''
}
Design goals
Familiar: strongly resembles JSON
Clean: forgoes unnecessary commas and quotes
Powerful: supports arbitrary map keys and sum types (e.g. Rust enums)
Main differences from JSON
No need to wrap entire document in {}
Quotes around map keys are optional for identifiers
Map keys can be any value (not just string)
Commas are optional
Eon adds:
// Comments
Special floats: +inf, -inf, +nan
Named sum-type variants
Formatter
You can format any Eon file using the eonfmt binary
cargo install --locked eonfmt
eonfmt *.eon
Why another config format?
I wanted a format designed for human eyes with
Indented hierarchy using { } and [ ] (like JSON, C, Rust, …). Rules out YAML and TOML.
No top-level { } wrapping the whole file. Rules out JSON5, RON, and others.
Why not JSON5?
JSON5 is almost great, but requires wrapping the whole file in an extra { } block, and indent that. That's too ugly for me.
It also has a bunch of unnecessary commas between values.
RON has the same problem.
Why not RON?
The goal of RON is to perfectly map the Rust datatypes, which is cool, but it means it leans more towards being verobse and complex while Eon wants to be lean and simple.
Why not Toml?
Toml is a very nice and clean language.
However, unlike almost every other programming language known, it does not use any indentation to aid the reader, leading to very confusing hierarchies.
This means that when (visually) scanning a Toml document it's hard to figure out where one section starts and another ends.
It also means Toml is a bad candidate whenever you have deeply nested structures.
The [[array.of.tables]] syntax is also quite confusing to newcomers.
Why not YAML?
Yaml is clean, but over-complicated, inconsistent, and filled with foot guns. It is known.
Performance
The Eon language (and library) are designed for config files that humans edit by hand.
There is nothing in the Eon spec that would not make it as fast (or as slow, depending on your perspective) as JSON, but the library has not been optimized for performance (no crazy SIMD stuff etc).
It still parses a chunky 1MB file in under 10ms on an M3 MacBook.
I would not recommend using Eon as a data transfer format. For that, use a binary format (like MsgPack or protobuffs), or JSON (which has optimized parser/formatters for every programming language).
Roadmap
Future work, which I may or may not get to (contributions welcome!)
Additional tools
VSCode extension for
Syntax highlighting
Formatting
Extending the spec
Add special types?
ISO 8601
datetimes
local times
Durations? But ISO 8601 durations are so ugly
UUID?
Hex floats?
Eon specification
An Eon document is always encoded as UTF-8.
A document can be one of:
A single value, e.g. 42 or {foo: 1337, bar: 32}
The contents of a Map, e.g. foo: 42, bar: 32 (this is syntactic sugar so you don't have to wrap the document in {})
The contents of a List, e.g. 32 46 12 (useful for a stream of values, e.g. like ndjson)
Commas are optional in Eon, so [1, 2, 3] is the same as [1 2 3].
By convention, commas are included when multiple values are on the same line, but omitted for multi-line maps and lists.
Whitespace is not significant (other than as a token separator).
By convention, we indent everything wrapped in [], {}, ().
Comments are prefixed with //.
Supported types
An Eon value is one of:
null
A special null value, signifying nothingness.
Boolean
true or false.
Number
Numbers in Eon can have an optional sign (+ or -) followed by either:
a decimal (42)
a hexadecimal (0xbeef, case insensitive)
a binary (0b0101)
a decimal (3.14, 6.022e23 etc)
Numbers can use _ anywhere in them as a visual separator, e.g. 123_456 or 0xdead_beef.
There is not explicit bounds on the precision and magnitude of supported numbers in an Eon file,
but the eon crate is currently only support integers in the [-2^127, 2^128) range, and decimals are limited to the precision of f64.
Eon also support the special values:
+nan: IEEE 754 NaN
+inf: positive infinity
-inf: negative infinity
Note that these special values MUST be prefixed with a sign (they are not keywords like true/false/null are).
Strings
Text in Eon comes in four flavors:
"basic string"
"""multiline basic string"""
'literal string'
'''multiline literal string'''
"Basic strings"
Basic strings uses double-quoted, and can contain escape sequences:
"I'm a string."
"I contain \"quotes\"."
"Newline:\nUnicode: \u{262E} (☮)"
"""Multi-line basic strings"""
When you have long text it can be useful to have a string span multiple lines, using triple-quotes.
Escape sequences still work, and a line ending with \ removes the newline and any whitespace at the start of the next line.
This means these two strings are equivalent:
str1: """\
It was the best of strings.
It was the worst of strings."""
str2: "It was the best of strings.\n\tIt was the worst of strings."
'Literal strings'
Literal strings uses single quotes, and no escaping is performed. What you see is exactly what you get:
windows_path: 'C:\System32\foo.dll'
quotes: 'I use "quotes" in this string'
regex: '[+\-0-9\.][0-9a-zA-Z\.+\-_]*'
There is no way to put a single quote inside of a literal strings, but you can in a…
'''Multi-line literal strings'''
A multi-line literal string uses three single quotes. Within that, everything is taken verbatim, except that the very first newline (if any) is ignored:
quote_re: '''(["'])[^"']*$1'''
python: '''
# The first newline is ignored, but everything else is kept
def main():
print('Hello world!')
'''
List
Lists are written as [ … ], with optional commas between values.
Usually the commas are omitted for lists that span multiple lines,
and included for lists that are on a single line.
A list can contain any Eon value (including other lists).
Map
Maps are written as { key: value, … }, again with optional commas between key-value pairs.
Usually the commas are omitted for maps that span multiple lines,
and included for maps that are on a single line.
Maps are used to represent either a record type (like a struct) or a table type (e.g. a hash map).
For instance, say you have a hash map for looking up country code based on the name of the country.
This can be serialized to Eon as:
Both keys and values of an Eon map can be any Eon value.
This is significantly different from e.g. JSON, where keys can only be strings.
So, a reverse map (from code to country name) can we written as:
complex_map: {
{"foo": 42, "bar": "mushroom"}: "Yes, this is fine"
}
You are allowed to omit the quotes around map keys (NOT values!) when the keys are identifiers.
An identifier is defined in Eon as any string matching the regex [a-zA-Z_][a-zA-Z0-9_]*.
This definition matches most programming languages (e.g. what is allowed as a variable name in C).
This means these two are equivalent:
explicit: {
"a": 1
"b": 2
}
same: {
a: 1
b: 2
}
The convention is to use quotes for general strings (e.g. when representing a HashMap<String, …>
and to use identifiers when representing struct fields.
Examples of what is and isn't allowed:
snake_case: true // OK!
kebab-case: false // ERROR! 'kebab-case' is not an identifier, and must be quoted
"kebab-case": true // OK!
string: Hello // ERROR! "Hello" should be in quotes
key: null // OK! 'null' is a special value (it's NOT a string)
42: "forty-two" // OK! Maps the integer 42 to a string
"42": "forty-two" // OK! Maps the string "42" to a string (which is different from the above!)
true: "confusing" // ⚠️ Confusing, but OK. Uses a boolean as key (not a string!).
"true": "fine" // OK! Uses the string "true" as key
null/true/false as map keys
The last two lines in the above example show that you need to be careful when using key names that matches one of the three keywords (true/false/null). This is is a (small) footgun in Eon, but hopefully these key names are rare (they are already forbidden identifiers in many programming languages).
Alternative designs I've considered:
Always require quotes for map keys (like JSON). Con: very ugly.
Only allow strings as map keys. Con: can't express general maps (limiting).
Only allow identifiers as map keys (like a Rust struct). Con: can't serialize a HashMap<String, …>.
Change null/true/false to something else (e.g. %null, %true, %false). Would be both surprising and ugly.
Forbid using unquoted null/true/false as map keys. Con: can't serialize HashMap<bool, …> or a general HashMap<Value, …>. Feels arbitrary.
Named sum-type variants
Let's first consider a simple enum, like one you would find in C or Java:
enum Side {
Left,
Middle,
Right,
}
The variants are encoded as strings in Eon, e.g.
side: "Middle"
In other words, there is no difference between a string and an enum variant, as far as Eon is concerned.
Here a simple string will not suffice, as some of the enum variants contain data.
There are several competing techniques of encoding this in JSON (external tagging, internal tagging, adjaceny tagging, …) all with their own shortcomings.
In Eon, enum variants are written as "Variant"(data).
So different values for the above choice would be written as:
"Black" (equivalent to "Black"())
"Gray"(128)
"Hsl"(0, 100, 200)
"Rgb"({r: 255, g: 0, b: 0})
Digression: why this syntax for sum types?
Why the quotes, and not just Black, Gray(128), etc?
Consider this hypothetical Eon file:
color: Black
name: Emil
Is name really a multiple-choice enum? Maybe. Maybe not.
But the Eon parser wouldn't know, so must accept it.
And this will leave the door open to weirdness where some strings need quotes and not others (and we'll end up similar to YAML).
So instead we explicitly forbid the above, and always require quotes for strings (…except for map keys that are identifiers).
The most recent commit recorded on emilk/eon was 7 months ago, based on the GitHub push timestamp. The repository has 11 forks — one of the better signals of community interest.
How many stars does emilk/eon have?
emilk/eon has 174 GitHub stars — refresh the page for the live number, or check github.com/emilk/eon. TopGit mirrors GitHub's count but does not claim minute-by-minute accuracy.
Is emilk/eon open source?
Yes — emilk/eon ships under the Apache-2.0 license, which makes its source code freely readable (and, depending on license terms, forkable and reusable). Source: github.com/emilk/eon.
What is emilk/eon?
emilk/eon (emilk/eon) is a Rust project on GitHub. From the project's own README: A simple and friendly config format
What language is emilk/eon written in?
emilk/eon is written primarily in Rust. GitHub's language field is based on the largest share of bytes in the default branch.
What license does emilk/eon use?
emilk/eon is released under the Apache-2.0 license. Always verify the LICENSE file directly on GitHub for the authoritative terms — license strings can be edited out of sync with a project's actual stance.
Where do I read more about emilk/eon?
This TopGit page is a snapshot — the READ ME tab shows the project's own README content (links stripped, images preserved). The GitHub repository at github.com/emilk/eon is the definitive source.
Read full README in the tab above.
Is eon worth your time?
ChatGPT, Claude and Perplexity can all read this page. Ask one of them what it makes of eon.