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

key-bindings.mddocs/

Key Bindings and Events

Global and widget-specific key binding system for handling user input, navigation, and custom commands in both overview and focus modes.

Capabilities

Global Key Bindings

System for binding keys to functions that work in overview mode (when no widget is focused).

def add_key_command(key: Union[int, List[int]], command: Callable[[], Any]) -> None:
    """
    Add a global key binding for overview mode.
    
    Parameters:
    - key: Key code or list of key codes to bind
    - command: No-argument function to execute when key is pressed
    """

Usage example:

import py_cui

def save_action():
    print('Save action triggered')

def quit_action():
    print('Quitting application')
    root.stop()

def help_action():
    root.show_message_popup('Help', 'F1: Help, S: Save, Q: Quit')

root = py_cui.PyCUI(3, 3)

# Single key binding
root.add_key_command(py_cui.keys.KEY_S_LOWER, save_action)

# Multiple keys for same action
root.add_key_command([py_cui.keys.KEY_Q_LOWER, py_cui.keys.KEY_ESCAPE], quit_action)

# Function key binding
root.add_key_command(py_cui.keys.KEY_F1, help_action)

Widget Key Bindings

System for binding keys to functions that work when a specific widget is in focus mode.

# Widget method for adding key commands
def add_key_command(key: Union[int, List[int]], command: Callable[[], Any]) -> None:
    """
    Add a key binding specific to this widget (focus mode).
    
    Parameters:
    - key: Key code or list of key codes to bind
    - command: No-argument function to execute when key is pressed in focus mode
    """

Usage example:

import py_cui

root = py_cui.PyCUI(3, 3)
menu = root.add_scroll_menu('Options', 0, 0)
text_box = root.add_text_box('Input', 1, 0)

# Menu-specific key bindings
def delete_item():
    menu.remove_selected_item()
    
def clear_menu():
    menu.clear()

menu.add_key_command(py_cui.keys.KEY_DELETE, delete_item)
menu.add_key_command(py_cui.keys.KEY_CTRL_K, clear_menu)

# Text box specific key bindings  
def clear_text():
    text_box.clear()
    
def insert_timestamp():
    import datetime
    text_box.write(f' [{datetime.datetime.now()}]')

text_box.add_key_command(py_cui.keys.KEY_CTRL_L, clear_text)
text_box.add_key_command(py_cui.keys.KEY_F5, insert_timestamp)

Widget Navigation Control

Configuration for navigation keys and widget cycling behavior.

def set_widget_cycle_key(forward_cycle_key: int = None, 
                        reverse_cycle_key: int = None) -> None:
    """
    Set keys for cycling between widgets.
    
    Parameters:
    - forward_cycle_key: Key for forward widget cycling (default: Ctrl+Right)
    - reverse_cycle_key: Key for reverse widget cycling (default: Ctrl+Left)
    """

Usage example:

root = py_cui.PyCUI(3, 3)

# Use Tab/Shift+Tab for widget cycling
root.set_widget_cycle_key(
    forward_cycle_key=py_cui.keys.KEY_TAB,
    reverse_cycle_key=py_cui.keys.KEY_SHIFT_TAB
)

# Add some widgets to cycle through
menu = root.add_scroll_menu('Menu', 0, 0)
text_box = root.add_text_box('Input', 0, 1)
button = root.add_button('Submit', 0, 2)

Mouse Event Bindings

System for handling mouse clicks and events on widgets.

# Widget method for adding mouse commands
def add_mouse_command(mouse_event: int, command: Callable[[], Any]) -> None:
    """
    Add a mouse event binding to this widget.
    
    Parameters:
    - mouse_event: Mouse event code (button click, double-click, etc.)
    - command: No-argument function to execute on mouse event
    """

Usage example:

import py_cui

def handle_right_click():
    root.show_menu_popup('Context Menu', ['Edit', 'Delete', 'Properties'], 
                        lambda x: print(f'Selected: {x}'))

def handle_double_click():
    print('Double-clicked on menu item')

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

# Add mouse event handlers
menu.add_mouse_command(py_cui.keys.MOUSE_RIGHT_CLICK, handle_right_click)
menu.add_mouse_command(py_cui.keys.MOUSE_DOUBLE_CLICK, handle_double_click)

Key Constants and Utilities

Key codes and utilities for working with keyboard input.

# Common key constants
KEY_ENTER: int
KEY_ESCAPE: int  
KEY_TAB: int
KEY_BACKSPACE: int
KEY_DELETE: int

# Arrow keys
KEY_UP_ARROW: int
KEY_DOWN_ARROW: int
KEY_LEFT_ARROW: int
KEY_RIGHT_ARROW: int
ARROW_KEYS: List[int]  # List of all arrow key codes

# Function keys
KEY_F1: int
KEY_F2: int
# ... F3 through F12

