or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-simple-term-menu

A Python package which creates simple interactive menus on the command line.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/simple-term-menu@1.6.x

To install, run

npx @tessl/cli install tessl/pypi-simple-term-menu@1.6.0

index.mddocs/

Simple Terminal Menu

A Python package which creates simple interactive menus on the command line. It provides customizable terminal menus with navigation, multi-selection, search functionality, and preview capabilities, supporting cross-platform terminal environments with automatic feature detection.

Package Information

  • Package Name: simple-term-menu
  • Language: Python
  • Installation: pip install simple-term-menu
  • Supported Platforms: Linux, macOS
  • Python Version: 3.5+

Core Imports

from simple_term_menu import TerminalMenu

For exceptions:

from simple_term_menu import (
    InvalidParameterCombinationError,
    InvalidStyleError,
    NoMenuEntriesError,
    PreviewCommandFailedError,
    UnknownMenuEntryError
)

For utility functions and constants:

from simple_term_menu import (
    get_locale, 
    wcswidth,
    BoxDrawingCharacters,
    # Default constants (optional, for customization)
    DEFAULT_MENU_CURSOR,
    DEFAULT_MENU_CURSOR_STYLE,
    DEFAULT_QUIT_KEYS
)

For CLI functions:

from simple_term_menu import main, parse_arguments, get_argumentparser

Basic Usage

from simple_term_menu import TerminalMenu

def main():
    options = ["entry 1", "entry 2", "entry 3"]
    terminal_menu = TerminalMenu(options)
    menu_entry_index = terminal_menu.show()
    
    if menu_entry_index is not None:
        print(f"You have selected {options[menu_entry_index]}!")
    else:
        print("Menu was cancelled")

if __name__ == "__main__":
    main()

Multi-selection example:

from simple_term_menu import TerminalMenu

options = ["Option 1", "Option 2", "Option 3", "Option 4"]
terminal_menu = TerminalMenu(
    options,
    multi_select=True,
    show_multi_select_hint=True
)
menu_entry_indices = terminal_menu.show()

if menu_entry_indices:
    selected_options = [options[i] for i in menu_entry_indices]
    print(f"Selected: {', '.join(selected_options)}")

Error handling example:

from simple_term_menu import (
    TerminalMenu,
    NoMenuEntriesError,
    InvalidParameterCombinationError,
    PreviewCommandFailedError
)

try:
    # Example of handling common errors
    options = []  # Empty list will raise NoMenuEntriesError
    terminal_menu = TerminalMenu(
        options,
        preview_command="invalid_command {}"  # May cause PreviewCommandFailedError
    )
    result = terminal_menu.show()
    
except NoMenuEntriesError as e:
    print(f"Error: No menu entries provided - {e}")
    
except InvalidParameterCombinationError as e:
    print(f"Error: Invalid parameter combination - {e}")
    
except PreviewCommandFailedError as e:
    print(f"Error: Preview command failed - {e}")
    
except KeyboardInterrupt:
    print("Menu cancelled by user")
    # Note: Set raise_error_on_interrupt=True to get this exception
    
except NotImplementedError as e:
    print(f"Error: Platform not supported - {e}")
    # Raised on Windows or when TERM environment variable is missing

Capabilities

Terminal Menu Creation

Creates interactive terminal menus with extensive customization options including cursor styles, keyboard shortcuts, multi-selection, search functionality, and preview windows.

