Skip to content

xnano.rendering

xnano.rendering

xnano.rendering


Display styled values through a live runtime or print them as terminal text.

Functions:

  • clear_stream

    Forget a named live-output stream.

  • get_stream_content

    Return the text currently owned by a named stream.

  • render

    Display renderables as print-like terminal output.

clear_stream

clear_stream(stream: str | bool = True) -> None

Forget a named live-output stream.

Parameters:

  • stream (str | bool, default: True ) –

    Stream name, or True for the default stream.

Source code in xnano/rendering.py
def clear_stream(stream: str | bool = True) -> None:
    """Forget a named live-output stream.

    Args:
        stream: Stream name, or ``True`` for the default stream.
    """
    stream_id = _normalize_stream_id(stream)
    if stream_id is not None:
        _STREAM_REGIONS.pop(stream_id, None)

get_stream_content

get_stream_content(stream: str | bool = True) -> str

Return the text currently owned by a named stream.

Parameters:

  • stream (str | bool, default: True ) –

    Stream name, or True for the default stream.

Returns:

  • str

    Accumulated stream text, or an empty string when it does not exist.

Source code in xnano/rendering.py
def get_stream_content(stream: str | bool = True) -> str:
    """Return the text currently owned by a named stream.

    Args:
        stream: Stream name, or ``True`` for the default stream.

    Returns:
        Accumulated stream text, or an empty string when it does not exist.
    """
    stream_id = _normalize_stream_id(stream)
    region = _STREAM_REGIONS.get(stream_id) if stream_id is not None else None
    return "" if region is None else region.content

render

render(
    *renderables: Any,
    direction: Direction = "vertical",
    foreground: ColorLike | None = None,
    background: ColorLike | None = None,
    modifiers: Sequence[CharacterModifier] | None = None,
    horizontal_align: Alignment | None = None,
    vertical_align: VerticalAlignment | None = None,
    border: Border | None = None,
    border_sides: Sequence[Side] | None = None,
    border_color: ColorLike | None = None,
    title: str | None = None,
    title_position: FrameTitlePosition | None = None,
    padding: PaddingLike | None = None,
    gap: int = 0,
    sep: str | None = " ",
    end: str | None = "\n",
    file: IO[str] | TextIO | None = None,
    flush: bool = False,
    stream: str | bool | None = None,
    update: bool = False,
    color: ColorLike | None = None,
    align: Alignment | None = None
) -> None

Display renderables as print-like terminal output.

A live runtime paints the values into its current viewport. Otherwise xnano uses an offscreen native terminal and writes the resulting cells to file or standard output.

Parameters:

  • *renderables (Any, default: () ) –

    Grids, components, content primitives, or plain values.

  • direction (Direction, default: 'vertical' ) –

    Direction used to lay out multiple renderables.

  • foreground (ColorLike | None, default: None ) –

    Foreground color applied to plain values.

  • background (ColorLike | None, default: None ) –

    Background color for the rendered area.

  • modifiers (Sequence[CharacterModifier] | None, default: None ) –

    Character modifiers applied to plain values.

  • horizontal_align (Alignment | None, default: None ) –

    Horizontal alignment applied to plain values.

  • vertical_align (VerticalAlignment | None, default: None ) –

    Vertical alignment applied to plain values.

  • border (Border | None, default: None ) –

    Border style around the rendered area.

  • border_sides (Sequence[Side] | None, default: None ) –

    Border sides to draw.

  • border_color (ColorLike | None, default: None ) –

    Border foreground color.

  • title (str | None, default: None ) –

    Optional border title.

  • title_position (FrameTitlePosition | None, default: None ) –

    Border edge that holds the title.

  • padding (PaddingLike | None, default: None ) –

    Space between the border and content.

  • gap (int, default: 0 ) –

    Cells between multiple renderables.

  • sep (str | None, default: ' ' ) –

    Separator used between horizontally arranged plain values.

  • end (str | None, default: '\n' ) –

    Text appended after the rendered output.

  • file (IO[str] | TextIO | None, default: None ) –

    Text stream written outside a live runtime.

  • flush (bool, default: False ) –

    Whether to flush the output stream after writing.

  • stream (str | bool | None, default: None ) –

    Named append-or-replace output region.

  • update (bool, default: False ) –

    Replace the named stream instead of appending to it.

