doc

package
v0.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 8, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package doc implements the Wadler/Prettier document IR and a width-aware printer. A document is a declarative description of formatted output: text, lines that break or stay flat depending on available width, groups that decide independently whether they fit, and conditional pieces. The single printer turns any document into a string given a print width.

This is a faithful port of Prettier's document algebra (src/document/builders and src/document/printer).

A document passed to Print is mutated by break propagation. Do not print the same document concurrently, and do not reuse a document after printing it.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Dump

func Dump(d Doc) string

Dump renders the document IR as an indented tree, for debugging: every node with its type, text, group id and break state. Printing a doc mutates group break states in place, so dumping after Print shows the layout decisions.

func Print

func Print(d Doc, o Options) (string, error)

Print renders doc to a string. Options are validated; a document of an unknown shape returns an error (unreachable with the sealed Doc interface). Print mutates doc: break propagation sets group break flags.

Types

type Arena

type Arena struct {
	// contains filtered or unexported fields
}

Arena is a bump allocator for doc nodes. A document built through an arena allocates its nodes from a few growing regions instead of one heap allocation per node, at the cost of the arena retaining the regions until it is discarded. The arena must outlive the printing of the documents it built, must not be used by concurrent builders, and must not be copied after first use (it holds a printer with scratch buffers). The zero value is ready to use.

func (*Arena) Align

func (a *Arena) Align(n int, d Doc) Doc

Align indents its contents by n columns, from the arena.

func (*Arena) Concat

func (a *Arena) Concat(parts ...Doc) Doc

Concat returns a doc for parts, allocated from the arena. parts may be a Parts slice; it is kept as the node's children, so it must not be reused by the caller.

func (*Arena) ConditionalGroup

func (a *Arena) ConditionalGroup(id int, states ...Doc) Doc

ConditionalGroup tries each state in order, from the arena.

func (*Arena) Group

func (a *Arena) Group(d Doc) Doc

Group wraps d in a group allocated from the arena.

func (*Arena) GroupBreak

func (a *Arena) GroupBreak(d Doc) Doc

GroupBreak wraps d in a group that always breaks, from the arena.

func (*Arena) GroupID

func (a *Arena) GroupID(id int, d Doc) Doc

GroupID wraps d in a group with an ID, from the arena.

func (*Arena) IfBreak

func (a *Arena) IfBreak(broken, flat Doc) Doc

IfBreak builds an IfBreak for the innermost enclosing group, from the arena.

func (*Arena) IfBreakFor

func (a *Arena) IfBreakFor(broken, flat Doc, groupID int) Doc

IfBreakFor builds an IfBreak following the group with the given ID, from the arena.

func (*Arena) Indent

func (a *Arena) Indent(d Doc) Doc

Indent increases the indentation of its contents by one level, from the arena.

func (*Arena) Join

func (a *Arena) Join(sep Doc, parts []Doc) Doc

Join returns a doc for parts joined by sep, allocated from the arena.

func (*Arena) LineSuffix

func (a *Arena) LineSuffix(d Doc) Doc

LineSuffix prints its contents at the end of the current line, from the arena.

func (*Arena) Parts

func (a *Arena) Parts(capacity int) []Doc

Parts returns a scratch slice of docs with the given capacity, allocated from the arena's parts region. The region is never reused for the arena's lifetime, so the slice may become a node's children.

func (*Arena) Print

func (a *Arena) Print(d Doc, o Options) (string, error)

Print renders doc with the arena's own printer, whose scratch survives the GC as long as the arena does. Like Print, it mutates doc, and the arena must not be used concurrently.

func (*Arena) Reset

func (a *Arena) Reset()

Reset reuses the arena's regions for a fresh document: the previous document built from this arena must be dead (no references to its nodes), as its storage is overwritten. The zero value is already reset.

func (*Arena) Text

func (a *Arena) Text(s string) Doc

Text returns a doc for literal output, allocated from the arena.

type Concat

type Concat []Doc

Concat is a sequence of documents printed in order.

type Doc

type Doc interface {
	// contains filtered or unexported methods
}

Doc is a formatted document. The interface is sealed: only the concrete types in this package can implement it, so the printer can exhaustively switch over it.