class TerminalMenu:
    def __init__(
        self,
        menu_entries: Iterable[str],
        *,
        accept_keys: Iterable[str] = ("enter",),
        clear_menu_on_exit: bool = True,
        clear_screen: bool = False,
        cursor_index: Optional[int] = None,
        cycle_cursor: bool = True,
        exit_on_shortcut: bool = True,
        menu_cursor: Optional[str] = "> ",
        menu_cursor_style: Optional[Iterable[str]] = ("fg_red", "bold"),
        menu_highlight_style: Optional[Iterable[str]] = ("standout",),
        multi_select: bool = False,
        multi_select_cursor: str = "[*] ",
        multi_select_cursor_brackets_style: Optional[Iterable[str]] = ("fg_gray",),
        multi_select_cursor_style: Optional[Iterable[str]] = ("fg_yellow", "bold"),
        multi_select_empty_ok: bool = False,
        multi_select_keys: Optional[Iterable[str]] = (" ", "tab"),
        multi_select_select_on_accept: bool = True,
        preselected_entries: Optional[Iterable[Union[str, int]]] = None,
        preview_border: bool = True,
        preview_command: Optional[Union[str, Callable[[str], str]]] = None,
        preview_size: float = 0.25,
        preview_title: str = "preview",
        quit_keys: Iterable[str] = ("escape", "q", "ctrl-g"),
        raise_error_on_interrupt: bool = False,
        search_case_sensitive: bool = False,
        search_highlight_style: Optional[Iterable[str]] = ("fg_black", "bg_yellow", "bold"),
        search_key: Optional[str] = "/",
        shortcut_brackets_highlight_style: Optional[Iterable[str]] = ("fg_gray",),
        shortcut_key_highlight_style: Optional[Iterable[str]] = ("fg_blue",),
        show_multi_select_hint: bool = False,
        show_multi_select_hint_text: Optional[str] = None,
        show_search_hint: bool = False,
        show_search_hint_text: Optional[str] = None,
        show_shortcut_hints: bool = False,
        show_shortcut_hints_in_status_bar: bool = True,
        skip_empty_entries: bool = False,
        status_bar: Optional[Union[str, Iterable[str], Callable[[str], str]]] = None,
        status_bar_below_preview: bool = False,
        status_bar_style: Optional[Iterable[str]] = ("fg_yellow", "bg_black"),
        title: Optional[Union[str, Iterable[str]]] = None
    ):
        """
        Create a terminal menu.

        Parameters:
        - menu_entries: List of menu entry strings to display
        - accept_keys: Keys that accept the current selection
        - clear_menu_on_exit: Whether to clear the menu when exiting
        - clear_screen: Whether to clear the screen before showing the menu
        - cursor_index: Initial cursor position (0-based index)
        - cycle_cursor: Whether cursor wraps around at ends
        - exit_on_shortcut: Whether to exit immediately on shortcut key
        - menu_cursor: String to display as cursor
        - menu_cursor_style: Style tuple for cursor (e.g., ("fg_red", "bold"))
        - menu_highlight_style: Style tuple for highlighted entries
        - multi_select: Enable multi-selection mode
        - multi_select_cursor: Cursor for selected items in multi-select
        - multi_select_cursor_brackets_style: Style for selection brackets
        - multi_select_cursor_style: Style for multi-select cursor
        - multi_select_empty_ok: Allow empty selection in multi-select
        - multi_select_keys: Keys for toggling selection in multi-select
        - multi_select_select_on_accept: Select current item on accept in multi-select
        - preselected_entries: Pre-selected entries by string or index
        - preview_border: Show border around preview area
        - preview_command: Command or function to generate preview content
        - preview_size: Preview area size as fraction of screen (0.0-1.0)
        - preview_title: Title for preview area
        - quit_keys: Keys that quit the menu without selection
        - raise_error_on_interrupt: Raise exception on keyboard interrupt
        - search_case_sensitive: Whether search is case sensitive
        - search_highlight_style: Style for search highlighting
        - search_key: Key to activate search mode
        - shortcut_brackets_highlight_style: Style for shortcut brackets
        - shortcut_key_highlight_style: Style for shortcut keys
        - show_multi_select_hint: Show multi-select hint text
        - show_multi_select_hint_text: Custom multi-select hint text
        - show_search_hint: Show search hint text
        - show_search_hint_text: Custom search hint text
        - show_shortcut_hints: Show shortcut hints
        - show_shortcut_hints_in_status_bar: Show shortcuts in status bar
        - skip_empty_entries: Skip empty entries in navigation
        - status_bar: Status bar content (string, list, or callable)
        - status_bar_below_preview: Position status bar below preview
        - status_bar_style: Style for status bar
        - title: Menu title (string or list of strings)
        """

    def show(self) -> Optional[Union[int, Tuple[int, ...]]]:
        """
        Display the menu and wait for user interaction.

        Returns:
        - For single-select: Selected menu entry index (int) or None if cancelled
        - For multi-select: Tuple of selected indices or None if cancelled
        """

