TOML + omelette · a tidy little parser for Gleam
TOML that
keeps your
comments.
tomlet parses TOML 1.0.0 into a document that remembers every comment, key order, and bit of whitespace. Edit a value, write it back, and the rest of the file comes out exactly how the human left it.
gleam add tomlet # the user's favorite snack
snack = "tomato" # raw, with salt # the user's favorite snack
snack = "tomato sandwich" # raw, with salt parse(s) |> to_string == s
An unedited document writes back byte for byte. Comments, key order, string style, integer base, CRLF vs LF: all of it survives the round trip. No reformatting, no surprises in the diff.
// the whole point
Edit a value.
Leave the file alone.
In the BEAM world, most TOML libraries only read — and the rare one that can write hands you a freshly reformatted file with the comments gone. tomlet treats the surrounding text as sacred: it changes the bytes you asked for and nothing else.
# package metadata
name = "tomlet"
version = 0
draft = true let doc = tomlet.set_int(doc, ["version"], 1)
let doc = tomlet.remove(doc, ["draft"])
let doc = tomlet.insert_comment_before(
doc, ["version"], "first stable release") # package metadata
name = "tomlet"
# first stable release
version = 1 The package metadata header never moved, name is untouched, the new comment landed right where you asked, and draft is simply gone.
// what's folded in
Everything you'd want in a
round-tripping parser.
-
Lossless round-trip
Parse and write back byte-for-byte. Whitespace, key order, string style and integer base are all preserved.
-
Edits keep their neighbours
Setting a value rewrites only that value's text. Comments above and beside it are never disturbed.
-
Friendly typed access
get_string,get_int,get_bool,get_dateand friends, addressed by key path, with stableWrongTypeerrors. -
Checked edits, no panics
Every edit returns a
Result, so bad paths, key conflicts and forbidden comment characters are errors you handle, not crashes. -
TOML 1.0.0, by the book
Validated against the official
toml-testsuite, both thevalid/andinvalid/corpora. -
Pure Gleam, both targets
No NIFs, no native deps. Runs the same on Erlang and JavaScript, and parses raw bytes with UTF-8 and BOM validation.
// reading is just as tidy
Pull out the value
you came for.
Typed accessors take a key path and hand back exactly the type you
asked for, including dates and times as opaque values with lexical
*_to_string helpers. Mismatch a type and you get a clear,
matchable error instead of a guess.
let assert Ok(doc) = tomlet.parse(input)
let assert Ok(title) = tomlet.get_string(doc, ["title"])
let assert Ok(version) = tomlet.get_int(doc, ["version"])
let assert Ok(enabled) = tomlet.get_bool(doc, ["enabled"])
# nested keys use the same path syntax
let assert Ok(name) = tomlet.get_string(doc, ["pkg", "name"]) // why it exists
The BEAM didn't have one.
No existing Erlang, Elixir or Gleam TOML library round-trips comments
— they parse into plain maps and throw the comments away. Most can
only read; the few that can write give you back a reformatted file. If
you wanted to bump a version in gleam.toml or rewrite a
pyproject.toml as a build step without nuking the author's
notes, you were out of luck.
tomlet fills that gap. It's a fresh library with an AST built from the start for lossless round-trip, inspired by Rust's toml_edit and Python's tomlkit, now with a friendly Gleam accent.