molt
molt: TOML manipulation kit
Molt parses a TOML document into a concrete syntax representation that can be transformed and rewritten while preserving comments associated with nodes.
Path Syntax
Molt functions and operations accept a path string made up of key
segments separated by . (like a.b) and array indexes in brackets
(like [0] or [-1]).
Bare key segments may contain ASCII letters, digits, underscores, and
dashes. Segments requiring other characters (such as spaces or dots) must
be quoted with single quotes (no escape processing) or double quotes (with
escape processing, e.g. \").
a.b.c.d // ["a", "b", "c", "d"]
a.b.-1.d // ["a", "b", "-1", "d"]
a.b."with space".'[3]' // ["a", "b", "with space", "[3]"]
a.b."\e".'\e' // ["a", "b", "\u{001b}", "\\e"]
Array indexes must be integer values within brackets and negative indexing
is supported. 0 is the first value in an array or array of tables, -1 is
the last value in an array or array of tables.
a.b[-1].c // ["a", "b", -1, "c"]
a.b[3].c // ["a", "b", 3, "c"]
Path resolution behaviour with key or index values that do not resolve to a logical entry in the document depends on the operation performed.
When operations are required against the document root, use an empty path
string ("").
The InvalidPath variant of MoltError will be returned from
molt functions if the path syntax is invalid.
In some contexts, only key paths may be provided.
Types
pub type DocumentCommentPosition {
Header
Trailer
}
Constructors
-
HeaderDocument header comments are stored in this position before any value node. When rendered, a blank line will be placed between these comments and the first value node.
-
TrailerDocument trailer comments are stored in this position after all value nodes. When rendered, a newline may be placed between the final value node and these comments.
Values
pub fn append(
doc doc: types.Document,
path path: String,
value value: value.Value,
) -> Result(types.Document, error.MoltError)
Appends to an array at path.
path must resolve to either a value node containing an array or an array
of tables. When path resolves to an array of tables, the value
provided must be table-like.
pub fn concat(
doc doc: types.Document,
path path: String,
values values: List(value.Value),
) -> Result(types.Document, error.MoltError)
Concatenate multiple values to an array at path.
path must resolve to either a value node containing an array or an array
of tables. When path resolves to an array of tables, all entries in
values must be table-like.
pub fn document_errors(
doc: types.Document,
) -> List(types.SyntaxError)
Every validation error in the document as a fully-positioned SyntaxError,
computed on demand from the current tree. Returns [] for a valid document.
This is the only path that builds error spans; parsing and construction only count, so positions are paid for solely when you ask for them here.
pub fn ensure_exists(
doc doc: types.Document,
path path: String,
kind kind: types.TomlKind,
) -> Result(types.Document, error.MoltError)
Ensures that a table or array of tables exists at path.
kind must be types.Table or types.ArrayOfTables; other kinds are
rejected.
If the matching structure already exists, nothing is done. If path does
not resolve, an empty entry is created with implicit table ancestors as
required. If path resolves to an implicit table and kind is
types.Table, the implicit table is concretized into an emitted header
using the key segments of path.
A TypeMismatch error is returned if path resolves to any other value
shape, or if any ancestor in the path is anything other than an implicit
table, concrete table, or array of tables entry.
pub fn error_count(doc: types.Document) -> Int
The number of validation errors found in the document.
pub fn get(
doc doc: types.Document,
path path: String,
) -> Result(value.Value, error.MoltError)
Get the value or structure at path as a molt Value.
Implicit tables are returned as table values.
pub fn get_comments(
doc doc: types.Document,
path path: String,
) -> Result(ops.Comments, error.MoltError)
Reads the comments attached to the node at path.
path must resolve to a concrete node (not an implicit table) or the root
of the document (""); other paths return an error.
The result mirrors set_comments: leading comment lines and an optional
trailing (inline) comment. Comment text is returned verbatim, including the
leading #, so a value read here round-trips back through set_comments
unchanged.
pub fn get_document_comments(
doc doc: types.Document,
at at: DocumentCommentPosition,
) -> List(String)
Reads Header or Trailer document comments.
Returns the comment lines verbatim (including the leading # but without
newlines) or [] when there are no comments.
pub fn has(doc doc: types.Document, path path: String) -> Bool
Check if path exists in the document.
pub fn has_errors(doc: types.Document) -> Bool
Whether the document has any validation errors. Most document-level
operations refuse to run while this is True.
pub fn insert(
doc doc: types.Document,
path path: String,
before before: Int,
value value: value.Value,
) -> Result(types.Document, error.MoltError)
Inserts a value before index before in an array at path.
path must resolve to a value node containing an array or an array of
tables. When path resolves to an array of tables, value must be
table-like.
pub fn insert_key(
doc doc: types.Document,
path path: String,
before before: String,
key key: String,
value value: value.Value,
) -> Result(types.Document, error.MoltError)
Inserts a key/value pair before an existing key in the table at path.
path must resolve to a concrete table, array of tables entry, or
implicit table. Both before and key are literal key names (immediate
children of path). If before is not found, the entry is appended.
When path is an implicit table, the new entry is emitted as a
root-level dotted key.
pub fn keys(
doc doc: types.Document,
path p: String,
) -> Result(List(String), error.MoltError)
Return the list of keys in a table-like value at the provided path.
pub fn length(
doc doc: types.Document,
path p: String,
) -> Result(Int, error.MoltError)
Return the number of entries in an array or array of tables at path.
pub fn merge_values(
doc doc: types.Document,
path path: String,
entries entries: List(#(String, value.Value)),
on_conflict on_conflict: ops.ConflictStrategy,
) -> Result(types.Document, error.MoltError)
Merge key/value entries into the resolved table at path.
path must resolve to a concrete table or an array of tables entry;
implicit tables and other shapes are rejected with a TypeMismatch error.
Each key in entries is parsed as a path value relative to the table at
path. Index segments in entry keys will be rejected with an
InvalidPath error, and entry keys redefining any existing concrete table
or value are rejected.
The on_conflict parameter controls how collisions with existing leaf
keys are resolved.
pub fn move(
doc doc: types.Document,
from from: String,
to to: String,
) -> Result(types.Document, error.MoltError)
Moves the node at from to to.
from must resolve to an existing node of any kind except the root. to
must not already exist, and its last segment must be a key (not an index).
The node is removed from from and re-inserted at to, preserving its
structure.
pub fn move_comments(
doc doc: types.Document,
from from: String,
to to: String,
) -> Result(types.Document, error.MoltError)
Moves comments from the node at from to the node at to.
Both from and to must resolve to concrete nodes or the root of the
document ("").
pub fn move_keys(
doc doc: types.Document,
from from: String,
to to: String,
keys keys: List(String),
on_conflict on_conflict: ops.ConflictStrategy,
) -> Result(types.Document, error.MoltError)
Moves a subset of keys from the table at from into the table at to.
from must resolve to a concrete table, implicit table, or array of
tables entry. keys are literal key names naming the immediate children
of the from table. Keys not present in the from table are ignored.
If to does not exist or is an implicit table, a concrete table header
will be created. The on_conflict parameter controls how collisions
with existing keys in the to table are resolved.
pub fn normalize(doc doc: types.Document) -> types.Document
Returns a copy of the document with its tree normalized:
- Unix newlines (LF) throughout.
- Table header declarations have excess leading and interior space removed.
- Key/value pairs have excess leading space removed, a single space after
the key and a single space before the value, resulting in
key = value. - A single blank line separates table and array of tables headers.
- Leading comments are preserved immediately before their node.
- Trailing (inline) comments on key-value and header lines are preserved.
- Inline arrays and tables without comments are collapsed to a single-line form.
- The document ends with a single trailing newline.
The returned document is valid for further operations or for piping into
to_string.
pub fn parse(
source: String,
) -> Result(types.Document, error.MoltError)
Parse a TOML source string into a Document.
Returns an error if the the document cannot be parsed. Note that most documents can be parsed, but not all documents with errors produce usable or easily recoverable syntax trees.
The document’s error_count records how many validation errors were found;
retrieve the full positioned list with document_errors.
The parsed document defaults to TOML 1.1 format, even if the source file was TOML 1.0.
pub fn parse_bits(
source: BitArray,
) -> Result(types.Document, error.MoltError)
Parses a TOML source BitArray into a Document.
Returns an error if the source is not valid UTF-8 data or if the transformed
UTF-8 data fails on parse.
pub fn place(
doc doc: types.Document,
path path: String,
value value: value.Value,
) -> Result(types.Document, error.MoltError)
Unconditionally places value at path.
If path already exists, it is removed before writing the value.
Structural Values (table, array of tables, etc.) are permitted.
pub fn remove(
doc doc: types.Document,
path path: String,
) -> Result(types.Document, error.MoltError)
Removes the node at path from the document.
If path resolves to an implicit table, the implicit table and all
concrete nodes beneath it are removed.
pub fn rename(
doc doc: types.Document,
path path: String,
to to: String,
) -> Result(types.Document, error.MoltError)
Renames the last segment of path to to.
The last segment of path must be a key. to is a literal key name and
must not already exist as a sibling.
Renaming an implicit table renames all concrete descendants that reference it.
pub fn representation(
doc doc: types.Document,
path path: String,
form form: ops.Form,
) -> Result(types.Document, error.MoltError)
Converts the structure at path between inline and block forms.
path must resolve to a table or array of tables. The data is preserved;
only the representation changes (inline table ↔ table section, array of
inline tables ↔ array of tables entries).
A path that does not reference a convertible structure is
a TypeMismatch. Conversions that would produce invalid TOML (e.g.,
inlining a table with sub-table descendants) are rejected.
pub fn run(
doc doc: types.Document,
ops ops: List(ops.Operation),
) -> Result(types.Document, error.MoltError)
Execute a batch of Operations over a Document where all operations must
succeed for an update.
Operations will not run over a Document with errors.
pub fn set(
doc doc: types.Document,
path path: String,
value value: value.Value,
) -> Result(types.Document, error.MoltError)
Sets a value at path in the document.
Creates or overwrites a key/value node. If path does not exist, it is
created (with implicit ancestors as needed). If path resolves to an
existing value node, the value is replaced.
If path resolves to a structural node (table sections, array of tables,
implicit tables), Set will return a TypeMismatch error.
pub fn set_comments(
doc doc: types.Document,
path path: String,
comments comments: ops.Comments,
) -> Result(types.Document, error.MoltError)
Sets comments on the node at path.
path must resolve to a concrete node (not an implicit table) or the root
of the document (""). Replaces any existing comments on the node with the
provided comments.
pub fn set_document_comments(
doc doc: types.Document,
at at: DocumentCommentPosition,
comments comments: List(String),
) -> types.Document
Replaces Header or Trailer document comments, returning the updated
document. If the comment text does not include #, the comment text will
have # prepended. Comments must not include newlines; they will be added
appropriately on emit.
Passing [] clears the comments.
pub fn set_version(
doc doc: types.Document,
to version: types.TomlVersion,
) -> types.Document
Set the target TOML version for output.
Parsed documents default to TOML 1.1 (molt.v1_1).
pub fn to_normalized_string(doc doc: types.Document) -> String
Outputs a normalized version of the document as a string.
pub fn to_string(doc: types.Document) -> String
Generate a TOML string from the document.
If the document version is the same as the original version and no changes have been made, the original document will be reproduced exactly.
pub fn transfer(
doc doc: types.Document,
from from: String,
to to: String,
on_conflict on_conflict: ops.ConflictStrategy,
) -> Result(types.Document, error.MoltError)
Transfers all keys from from to to, then removes from.
from must resolve to a concrete or implicit table. to will be
created as a concrete table if it does not exist. The on_conflict
parameter controls how collisions with existing keys in to are
resolved.
pub fn update(
doc doc: types.Document,
path path: String,
with with: fn(value.Value) -> Result(
value.Value,
error.MoltError,
),
) -> Result(types.Document, error.MoltError)
Transforms a value in place via callback.
path must resolve to a scalar, array, or inline table value node.
Structural types (concrete tables, implicit tables, array of tables) are
rejected with TypeMismatch.
Transforming inline tables or arrays round-trips through Value, which
loses internal comments and multiline formatting.
pub fn update_error(message: String) -> error.MoltError
Creates a MoltError for returning from Update callbacks.
Update callbacks must return Result(Value, MoltError). Use this
function to signal a failure with a descriptive message.