Menu Interaction Properties

Access information about the last menu interaction, including selected entries and the key used to accept the selection.

@property
def chosen_accept_key(self) -> Optional[str]:
    """Key used to accept the last selection."""

@property
def chosen_menu_entry(self) -> Optional[str]:
    """Text of the last chosen menu entry (single-select)."""

@property
def chosen_menu_entries(self) -> Optional[Tuple[str, ...]]:
    """Texts of the last chosen menu entries (multi-select)."""

@property
def chosen_menu_index(self) -> Optional[int]:
    """Index of the last chosen menu entry (single-select)."""

@property
def chosen_menu_indices(self) -> Optional[Tuple[int, ...]]:
    """Indices of the last chosen menu entries (multi-select)."""

Exception Handling

Custom exceptions for various error conditions that may occur during menu creation and operation.

class InvalidParameterCombinationError(Exception):
    """Raised when incompatible parameters are used together."""

class InvalidStyleError(Exception):
    """Raised when an invalid style is specified."""

class NoMenuEntriesError(Exception):
    """Raised when no menu entries are provided."""

class PreviewCommandFailedError(Exception):
    """Raised when a preview command fails to execute."""

class UnknownMenuEntryError(Exception):
    """Raised when referencing a non-existent menu entry."""

Box Drawing Characters

Provides platform-appropriate box drawing characters for terminal UIs. Automatically detects UTF-8 support and uses Unicode or ASCII characters accordingly.

class BoxDrawingCharacters:
    """
    Box drawing characters that adapt to terminal capabilities.
    
    Uses Unicode box characters (─│┌┐└┘) for UTF-8 locales,
    falls back to ASCII characters (-|+++) for other locales.
    """
    horizontal: str  # "─" or "-"
    vertical: str    # "│" or "|"
    upper_left: str  # "┌" or "+"
    upper_right: str # "┐" or "+"
    lower_left: str  # "└" or "+"
    lower_right: str # "┘" or "+"

Utility Functions

Helper functions for locale handling and text width calculation, useful for custom terminal applications.

def get_locale() -> str:
    """
    Get the current system locale.

    Returns:
    Current locale string
    """

def wcswidth(text: str) -> int:
    """
    Calculate the width of text considering wide characters.

    Parameters:
    - text: Text string to measure

    Returns:
    Width of the text in terminal columns
    """

Command Line Interface

Functions for using simple-term-menu as a command-line tool, allowing integration with shell scripts and other tools.

def main() -> None:
    """
    Main entry point for command-line usage.
    
    Parses command-line arguments and creates a terminal menu.
    Available as 'simple-term-menu' console script.
    
    Example usage:
    simple-term-menu "Option 1" "Option 2" "Option 3"
    simple-term-menu -m "Item 1" "Item 2" "Item 3"  # Multi-select
    echo -e "Choice A\\nChoice B\\nChoice C" | simple-term-menu
    """

def parse_arguments() -> AttributeDict:
    """
    Parse command-line arguments for the CLI interface.

    Returns:
    Parsed arguments as AttributeDict
    """

def get_argumentparser() -> argparse.ArgumentParser:
    """
    Create and return the argument parser for CLI usage.

    Returns:
    Configured ArgumentParser instance
    """

CLI Arguments

The command-line interface supports extensive configuration through these arguments:

Navigation and Display:

  • -s, --case-sensitive: Make searches case sensitive
  • -X, --no-clear-menu-on-exit: Do not clear the menu on exit
  • -l, --clear-screen: Clear the screen before showing menu
  • -C, --no-cycle: Do not cycle the menu selection
  • -E, --no-exit-on-shortcut: Do not exit on shortcut keys
  • -i, --cursor-index N: Initially selected item index (default: 0)
  • --cursor STR: Menu cursor string (default: "> ")

Styling:

  • --cursor-style STYLES: Cursor style as comma-separated list (default: "fg_red,bold")
  • --highlight-style STYLES: Selected entry style (default: "standout")
  • --search-highlight-style STYLES: Search highlight style (default: "fg_black,bg_yellow,bold")

