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 a comprehensive set of utility functions for text processing, debugging, prettification, syntax highlighting, and development tools that enhance the framework's capabilities and developer experience.
Text manipulation utilities for handling markup, ANSI sequences, and display calculations.
def strip_ansi(text: str) -> str:
"""
Remove ANSI escape sequences from text.
Parameters:
- text (str): Text containing ANSI sequences
Returns:
Plain text with ANSI sequences removed
"""
def strip_markup(text: str) -> str:
"""
Remove TIM markup tags from text.
Parameters:
- text (str): Text containing TIM markup
Returns:
Plain text with markup removed
"""
def escape_markup(text: str) -> str:
"""
Escape TIM markup characters in text.
Parameters:
- text (str): Text to escape
Returns:
Text with markup characters escaped
"""
def real_length(text: str) -> int:
"""
Get display length of text excluding formatting.
Parameters:
- text (str): Text with possible markup/ANSI
Returns:
Actual display width of text
"""
def break_line(text: str, width: int, **kwargs) -> list[str]:
"""
Break text into lines fitting specified width.
Parameters:
- text (str): Text to break
- width (int): Maximum line width
- **kwargs: Additional breaking options
Returns:
List of text lines
"""Enhanced object display and prettification tools for development and debugging.
def pprint(*items, indent: int = 2, **kwargs):
"""
Pretty print objects with PyTermGUI formatting.
Parameters:
- items: Objects to print
- indent (int): Indentation level
- **kwargs: Additional formatting options
"""
def install():
"""Install pprint as default print function."""
def prettify(obj) -> str:
"""
Prettify object for display.
Parameters:
- obj: Object to prettify
Returns:
Formatted string representation
"""Code syntax highlighting with customizable highlighters and built-in language support.
class Highlighter:
"""Base syntax highlighter."""
def __init__(self):
"""Initialize highlighter."""
def highlight(self, text: str) -> str:
"""
Apply syntax highlighting to text.
Parameters:
- text (str): Source code to highlight
Returns:
Text with TIM markup for syntax colors
"""
class RegexHighlighter(Highlighter):
"""Regex-based syntax highlighter."""
def __init__(self, patterns: dict[str, str]):
"""
Create regex highlighter.
Parameters:
- patterns (dict): Mapping of regex patterns to TIM styles
"""
def add_pattern(self, name: str, pattern: str, style: str):
"""Add highlighting pattern."""
def highlight_python(text: str) -> str:
"""
Highlight Python code syntax.
Parameters:
- text (str): Python source code
Returns:
Code with syntax highlighting markup
"""
def highlight_tim(text: str) -> str:
"""
Highlight TIM markup syntax.
Parameters:
- text (str): TIM markup text
Returns:
Markup with syntax highlighting
"""Interactive object inspection tool for debugging and exploration.
class Inspector(Container):
"""Interactive object inspection widget for any Python object."""
def __init__(self, target: object = None, show_private: bool = False,
show_dunder: bool = False, show_methods: bool = False,
show_full_doc: bool = False, show_qualname: bool = True,
show_header: bool = True, **attrs):
"""
Initialize inspector widget.
Parameters:
- target: Object to inspect
- show_private (bool): Whether _private attributes should be shown
- show_dunder (bool): Whether __dunder__ attributes should be shown
- show_methods (bool): Whether methods should be shown for classes
- show_full_doc (bool): Show full docstrings vs first line only
- show_qualname (bool): Show fully-qualified names
- show_header (bool): Show header with path and qualname
"""
def inspect(self, target: object) -> "Inspector":
"""
Inspect new target object.
Parameters:
- target: Object to inspect
Returns:
Updated Inspector instance
"""
def inspect(target: object, **inspector_args) -> Inspector:
"""
Create inspector widget for object with smart defaults.
Parameters:
- target: Object to inspect
- **inspector_args: Arguments passed to Inspector constructor
Returns:
Inspector widget configured for the target type
Automatically sets appropriate defaults based on target type:
- Modules: Hide dunder/private, show methods
- Classes: Hide dunder/private, show full docs and methods
- Functions: Show full docs and qualname
"""Export terminal content to various formats for documentation and sharing.
def to_html(content: str, title: str = "Terminal Output") -> str:
"""
Export terminal content to HTML.
Parameters:
- content (str): Terminal content with ANSI/markup
- title (str): HTML document title
Returns:
Complete HTML document with styled content
"""
def token_to_css(token) -> str:
"""
Convert markup token to CSS styles.
Parameters:
- token: Markup token to convert
Returns:
CSS style string
"""Framework-specific exception classes for error handling.
class TimeoutException(Exception):
"""Raised when an action has timed out."""
class WidthExceededError(Exception):
"""Raised when an element's width is larger than the screen."""
class LineLengthError(Exception):
"""Raised when a widget line is not the expected length."""
class ColorSyntaxError(Exception):
"""Raised when a color string could not be parsed into a Color."""
class ParserSyntaxError(Exception):
"""Parent exception for unparsable strings."""
def __init__(self, tag: str, cause: str, context: str):
"""
Create parser syntax error.
Parameters:
- tag (str): The problematic tag
- cause (str): Description of the error
- context (str): Context string where error occurred
"""
@property
def message(self) -> str:
"""Create formatted error message from tag, context and cause."""
def escape_message(self) -> str:
"""Return message with markup tags escaped."""
class MarkupSyntaxError(ParserSyntaxError):
"""Raised when parsed markup text contains an error."""
class AnsiSyntaxError(ParserSyntaxError):
"""Raised when parsed ANSI text contains an error."""Protocol for enhanced object representation with TIM formatting.
class SupportsFancyRepr:
"""Protocol for objects supporting fancy representation."""
def __fancy_repr__(self) -> str:
"""Return fancy representation with TIM markup."""
def supports_fancy_repr(obj) -> bool:
"""
Check if object supports fancy repr protocol.
Parameters:
- obj: Object to check
Returns:
True if object has __fancy_repr__ method
"""
def build_fancy_repr(obj) -> str:
"""
Build fancy representation for object.
Parameters:
- obj: Object to represent
Returns:
Formatted representation with TIM markup
"""Utility context managers for common terminal operations.
def timeout(duration: float):
"""
Context manager for operations with timeout.
Parameters:
- duration (float): Timeout in seconds
"""
def alt_buffer():
"""Context manager for alternate screen buffer."""
def cursor_at(pos: tuple[int, int]):
"""
Context manager for cursor positioning.
Parameters:
- pos (tuple): (row, col) position
"""
def mouse_handler():
"""Context manager for mouse event handling."""import pytermgui as ptg
# Process text with markup and ANSI
marked_text = "[bold red]Error:[/red bold] Something went wrong"
ansi_text = "\033[1;31mError:\033[0m Something went wrong"
# Remove formatting
plain1 = ptg.strip_markup(marked_text)
plain2 = ptg.strip_ansi(ansi_text)
# Get display width
width = ptg.real_length(marked_text)
print(f"Display width: {width}")
# Break long text into lines
long_text = "This is a very long line that needs to be broken"
lines = ptg.break_line(long_text, width=20)
for line in lines:
print(f"'{line}'")
# Escape markup characters
user_input = "User said: [hello] and /goodbye/"
safe_text = ptg.escape_markup(user_input)import pytermgui as ptg
# Pretty print complex objects
data = {
"users": [
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25}
],
"settings": {
"theme": "dark",
"notifications": True
}
}
# Enhanced pretty printing
ptg.pprint(data, indent=4)
# Prettify for string representation
formatted = ptg.prettify(data)
print(formatted)
# Install as default print function
ptg.install() # Now print() uses ptg.pprintimport pytermgui as ptg
# Highlight Python code
python_code = """
def hello_world():
print("Hello, PyTermGUI!")
return True
"""
highlighted = ptg.highlight_python(python_code)
print(highlighted)
# Highlight TIM markup
markup_example = "[bold red]Error:[/red] [italic]Something happened[/italic]"
highlighted_markup = ptg.highlight_tim(markup_example)
print(highlighted_markup)
# Create custom highlighter
patterns = {
"keywords": (r"\b(if|else|for|while)\b", "[bold blue]"),
"strings": (r'"[^"]*"', "[green]"),
"numbers": (r'\b\d+\b', "[yellow]")
}
highlighter = ptg.RegexHighlighter(patterns)
code = 'if x == 42: print("Found answer")'
highlighted_code = highlighter.highlight(code)import pytermgui as ptg
# Create widget to inspect
button = ptg.Button("Test Button", lambda: print("Clicked"))
# Launch interactive inspector
ptg.inspect(button)
# Get inspection info programmatically
inspector = ptg.Inspector()
info = inspector.get_info(button)
print(info)
# Create inspection widget
inspection_widget = inspector.inspect(button)import pytermgui as ptg
# Create some terminal content
content = ptg.Container(
"[bold 210]Terminal Application",
"",
ptg.Label("[green]Status: [/green][bold]Running"),
ptg.Button("Stop", lambda: None),
width=40
)
# Export to HTML
terminal_output = str(content)
html_doc = ptg.to_html(terminal_output, title="App Screenshot")
# Save to file
with open("terminal_output.html", "w") as f:
f.write(html_doc)import pytermgui as ptg
try:
# Create widget with invalid width
container = ptg.Container(width=1000) # May exceed terminal
container.add(ptg.Label("Very long text that exceeds width"))
except ptg.WidthExceededError as e:
print(f"Width error: {e}")
try:
# Invalid markup
label = ptg.Label("[invalid markup")
except ptg.MarkupSyntaxError as e:
print(f"Markup error: {e}")import pytermgui as ptg
class CustomWidget(ptg.Widget):
"""Widget with fancy representation."""
def __init__(self, name):
super().__init__()
self.name = name
def __fancy_repr__(self) -> str:
return f"[bold blue]CustomWidget[/blue]([yellow]{self.name}[/yellow])"
# Usage
widget = CustomWidget("MyWidget")
# Check if supports fancy repr
if ptg.supports_fancy_repr(widget):
fancy_str = ptg.build_fancy_repr(widget)
print(fancy_str)import pytermgui as ptg
# Debug widget hierarchy
def debug_widget_tree(widget, indent=0):
"""Print widget hierarchy."""
spacing = " " * indent
widget_type = type(widget).__name__
widget_id = getattr(widget, 'id', 'no-id')
print(f"{spacing}{widget_type} (id: {widget_id})")
if hasattr(widget, 'widgets'):
for child in widget.widgets:
debug_widget_tree(child, indent + 1)
# Usage
container = ptg.Container(
ptg.Label("Title", id="title"),
ptg.Button("Click", id="button"),
id="main-container"
)
debug_widget_tree(container)Install with Tessl CLI
npx tessl i tessl/pypi-pytermgui