Skip to content

Runtime Context

The second parameter on a hook is a Context: the event that fired, application state, runtime/host controls, and related helpers.

You do not construct Context yourself. The host builds one per hook call.

Reading the event

Optional

Defining a ctx parameter on a hook is optional, all of these are accepted forms of defining a hook:

@on_tick(1000)
def tick(self) -> None:
    ...

@on_tick(1000)
def tick(self, ctx: Context) -> None:
    ...

@on_tick(1000)
def tick(self, ctx: Context[SomeState]) -> None:
  ...
Reading the Event
from xnano import Context, on_keyboard

@on_keyboard("enter")
def submit(self, ctx: Context) -> None:
    key = ctx.keyboard_event  # KeyboardEventData, or None
    runtime = ctx.runtime     # active Runtime

ctx.keyboard_event and ctx.mouse_event are set only when that kind of event triggered the hook. A @on_tick handler sees None for both.

ctx.surface reports the presentation surface ("terminal", "web", or offscreen).

Typing Context by state

Context is generic over the object passed to Terminal(state=...) or Web(state=...). How application state relates to Field(state=True) and painted fields is covered under State.

Typing Context by State
import dataclasses

from xnano import BaseGrid, Context, Field, Terminal, on_keyboard

@dataclasses.dataclass
class AppState:
    count: int = 0

class Counter(BaseGrid, direction="vertical"):
    label: str = Field(default="Count: 0", height=1)

    @on_keyboard("up")
    def inc(self, ctx: Context[AppState]) -> None: # (1)!
        ctx.state.count += 1 # (2)!
        self.label = f"Count: {ctx.state.count}"

Terminal(state=AppState()).run(Counter())
  1. Context[AppState] is for type checkers; runtime behavior is unchanged.
  2. ctx.state is the same object handed to the host. ctx.get_state() raises if no state was attached.

A plain dataclass or Pydantic model works. State is an optional convenience bag (not exported from the package root):

from xnano.state import State

state = State(name="John", count=0)

Other attributes

Attribute / method Role
ctx.event Full event object
ctx.keyboard_event / ctx.mouse_event / ctx.tick_event Typed payloads (or None)
ctx.request HTTP Request when a request hook fired
ctx.surface "terminal", "web", or "offscreen"
ctx.device / ctx.cursor Host chrome (Device)
ctx.actions Synthetic actions (perform, keyboard, click, request)
ctx.stage Layout map for advanced paint
ctx.focus(group) / ctx.blur() Field focus by Field(group=...)
ctx.focused_group Current focus group name
ctx.scroll(group) Scroll handle for a named group
ctx.call_soon(...) Schedule work on the runtime
ctx.has_*_event() Predicates for keyboard, mouse, focus, resize, clipboard

ctx.terminal / ctx.host are aliases for the same runtime object as ctx.runtime. Prefer ctx.runtime in new code.

Deprecated aliases still work: ctx.keyboard, ctx.mouse, ctx.tick.

API

Context · Action · Runtime · State