pick

repository·master·Indexed 21 days ago

https://github.com/aisk/pick

A small Python library for creating interactive selection lists in the terminal with a simple GUI. It supports single and multiple selection modes, custom options via the Option class, and multiple rendering backends including curses (default) and blessed.

Tokens
2.9K
Snippets
10
Records
13
Agent score
72%

What's inside pick

  1. Install the optional `blessed` backend

    master

    By default, pick uses the curses backend. If you prefer using blessed, install the optional extra:

    $ pip install "pick[blessed]"

    To use it, pass backend="blessed" to the pick() function.

  2. Use different backends for rendering

    master

    The pick library supports different terminal rendering backends via the backend parameter in pick() or Picker.

    • 'curses': The default backend using the standard Python curses module. Best for standalone terminal applications.
    • 'blessed': Uses the blessed library for more advanced terminal capabilities.
    • Backend instance: You can provide a custom implementation of the Backend interface to support different terminal environments or custom UI logic.
  3. Install the blessed backend for pick

    master

    The BlessedBackend requires the blessed library as an optional dependency. If you attempt to use it without this library, an ImportError will be raised. You can install it using the following command:

    pip install pick[blessed]
    pip install pick[blessed]
  4. Create a basic single-selection list

    master

    Use the pick function to present a list of options to a user. It returns a tuple containing the selected option and its index.

    import pick
    
    title = 'Please choose your favorite programming language: '
    options = ['Java', 'JavaScript', 'Python', 'PHP', 'C++', 'Erlang', 'Haskell']
    option, index = pick(options, title)
    
    print(option)
    print(index)
  5. Create a multiselect list

    master

    To allow users to select multiple items, set multiselect=True. Users can mark items by pressing SPACE and confirm their selection with ENTER. When multiselect=True, the function returns a list of tuples, where each tuple contains (option, index).

    from pick import pick
    
    title = 'Please choose your favorite programming language (press SPACE to mark, ENTER to continue): '
    options = ['Java', 'JavaScript', 'Python', 'PHP', 'C++', 'Erlang', 'Haskell']
    selected = pick(options, title, multiselect=True, min_selection_count=1)
    
    print(selected)
    # Example output: [('Java', 0), ('C++', 4)]
  6. Reference: pick() function options

    master

    The pick() function accepts the following arguments:

    OptionDescription
    optionsA list of options to choose from
    title(optional) A title displayed above the options list
    indicator(optional) Custom selection indicator; defaults to '*'
    default_index(optional) Set the index of the default selected option
    multiselect(optional) If True, allows selecting multiple items by hitting SPACE
    min_selection_count(optional) For multiselect, dictates the minimum number of items required before continuing
    screen(optional) If using pick within an existing curses application, pass the existing screen object
    position(optional) If using pick within an existing curses application, set the starting write position (e.g., position=pick.Position(y=1, x=1))
    quit_keys(optional) Pass key codes that will cause the menu to quit early if pressed
    backend(optional) The rendering backend to use. Accepts 'curses' (default), 'blessed' (requires pip install pick[blessed]), or a custom Backend instance
  7. Use the pick() function for quick selection menus

    master

    The pick() function is the simplest way to create a terminal-based selection menu. It initializes a Picker and starts the interaction loop immediately. You can pass a list of strings or Option objects.

    Returns:

    • In single-select mode: A tuple of (selected_option, index).
    • In multiselect mode: A list of tuples [(option, index), ...].
    • If the user quits via quit_keys: None, -1 (single-select) or [] (multiselect).
    from pick import pick, Option
    
    # Simple string selection
    result, index = pick(['Apple', 'Banana', 'Cherry'], title='Select a fruit')
    
    # Advanced selection with Option objects
    options = [
        Option('Apple', value=1, description='Red and crunchy'),
        Option('Banana', value=2, description='Yellow and soft'),
        Option('Cherry', value=3, description='Small and sweet'),
    ]
    result, index = pick(options, title='Select a fruit')
  8. Use CursesBackend for terminal UI

    master

    The CursesBackend class provides a terminal-based implementation of the Backend interface using the Python curses standard library. It is useful for creating interactive terminal user interfaces.

    When initializing, you can optionally provide an existing curses.window object. The setup() method initializes the terminal environment (setting default colors and hiding the cursor), while teardown() is intended to be handled by a curses.wrapper to ensure proper cleanup.

    import curses
    from pick.curses_backend import CursesBackend
    
    # Example of manual initialization (though typically managed by a wrapper)
    stdscr = curses.initscr()
    backend = CursesBackend(screen=stdscr)
    backend.setup()
    
    # ... perform operations ...
    
    backend.teardown()
  9. Implement a custom Backend for pick

    master

    To create a custom terminal rendering engine for pick, you must implement the Backend abstract base class. This interface defines the lifecycle and primitive operations required to manage the terminal UI, including setup, teardown, screen clearing, and character rendering.

    Required methods to implement:

    • setup(): Initialize the terminal environment.
    • teardown(): Clean up and restore the terminal state.
    • clear(): Clear the current terminal screen.
    • getmaxyx(): Return a Tuple[int, int] representing the current terminal dimensions (height, width).
    • addnstr(y: int, x: int, s: str, n: int): Write a string s of length n at coordinates (y, x).
    • getch(): Wait for and return a single character input as an int.
    • refresh(): Update the terminal display to reflect changes made via addnstr.
    from pick.backend import Backend
    
    class MyCustomBackend(Backend):
        def setup(self) -> None:
            # Initialize terminal
            pass
    
        def teardown(self) -> None:
            # Restore terminal
            pass
    
        def clear(self) -> None:
            # Clear screen
            pass
    
        def getmaxyx(self) -> tuple[int, int]:
            # Return (height, width)
            return (24, 80)
    
        def addnstr(self, y: int, x: int, s: str, n: int) -> None:
            # Render string
            pass
    
        def getch(self) -> int:
            # Get keypress
            return 0
    
        def refresh(self) -> None:
            # Refresh screen
            pass
  10. Configure selection behavior with the Picker class

    master

    For more control, instantiate the Picker class directly. This allows you to manage the lifecycle of the picker and customize the UI behavior.

    Key Parameters:

    • options: A sequence of str or Option objects.
    • title: An optional string (supports \n for newlines) displayed above options.
    • indicator: The character/string used to mark the current focus (default: *).
    • default_index: The index to start the cursor at.
    • multiselect: If True, allows selecting multiple items using the spacebar.
    • min_selection_count: The minimum number of items required to be selected before Enter is accepted (only applicable if multiselect=True).
    • backend: The rendering engine. Accepts 'curses', 'blessed', or a custom Backend instance.
    • quit_keys: A collection of keys that will trigger a quit action.
    • position: A Position(y, x) namedtuple defining where on the screen the picker starts.
    from pick import Picker, Option, Position
    
    picker = Picker(
        options=[Option("A"), Option("B")],
        title="My Menu",
        multiselect=True,
        min_selection_count=1,
        position=Position(y=5, x=10),
        backend="blessed"
    )
    
    # Start the interaction loop
    results = picker.start()
  11. Reference: Picker configuration parameters

    master

    The following parameters are available when initializing a Picker or calling pick():

    ParameterTypeDefaultDescription
    optionsSequence[Union[str, Option]]RequiredThe list of items to pick from
    titleOptional[str]NoneTitle displayed above the list
    indicatorstr"*"Character used to show current focus
    default_indexint0Starting index for the cursor
    multiselectboolFalseEnable multiple selection mode
    min_selection_countint0Min items required for multiselect success
    screenOptional[curses.window]NoneExisting curses window to use (for embedding)
    positionPositionPosition(0, 0)Starting coordinates (y, x)
    clear_screenboolTrueWhether to clear the screen before drawing
    quit_keysOptional[Union[Container[int], Iterable[int]]]NoneKeys that trigger a quit/exit
    backendUnion[str, Backend]'curses'Rendering engine to use