Skip to content

xnano.terminal

xnano.terminal

xnano.terminal


Run grids and components in live or offscreen terminal sessions.

Classes:

  • Terminal

    Paint and interact with an application in a terminal.

Terminal

Terminal(
    *,
    state: StateT | None = None,
    title: str | None = None,
    tick_interval: int = 16,
    mouse_events: bool = False
)

Bases: Generic[StateT]

Paint and interact with an application in a terminal.

Terminal selects a live session when one is available and otherwise uses an offscreen buffer. Use :meth:offscreen explicitly in tests.

Pass mouse_events=True to receive clicks, drags, hovers, and wheel events — required for click-to-focus and @on_click/@on_mouse hooks; it is off by default so a keyboard-only app pays nothing.

Attributes:

  • runtime (Runtime[StateT]) –

    Runtime owned by the terminal.

  • state (StateT | None) –

    Application state shared with event hooks.

  • device

    Display controls for the active session.

  • cursor

    Cursor controls for the active session.

  • actions

    Synthetic action performer.

  • stage

    Layout stage for the current root.

  • size (tuple[int, int]) –

    Viewport width and height in cells.

  • focused_group (str | None) –

    Name of the focused field group.

  • surface

    Active presentation surface.

Example

terminal = Terminal.offscreen(cols=24, rows=3) frame = terminal.render("Hello, xnano") "Hello, xnano" in frame.text True terminal.close()

Methods:

  • offscreen

    Create a terminal backed by an in-memory cell buffer.

  • supports_live_terminal

    Return whether interactive terminal sessions are available.

  • attach_grid

    Set the grid used by subsequent renders and dispatch.

  • render

    Paint one frame and return its immutable snapshot.

  • run

    Render and dispatch events until an exit is requested.

  • request_exit

    Stop the active run loop.

  • focus

    Focus a named field group.

  • blur

    Clear field focus.

  • focus_next

    Move focus forward.

  • focus_previous

    Move focus backward.

  • get_output

    Return the current cell buffer as plain text.

  • get_output_as_ansi

    Return the current cell buffer with ANSI styling.

  • copy_to_clipboard

    Copy text when the active platform supports clipboard writes.

  • close

    Restore and release the owned runtime.

Source code in xnano/terminal.py
def __init__(
    self,
    *,
    state: StateT | None = None,
    title: str | None = None,
    tick_interval: int = 16,
    mouse_events: bool = False,
) -> None:
    self._state = state
    self._title = title
    self._tick_interval = tick_interval
    self._mouse_events = mouse_events
    self._runtime: Runtime[StateT] | None = None
    self.surface = "terminal"

runtime property

runtime: Runtime[StateT]

Runtime owned by this terminal.

state property writable

state: StateT | None

Application state shared with event hooks.

device property

device

Display controls.

cursor property

cursor

Caret controls.

actions property

actions

Synthetic action performer.

stage property

stage

Layout stage for the current root.

size property

size: tuple[int, int]

Viewport width and height in cells.

focused_group property

focused_group: str | None

Name of the focused field group.

offscreen classmethod

offscreen(
    *,
    cols: int = 40,
    rows: int = 12,
    state: StateT | None = None,
    title: str | None = None
) -> "Terminal[StateT]"

Create a terminal backed by an in-memory cell buffer.

Source code in xnano/terminal.py
@classmethod
def offscreen(
    cls,
    *,
    cols: int = 40,
    rows: int = 12,
    state: StateT | None = None,
    title: str | None = None,
) -> "Terminal[StateT]":
    """Create a terminal backed by an in-memory cell buffer."""
    terminal = cls(state=state, title=title)
    terminal._runtime = Runtime.offscreen(
        cols,
        rows,
        state=state,
        title=title,
    )
    terminal.surface = "offscreen"
    return terminal

supports_live_terminal staticmethod

supports_live_terminal() -> bool

Return whether interactive terminal sessions are available.

Source code in xnano/terminal.py
@staticmethod
def supports_live_terminal() -> bool:
    """Return whether interactive terminal sessions are available."""
    return Runtime.supports_live_terminal()

attach_grid

attach_grid(grid: Any) -> None

Set the grid used by subsequent renders and dispatch.

Source code in xnano/terminal.py
def attach_grid(self, grid: Any) -> None:
    """Set the grid used by subsequent renders and dispatch."""
    self.runtime.set_root(grid)

render

render(
    *renderables: Any,
    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,
    direction: Direction = "vertical",
    color: ColorLike | None = None,
    align: Alignment | None = None
) -> Frame

Paint one frame and return its immutable snapshot.

