Document Printer¶
A Wadler-Leijen Pretty Printer in Python.
Documents¶
- class doc_printer.doc.Doc¶
The abstract class for all documents.
- doc_printer.doc.DocLike¶
DocLike is an alias for any type which can be coerced into a document:
a string;
a document;
a sequence of things that can be coerced into documents.
Strings are converted using
Text.lines()
. alias ofstr
|Doc
|Iterable
[DocLike
] |None
Basic tokens¶
Text is the type for all concrete tokens in the document.
Text tokens are assumed to be free from whitespaces and newlines, but the constructor cannot guarantee that. The safe way to construct tokens from unknown strings is to use
Text.lines()
.
- class doc_printer.doc.Text(text: str)¶
A single line of text.
The type of string tokens.
There are several singleton instances of
Text
:
Concatenating documents¶
Two documents can be combined as
doc1 / doc2
or, separated by a space, asdoc1 // doc2
.
- Doc.__floordiv__(other: str | Doc | Iterable[DocLike] | None) Doc ¶
Compose two documents, separated by a space.
There are corresponding implementations of
__rtruediv__
and__rfloordiv__
, so that either the left or the right argument to the operator can be a string.These methods are implemented in terms of
Doc.then()
.A stream of documents can be combined with a separator using
Doc.join()
.
- Doc.join(*others: str | Doc | Iterable[DocLike] | None) Doc ¶
Compose a series of documents separated by this document.
All of these methods are implemented in terms of
cat()
.
Parentheses¶
Alternative layout options¶
Two alternative layouts can be combined as alt1 | alt2.
- Doc.__or__(other: str | Doc | Iterable[DocLike] | None) Doc ¶
Combine two documents as alternatives.
When alternatives are combined, it’s important that the alternative whose first line is the shortest comes first.
There is a corresponding implementations of
__ror__
, so that either the left or the right argument to the operator can be a string.This method is implemented in terms of
alt()
.
- class doc_printer.doc.Alt(alts: Tuple[Doc, ...])¶
Alternatives for the document layout.
The type of alternate document layouts.
There are several singleton instances of
Alt
:
- doc_printer.doc.Fail = Fail¶
Alternatives for the document layout.
The empty list of alternatives, meaning the current layout has failed.
- doc_printer.doc.SoftLine = SoftLine¶
Alternatives for the document layout.
The optional newline, which lets the renderer know it is allowed to insert a newline in this place.
Identation¶
Alignment¶
Alignment is done via
Row
andTable
. You can create tables usingrow()
andtable()
.
- doc_printer.doc.row(*doclike: str | Doc | Iterable[DocLike] | None, table_type: str | None = None, hpad: str | Text = Space, hsep: str | Text = Space, min_col_widths: Tuple[int | None, ...] = ()) Doc ¶
Smart constructor for
Row
.Alternatively, you can merge existing rows into a table using
create_tables()
.
- doc_printer.doc.create_tables(docs: Iterator[Doc], *, separator: Text = Line) Iterator[Doc] ¶
Merges sequences of rows with the same
RowInfo.table_type
into a table, and inserts it as an alternative into the document.
Rendering¶
Documents are rendered as a stream of doc_printer.doc.Token
, which are joined into a string by doc_printer.abc.DocRenderer.to_str
.
- doc_printer.doc.Token: TypeAlias = <class 'doc_printer.doc.Text'>¶
A single line of text.
Rendering Naively¶
The simple renderer for documents ignores all alternatives, simply choosing the first alternative, which should have the shortest line length.
- class doc_printer.simple.SimpleDocRenderer(simple_layout: doc_printer.simple.SimpleLayout = <SimpleLayout.ShortestLines: 0>, on_emit: List[Callable[[doc_printer.doc.Text], doc_printer.doc.Text]] = <factory>)¶
- render_simple(doc: Doc) Iterator[Text] ¶
- render_simple(doc: Text) Iterator[Text]
- render_simple(doc: Alt) Iterator[Text]
- render_simple(doc: Cat) Iterator[Text]
- render_simple(doc: Row) Iterator[Text]
- render_simple(doc: Table) Iterator[Text]
- render_simple(doc: Nest) Iterator[Text]
- render_simple(doc: Edit) Iterator[Text]
Rendering Tables¶
Tables are cached, to calculate their column widths and insert the appropriate spacing.
To create these buffers, SimpleDocRenderer.buffer_table()
and SimpleDocRenderer.buffer_row()
are provided.
- SimpleDocRenderer.buffer_table(table: Table) TableBuffer ¶
Table buffers are rendered using the TableBuffer.render()
.
It is important to call TableBuffer.update()
once, just before rendering, as this calculates the needed column widths.
- class doc_printer.table.RowBuffer(hsep: Text, min_col_widths: Tuple[int | None, ...])¶
- append(cell: CellBuffer) None ¶
- extend(cells: Iterable[CellBuffer]) None ¶
Rendering with Lookahead¶
Finally, the smart renderer uses one level of lookahead.
When rendering a series of alternatives, it renders the first line of each alternative using the simple renderer, and picks the alternative that best fills up the current line.
- class doc_printer.smart.SmartDocRenderer(simple_layout: doc_printer.simple.SimpleLayout = <SimpleLayout.ShortestLines: 0>, on_emit: List[Callable[[doc_printer.doc.Text], doc_printer.doc.Text]] = <factory>, max_line_width: int = 80)¶