Python TUI framework with mouse support, modular widget system, customizable and rapid terminal markup language and more
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
PyTermGUI provides comprehensive terminal control including ANSI escape sequences, cursor management, screen control, input handling, and mouse support. The terminal interface handles cross-platform compatibility and terminal capability detection.
Core terminal interface providing screen size detection, output management, and capability detection.
class Terminal:
"""Terminal interface and capabilities manager."""
def __init__(self):
"""Initialize terminal interface."""
@property
def size(self) -> tuple[int, int]:
"""Get terminal size as (width, height)."""
@property
def width(self) -> int:
"""Get terminal width in columns."""
@property
def height(self) -> int:
"""Get terminal height in rows."""
def print(self, *args, **kwargs):
"""Print to terminal with markup support."""
def write(self, text: str):
"""Write text directly to terminal."""
def flush(self):
"""Flush terminal output buffer."""
def record(self) -> "Recorder":
"""Start recording terminal output."""
class Recorder:
"""Terminal output recording for playback."""
def __init__(self):
"""Initialize recorder."""
def stop(self) -> str:
"""Stop recording and return content."""
def save(self, filename: str):
"""Save recording to file."""
def get_terminal() -> Terminal:
"""Get global terminal instance."""
def set_global_terminal(terminal: Terminal):
"""Set global terminal instance."""
# Global terminal instance
terminal: TerminalFunctions for managing screen buffer, clearing display, and alternate screen buffer.
def save_screen() -> None:
"""Save current screen content."""
def restore_screen() -> None:
"""Restore saved screen content."""
def set_alt_buffer() -> None:
"""Switch to alternate screen buffer."""
def unset_alt_buffer() -> None:
"""Switch back to main screen buffer."""
def clear(what: str = "screen") -> None:
"""
Clear screen or line content.
Parameters:
- what (str): What to clear ('screen', 'line', 'line_to_end', 'line_to_start')
"""Comprehensive cursor positioning and visibility control.
def hide_cursor() -> None:
"""Hide terminal cursor."""
def show_cursor() -> None:
"""Show terminal cursor."""
def save_cursor() -> None:
"""Save current cursor position."""
def restore_cursor() -> None:
"""Restore saved cursor position."""
def report_cursor() -> tuple[int, int] | None:
"""Get current cursor position as (row, col)."""
def move_cursor(pos: tuple[int, int]) -> None:
"""
Move cursor to position.
Parameters:
- pos (tuple): (row, col) position
"""
def cursor_up(num: int = 1) -> None:
"""Move cursor up by num rows."""
def cursor_down(num: int = 1) -> None:
"""Move cursor down by num rows."""
def cursor_right(num: int = 1) -> None:
"""Move cursor right by num columns."""
def cursor_left(num: int = 1) -> None:
"""Move cursor left by num columns."""
def cursor_next_line(num: int = 1) -> None:
"""Move cursor to start of next line."""
def cursor_prev_line(num: int = 1) -> None:
"""Move cursor to start of previous line."""
def cursor_column(num: int = 0) -> None:
"""Move cursor to column number."""
def cursor_home() -> None:
"""Move cursor to home position (0, 0)."""Keyboard input handling with timeout support and key code management.
class Keys:
"""Key code constants and utilities for input handling."""
def __init__(self, platform_keys: dict[str, str], platform: str):
"""
Initialize Keys object.
Parameters:
- platform_keys (dict): Platform-specific key mappings
- platform (str): Platform identifier ("nt" or "posix")
"""
# Special keys
UP: str
DOWN: str
LEFT: str
RIGHT: str
ENTER: str
RETURN: str
ESCAPE: str
ESC: str
BACKSPACE: str
DELETE: str
TAB: str
SPACE: str
ALT: str
CARRIAGE_RETURN: str
# Control keys (CTRL_A through CTRL_Z)
CTRL_A: str
CTRL_B: str
CTRL_C: str
CTRL_D: str
CTRL_E: str
CTRL_F: str
CTRL_G: str
CTRL_H: str
CTRL_I: str
CTRL_J: str
CTRL_K: str
CTRL_L: str
CTRL_M: str
CTRL_N: str
CTRL_O: str
CTRL_P: str
CTRL_Q: str
CTRL_R: str
CTRL_S: str
CTRL_T: str
CTRL_U: str
CTRL_V: str
CTRL_W: str
CTRL_X: str
CTRL_Y: str
CTRL_Z: str
CTRL_SPACE: str
# Function keys
F1: str
F2: str
F3: str
F4: str
F5: str
F6: str
F7: str
F8: str
F9: str
F10: str
F11: str
F12: str
def normalize(self, key: str) -> str:
"""Normalize key representation for consistent handling."""
def __getitem__(self, key: str) -> str:
"""Get key code by name."""
def __contains__(self, key: str) -> bool:
"""Check if key exists in mapping."""
def getch(timeout: float = None) -> str:
"""
Get single character input.
Parameters:
- timeout (float, optional): Input timeout in seconds
Returns:
Character or key code string
"""
def getch_timeout(timeout: float, interval: float = 0.01) -> str | None:
"""
Get character with timeout and polling interval.
Parameters:
- timeout (float): Maximum wait time
- interval (float): Polling interval
Returns:
Character or None if timeout
"""
def feed(text: str) -> None:
"""
Feed text to input system for testing.
Parameters:
- text (str): Text to inject into input stream
"""
# Global keys instance
keys: KeysMouse event handling and parsing for interactive applications.
class MouseAction(Enum):
"""Mouse action types."""
LEFT_CLICK: str
RIGHT_CLICK: str
MIDDLE_CLICK: str
SCROLL_UP: str
SCROLL_DOWN: str
DRAG: str
MOVE: str
class MouseEvent:
"""Mouse event data."""
def __init__(self, action: MouseAction, position: tuple[int, int]):
"""
Create mouse event.
Parameters:
- action (MouseAction): Type of mouse action
- position (tuple): (x, y) mouse position
"""
@property
def action(self) -> MouseAction:
"""Get mouse action type."""
@property
def position(self) -> tuple[int, int]:
"""Get mouse position as (x, y)."""Terminal mode management for input/output control.
def set_mode(mode: str | int, write: bool = True) -> str:
"""
Set terminal mode.
Parameters:
- mode: Mode identifier
- write (bool): Whether to write to terminal
Returns:
ANSI escape sequence
"""
def set_echo() -> None:
"""Enable input echo."""
def unset_echo() -> None:
"""Disable input echo."""Convenient context managers for terminal state management.
def alt_buffer(echo: bool = False, cursor: bool = True):
"""
Context manager for alternate screen buffer.
Parameters:
- echo (bool): Whether to disable echo, defaults to False
- cursor (bool): Whether to hide cursor, defaults to True
Usage:
with alt_buffer():
# Terminal operations in alternate buffer
pass
"""
def cursor_at(pos: tuple[int, int]):
"""
Context manager for cursor positioning with auto-incrementing y.
Parameters:
- pos (tuple): (x, y) starting position
Returns:
Callable printer function that prints at cursor position
Usage:
with cursor_at((10, 5)) as printer:
printer("Line 1") # Prints at (10, 5)
printer("Line 2") # Prints at (10, 6)
"""
def mouse_handler(events: list[str], method: str = "decimal_xterm"):
"""
Context manager for mouse input handling.
Parameters:
- events (list): List of mouse events to capture ("press", "hover", etc.)
- method (str): Mouse reporting method ("decimal_xterm" or "decimal_urxvt")
Returns:
Mouse translator function that converts key codes to MouseEvent objects
Usage:
with mouse_handler(["press", "hover"]) as mouse:
while True:
key = getch()
event = mouse(key)
if event:
print(f"Mouse {event.action} at {event.position}")
"""Context manager for input timeout operations.
def timeout(duration: float):
"""
Context manager for input timeout using SIGALRM.
Note: Not supported on Windows due to signal limitations.
Parameters:
- duration (float): Timeout duration in seconds
Raises:
- TimeoutException: When the timeout duration is exceeded
Usage:
try:
with timeout(5.0):
key = getch() # Will timeout after 5 seconds
print(f"Key pressed: {key}")
except TimeoutException:
print("Timed out waiting for input")
"""import pytermgui as ptg
# Get terminal info
term = ptg.get_terminal()
width, height = term.size
print(f"Terminal: {width}x{height}")
# Clear screen and position cursor
ptg.clear()
ptg.move_cursor((10, 5))
print("Text at position (10, 5)")
# Hide cursor during updates
ptg.hide_cursor()
# ... update display
ptg.show_cursor()import pytermgui as ptg
# Simple input loop
while True:
key = ptg.getch()
if key == ptg.keys.ESCAPE:
break
elif key == ptg.keys.UP:
print("Up arrow pressed")
elif key == ptg.keys.CTRL_C:
break
else:
print(f"Key pressed: {key}")import pytermgui as ptg
# Wait for input with timeout
try:
with ptg.timeout(5.0):
key = ptg.getch()
print(f"Key pressed: {key}")
except TimeoutError:
print("No input received within 5 seconds")import pytermgui as ptg
# Use alternate screen for full-screen app
with ptg.alt_buffer():
ptg.clear()
print("This is in the alternate buffer")
ptg.getch() # Wait for key
# Automatically returns to main bufferimport pytermgui as ptg
# Record terminal output
recorder = ptg.terminal.record()
print("This output will be recorded")
ptg.move_cursor((5, 5))
print("More recorded output")
content = recorder.stop()
recorder.save("session.txt")import pytermgui as ptg
with ptg.mouse_handler():
while True:
key = ptg.getch()
if isinstance(key, ptg.MouseEvent):
action = key.action
x, y = key.position
print(f"Mouse {action} at ({x}, {y})")
elif key == ptg.keys.ESCAPE:
breakInstall with Tessl CLI
npx tessl i tessl/pypi-pytermgui