Parameters:

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

    Grids, components, content primitives, or plain values to paint.

  • 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: 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. direction: Direction used to lay out multiple renderables.

Returns:

  • Frame

    A snapshot of the rendered terminal frame.

Source code in xnano/terminal.py
def render(
    self,
    *renderables: Any,
    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,
    direction: Direction = "vertical",
    color: ColorLike | None = None,
    align: Alignment | None = None,
) -> Frame:
    """Paint one frame and return its immutable snapshot.

    Args:
        *renderables: Grids, components, content primitives, or plain
            values to paint.
        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.
        direction: Direction used to lay out multiple renderables.

    Returns:
        A snapshot of the rendered terminal frame.
    """
    foreground = resolve_color_alias(foreground, color, stacklevel=3)
    horizontal_align = resolve_renamed_alias(
        horizontal_align,
        align,
        old="align",
        new="horizontal_align",
        stacklevel=3,
    )
    runtime = self._ensure_runtime()
    if renderables:
        runtime.set_root(renderables[0] if len(renderables) == 1 else None)
    return runtime.render(
        *renderables,
        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,
        direction=direction,
    )

run

run(
    *renderables: Any,
    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,
    direction: Direction = "vertical",
    color: ColorLike | None = None,
    align: Alignment | None = None
) -> None

Render and dispatch events until an exit is requested.

Parameters:

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

    Grids, components, content primitives, or plain values to paint.

  • 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: 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. direction: Direction used to lay out multiple renderables.

Source code in xnano/terminal.py
def run(
    self,
    *renderables: Any,
    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,
    direction: Direction = "vertical",
    color: ColorLike | None = None,
    align: Alignment | None = None,
) -> None:
    """Render and dispatch events until an exit is requested.

    Args:
        *renderables: Grids, components, content primitives, or plain
            values to paint.
        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.
        direction: Direction used to lay out multiple renderables.
    """
    foreground = resolve_color_alias(foreground, color, stacklevel=3)
    horizontal_align = resolve_renamed_alias(
        horizontal_align,
        align,
        old="align",
        new="horizontal_align",
        stacklevel=3,
    )
    runtime = self._ensure_runtime(live=True)
    if renderables:
        runtime.set_root(renderables[0] if len(renderables) == 1 else None)
    live = runtime.is_live
    render_frame = runtime._render if live else runtime.render
    try:
        while True:
            render_frame(
                *renderables,
                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,
                direction=direction,
            )
            if live:
                runtime._frame_commands.clear()
            if not runtime.pump():
                break
    finally:
        self.close()

request_exit

request_exit() -> None

Stop the active run loop.

Source code in xnano/terminal.py
def request_exit(self) -> None:
    """Stop the active run loop."""
    if self._runtime is not None:
        self._runtime.request_exit()

focus

focus(group: str) -> bool

Focus a named field group.

Source code in xnano/terminal.py
def focus(self, group: str) -> bool:
    """Focus a named field group."""
    return self.runtime.focus(group)

blur

blur() -> None

Clear field focus.

Source code in xnano/terminal.py
def blur(self) -> None:
    """Clear field focus."""
    self.runtime.blur()

focus_next

focus_next() -> bool

Move focus forward.

Source code in xnano/terminal.py
def focus_next(self) -> bool:
    """Move focus forward."""
    return self.runtime.focus_next()

focus_previous

focus_previous() -> bool

Move focus backward.

Source code in xnano/terminal.py
def focus_previous(self) -> bool:
    """Move focus backward."""
    return self.runtime.focus_previous()

get_output

get_output() -> str

Return the current cell buffer as plain text.

Source code in xnano/terminal.py
def get_output(self) -> str:
    """Return the current cell buffer as plain text."""
    return self.runtime.get_output()

get_output_as_ansi

get_output_as_ansi() -> str

Return the current cell buffer with ANSI styling.

Source code in xnano/terminal.py
def get_output_as_ansi(self) -> str:
    """Return the current cell buffer with ANSI styling."""
    return self.runtime.get_output_as_ansi()

copy_to_clipboard

copy_to_clipboard(text: str) -> bool

Copy text when the active platform supports clipboard writes.

Source code in xnano/terminal.py
def copy_to_clipboard(self, text: str) -> bool:
    """Copy text when the active platform supports clipboard writes."""
    return self.runtime.device.copy_to_clipboard(text)

close

close() -> None

Restore and release the owned runtime.

Source code in xnano/terminal.py
def close(self) -> None:
    """Restore and release the owned runtime."""
    if self._runtime is not None:
        self._runtime.close()
        self._runtime = None