Multi-Selection:

  • -m, --multi-select: Enable multi-selection mode (implies --stdout)
  • --multi-select-cursor STR: Multi-select cursor (default: "[*] ")
  • --multi-select-cursor-style STYLES: Multi-select cursor style (default: "fg_yellow,bold")
  • --multi-select-cursor-brackets-style STYLES: Bracket style (default: "fg_gray")
  • --multi-select-keys KEYS: Toggle keys (default: " ,tab")
  • --multi-select-no-select-on-accept: Don't select current item on accept
  • --multi-select-empty-ok: Allow empty multi-selection

Preview:

  • -p, --preview COMMAND: Preview command for entries
  • --preview-size FLOAT: Preview area size as fraction (default: 0.25)
  • --preview-title STR: Preview area title (default: "preview")
  • --no-preview-border: Disable preview border

Search:

  • --search-key KEY: Search activation key (default: "/")
  • --no-search-key: Activate search on any letter key

Shortcuts and Hints:

  • --shortcut-key-highlight-style STYLES: Shortcut key style (default: "fg_blue")
  • --shortcut-brackets-highlight-style STYLES: Shortcut bracket style (default: "fg_gray")
  • --show-shortcut-hints: Show shortcut hints
  • --show-multi-select-hint: Show multi-select hint
  • --show-search-hint: Show search hint

Status Bar:

  • --status-bar STR: Status bar content
  • --status-bar-below-preview: Position status bar below preview
  • --status-bar-style STYLES: Status bar style (default: "fg_yellow,bg_black")

Output:

  • --stdout: Output to stdout instead of stderr
  • --title STR: Menu title
  • -V, --version: Show version and exit

Styling Options

The package supports extensive styling through tuples of style keywords:

Color Options

  • Foreground colors: fg_black, fg_blue, fg_cyan, fg_gray, fg_green, fg_purple, fg_red, fg_yellow
  • Background colors: bg_black, bg_blue, bg_cyan, bg_gray, bg_green, bg_purple, bg_red, bg_yellow

Style Options

  • Text formatting: bold, dim, italic, underline, blink, reverse, strikethrough
  • Special: standout (platform-specific highlighting)

Example styling:

menu = TerminalMenu(
    options,
    menu_cursor_style=("fg_red", "bold"),
    menu_highlight_style=("bg_blue", "fg_white"),
    search_highlight_style=("bg_yellow", "fg_black", "bold")
)

Keyboard Navigation

Default Key Bindings

  • Navigation: Arrow keys, j/k (vim-style), Ctrl-n/Ctrl-p (emacs-style), Page Up/Down, Ctrl-f/Ctrl-b
  • Selection: Enter (accept), Space/Tab (multi-select toggle)
  • Search: / (activate search), Escape (exit search)
  • Exit: Escape, q, Ctrl-g, Ctrl-c

Shortcut Keys

Menu entries can include shortcut keys for quick selection. Enclose the shortcut character in brackets:

options = ["[a]pple", "[b]anana", "[c]herry"]
menu = TerminalMenu(options)

Search Feature

Built-in search functionality allows filtering menu entries:

  • Default search key: / (like vim, less)
  • Search supports regex patterns
  • Set search_key=None to activate search on any letter key
  • Case sensitivity controlled by search_case_sensitive parameter

Custom Key Configuration

Keys can be customized through the various *_keys parameters. Keys are specified as strings:

  • Single characters: "a", "/", " " (space)
  • Special keys: "enter", "escape", "tab", "space"
  • Control combinations: "ctrl-g", "ctrl-c"
  • Alt combinations: "alt-a", "alt-x"

Types

from typing import Iterable, Optional, Union, Tuple, Callable, Any, Dict

# Menu entry types
MenuEntry = str
MenuEntries = Iterable[MenuEntry]

# Selection result types
SingleSelection = Optional[int]
MultiSelection = Optional[Tuple[int, ...]]
Selection = Union[SingleSelection, MultiSelection]

# Style specification
StyleTuple = Tuple[str, ...]
Style = Optional[StyleTuple]

# Preview command types
PreviewCommand = Union[str, Callable[[str], str]]

# Status bar types
StatusBar = Union[str, Iterable[str], Callable[[str], str]]

