CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-py-cui

A widget and grid based framework for building command line user interfaces in python.

Pending
Overview
Eval results
Files

widgets.mddocs/

Widget Creation and Management

Methods for creating and managing all widget types including scroll menus, text boxes, buttons, labels, and custom widgets. Includes widget positioning, removal, and focus management.

Capabilities

Scroll Menu Widgets

Scrollable menu widgets for displaying selectable lists of items.

def add_scroll_menu(title: str, row: int, column: int, row_span: int = 1,
                   column_span: int = 1, padx: int = 1, pady: int = 0) -> ScrollMenu:
    """
    Add a scrollable menu widget to the grid.
    
    Parameters:
    - title: Widget title displayed in border
    - row: Grid row position (0-indexed)
    - column: Grid column position (0-indexed)  
    - row_span: Number of rows to span (default: 1)
    - column_span: Number of columns to span (default: 1)
    - padx: Horizontal padding in characters (default: 1)
    - pady: Vertical padding in characters (default: 0)
    
    Returns:
    ScrollMenu widget instance
    """

class ScrollMenu:
    def add_item(item: Any) -> None: ...
    def add_item_list(item_list: List[Any]) -> None: ...
    def remove_selected_item() -> None: ...
    def remove_item(item: Any) -> None: ...
    def get_item_list() -> List[Any]: ...
    def get() -> Optional[Any]: ...
    def get_selected_item() -> Optional[Any]: ...
    def is_empty() -> bool: ...
    def set_selected_item(selected_item: Any) -> None: ...
    def get_selected_item_index() -> int: ...
    def set_selected_item_index(selected_item_index: int) -> None: ...
    def clear() -> None: ...
    def set_on_selection_change_event(callback: Callable[[Any], Any]) -> None: ...

Usage example:

root = py_cui.PyCUI(3, 3)
menu = root.add_scroll_menu('Options', 0, 0, row_span=2)

menu.add_item('Option 1')
menu.add_item('Option 2') 
menu.add_item_list(['Option 3', 'Option 4', 'Option 5'])

def handle_selection():
    selected = menu.get_selected_item()
    print(f'Selected: {selected}')
    
menu.add_key_command(py_cui.keys.KEY_ENTER, handle_selection)

Checkbox Menu Widgets

Menu widgets with checkboxes for multiple selections.

def add_checkbox_menu(title: str, row: int, column: int, row_span: int = 1,
                     column_span: int = 1, padx: int = 1, pady: int = 0,
                     checked_char: str = "X") -> CheckBoxMenu:
    """
    Add a checkbox menu widget to the grid.
    
    Parameters:
    - title: Widget title displayed in border
    - row: Grid row position (0-indexed)
    - column: Grid column position (0-indexed)
    - row_span: Number of rows to span (default: 1)
    - column_span: Number of columns to span (default: 1)
    - padx: Horizontal padding in characters (default: 1)
    - pady: Vertical padding in characters (default: 0)
    - checked_char: Character to display for checked items (default: "X")
    
    Returns:
    CheckBoxMenu widget instance
    """

class CheckBoxMenu:
    def add_item(text: str, checked: bool = False) -> None: ...
    def add_item_list(item_list: List[str]) -> None: ...
    def get_checked_items() -> List[str]: ...
    def mark_item_as_checked(item_index: int) -> None: ...
    def mark_item_as_unchecked(item_index: int) -> None: ...
    def toggle_item_checked(item_index: int) -> None: ...

Usage example:

root = py_cui.PyCUI(3, 3)
checkbox_menu = root.add_checkbox_menu('Features', 0, 1, checked_char='✓')

checkbox_menu.add_item('Feature A', True)  # Initially checked
checkbox_menu.add_item('Feature B', False)
checkbox_menu.add_item_list(['Feature C', 'Feature D'])

def show_checked():
    checked = checkbox_menu.get_checked_items()
    print(f'Checked items: {checked}')
    
def toggle_current():
    current_index = checkbox_menu.get_selected_item_index()
    checkbox_menu.toggle_item_checked(current_index)

checkbox_menu.add_key_command(py_cui.keys.KEY_SPACE, toggle_current)

Text Input Widgets

Single-line text input widgets for user text entry.

def add_text_box(title: str, row: int, column: int, row_span: int = 1,
                 column_span: int = 1, padx: int = 1, pady: int = 0,
                 initial_text: str = "", password: bool = False) -> TextBox:
    """
    Add a text input box widget to the grid.
    
    Parameters:
    - title: Widget title displayed in border
    - row: Grid row position (0-indexed)
    - column: Grid column position (0-indexed)
    - row_span: Number of rows to span (default: 1)
    - column_span: Number of columns to span (default: 1) 
    - padx: Horizontal padding in characters (default: 1)
    - pady: Vertical padding in characters (default: 0)
    - initial_text: Initial text content (default: "")
    - password: If True, display '*' instead of characters (default: False)
    
    Returns:
    TextBox widget instance
    """

