CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-prettyprinter

Syntax-highlighting, declarative and composable pretty printer for Python 3.5+

Pending
Overview
Eval results
Files

document-system.mddocs/

Document System

Low-level document creation and manipulation functions for building custom layout algorithms and pretty printers. The document system provides the foundation for prettyprinter's flexible and composable formatting capabilities.

Capabilities

Document Creation

Core functions for creating and combining document elements that represent formatted output structure.

def concat(docs):
    """
    Create document by concatenating a sequence of documents.
    
    Parameters:
    - docs: Iterable of documents (Doc instances or strings)
    
    Returns:
    - Doc: Concatenated document
    
    Notes:
    - Empty documents (NIL) are automatically filtered out
    - String arguments are automatically converted to document format
    """

def group(doc):
    """
    Create document that attempts single-line layout when possible.
    
    Parameters:
    - doc: Document to attempt to lay out on single line
    
    Returns:
    - Doc: Grouped document that tries flat layout first
    
    Notes:
    - Uses 'when_flat' branch of FlatChoice documents when fitting on one line
    - Falls back to multiline layout when content doesn't fit
    """

def nest(i, doc):
    """
    Create document with increased indentation level.
    
    Parameters:
    - i (int): Number of spaces to add to indentation
    - doc: Document to indent
    
    Returns:
    - Doc: Document with increased indentation
    """

Document Annotation

Functions for adding metadata and annotations to documents for syntax highlighting and other purposes.

def annotate(annotation, doc):
    """
    Annotate document with arbitrary metadata value.
    
    Parameters:
    - annotation: Arbitrary annotation value (often Token for syntax highlighting)
    - doc: Document to annotate
    
    Returns:
    - Doc: Annotated document with metadata
    
    Notes:
    - Annotations are preserved through layout process
    - Used extensively for syntax highlighting with Token values
    """

Contextual Documents

Create documents that are evaluated lazily based on layout context, enabling adaptive formatting based on available space and current formatting state.

def contextual(fn):
    """
    Create document that is lazily evaluated during layout.
    
    Parameters:
    - fn: Function accepting (indent, column, page_width, ribbon_width) parameters
    
    Returns:
    - Doc: Contextual document evaluated during layout
    
    Notes:
    - Enables adaptive formatting based on current layout state
    - Function is called during layout with current position and constraints
    - Returned value from function must be a valid document
    """

Advanced Layout Control

Functions providing fine-grained control over document layout behavior and line breaking.

def always_break(doc):
    """
    Create document that forces multiline layout.
    
    Parameters:
    - doc: Document to force to multiple lines
    
    Returns:
    - Doc: Document that will always break to multiple lines
    
    Notes:
    - Forces parent documents to also break to multiple lines
    - Nested documents may still be laid out flat independently
    """

def flat_choice(when_broken, when_flat):
    """
    Create document with conditional layout options.
    
    Parameters:
    - when_broken: Document used when parent is broken to multiple lines
    - when_flat: Document used when parent fits on single line
    
    Returns:
    - Doc: Document with conditional layout behavior
    
    Notes:
    - Layout algorithm chooses appropriate branch based on fitting constraints
    - Used internally by LINE, SOFTLINE constants
    """

def align(doc):
    """
    Align each new line in document with the first new line.
    
    Parameters:
    - doc: Document to align
    
    Returns:
    - Doc: Document with aligned continuation lines
    """

def hang(i, doc):
    """
    Create hanging indent document.
    
    Parameters:
    - i (int): Hanging indentation amount
    - doc: Document to apply hanging indent to
    
    Returns:
    - Doc: Document with hanging indentation
    """

def fill(docs):
    """
    Create document that fills lines optimally with content.
    
    Parameters:
    - docs: Iterable of documents to fill
    
    Returns:
    - Doc: Document with optimal line filling
    
    Notes:
    - Attempts to fit as much content as possible on each line
    - Breaks to new lines when content doesn't fit
    """

Document Constants

Pre-defined document constants for common layout elements.

# Document constants
NIL  # Empty document (no output)
LINE  # Line break or space (context-dependent)
SOFTLINE  # Line break or nothing (context-dependent)  
HARDLINE  # Forced line break

Usage Examples

Basic Document Construction

from prettyprinter.doc import concat, group, nest, always_break
from prettyprinter.doc import NIL, LINE, SOFTLINE, HARDLINE

# Simple concatenation
doc = concat(['Hello', ' ', 'World'])

# Grouped content that tries to fit on one line
grouped = group(concat(['[', '1', ',', LINE, '2', ',', LINE, '3', ']']))

# Nested indentation
indented = nest(4, concat(['def foo():', HARDLINE, 'return 42']))

Custom Pretty Printer with Documents

from prettyprinter import register_pretty
from prettyprinter.doc import concat, group, nest, annotate
from prettyprinter.doc import LINE, HARDLINE
from prettyprinter.syntax import Token

