Core terminal control functionality providing low-level access to screen operations, cursor positioning, color handling, keyboard/mouse input, and cross-platform terminal compatibility. This forms the foundation for all asciimatics functionality.
The Screen class provides the main interface to terminal operations, offering comprehensive control over display output and input handling.
class Screen:
"""Abstract base class for terminal screen control"""
@classmethod
def open(cls, height=None, catch_interrupt=False, unicode_aware=None):
"""
Create and open a new Screen instance.
Parameters:
- height (int): Screen height (None = auto-detect)
- catch_interrupt (bool): Whether to catch interrupt signals
- unicode_aware (bool): Unicode support (None = auto-detect)
Returns:
Screen: Opened screen instance
"""
@classmethod
def wrapper(cls, func, height=None, catch_interrupt=False, arguments=None, unicode_aware=None):
"""
Context manager decorator for screen operations with automatic cleanup.
Parameters:
- func (callable): Function to execute with screen
- height (int): Screen height (None = auto-detect)
- catch_interrupt (bool): Whether to catch interrupt signals
- arguments (list): Arguments to pass to func
- unicode_aware (bool): Unicode support (None = auto-detect)
"""
def close(self, restore=True):
"""
Close screen and clean up resources.
Parameters:
- restore (bool): Whether to restore terminal state
"""
def print_at(self, text, x, y, colour=7, attr=2, bg=0):
"""
Print text at specific screen coordinates with color and attributes.
Parameters:
- text (str): Text to display
- x (int): X coordinate (column)
- y (int): Y coordinate (row)
- colour (int): Foreground color (0-7 or 256-color value)
- attr (int): Text attributes (A_BOLD, A_NORMAL, A_REVERSE, A_UNDERLINE)
- bg (int): Background color (0-7 or 256-color value)
"""
def get_from(self, x, y, length):
"""
Get character data from screen at coordinates.
Parameters:
- x (int): X coordinate (column)
- y (int): Y coordinate (row)
- length (int): Number of characters to get
Returns:
list: List of (ascii_code, colour, attr, bg) tuples
"""
def clear_buffer(self, fg, attr, bg):
"""
Clear screen buffer with specified colors.
Parameters:
- fg (int): Foreground color
- attr (int): Text attributes
- bg (int): Background color
"""
def refresh(self):
"""Update physical screen with buffer contents"""
def get_event(self):
"""
Get next input event (blocking).
Returns:
Event or None: KeyboardEvent, MouseEvent, or None if no event
"""
def has_resized(self):
"""
Check if terminal has been resized.
Returns:
bool: True if terminal was resized
"""
def play(self, scenes, stop_on_resize=False, unhandled_input=None, allow_int=False, start_scene=None, repeat=True):
"""
Play sequence of scenes.
Parameters:
- scenes (list): List of Scene objects to play
- stop_on_resize (bool): Whether to stop on terminal resize
- unhandled_input (callable): Function to handle unhandled input
- allow_int (bool): Whether to allow interrupt signals
- start_scene (str): Name of scene to start with
- repeat (bool): Whether to repeat scene sequence
"""
def set_scenes(self, scenes, unhandled_input=None, start_scene=None):
"""
Set up scenes for playback without starting.
Parameters:
- scenes (list): List of Scene objects
- unhandled_input (callable): Function to handle unhandled input
- start_scene (str): Name of scene to start with
"""
def draw_next_frame(self, repeat=True):
"""
Render next animation frame.
Parameters:
- repeat (bool): Whether to repeat scene sequence
Returns:
bool: True if more frames to render
"""
def wait_for_input(self, timeout):
"""
Wait for input with timeout.
Parameters:
- timeout (float): Timeout in seconds
Returns:
Event or None: Input event or None if timeout
"""
def set_title(self, title):
"""
Set terminal window title.
Parameters:
- title (str): Window title text
"""
def force_update(self, full_refresh=False):
"""
Force screen update.
Parameters:
- full_refresh (bool): Whether to do full screen refresh
"""
@staticmethod
def ctrl(char):
"""
Get control character code.
Parameters:
- char (str): Character to get control code for
Returns:
int: Control character code
"""
def centre(self, text, y, colour=7, attr=2, bg=0):
"""
Print centered text on specified row.
Parameters:
- text (str): Text to center
- y (int): Row to print on
- colour (int): Foreground color
- attr (int): Text attributes
- bg (int): Background color
"""
def move(self, x, y):
"""
Move cursor to coordinates.
Parameters:
- x (int): X coordinate
- y (int): Y coordinate
"""
def draw(self, x, y, text, colour, bg=0):
"""
Draw text with anti-aliased effects.
Parameters:
- x (int): X coordinate
- y (int): Y coordinate
- text (str): Text to draw
- colour (int): Color for drawing
- bg (int): Background color
"""
def fill_polygon(self, points, colour, bg=0):
"""
Fill polygon with specified color.
Parameters:
- points (list): List of (x, y) coordinate tuples
- colour (int): Fill color
- bg (int): Background color
"""
@property
def width(self):
"""Terminal width in characters"""
@property
def height(self):
"""Terminal height in characters"""
@property
def colours(self):
"""Number of colors supported by terminal"""
@property
def unicode_aware(self):
"""Whether terminal supports unicode characters"""
@property
def current_scene(self):
"""Currently active scene"""
@property
def dimensions(self):
"""Screen dimensions as (width, height) tuple"""
@property
def palette(self):
"""Available color palette"""
# Key Constants
KEY_ESCAPE = -1
KEY_F1 = -2
KEY_F2 = -3
KEY_F3 = -4
KEY_F4 = -5
KEY_F5 = -6
KEY_F6 = -7
KEY_F7 = -8
KEY_F8 = -9
KEY_F9 = -10
KEY_F10 = -11
KEY_F11 = -12
KEY_F12 = -13
KEY_F13 = -14
KEY_F14 = -15
KEY_F15 = -16
KEY_F16 = -17
KEY_F17 = -18
KEY_F18 = -19
KEY_F19 = -20
KEY_F20 = -21
KEY_F21 = -22
KEY_F22 = -23
KEY_F23 = -24
KEY_F24 = -25
KEY_LEFT = -26
KEY_RIGHT = -27
KEY_UP = -28
KEY_DOWN = -29
KEY_HOME = -30
KEY_END = -31
KEY_PAGE_UP = -32
KEY_PAGE_DOWN = -33
KEY_INSERT = -34
KEY_DELETE = -35
KEY_BACK = -36
KEY_TAB = -37
KEY_BACK_TAB = -38
KEY_PRINT_SCREEN = -39
KEY_PAUSE = -40
KEY_MENU = -41
KEY_CAPS_LOCK = -42
KEY_NUM_LOCK = -43
KEY_SCROLL_LOCK = -44ManagedScreen provides a context manager for safe screen operations with automatic cleanup and error handling.
class ManagedScreen:
"""Context manager for Screen operations with automatic cleanup"""
def __init__(self, func=lambda: None):
"""
Initialize managed screen context.
Parameters:
- func (callable): Function to execute with screen (default: lambda: None)
"""
def run(self):
"""Execute the managed screen function"""
def __enter__(self):
"""Enter context manager"""
def __exit__(self, exc_type, exc_val, exc_tb):
"""Exit context manager with cleanup"""Canvas classes provide drawing surfaces for complex graphics operations and temporary drawing contexts.
class Canvas:
"""Main drawing canvas for complex graphics"""
def __init__(self, screen, height, width, x, y, buffer=None):
"""
Initialize drawing canvas.
Parameters:
- screen (Screen): Parent screen
- height (int): Canvas height
- width (int): Canvas width
- x (int): Canvas X position
- y (int): Canvas Y position
- buffer (list): Optional existing buffer
"""
def print_at(self, text, x, y, colour=7, attr=2, bg=0):
"""Print text on canvas at coordinates"""
def clear_buffer(self, fg, attr, bg):
"""Clear canvas buffer"""
def update(self, frame_no):
"""Update canvas for animation frame"""
class TemporaryCanvas:
"""Temporary drawing canvas for short-lived operations"""
def __init__(self, screen, height, width, x=0, y=0):
"""
Initialize temporary canvas.
Parameters:
- screen (Screen): Parent screen
- height (int): Canvas height
- width (int): Canvas width
- x (int): Canvas X position
- y (int): Canvas Y position
"""
def close(self, restore=True):
"""
Close temporary canvas.
Parameters:
- restore (bool): Whether to restore previous screen content
"""Event classes for processing keyboard and mouse input with unicode support and detailed event information.
class Event:
"""Base class for all input events"""
pass
class KeyboardEvent(Event):
"""Keyboard input event with unicode support"""
def __init__(self, key_code):
"""
Initialize keyboard event.
Parameters:
- key_code (int): Key code or unicode value
"""
@property
def key_code(self):
"""The key code that was pressed"""
class MouseEvent(Event):
"""Mouse input event with position and button information"""
def __init__(self, x, y, buttons):
"""
Initialize mouse event.
Parameters:
- x (int): Mouse X coordinate
- y (int): Mouse Y coordinate
- buttons (int): Button state bitfield
"""
@property
def x(self):
"""Mouse X coordinate"""
@property
def y(self):
"""Mouse Y coordinate"""
@property
def buttons(self):
"""Button state (bitfield)"""Utility functions and classes for screen-related operations and drawing assistance.
def readable_mem(mem):
"""
Convert bytes to human-readable format.
Parameters:
- mem (int): Memory size in bytes
Returns:
str: Human-readable memory string (e.g., "1.5 KB", "2.3 MB")
"""
def readable_timestamp(stamp):
"""
Convert POSIX timestamp to human-readable format.
Parameters:
- stamp (float): POSIX timestamp
Returns:
str: Human-readable timestamp string
"""
class BoxTool:
"""Utility for drawing bordered boxes"""
def __init__(self, unicode_aware, style=1):
"""
Initialize box drawing tool.
Parameters:
- unicode_aware (bool): Whether to use unicode line drawing
- style (int): Line style (ASCII_LINE, SINGLE_LINE, DOUBLE_LINE)
"""
def box(self, width, height):
"""
Generate complete box string.
Parameters:
- width (int): Box width
- height (int): Box height
Returns:
list: List of strings representing box lines
"""
def box_top(self, width):
"""
Generate top border string.
Parameters:
- width (int): Border width
Returns:
str: Top border string
"""
def box_bottom(self, width):
"""
Generate bottom border string.
Parameters:
- width (int): Border width
Returns:
str: Bottom border string
"""
def box_line(self, width):
"""
Generate side borders string.
Parameters:
- width (int): Content width
Returns:
str: Side borders template string
"""from asciimatics.screen import ManagedScreen
from asciimatics import constants
def demo(screen):
# Clear screen with blue background
screen.clear_buffer(constants.COLOUR_WHITE, constants.A_NORMAL, constants.COLOUR_BLUE)
# Print colored text
screen.print_at("Hello World!", 10, 5,
constants.COLOUR_YELLOW, constants.A_BOLD, constants.COLOUR_BLUE)
# Center text on screen
screen.centre("Centered Text", screen.height // 2,
constants.COLOUR_GREEN, constants.A_NORMAL)
# Draw a simple line
for x in range(20, 60):
screen.print_at("-", x, 10, constants.COLOUR_RED)
# Update screen and wait for key
screen.refresh()
screen.get_event()
ManagedScreen(demo).run()from asciimatics.screen import ManagedScreen
from asciimatics.event import KeyboardEvent, MouseEvent
from asciimatics import constants
def interactive_demo(screen):
screen.print_at("Press keys or move mouse. 'q' to quit.", 0, 0)
screen.refresh()
while True:
event = screen.get_event()
if event:
if isinstance(event, KeyboardEvent):
if event.key_code == ord('q'):
break
screen.print_at(f"Key: {event.key_code}", 0, 2, constants.COLOUR_GREEN)
elif isinstance(event, MouseEvent):
screen.print_at(f"Mouse: ({event.x}, {event.y}) buttons:{event.buttons}",
0, 3, constants.COLOUR_YELLOW)
screen.refresh()
ManagedScreen(interactive_demo).run()from asciimatics.screen import ManagedScreen, Canvas
from asciimatics import constants
def canvas_demo(screen):
# Create a canvas for drawing
canvas = Canvas(screen, 20, 40, 10, 5)
# Draw on canvas
canvas.print_at("Canvas Drawing", 5, 2, constants.COLOUR_CYAN, constants.A_BOLD)
# Draw a border
for x in range(40):
canvas.print_at("*", x, 0, constants.COLOUR_RED)
canvas.print_at("*", x, 19, constants.COLOUR_RED)
for y in range(20):
canvas.print_at("*", 0, y, constants.COLOUR_RED)
canvas.print_at("*", 39, y, constants.COLOUR_RED)
# Update screen
canvas.update(0)
screen.get_event()
ManagedScreen(canvas_demo).run()