class TextBox:
    def get() -> str: ...
    def set_text(text: str) -> None: ...
    def clear() -> None: ...
    def write(text: str) -> None: ...

Usage example:

root = py_cui.PyCUI(3, 3)
name_box = root.add_text_box('Name', 0, 0, initial_text='Enter name...')
password_box = root.add_text_box('Password', 1, 0, password=True)

def submit_form():
    name = name_box.get()
    password = password_box.get()
    print(f'Name: {name}, Password: {"*" * len(password)}')
    
submit_btn = root.add_button('Submit', 2, 0, command=submit_form)

Multi-line Text Display

Scrollable text block widgets for displaying multi-line text content.

def add_text_block(title: str, row: int, column: int, row_span: int = 1,
                   column_span: int = 1, padx: int = 1, pady: int = 0,
                   initial_text: str = "") -> ScrollTextBlock:
    """
    Add a scrollable text block widget to the grid.
    
    Parameters:
    - title: Widget title displayed in border
    - row: Grid row position (0-indexed)
    - column: Grid column position (0-indexed)
    - row_span: Number of rows to span (default: 1)
    - column_span: Number of columns to span (default: 1)
    - padx: Horizontal padding in characters (default: 1)
    - pady: Vertical padding in characters (default: 0)
    - initial_text: Initial text content (default: "")
    
    Returns:
    ScrollTextBlock widget instance
    """

class ScrollTextBlock:
    def set_text(text: str) -> None: ...
    def get_text() -> str: ...
    def write(text: str) -> None: ...
    def clear() -> None: ...
    def scroll_up() -> None: ...
    def scroll_down() -> None: ...

Usage example:

root = py_cui.PyCUI(3, 3)
log_block = root.add_text_block('Log Output', 0, 0, row_span=3, column_span=2)

log_block.set_text('Application started...\nInitializing components...')
log_block.write('\nReady for input.')

# Add scroll controls
log_block.add_key_command(py_cui.keys.KEY_UP_ARROW, log_block.scroll_up)
log_block.add_key_command(py_cui.keys.KEY_DOWN_ARROW, log_block.scroll_down)

Label Widgets

Simple text labels for displaying static text.

def add_label(title: str, row: int, column: int, row_span: int = 1,
              column_span: int = 1, padx: int = 1, pady: int = 0) -> Label:
    """
    Add a simple label widget to the grid.
    
    Parameters:
    - title: Widget title and text content
    - row: Grid row position (0-indexed)
    - column: Grid column position (0-indexed)
    - row_span: Number of rows to span (default: 1)
    - column_span: Number of columns to span (default: 1)
    - padx: Horizontal padding in characters (default: 1)
    - pady: Vertical padding in characters (default: 0)
    
    Returns:
    Label widget instance
    """

def add_block_label(title: str, row: int, column: int, row_span: int = 1,
                   column_span: int = 1, padx: int = 1, pady: int = 0,
                   center: bool = True) -> BlockLabel:
    """
    Add a block-style label widget to the grid.
    
    Parameters:
    - title: Widget title and text content
    - row: Grid row position (0-indexed)
    - column: Grid column position (0-indexed)  
    - row_span: Number of rows to span (default: 1)
    - column_span: Number of columns to span (default: 1)
    - padx: Horizontal padding in characters (default: 1)
    - pady: Vertical padding in characters (default: 0)
    - center: Whether to center the text (default: True)
    
    Returns:
    BlockLabel widget instance
    """

class Label:
    def set_title(title: str) -> None: ...
    def get_title() -> str: ...

class BlockLabel(Label):
    def set_text(text: str) -> None: ...
    def get_text() -> str: ...

Usage example:

root = py_cui.PyCUI(3, 3)
header = root.add_block_label('Welcome to My App', 0, 0, column_span=3, center=True)
status = root.add_label('Status: Ready', 2, 0)

status.set_title('Status: Processing...')

Button Widgets

Clickable button widgets that execute commands when activated.

def add_button(title: str, row: int, column: int, row_span: int = 1,
               column_span: int = 1, padx: int = 1, pady: int = 0,
               command: Callable[[], Any] = None) -> Button:
    """
    Add a button widget to the grid.
    
    Parameters:
    - title: Button text
    - row: Grid row position (0-indexed)
    - column: Grid column position (0-indexed)
    - row_span: Number of rows to span (default: 1)
    - column_span: Number of columns to span (default: 1)
    - padx: Horizontal padding in characters (default: 1)
    - pady: Vertical padding in characters (default: 0)
    - command: Function to execute when button is pressed (optional)
    
    Returns:
    Button widget instance
    """

class Button:
    def set_command(command: Callable[[], Any]) -> None: ...
    def get_command() -> Callable[[], Any]: ...

Usage example:

def save_data():
    print('Saving data...')
    
def load_data():
    print('Loading data...')

root = py_cui.PyCUI(3, 3)
save_btn = root.add_button('Save', 0, 0, command=save_data)
load_btn = root.add_button('Load', 0, 1, command=load_data)

