simvx.core.ui.terminal

TerminalEmulator – VT100 terminal emulator widget with character cell grid, cursor, scrollback buffer, and ANSI escape sequence handling.

Supports enough VT100/xterm to run interactive applications like bash, nano, vim.

Module Contents

Classes

TerminalEmulator

VT100 terminal emulator widget.

Data

API

simvx.core.ui.terminal.log

‘getLogger(…)’

simvx.core.ui.terminal.__all__

[‘TerminalEmulator’]

class simvx.core.ui.terminal.TerminalEmulator(cols: int = 80, rows: int = 24, **kwargs)[source]

Bases: simvx.core.ui.core.Control

VT100 terminal emulator widget.

Supports ANSI/VT100 escape sequences for cursor movement, text styling, scroll regions, alternate screen buffer, and more. Enough for bash + nano.

Example: term = TerminalEmulator() proc = ShellNode(“bash”, use_pty=True) term.attach(proc)

Initialization

dynamic

True

font_size

‘Property(…)’

cols

‘Property(…)’

rows

‘Property(…)’

‘Property(…)’

max_scrollback

‘Property(…)’

focus_mode

‘Property(…)’

border_colour

‘ThemeColour(…)’

resize(cols: int, rows: int)[source]

Resize the terminal grid, preserving visible content where possible.

get_minimum_size() simvx.core.math.types.Vec2[source]

Size of the whole character grid plus the scrollbar strip.

A terminal cannot be shown smaller than its grid without losing columns, so its minimum is its full size.

content_signature() object[source]
content_uses(chars: str) bool[source]
property cell_size: tuple[float, float][source]

Width and height of one character cell, in pixels.

The width is the widest advance the drawn font gives any printable ASCII character, so the grid the cursor and the click hit-testing use is the grid the glyphs actually land on and no character can reach the column beside it. Taking it from a digit instead would be right only for a face that draws every character on one body, and the face a terminal is drawn in is not always one: the engine’s own "ui" face is proportional, and a project can point the renderer at anything.

Public because anything that sizes a terminal has to work in the same cells it draws in: a panel deciding how many columns fit its width must divide by this, not by a second guess at the font’s advance, or its columns and the terminal’s stop being the same columns.

write(data: str)[source]

Feed data into the terminal, processing VT100 escape sequences.

attach(shell_node)[source]

Connect to a ShellNode’s stdout/stderr and wire input.

detach()[source]

Disconnect from the currently attached ShellNode.

get_row_text(row: int) str[source]
get_cell(row: int, col: int) simvx.core.ui.terminal._Cell | None[source]
property selected_text: str[source]

Text currently selected, or empty string.

clear_selection()[source]

Clear the current selection.

copy_selection()[source]

Copy the current selection to the system clipboard.

on_update(dt: float)[source]
on_draw(renderer)[source]
size_x

‘Property(…)’

size_y

‘Property(…)’

min_size_x

‘Property(…)’

min_size_y

‘Property(…)’

anchor_left

‘Property(…)’

anchor_top

‘Property(…)’

anchor_right

‘Property(…)’

anchor_bottom

‘Property(…)’

margin_left

‘Property(…)’

margin_top

‘Property(…)’

margin_right

‘Property(…)’

margin_bottom

‘Property(…)’

dismiss_on_outside_click

‘Property(…)’

clip_contents

‘Property(…)’

tooltip

‘Property(…)’

mouse_filter

‘Property(…)’

size_flags_horizontal

‘Property(…)’

size_flags_vertical

‘Property(…)’

stretch_ratio

‘Property(…)’

max_size

‘Property(…)’

property size: simvx.core.math.types.Vec2
property min_size: simvx.core.math.types.Vec2
autosize_to_content() None
touch_mode: str

‘mouse’

property theme: simvx.core.ui.types.Theme | None
property mouse_over: bool
property focused: bool
property disabled: bool
get_theme() simvx.core.ui.types.Theme
queue_redraw()
add_child(node: simvx.core.node.T) simvx.core.node.T
get_rect() tuple[float, float, float, float]
get_global_rect() tuple[float, float, float, float]
is_point_inside(point) bool
place_bottom_strip(height: float) None
place_top_strip(height: float) None
set_anchor_preset(preset: simvx.core.ui.enums.AnchorPreset)
activate() bool
set_focus()
grab_focus()
release_focus()
has_focus() bool
focus_next_control()
focus_previous_control()
grab_mouse()
release_mouse()
set_drag_preview(control: simvx.core.ui.core.Control)
property is_overlay_open: bool
show_overlay(modality: str = 'light', *, dim: bool | None = None, dismiss: bool | None = None, inert: bool | None = None, owner: simvx.core.ui.core.Control | None = None, initial_focus: simvx.core.ui.core.Control | None = None) None
close_overlay() None
position

‘_SpatialVecProperty(…)’

rotation

‘Property(…)’

scale

‘_SpatialVecProperty(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

render_layer

‘Property(…)’

set_render_layer(index: int, enabled: bool = True) None
is_on_render_layer(index: int) bool
property absolute_z_index: int
property rotation_degrees: float
property world_position: simvx.core.math.types.Vec2
property world_rotation: float
property world_scale: simvx.core.math.types.Vec2
property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]
property forward: simvx.core.math.types.Vec2
property right: simvx.core.math.types.Vec2
translate(offset: tuple[float, float] | numpy.ndarray)
rotate(radians: float)
rotate_deg(degrees: float)
look_at(target: tuple[float, float] | numpy.ndarray)
transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]
draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)
wrap_screen(margin: float = 20)
hdr

‘Property(…)’

property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

dev_checks: ClassVar[bool]

None

script_error_raised

‘Signal(…)’

visible

‘Property(…)’

update_mode

‘Property(…)’

__properties__: ClassVar[dict[str, simvx.core.descriptors.Property]]

None

classmethod __init_subclass__(**kwargs)
property name: str
property visible_in_tree: bool
reset_error() None
remove_child(node: simvx.core.node.Node) None
reparent(new_parent: simvx.core.node.Node)
node_at(path, default=_NO_DEFAULT)
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
expect(target, *, direct: bool = False)
ancestor(target)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
property is_scene_root: bool
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_enter_tree() None
on_exit_tree() None
on_fixed_update(dt: float) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
property render_dirty: bool
clear_children()
destroy()
property destroying: bool
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()