var (
	Line               Doc = LineDoc{}
	SoftLine           Doc = LineDoc{Soft: true}
	HardLine           Doc = Concat{LineDoc{Hard: true}, BreakParent}
	LiteralLine        Doc = Concat{LineDoc{Hard: true, Literal: true}, BreakParent}
	CommentLine        Doc = Concat{LineDoc{Hard: true, Comment: true}, BreakParent}
	AfterCommentLine   Doc = LineDoc{Soft: true, AfterComment: true}
	HardLineNoBreak    Doc = LineDoc{Hard: true}
	LiteralLineNoBreak Doc = LineDoc{Hard: true, Literal: true}
)

Lines, matching Prettier's builders:

Line          - a space in flat mode, a newline in break mode
SoftLine      - nothing in flat mode, a newline in break mode
HardLine      - always a newline; breaks enclosing groups
LiteralLine   - always a newline with no indentation; breaks enclosing groups
CommentLine   - a hard line owning a line comment's line end; breaks
                enclosing groups; the printer remembers the line was
                comment-ended
AfterCommentLine - a soft structural line that renders a newline unless
                the output already ended with a CommentLine
var BreakParent Doc = breakParent{}

BreakParent forces the nearest enclosing group to break.

var LineSuffixBoundary Doc = lineSuffixBoundary{}

LineSuffixBoundary ends the current line-suffix group: suffixes before the boundary print at the next line break, suffixes after it wait for the one after that.

var TrimDoc Doc = trim{}

TrimDoc removes trailing whitespace from the output produced so far.

func Align

func Align(n int, d Doc) Doc

Align indents its contents by n columns relative to the current indentation. With tabs enabled, n is rounded up to one tab.

func ConditionalGroup

func ConditionalGroup(id int, states ...Doc) Doc

ConditionalGroup tries each state in order (least expanded first) and prints the first that fits; the last state breaks if none fit.

func Group

func Group(d Doc) Doc

Group wraps d in a group that breaks only when it does not fit.

func GroupBreak

func GroupBreak(d Doc) Doc

GroupBreak wraps d in a group that always breaks.

func GroupID

func GroupID(id int, d Doc) Doc

GroupID wraps d in a group with an ID so IfBreak can query its mode.

func IfBreak

func IfBreak(broken, flat Doc) Doc

IfBreak builds an IfBreak for the innermost enclosing group.

func IfBreakFor

func IfBreakFor(broken, flat Doc, groupID int) Doc

IfBreakFor builds an IfBreak that follows the group with the given ID.

func Indent

func Indent(d Doc) Doc

Indent increases the indentation of its contents by one level.

func Join

func Join(sep Doc, parts []Doc) Doc

Join returns a Concat of parts joined by sep.

func LineSuffix

func LineSuffix(d Doc) Doc

LineSuffix prints its contents at the end of the current line, after the next line break (used for end-of-line comments).

func NewText

func NewText(s string) Doc

NewText returns a doc for literal output. The value type Text also exists for direct construction; prefer NewText or Arena.Text so the node is a pointer.

type LineDoc

type LineDoc struct {
	Soft         bool
	Hard         bool
	Literal      bool // like Hard, but the newline is followed by no indentation
	Comment      bool // hard line ending a line comment's line
	AfterComment bool // soft structural line collapsing after a Comment line
}

LineDoc is a line separator. In flat mode a plain line prints a space, a soft line prints nothing, and a hard line prints a newline regardless of mode. In break mode every line prints a newline followed by the current indentation. Comment marks a hard line that ends a line comment's line: the printer remembers that the line was comment-ended, so a following AfterComment line can collapse instead of leaving a blank. AfterComment marks a soft structural line that renders a newline unless the output already ended with a Comment line (a blank line before it still renders).

type Options

type Options struct {
	// PrintWidth is the target line width; groups that do not fit within it
	// break. Must be positive.
	PrintWidth int
	// Indent is the string emitted for one indentation level (spaces or a
	// tab). Its display width is TabWidth.
	Indent string
	// TabWidth is the display width of one indentation level. Must be
	// positive.
	TabWidth int
	// NewLine is the line separator, "\n" or "\r\n".
	NewLine string
}

Options control how a document is printed.

type Text

type Text string

Text is literal output.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL