Python library to build pretty command line user prompts with interactive forms and validation
Overall
score
96%
Selection prompts enable users to choose from predefined options using single-choice selection, multi-choice checkboxes, or keyboard shortcut-based selection.
Interactive single-choice selection from a list of options with arrow key navigation, search filtering, and keyboard shortcuts.
def select(message: str, choices: Sequence[Union[str, Choice, Dict]],
default: Optional[Union[str, Choice, Dict]] = None, qmark: str = "?",
pointer: Optional[str] = "»", style: Optional[Style] = None,
use_shortcuts: bool = False, use_arrow_keys: bool = True,
use_indicator: bool = False, use_jk_keys: bool = True,
use_emacs_keys: bool = True, use_search_filter: bool = False,
show_selected: bool = False, show_description: bool = True,
instruction: Optional[str] = None, **kwargs) -> Question:
"""
Create a single-choice selection prompt.
Args:
message: The question/prompt text to display
choices: List of options (strings, Choice objects, or dicts)
default: Default selected choice
qmark: Question prefix symbol (default "?")
pointer: Selection pointer symbol (default "»")
style: Custom styling configuration
use_shortcuts: Enable keyboard shortcuts for choices
use_arrow_keys: Enable up/down arrow navigation
use_indicator: Show selection indicator next to choices
use_jk_keys: Enable j/k vim-style navigation
use_emacs_keys: Enable Emacs-style key bindings
use_search_filter: Enable search/filter functionality
show_selected: Display selected choice after selection
show_description: Show choice descriptions if available
instruction: Additional instruction text
**kwargs: Additional prompt_toolkit arguments
Returns:
Question instance ready for execution
"""Multi-choice selection prompt allowing users to select multiple options with checkbox-style indicators.
def checkbox(message: str, choices: Sequence[Union[str, Choice, Dict]],
default: Optional[str] = None,
validate: Callable[[List[str]], Union[bool, str]] = lambda a: True,
qmark: str = "?", pointer: Optional[str] = "»",
style: Optional[Style] = None,
initial_choice: Optional[Union[str, Choice, Dict]] = None,
use_arrow_keys: bool = True, use_jk_keys: bool = True,
use_emacs_keys: bool = True, use_search_filter: bool = False,
instruction: Optional[str] = None, show_description: bool = True,
cycle_list: bool = True, **kwargs) -> Question:
"""
Create a multiple-choice checkbox prompt.
Args:
message: The question/prompt text to display
choices: List of options (strings, Choice objects, or dicts)
default: Default selected choice name
validate: Validation function for selected choices
qmark: Question prefix symbol (default "?")
pointer: Selection pointer symbol (default "»")
style: Custom styling configuration
initial_choice: Initially focused choice
use_arrow_keys: Enable up/down arrow navigation
use_jk_keys: Enable j/k vim-style navigation
use_emacs_keys: Enable Emacs-style key bindings
use_search_filter: Enable search/filter functionality
instruction: Additional instruction text
show_description: Show choice descriptions if available
cycle_list: Allow cycling through list boundaries
**kwargs: Additional prompt_toolkit arguments
Returns:
Question instance ready for execution
"""Single-choice selection using only keyboard shortcuts without arrow key navigation.
def rawselect(message: str, choices: Sequence[Union[str, Choice, Dict]],
default: Optional[str] = None, qmark: str = "?",
pointer: Optional[str] = "»", style: Optional[Style] = None,
**kwargs) -> Question:
"""
Create a keyboard shortcut-based selection prompt.
Args:
message: The question/prompt text to display
choices: List of options (strings, Choice objects, or dicts)
default: Default selected choice
qmark: Question prefix symbol (default "?")
pointer: Selection pointer symbol (default "»")
style: Custom styling configuration
**kwargs: Additional prompt_toolkit arguments
Returns:
Question instance ready for execution
"""Advanced choice configuration with custom values, descriptions, and states.
class Choice:
def __init__(self, title: FormattedText, value: Optional[Any] = None,
disabled: Optional[str] = None, checked: Optional[bool] = False,
shortcut_key: Optional[Union[str, bool]] = True,
description: Optional[str] = None) -> None:
"""
Configure a choice for selection prompts.
Args:
title: Display text for the choice
value: Return value when choice is selected (defaults to title)
disabled: Reason text if choice is disabled (None = enabled)
checked: Initially selected state for checkbox prompts
shortcut_key: Keyboard shortcut (True = auto-generate, False = none)
description: Additional description text
"""
@staticmethod
def build(c: Union[str, Choice, Dict]) -> Choice:
"""
Build Choice from string, existing Choice, or dictionary.
Args:
c: Choice specification
Returns:
Choice instance
"""Visual separators for organizing choice lists.
class Separator(Choice):
def __init__(self, line: Optional[str] = None) -> None:
"""
Create a visual separator for choice lists.
Args:
line: Custom separator text (default: 15 dashes)
"""import questionary
# Simple string choices
color = questionary.select(
"Choose a color:",
choices=["Red", "Green", "Blue"]
).ask()
# With default selection
size = questionary.select(
"Choose size:",
choices=["Small", "Medium", "Large"],
default="Medium"
).ask()import questionary
from questionary import Choice, Separator
# Using Choice objects with custom values
action = questionary.select(
"What would you like to do?",
choices=[
Choice("Create new project", value="create"),
Choice("Open existing project", value="open"),
Choice("Delete project", value="delete", disabled="Not implemented"),
Separator(),
Choice("Exit", value="exit")
]
).ask()
# Choices with descriptions
framework = questionary.select(
"Choose framework:",
choices=[
Choice("Django", description="Full-featured web framework"),
Choice("Flask", description="Lightweight WSGI framework"),
Choice("FastAPI", description="Modern async web framework")
],
show_description=True
).ask()import questionary
# Basic checkbox selection
toppings = questionary.checkbox(
"Select pizza toppings:",
choices=["Cheese", "Pepperoni", "Mushrooms", "Olives", "Peppers"]
).ask()
# With validation requiring at least one selection
def validate_selection(answers):
if len(answers) == 0:
return "Please select at least one option"
return True
services = questionary.checkbox(
"Which services to enable?",
choices=["Database", "Cache", "Queue", "Storage"],
validate=validate_selection
).ask()
# Pre-checked options
features = questionary.checkbox(
"Select features:",
choices=[
Choice("Authentication", checked=True),
Choice("API Documentation", checked=True),
Choice("Admin Panel", checked=False),
Choice("Email Service", checked=False)
]
).ask()import questionary
# Automatic shortcut generation
priority = questionary.rawselect(
"Select priority:",
choices=["High", "Medium", "Low"]
).ask()
# Custom shortcuts
environment = questionary.rawselect(
"Deploy to:",
choices=[
Choice("Development", shortcut_key="d"),
Choice("Staging", shortcut_key="s"),
Choice("Production", shortcut_key="p")
]
).ask()import questionary
# Enable search functionality
country = questionary.select(
"Select country:",
choices=["United States", "Canada", "United Kingdom", "Germany", "France", "Japan"],
use_search_filter=True,
instruction="Type to filter options"
).ask()import questionary
# Customize navigation keys
option = questionary.select(
"Choose option:",
choices=["Option 1", "Option 2", "Option 3"],
use_arrow_keys=True, # Up/down arrows
use_jk_keys=True, # j/k vim-style
use_emacs_keys=True, # Emacs bindings
use_shortcuts=True # Number shortcuts
).ask()Install with Tessl CLI
npx tessl i tessl/pypi-questionarydocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10