[meta] {
[title] Sona, a markup language
[subtitle] Yes, another one.
[author] Vince Mutolo
[date] // TODO
}
[section] {
[title] Feature survey
Sona has very few features. The goal is to do as much as possible with
as little syntax as we can. In many places we succeed, and in others we'll
punt the problem to another layer.
[section] {
[title] Consistent syntax
[example] {
[label] syntax-parts
The below example demonstrates Sona's two types of syntax:
labels and text.
[code] {
[lang] sona
\raw#{
[title] Birds aren't real, a treatise
}#
}
}
Everything in Sona is one of two objects:
[definitions] {
[item] {
[term] label
[def] {
provides metadata about a subsequent block. In
[ref]{syntax-parts}, the text [code]{title} is a [em]{label}.
It specifies that the contents of its [em]{scope} are labeled
as a title. It's up to some other layer to figure out what to
do with that information.
}
}
[item] {
[term] text
[def] {
provides the actual content of a Sona document. If labels
are metadata, text is the data itself. In [ref]{syntax-parts},
the text [code]{Birds aren't real, a treatise} is a text object.
Text doesn't always have to show up in a rendered document. Sona
doesn't have to produce rendered documents at all. It can, for
example, be used for config files. In that case, a text object
is likely to be interpreted as the value corresponding to a
certain key (which is likely a label).
}
}
}
}
[section] {
[title] Simple data model and output
Because Sona has so few data types, the abstract syntax tree can be
compactly represented in JSON. Labels become keys in objects, and the
values are (mixed) arrays of either text blocks or other label objects.
[example] {
This Sona document:
\sona#{
[A] {
T minus [SI]{123 [u]{ms}}.
[B] b
}
[C] c
}#
is converted to the following JSON:
\json#{
[
{"A": [
"T minus ",
{"SI": ["123 ", {"u": ["ms"]}]},
{},
{"B": ["b"]}
]},
{},
{"C": "c"}
]
}#
}
}
[section] {
[title] Macros
Sona allows users to define macros that take in arbitrary text and emit
a valid Sona document. For example, if we know that we'll be writing
out lots of JSON code, we may want to define a macro to save space.
A hypothetical JSON macro would be used as follows:
\sona##{
\json#{
{"a": "b"}
}#
}##
and would expand to a syntax tree equivalent to the following
Sona document:
\sona##{
[code] {
[lang] json
\raw#{
{"a": "b"}
}#
}
}##
}
}
[section] {
[title] Why not one of the existing formats
[ordered] {
[item] Markdown isn't powerful enough. I want to be able to have
callouts and "warnings" and "notes" all throughout an article. With
Markdown, these blocks need to be written in raw HTML, which is
annoying because Markdown is disabled in those blocks. And writing
HTML is generally annoying.
[item] HTML is annoying. See above.
[item] LaTeX is a mish-mosh of ideas organically thrown together over
decades. I love LaTeX, and TeX's output is second to none, but it's
not the format I want for content authorship.
}
}
[section] {
[title] Use cases
[section] {
[title] Configuration files
Imagine we need to create a configuration file for some video game.
The game needs to know how many tries the player gets, the score
needed to win, and some starting position.
In TOML, that config looks like:
\toml#{
[config]
max_tries = 30
max_score = 100.0
[config.waypoint]
x = 10
y = -3
}#
In Sona, we might write something like the following:
\sona#{
[config] {
[num_tries] 30
[max_score] 100.0
[waypoint] {
[x] 10
[y] -3
}
}
}#
TOML is already a great configuration format, and Sona makes different
trade-offs. TOML doesn't need braces because it's completely whitespace-
dependent. This results in a cleaner look. Sona needs the braces to
help differentiate between paragraph breaks and scope changes for other
use cases.
Still, subjectively I think Sona more cleanly expresses the hierarchical
relationship between [code]{waypoint} and its parent [code]{config}.
It's somewhat well known that TOML doesn't handle nesting well. This is
a small example, but already it's a little awkward to write
[code]{config.waypoint}.
Last, because Sona was built first and foremost for prose, including
long-form text in a config works perfectly well in Sona, but is much
more awkward in other formats.
Imagine we wanted to write a longer message that the player might find
on a scroll in a treasure chest. It might be nice to include that
paragraph-long message alongside the config.
In Sona:
\sona#{
[config] {
[num_tries] 30
[max_score] 100.0
[message] {
Here's a longer message that the player might see.
It can span multiple lines.
Even multiple paragraphs.
}
[waypoint] {
[x] 10
[y] -3
}
}
}
In TOML:
\toml#{
[config]
max_tries = 30
max_score = 100.0
message = """
Here's a longer message that the player might see.
It can span multiple lines.
Even multiple paragraphs."""
[config.waypoint]
x = 10
y = -3
}#
TOML does okay here (especially compared to JSON), but it's still awkward.
Then again, this is a fairly rare requirement for config languages, and
it's only presented because Sona performs well.
}
}