Install pick via pip
masterInstall the core library using pip:
$ pip install pickrepository·master·Indexed 21 days ago
https://github.com/aisk/pickA 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.
Install the core library using pip:
$ pip install pickBy 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.
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.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]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)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)]The pick() function accepts the following arguments:
| Option | Description |
|---|---|
options | A 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 |
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:
(selected_option, index).[(option, index), ...].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')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()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
passFor 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()The following parameters are available when initializing a Picker or calling pick():
| Parameter | Type | Default | Description |
|---|---|---|---|
options | Sequence[Union[str, Option]] | Required | The list of items to pick from |
title | Optional[str] | None | Title displayed above the list |
indicator | str | "*" | Character used to show current focus |
default_index | int | 0 | Starting index for the cursor |
multiselect | bool | False | Enable multiple selection mode |
min_selection_count | int | 0 | Min items required for multiselect success |
screen | Optional[curses.window] | None | Existing curses window to use (for embedding) |
position | Position | Position(0, 0) | Starting coordinates (y, x) |
clear_screen | bool | True | Whether to clear the screen before drawing |
quit_keys | Optional[Union[Container[int], Iterable[int]]] | None | Keys that trigger a quit/exit |
backend | Union[str, Backend] | 'curses' | Rendering engine to use |