# Control key combinations
KEY_CTRL_A: int
KEY_CTRL_C: int
KEY_CTRL_V: int
KEY_CTRL_X: int
KEY_CTRL_Z: int
# ... other Ctrl combinations

# Letter keys (upper and lower case)
KEY_A_UPPER: int
KEY_A_LOWER: int
# ... other letters

# Number keys
KEY_0: int
KEY_1: int
# ... other numbers

# Special keys
KEY_SPACE: int
KEY_SHIFT_TAB: int

# Mouse events
MOUSE_LEFT_CLICK: int
MOUSE_RIGHT_CLICK: int  
MOUSE_DOUBLE_CLICK: int

# Utility functions
def get_char_from_ascii(key_code: int) -> Optional[str]:
    """
    Convert key code to character representation.
    
    Parameters:
    - key_code: ASCII key code
    
    Returns:
    String representation of key or None if not printable
    """

Usage example:

import py_cui

def handle_key_press():
    # Example of using key constants
    print('Key pressed!')

def show_key_help():
    help_text = f"""
    Available Keys:
    {py_cui.keys.get_char_from_ascii(py_cui.keys.KEY_F1)} - Help
    {py_cui.keys.get_char_from_ascii(py_cui.keys.KEY_S_LOWER)} - Save
    {py_cui.keys.get_char_from_ascii(py_cui.keys.KEY_Q_LOWER)} - Quit
    Arrows - Navigate
    Enter - Select
    Escape - Cancel
    """
    root.show_message_popup('Key Help', help_text)

root = py_cui.PyCUI(3, 3)

# Bind various key types
root.add_key_command(py_cui.keys.KEY_F1, show_key_help)
root.add_key_command(py_cui.keys.KEY_CTRL_H, show_key_help)
root.add_key_command(py_cui.keys.KEY_SPACE, handle_key_press)

# Check if keys are arrow keys
def handle_any_key(key_code: int):
    if key_code in py_cui.keys.ARROW_KEYS:
        print('Arrow key pressed')
    char = py_cui.keys.get_char_from_ascii(key_code)
    if char:
        print(f'Printable key: {char}')

Advanced Key Binding Patterns

Examples of complex key binding scenarios and patterns.

# Advanced binding patterns (examples)

Usage example:

import py_cui

class KeyBindingDemo:
    def __init__(self):
        self.root = py_cui.PyCUI(3, 3)
        self.mode = 'normal'
        
        # Create widgets
        self.setup_widgets()
        self.setup_key_bindings()
    
    def setup_widgets(self):
        self.menu = self.root.add_scroll_menu('Commands', 0, 0)
        self.output = self.root.add_text_block('Output', 0, 1, column_span=2)
        self.input_box = self.root.add_text_box('Input', 1, 0, column_span=3)
    
    def setup_key_bindings(self):
        # Modal key bindings - different behavior based on mode
        self.root.add_key_command(py_cui.keys.KEY_I_LOWER, self.enter_insert_mode)
        self.root.add_key_command(py_cui.keys.KEY_ESCAPE, self.enter_normal_mode)
        
        # Conditional key bindings
        self.root.add_key_command(py_cui.keys.KEY_ENTER, self.context_sensitive_enter)
        
        # Multi-key sequences (simple implementation)
        self.last_key = None
        self.root.add_key_command(py_cui.keys.KEY_G_LOWER, self.handle_g_key)
    
    def enter_insert_mode(self):
        self.mode = 'insert'
        self.root.set_status_bar_text('-- INSERT MODE --')
        self.root.move_focus(self.input_box)
    
    def enter_normal_mode(self):
        self.mode = 'normal'
        self.root.set_status_bar_text('-- NORMAL MODE --')
        self.root.lose_focus()
    
    def context_sensitive_enter(self):
        if self.mode == 'normal':
            selected = self.root.get_selected_widget()
            if selected == self.menu:
                self.execute_command()
        elif self.mode == 'insert':
            self.process_input()
    
    def handle_g_key(self):
        # Simple two-key sequence: 'gg' to go to top
        if self.last_key == py_cui.keys.KEY_G_LOWER:
            self.goto_top()
            self.last_key = None
        else:
            self.last_key = py_cui.keys.KEY_G_LOWER
    
    def execute_command(self):
        command = self.menu.get_selected_item()
        self.output.write(f'Executing: {command}\n')
    
    def process_input(self):
        text = self.input_box.get()
        self.output.write(f'Input: {text}\n')
        self.input_box.clear()
    
    def goto_top(self):
        self.menu.set_selected_item_index(0)
        self.output.write('Jumped to top\n')
    
    def run(self):
        self.menu.add_item_list(['save', 'load', 'quit', 'help'])
        self.root.start()

# Usage
demo = KeyBindingDemo()
demo.run()

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