Source code in xnano/rendering.py
def render(
    *renderables: Any,
    direction: Direction = "vertical",
    foreground: ColorLike | None = None,
    background: ColorLike | None = None,
    modifiers: Sequence[CharacterModifier] | None = None,
    horizontal_align: Alignment | None = None,
    vertical_align: VerticalAlignment | None = None,
    border: Border | None = None,
    border_sides: Sequence[Side] | None = None,
    border_color: ColorLike | None = None,
    title: str | None = None,
    title_position: FrameTitlePosition | None = None,
    padding: PaddingLike | None = None,
    gap: int = 0,
    sep: str | None = " ",
    end: str | None = "\n",
    file: IO[str] | TextIO | None = None,
    flush: bool = False,
    stream: str | bool | None = None,
    update: bool = False,
    color: ColorLike | None = None,
    align: Alignment | None = None,
) -> None:
    """Display renderables as print-like terminal output.

    A live runtime paints the values into its current viewport. Otherwise
    xnano uses an offscreen native terminal and writes the resulting cells to
    ``file`` or standard output.

    Args:
        *renderables: Grids, components, content primitives, or plain values.
        direction: Direction used to lay out multiple renderables.
        foreground: Foreground color applied to plain values.
        background: Background color for the rendered area.
        modifiers: Character modifiers applied to plain values.
        horizontal_align: Horizontal alignment applied to plain values.
        vertical_align: Vertical alignment applied to plain values.
        border: Border style around the rendered area.
        border_sides: Border sides to draw.
        border_color: Border foreground color.
        title: Optional border title.
        title_position: Border edge that holds the title.
        padding: Space between the border and content.
        gap: Cells between multiple renderables.
        sep: Separator used between horizontally arranged plain values.
        end: Text appended after the rendered output.
        file: Text stream written outside a live runtime.
        flush: Whether to flush the output stream after writing.
        stream: Named append-or-replace output region.
        update: Replace the named stream instead of appending to it.
    """
    foreground = resolve_color_alias(foreground, color, stacklevel=3)
    horizontal_align = resolve_renamed_alias(
        horizontal_align,
        align,
        old="align",
        new="horizontal_align",
        stacklevel=3,
    )
    from xnano.core.runtime import get_active_runtime

    runtime = get_active_runtime()
    target = sys.stdout if file is None else file
    if runtime is not None and target is sys.stdout and stream is None:
        runtime.render(
            *renderables,
            direction=direction,
            foreground=foreground,
            background=background,
            modifiers=modifiers,
            horizontal_align=horizontal_align,
            vertical_align=vertical_align,
            border=border,
            border_sides=border_sides,
            border_color=border_color,
            title=title,
            title_position=title_position,
            padding=padding,
            gap=gap,
        )
        if flush:
            target.flush()
        return

    from xnano.terminal import Terminal

    values = renderables
    if direction == "horizontal" and all(
        isinstance(value, (str, int, float, bool)) for value in values
    ):
        values = ((sep if sep is not None else " ").join(map(str, values)),)
    measured_size = _plain_render_size(
        values,
        direction=direction,
        gap=gap,
        border=border,
        border_sides=border_sides,
        padding=padding,
    )
    columns, rows = (
        measured_size
        if measured_size is not None
        else shutil.get_terminal_size((80, 24))
    )
    terminal = Terminal.offscreen(cols=columns, rows=rows)
    try:
        frame = terminal.render(
            *values,
            direction=direction,
            foreground=foreground,
            background=background,
            modifiers=modifiers,
            horizontal_align=horizontal_align,
            vertical_align=vertical_align,
            border=border,
            border_sides=border_sides,
            border_color=border_color,
            title=title,
            title_position=title_position,
            padding=padding,
            gap=gap,
        )
    finally:
        terminal.close()

    # Emit ANSI when styling is present, matching print-like semantics: a
    # bare scalar with no style kwargs stays plain text, but any component,
    # grid, or content primitive carries its own color/modifiers and must
    # keep them — driving ``styled`` off the top-level kwargs alone dropped
    # the color from ``render(Text(...))``, ``render(chart)``, etc.
    styled = any(
        value is not None
        for value in (
            foreground,
            background,
            modifiers,
            border,
            border_sides,
            border_color,
        )
    ) or any(
        not isinstance(value, (str, int, float, bool)) for value in values
    )
    body = _frame_text(frame, styled=styled)
    chunk = body + ("\n" if end is None else end)
    stream_id = _normalize_stream_id(stream)
    if stream_id is None:
        target.write(chunk)
    else:
        region = _STREAM_REGIONS.setdefault(stream_id, _StreamRegion())
        if update:
            _rewind_stream_region(target, region.line_count)
            region.content = chunk
        else:
            region.content += chunk
        target.write(region.content if update else chunk)
        region.line_count = _count_display_lines(region.content)
    if flush:
        target.flush()