# Title types
Title = Union[str, Iterable[str]]

# CLI argument dictionary
class AttributeDict(dict):
    """
    Dictionary that allows attribute-style access to keys.
    
    Used by parse_arguments() to return CLI arguments that can be 
    accessed as attributes (args.multi_select) or dict keys (args['multi_select']).
    """
    def __getattr__(self, attr: str) -> Any: ...
    def __setattr__(self, attr: str, value: Any) -> None: ...

# Key specification types
KeySpec = str  # Key names like "enter", "escape", "ctrl-g", "alt-x"
KeySequence = Iterable[KeySpec]

# Preselection types
PreselectedEntry = Union[str, int]  # Menu entry by text or index
PreselectedEntries = Iterable[PreselectedEntry]

Module Constants

Version and Package Information

__author__: str = "Ingo Meyer"
__email__: str = "i.meyer@fz-juelich.de"  
__copyright__: str = "Copyright © 2021 Forschungszentrum Jülich GmbH. All rights reserved."
__license__: str = "MIT"
__version_info__: Tuple[int, int, int] = (1, 6, 6)
__version__: str = "1.6.6"

Default Configuration Values

Default parameter values used by TerminalMenu constructor:

# Navigation and behavior defaults
DEFAULT_ACCEPT_KEYS: Tuple[str, ...] = ("enter",)
DEFAULT_QUIT_KEYS: Tuple[str, ...] = ("escape", "q", "ctrl-g")
DEFAULT_CYCLE_CURSOR: bool = True
DEFAULT_EXIT_ON_SHORTCUT: bool = True

# Display defaults
DEFAULT_CLEAR_MENU_ON_EXIT: bool = True
DEFAULT_CLEAR_SCREEN: bool = False
DEFAULT_MENU_CURSOR: str = "> "
DEFAULT_MENU_CURSOR_STYLE: Tuple[str, ...] = ("fg_red", "bold")
DEFAULT_MENU_HIGHLIGHT_STYLE: Tuple[str, ...] = ("standout",)

# Multi-selection defaults
DEFAULT_MULTI_SELECT: bool = False
DEFAULT_MULTI_SELECT_CURSOR: str = "[*] "
DEFAULT_MULTI_SELECT_CURSOR_BRACKETS_STYLE: Tuple[str, ...] = ("fg_gray",)
DEFAULT_MULTI_SELECT_CURSOR_STYLE: Tuple[str, ...] = ("fg_yellow", "bold")
DEFAULT_MULTI_SELECT_KEYS: Tuple[str, ...] = (" ", "tab")
DEFAULT_MULTI_SELECT_SELECT_ON_ACCEPT: bool = True

# Search defaults
DEFAULT_SEARCH_CASE_SENSITIVE: bool = False
DEFAULT_SEARCH_HIGHLIGHT_STYLE: Tuple[str, ...] = ("fg_black", "bg_yellow", "bold")
DEFAULT_SEARCH_KEY: str = "/"

# Preview defaults
DEFAULT_PREVIEW_BORDER: bool = True
DEFAULT_PREVIEW_SIZE: float = 0.25
DEFAULT_PREVIEW_TITLE: str = "preview"

# Shortcut and hint defaults
DEFAULT_SHORTCUT_BRACKETS_HIGHLIGHT_STYLE: Tuple[str, ...] = ("fg_gray",)
DEFAULT_SHORTCUT_KEY_HIGHLIGHT_STYLE: Tuple[str, ...] = ("fg_blue",)
DEFAULT_SHOW_MULTI_SELECT_HINT: bool = False
DEFAULT_SHOW_SEARCH_HINT: bool = False
DEFAULT_SHOW_SHORTCUT_HINTS: bool = False
DEFAULT_SHOW_SHORTCUT_HINTS_IN_STATUS_BAR: bool = True

# Status bar defaults
DEFAULT_STATUS_BAR_BELOW_PREVIEW: bool = False
DEFAULT_STATUS_BAR_STYLE: Tuple[str, ...] = ("fg_yellow", "bg_black")

# Layout constraints
MIN_VISIBLE_MENU_ENTRIES_COUNT: int = 3