class Matrix:
    def __init__(self, rows):
        self.rows = rows

@register_pretty(Matrix)
def pretty_matrix(matrix, ctx):
    # Create rows as documents
    row_docs = []
    for row in matrix.rows:
        row_doc = concat([
            '[',
            concat([
                str(item) if i == 0 else concat([',', LINE, str(item)])
                for i, item in enumerate(row)
            ]),
            ']'
        ])
        row_docs.append(row_doc)
    
    # Combine rows with proper indentation
    return group(concat([
        annotate(Token.NAME_FUNCTION, 'Matrix'),
        '(',
        nest(ctx.indent, concat([
            HARDLINE,
            concat([
                row_doc if i == 0 else concat([',', HARDLINE, row_doc])
                for i, row_doc in enumerate(row_docs)
            ])
        ])),
        HARDLINE,
        ')'
    ]))

# Usage
matrix = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
pprint(matrix)

Contextual Document Example

from prettyprinter.doc import contextual, concat
from prettyprinter import register_pretty

class AdaptiveList:
    def __init__(self, items):
        self.items = items

@register_pretty(AdaptiveList) 
def pretty_adaptive_list(alist, ctx):
    def make_adaptive_doc(indent, column, page_width, ribbon_width):
        available_width = page_width - column
        
        if available_width > 50:
            # Wide format: all on one line
            return concat([
                'AdaptiveList([',
                ', '.join(str(item) for item in alist.items),
                '])'
            ])
        else:
            # Narrow format: vertical layout
            item_docs = [concat([str(item), ',' if i < len(alist.items)-1 else ''])
                        for i, item in enumerate(alist.items)]
            return concat([
                'AdaptiveList([',
                nest(4, concat([HARDLINE, *[concat([item_doc, HARDLINE]) 
                                          for item_doc in item_docs]])),
                '])'
            ])
    
    return contextual(make_adaptive_doc)

Advanced Layout with Flat Choice

from prettyprinter.doc import flat_choice, concat, always_break
from prettyprinter import register_pretty

class FlexibleDict:
    def __init__(self, data):
        self.data = data

@register_pretty(FlexibleDict)
def pretty_flexible_dict(fdict, ctx):
    if not fdict.data:
        return 'FlexibleDict({})'
    
    # Create key-value pair documents
    pairs = []
    for key, value in fdict.data.items():
        pair = flat_choice(
            when_broken=concat([
                repr(key), ':', HARDLINE,
                nest(4, str(value))
            ]),
            when_flat=concat([repr(key), ': ', str(value)])
        )
        pairs.append(pair)
    
    # Combine pairs
    combined = concat([
        pairs[0] if i == 0 else concat([',', LINE, pair])
        for i, pair in enumerate(pairs)
    ])
    
    return group(concat([
        'FlexibleDict({',
        nest(4, concat([SOFTLINE, combined])),
        SOFTLINE,
        '})'
    ]))

Document Validation and Debugging

from prettyprinter.doc import concat
from prettyprinter.doctypes import Doc

def debug_document_structure(doc, level=0):
    """Print document structure for debugging."""
    indent = '  ' * level
    
    if isinstance(doc, str):
        print(f"{indent}String: {repr(doc)}")
    elif isinstance(doc, Doc):
        print(f"{indent}{type(doc).__name__}")
        if hasattr(doc, 'docs'):  # Concat, Fill
            for subdoc in doc.docs:
                debug_document_structure(subdoc, level + 1)
        elif hasattr(doc, 'doc'):  # Group, Nest, AlwaysBreak, Annotated
            debug_document_structure(doc.doc, level + 1)
        elif hasattr(doc, 'when_flat'):  # FlatChoice
            print(f"{indent}  when_flat:")
            debug_document_structure(doc.when_flat, level + 2)
            print(f"{indent}  when_broken:")
            debug_document_structure(doc.when_broken, level + 2)

# Example usage
doc = group(concat(['hello', LINE, 'world']))
debug_document_structure(doc)

Custom Document Types

from prettyprinter.doctypes import Doc
from prettyprinter.doc import concat

class Highlight(Doc):
    """Custom document type for highlighting."""
    
    def __init__(self, doc, color='red'):
        self.doc = doc
        self.color = color
    
    def normalize(self):
        from prettyprinter.doc import validate_doc  # Internal function
        return Highlight(validate_doc(self.doc), self.color)
    
    def __repr__(self):
        return f'Highlight({self.doc!r}, {self.color!r})'

# Example class 
class ImportantData:
    def __init__(self, value):
        self.value = value

# Use in pretty printer
@register_pretty(ImportantData)
def pretty_important_data(data, ctx):
    return concat([
        'ImportantData(',
        Highlight(str(data.value), 'yellow'),
        ')'
    ])

Install with Tessl CLI

npx tessl i tessl/pypi-prettyprinter

docs

comments.md

configuration.md

core-printing.md

document-system.md

extras.md

index.md

registration.md

tile.json