simple-term-menu

repository·develop·Indexed 19 days ago

https://github.com/ingomeyer441/simple-term-menu

A Python library for creating interactive, styled terminal menus for command-line applications on Linux and macOS. It features support for arrow keys, Vim motions, regex-based searching, keyboard shortcuts, multi-select mode, and preview windows via shell commands or Python callables. The library can be used as a Python module via the TerminalMenu class or as a standalone CLI tool.

Tokens
3K
Snippets
7
Records
12
Agent score
19%

What's inside simple-term-menu

  1. Overview of simple-term-menu

    develop

    simple-term-menu is a tool for creating interactive command-line menus. It allows users to select from a list of options using arrow keys, j/k, or Emacs-style C-n/C-p keys.

    Key features:

    • Automatically detects terminal capabilities via the terminfo database and disables unsupported styles.
    • Supported platforms: Linux and macOS.
  2. Enable searching in the menu

    develop

    The menu includes a built-in search feature using Python regex syntax.

    • Activation: The default key is /. You can change this via the search_key parameter.
    • Instant Search: Pass search_key=None to activate search on every keystroke (note: this disables j/k motions; use Ctrl-j/Ctrl-k instead).
    • Case Sensitivity: By default, search is case-insensitive. Set search_case_sensitive=True for case-sensitive matching.
    • Search Hints: Pass show_search_hint=True to display a hint like (Press "/" to search) in the search line.
    • Highlighting: Matches are highlighted using the search_highlight_style.
  3. Enable multi-select mode

    develop

    To allow users to select multiple items, pass multi_select=True to the constructor.

    Usage:

    • Use space or tab to toggle selections.
    • Press an accept key to finish. The show() method returns a sorted tuple of indices.
    • Use the chosen_menu_entries property to get the actual strings of the selected items.

    Configuration:

    • multi_select_keys: Custom keys to toggle items (default: " ,tab").
    • show_multi_select_hint=True: Shows a hint in the status bar.
    • multi_select_select_on_accept=False: If False, the currently highlighted item is NOT automatically added to the selection upon pressing the accept key.
    • multi_select_empty_ok=True: Allows returning an empty selection if no items were explicitly selected.
    • preselected_entries: An iterable of integers (indices) or strings (matching entry text) to pre-select items on startup.
    from simple_term_menu import TerminalMenu
    
    def main():
        terminal_menu = TerminalMenu(
            ["dog", "cat", "mouse", "squirrel"],
            multi_select=True,
            show_multi_select_hint=True,
        )
        # Returns a tuple of indices, e.g., (0, 2)
        menu_entry_indices = terminal_menu.show()
        # Returns a tuple of strings, e.g., ("dog", "mouse")
        print(terminal_menu.chosen_menu_entries)
    
    if __name__ == "__main__":
        main()
  4. Use shortcuts for menu entries

    develop

    You can define keyboard shortcuts by prepending a single character in square brackets to a menu entry (e.g., [a] apple).

    • Behavior: By default, .show() returns immediately when a shortcut is pressed. To jump to the target without exiting, set exit_on_shortcut=False.
    • Hints: Use show_shortcut_hints=True to display hints in the status bar, or show_shortcut_hints_in_status_bar=False to show them in the title.
    • Note: Shortcuts are disabled if search is configured to activate on every letter key.
    from simple_term_menu import TerminalMenu
    
    def main():
        # Shortcuts are defined by [char] prefix
        fruits = ["[a] apple", "[b] banana", "[o] orange"]
        terminal_menu = TerminalMenu(fruits, title="Fruits")
        menu_entry_index = terminal_menu.show()
    
    if __name__ == "__main__":
        main()
  5. Migration from version 1.1 to 1.2

    develop

    If upgrading from version 1.1 to 1.2, note the following breaking changes:

    • Multi-select Keys: The multi_select_key parameter has been renamed to multi_select_keys. It now accepts an iterable of keys. The default keys are now space and tab, which enables toggling selected items while in search mode.
    • Style Parameter Renaming: The shortcut_parentheses_highlight_style parameter has been renamed to shortcut_brackets_highlight_style to maintain consistency with multi_select_cursor_brackets_style.
  6. Implement a preview window

    develop

    You can show a preview of the selected entry by passing a preview_command to the constructor.

    Command Formats:

    1. Shell Command String: A string where {} is a placeholder for the menu entry. If the entry contains a | separator (e.g., filename|data), the part after the | is passed to the placeholder instead.
    2. Python Callable: A function that takes the menu entry string and returns the preview output (can include ANSI color codes).

    Preview Settings:

    • preview_size: Height of the window as a fraction of terminal height (default: 0.25).
    • preview_title: Custom title for the window (default: "preview").
    • preview_border=False: Removes the border and the title.
    # Example using a Python callable for syntax highlighting
    from simple_term_menu import TerminalMenu
    
    def highlight_file(filepath):
        with open(filepath, "r") as f:
            return f.read() # Simplified for example
    
    def main():
        terminal_menu = TerminalMenu(
            ["file1.txt", "file2.txt"],
            preview_command=highlight_file,
            preview_size=0.75
        )
        terminal_menu.show()
    
    if __name__ == "__main__":
        main()
  7. Create a basic menu with TerminalMenu

    develop

    To create a simple interactive menu, instantiate the TerminalMenu class with a list of strings representing your options. Call the .show() method to display the menu and wait for user input.

    Return Values:

    • Returns the index (int) of the selected menu entry.
    • Returns None if the menu was canceled (e.g., by pressing escape, q, or Ctrl-C).

    Navigation:

    • Use arrow keys or j/k (Vim motions) to move.
    • Use Page Up/Page Down (or Ctrl-f/Ctrl-b) to scroll long menus.
    • Press Enter to accept a selection.
    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]}!")
    
    if __name__ == "__main__":
        main()
  8. Migration from version 0.x to 1.x

    develop

    If upgrading from version 0.x to 1.x, note the following breaking changes:

    • Constructor Change: The TerminalMenu constructor now accepts only keyword-only arguments (except for the first parameter, which is the list of menu entries). This change was made to improve parameter management and future extensibility.
    • CLI Changes: The command line interface was revised to use - instead of _ for word separation and has rearranged short options. Only essential short options are retained.
  9. Configure menu styling and appearance

    develop

    You can customize the visual appearance of the menu by passing tuples of keyword strings to the TerminalMenu constructor.

    Accepted Style Keywords:

    • Backgrounds: bg_black, bg_blue, bg_cyan, bg_gray, bg_green, bg_purple, bg_red, bg_yellow
    • Foregrounds: fg_black, fg_blue, fg_cyan, fg_gray, fg_green, fg_purple, fg_red, fg_yellow
    • Effects: bold, italics, standout, underline

    Stylable Components:

    • menu_cursor_style: Style of the cursor (default: ("fg_red", "bold")).
    • menu_highlight_style: Style of the selected entry (default: ("standout",)).
    • search_highlight_style: Style of matched search strings (default: ("fg_black", "bg_yellow", "bold")).
    • shortcut_key_highlight_style: Style of shortcut keys (default: ("fg_blue",)).
    • shortcut_brackets_highlight_style: Style of brackets around shortcuts (default: ("fg_gray",)).
    • status_bar_style: Style of the status bar (default: ("fg_yellow", "bg_black")).
    • multi_select_cursor_style: Style of the multi-selection cursor (default: ("fg_yellow", "bold")).
    • multi_select_cursor_brackets_style: Style of brackets in multi-select (default: ("fg_gray",)).

    Other Visual Options:

    • title: A string, multiline string, or list of strings displayed above the menu.
    • status_bar: A string, multiline string, list of strings, or a callable that takes the current entry and returns a string.
    • menu_cursor: Define a custom cursor string (default: "> ") or set to None to disable.
  10. Configure custom accept keys

    develop

    By default, Enter accepts a selection. You can define a custom set of keys using the accept_keys parameter (a tuple of strings).

    • Key Formats: Plain ASCII letters or modifiers like ctrl-<letter> or alt-<letter>.
    • Querying: Use the chosen_accept_key property on the TerminalMenu instance to see which specific accept key was pressed.

    Note: Compatibility depends on your terminal emulator.

    from simple_term_menu import TerminalMenu
    
    def main():
        # Accept via Enter, Alt-D, or Ctrl-I
        terminal_menu = TerminalMenu(["entry 1", "entry 2"], accept_keys=("enter", "alt-d", "ctrl-i"))
        menu_entry_index = terminal_menu.show()
        print(f"Key pressed: {terminal_menu.chosen_accept_key}")
    
    if __name__ == "__main__":
        main()
  11. Use simple-term-menu as a CLI tool

    develop

    The package can be used directly in shell scripts. The exit code is the 1-based index of the selected entry, or 0 if canceled.

    Key CLI Arguments:

    • -m, --multi-select: Enables multi-select mode (implies --stdout).
    • -p, --preview-command: Command for previews. Use {} as a placeholder.
    • --stdout: Prints selected indices to stdout (separated by ;) in addition to the exit status.
    • -r, --preselected-entries: Comma-separated list of strings to pre-select.
    • -R, --preselected-indices: Comma-separated list of numeric indices to pre-select.
    • -t, --title: Set the menu title.
    • -s, --case-sensitive: Enable case-sensitive search.
    • --skip-empty-entries: Skip empty string entries.
    # Example: Preview files using 'bat' from the command line
    simple-term-menu -p "bat --color=always {}" \
                     --preview-size 0.75 \
                     $(find . -maxdepth 1 -type f)