Skip to content

Terminal

A Terminal is a presentation host: it owns a live or offscreen session, paints frames, and dispatches keyboard, mouse, and tick events into your grids' @on_* hooks.

Grids do not open a session by themselves. Pass content to Terminal (or to render for a one-shot frame).

One frame

render paints once and returns control. It does not run the event loop.

Interactive

This code block runs in the browser via Pyodide.

Try editing the code!
  • Change the string.
  • Change color (e.g. "emerald-400").

Editor (session: default)Run
from xnano import render

render("hello, terminal!", foreground="blue")
OutputClear

render()
from xnano import render

render("hello, terminal!", foreground="blue") # (1)!
  1. Opens a short-lived paint path, writes the frame, then stops.

A live session

Terminal().run(...) keeps painting and dispatching until exit.

A Persistent Session
from xnano import Terminal

terminal = Terminal()
terminal.run("hello, terminal!") # (1)!
  1. Unlike render(), .run() stays open until the app exits.

Terminal also has .render(...) for a single frame on that host (returns a Frame).

Running a grid

Pass a BaseGrid as the root. Fields become regions of the screen; hooks on the grid receive events.

Running a Grid
from xnano import BaseGrid, Field, Terminal

class App(BaseGrid, direction="vertical"):
    title: str = Field(default="My App", border="rounded")
    name: str = Field(default="Hammad", state=True)

terminal = Terminal()
terminal.run(App()) # (1)!
  1. Layout and field details are covered under Grids and Fields.

Runnable Example

Interactive

This code block runs in the browser via Pyodide.

Try editing the code!
  • Change title's default=.
  • Change border on the title field.

Editor (session: default)Run
from xnano import BaseGrid, Field, render

class App(BaseGrid, direction="vertical"):
    title: str = Field(default="My App", border="rounded")
    body: str = Field(default="Hello")

# As Terminal.render() requires a live terminal session, we cannot use it
# here in the browser directly.
render(App())
OutputClear

State and mouse

Application-wide state is attached at construction and available on every hook as ctx.state (see Context):

Terminal(state=AppState()).run(App())

Mouse input is off by default. Enable it when you need click-to-focus, @on_click, or @on_mouse:

Terminal(state=AppState(), mouse_events=True).run(App())

Constructor options include state=, title=, tick_interval=, and mouse_events=. Exit a running loop with terminal.request_exit() or ctx.runtime.request_exit() from a hook.

Terminal does not serve HTTP. Browser hosting is Web. Request handlers are Requests.

Under the hood, Terminal owns a Runtime (terminal.runtime). Prefer Terminal in apps; use Runtime when you need explicit session ownership. Frame is the immutable snapshot returned by .render(...).

Next

API

Terminal · render() · Runtime · Frame