# Change button command later
save_btn.set_command(lambda: print('Save with new logic'))

Slider Widgets

Slider controls for numeric value selection.

def add_slider(title: str, row: int, column: int, row_span: int = 1,
               column_span: int = 1, padx: int = 1, pady: int = 0,
               min_val: int = 0, max_val: int = 100, step: int = 1,
               init_val: int = 0) -> SliderWidget:
    """
    Add a slider widget to the grid.
    
    Parameters:
    - title: Widget title displayed in border
    - row: Grid row position (0-indexed)
    - column: Grid column position (0-indexed)
    - row_span: Number of rows to span (default: 1)
    - column_span: Number of columns to span (default: 1)
    - padx: Horizontal padding in characters (default: 1) 
    - pady: Vertical padding in characters (default: 0)
    - min_val: Minimum slider value (default: 0)
    - max_val: Maximum slider value (default: 100)
    - step: Step size for value changes (default: 1)
    - init_val: Initial slider value (default: 0)
    
    Returns:
    SliderWidget instance
    """

class SliderWidget:
    def get_slider_value() -> float: ...
    def update_slider_value(offset: int) -> float: ...
    def set_slider_step(step: int) -> None: ...
    def set_bar_char(char: str) -> None: ...
    def toggle_title() -> None: ...
    def toggle_border() -> None: ...
    def toggle_value() -> None: ...
    def align_to_top() -> None: ...

Usage example:

root = py_cui.PyCUI(3, 3)
volume_slider = root.add_slider('Volume', 0, 0, min_val=0, max_val=100, init_val=50)

def update_volume():
    volume = volume_slider.get_slider_value()
    print(f'Volume set to: {volume}%')
    
volume_slider.add_key_command(py_cui.keys.KEY_ENTER, update_volume)

Custom Widget Support

System for adding custom widget types not included with py_cui by default.

def add_custom_widget(widget_class: type, title: str, row: int, column: int,
                     row_span: int, column_span: int, padx: int, pady: int,
                     *args, **kwargs) -> Widget:
    """
    Add a custom widget type to the grid.
    
    Parameters:
    - widget_class: Custom widget class (must inherit from Widget)
    - title: Widget title displayed in border
    - row: Grid row position (0-indexed)
    - column: Grid column position (0-indexed)
    - row_span: Number of rows to span
    - column_span: Number of columns to span
    - padx: Horizontal padding in characters
    - pady: Vertical padding in characters
    - *args, **kwargs: Additional arguments passed to widget constructor
    
    Returns:
    Custom widget instance
    
    Raises:
    TypeError: If widget_class is not a subclass of Widget
    """

Usage example:

import py_cui

class CustomProgressBar(py_cui.widgets.Widget):
    def __init__(self, id, title, grid, row, col, row_span, col_span, padx, pady, logger, max_val=100):
        super().__init__(id, title, grid, row, col, row_span, col_span, padx, pady, logger)
        self.max_val = max_val
        self.current_val = 0
        
    def set_progress(self, value):
        self.current_val = min(value, self.max_val)

root = py_cui.PyCUI(3, 3)
progress = root.add_custom_widget(CustomProgressBar, 'Progress', 0, 0, 1, 2, 1, 0, max_val=200)
progress.set_progress(75)

Widget Management

Functions for managing widgets after creation including selection, focus, and removal.

def get_widgets() -> Dict[int, Optional[Widget]]:
    """
    Get current set of widgets.
    
    Returns:
    Dictionary mapping widget IDs to widget instances
    """
    
def get_selected_widget() -> Optional[Widget]:
    """
    Get currently selected widget.
    
    Returns:
    Currently selected widget instance or None
    """
    
def set_selected_widget(widget_id: int) -> None:
    """
    Set the selected widget.
    
    Parameters:
    - widget_id: ID of widget to select
    """
    
def move_focus(widget: Widget, auto_press_buttons: bool = True) -> None:
    """
    Move focus to specified widget.
    
    Parameters:
    - widget: Widget to focus on
    - auto_press_buttons: Whether to auto-execute button commands (default: True)
    """
    
def lose_focus() -> None:
    """Exit focus mode and return to overview mode."""
    
def forget_widget(widget: Widget) -> None:
    """
    Remove widget from the UI.
    
    Parameters:
    - widget: Widget to remove
    
    Raises:
    TypeError: If widget is not a Widget instance
    KeyError: If widget does not exist in current UI
    """

Usage example:

root = py_cui.PyCUI(3, 3)
menu = root.add_scroll_menu('Menu', 0, 0)
button = root.add_button('Focus Menu', 1, 0, command=lambda: root.move_focus(menu))

# Get all widgets
widgets = root.get_widgets()
print(f'Total widgets: {len([w for w in widgets.values() if w is not None])}')

# Remove widget
root.forget_widget(button)

Install with Tessl CLI

npx tessl i tessl/pypi-py-cui

docs

colors-styling.md

index.md

key-bindings.md

main-interface.md

popups.md

widgets.md

tile.json