TomatenMark
TomatenMark is a work-in-progress lightweight markup language inspired by to D★Mark, with two changes: anonymous blocks, and indentation-free blocks.
Examples
Some technical writing:
@begin section[important]
#title Something
Pork belly et tattooed aut corporis quidem intelligentsia. Impedit schlitz gastropub nihil meditation voluptatem ullam viral.
#note[important] Blah
~listing[lang=ruby]
def greet(name)
puts "Uhh, hi #{name} I guess"
roll_eyes
end
~
Pork belly et tattooed aut corporis quidem intelligentsia. Impedit schlitz gastropub nihil meditation voluptatem ullam viral.
@end section
It’s intended for structured technical writing, but It could work for a play, too. Here is a scene with some set description, dialogue and stage directions:
@begin scene
#desc Old wooden house interior or something.
@begin dia[who=Nora]
okay
well
can we agree now that you’ll
do what you need to do
to make the divorce ‘official’.
@end dia
@begin dia[who=Torvald]
and why do I need to do that.
@end dia
#dir Something wild happens idk.
@end scene
This would be parsed as something like this (as XML, because XML is not too terrible at making up prose tbh):
<scene>
<desc>Old wooden house interior or something.</desc>
<dialogue who="Nora">
<p>okay</p>
<p>well</p>
<p>can we agree now that you’ll<br />do what you need to do<br />to make the divorce ‘official’.</p>
</dialogue>
<dialogue who="Torvald">
<p>and why do I need to do that.</p>
</dialogue>
<dir>Something wild happens idk.</dir>
</scene>
To do: figure out parentheticals in this example.
Syntax model
There are four block types (regular, anonymous, begin/end, and literal), and one inline type.
Blocks
Regular block:
#warning This is some admonition of sorts.
#note[target=instructors] This is a message only for instructors.
The block type follows the opening #
, and attributes can follow the block type.
Anonymous block:
Here is a regular paragraph.
Anonymous blocks don’t support attributes.
Begin/end:
@begin section
Here is a paragraph inside the section.
@end section
@begin monologue[who=Nora]
Oh woe blah blah etc.
@end monologue
The block type follows the @begin
and @end
keywords, and attributes can follow the block type.
Literal:
~listing
abc
something something
literal text here
~
~listing[lang=ruby]
def greet(name)
puts "Uhh, hi #{name} I guess"
roll_eyes
end
~
The block type follows the opening ~
, and attributes can follow the block type. The block consists of everything until the closing ~
; content between the opening and closing line will be treated as literal lines (i.e. no block elements will be interpreted), but can contain inline elements.
Inline
Inline is easier, because there is only one syntax: This is %emph{very} important.
Attributes
To do: Describe attributes
Document model
There are only two node types: text and element.
Text is just that — text.
Elements have a type (optional the element is anonymous; e.g. note
or nil
), optional attributes (a key-value map), and children (an array of elements and/or text nodes).
Context
I am creating this markup language so that I can write Article: Operator precedence parsing explained.1
In Weeknotes 2025 W04: Scary, man, I talked about this lightweight markup language for the first time. It has evolved since then — including the name.
See also
-
Look, I am fully aware that I do not need to create a markup language to write this article. Just… leave me be! I enjoy this stuff! ↩︎