Formatter DSL¶
The user-facing formatting DSL is built around pegium::AbstractFormatter. This page is the canonical API surface; it complements the task-oriented formatting guide.
Creating a formatter¶
To build a formatter:
- derive from
AbstractFormatter - call the base constructor with
services - register formatting methods in the constructor with
on<T>(...) - assign an instance to
services->lsp.formatter
class MyFormatter : public pegium::AbstractFormatter {
public:
explicit MyFormatter(const pegium::Services &services)
: AbstractFormatter(services) {
on<ast::Entity>(&MyFormatter::formatEntity);
onHidden("ML_COMMENT", &MyFormatter::formatComment);
}
protected:
virtual void formatEntity(pegium::FormattingBuilder &builder,
const ast::Entity *entity) const;
virtual void formatComment(HiddenNodeFormatter &comment) const;
};
Wire it into the services:
services->lsp.formatter = std::make_unique<lsp::MyFormatter>(*services);
Registration¶
Register one method per exact AST type:
on<ast::Module>(&MyFormatter::formatModule);
on<ast::Entity>(&MyFormatter::formatEntity);
onHidden("ML_COMMENT", &MyFormatter::formatComment);
Registering the same AST type or hidden terminal rule twice overrides the previous registration.
Don't override the global format(...) fallback. Register typed methods and let the formatter engine dispatch them as it walks the AST.
Main entry points¶
format(FormattingBuilder &, const AstNode *)¶
Override this only for advanced fallback behavior.
FormattingBuilder::getNodeFormatter(const NodeT *node)¶
Returns a node-scoped selector for the supplied AST node.
NodeFormatter<T> selectors¶
property<&T::member>()property<&T::vectorMember>(index)properties<&T::member...>()keyword("...")keyword("...", index)keywords("...", "...")hidden("RULE")hiddens("RULE")interior(start, end)
Every selection produces a FormattingRegion.
FormattingRegion¶
prepend(action)append(action)surround(action)slice(start)slice(start, end)
Selections are CST-backed and keep document order.
Built-in actions¶
These helpers are protected members of AbstractFormatter:
noSpaceoneSpacespaces(count)newLinenewLines(count)indentnoIndentfit(...)
Use them directly inside formatting methods:
formatter.keyword("entity").append(oneSpace);
formatter.property<&ast::Field::name>().prepend(oneSpace);
Hidden nodes¶
Format hidden nodes with HiddenNodeFormatter:
node()ruleName()text()baseIndentation()indentation(delta)replace(text)prepend(action)append(action)surround(action)
Generic helpers¶
AbstractFormatter provides higher-level helpers for common patterns such as brace blocks, comma-separated lists, and comment normalization:
formatBlock(open, close, content, options)formatSeparatedList(separators, options)formatLineComment(text, options)formatLineComment(hiddenNode, options)formatMultilineComment(text, options)formatMultilineComment(hiddenNode, options)