Python library to build pretty command line user prompts ⭐️
Project description
questionary
✨An easy to use python library to build pretty command line user prompts ✨
You need input from a user, e.g. how an output file should be named or if he really wants to execute that dangerous operation? This library will help you make the input prompts easy to read and answer for the user.
Used and Supported by:
Quickstart
To install questionary
, simply use pipenv (or pip, of
course):
$ pipenv install questionary
✨🎂✨
Satisfaction guaranteed. Let's create a first question:
import questionary
questionary.select(
"What do you want to do?",
choices=[
'Order a pizza',
'Make a reservation',
'Ask for opening hours'
]).ask() # returns value of selection
That's all it takes to create a user prompt! There are differen types of prompts, you'll find examples for all of them further down.
Documentation
Different question types
text
A free text input for the user.
questionary.text("What's your first name").ask()
password
A free text input for the user where the input is not
shown but replaced with ***
.
questionary.password("What's your secret?").ask()
confirm
A yes or no question. The user can either confirm or deny.
questionary.confirm("Are you amazed?").ask()
select
A list of items to select a choice from. The user can pick one option and confirm it.
questionary.select(
"What do you want to do?",
choices=[
"Order a pizza",
"Make a reservation",
"Ask for opening hours"
]).ask()
rawselect
A list of items to select a choice from. The user can pick one option using shortcuts and confirm it.
questionary.rawselect(
"What do you want to do?",
choices=[
"Order a pizza",
"Make a reservation",
"Ask for opening hours"
]).ask()
checkbox
A list of items to select multiple choices from. The user can pick none, one or multiple options and confirm the selection.
questionary.checkbox(
'Select toppings',
choices=[
"foo",
"bar",
"bazz"
]).ask()
autocomplete
Text input with autocomplete help.
questionary.autocomplete(
'Choose ant specie',
choices=[
'Camponotus pennsylvanicus',
'Linepithema humile',
'Eciton burchellii',
"Atta colombica",
'Polyergus lucidus',
'Polyergus rufescens',
]).ask()
Additional Features
Skipping questions using conditions
Sometimes it is helpful to e.g. provide a command line flag to your app to skip any prompts, to avoid the need for an if around any question you can pass that flag when you create the question:
DISABLED = True
response = questionary.confirm("Are you amazed?").skip_if(DISABLED, default=True).ask()
If the condition (in this case DISABLED
) is True
, the question will be
skipped and the default value gets returned, otherwise the user will be
prompted as usual and the default value will be ignored.
Alternative style to create questions using a configuration dictionary
Instead of creating questions using the python functions, you can also create them using a configuration dictionary.
questions = [
{
'type': 'text',
'name': 'phone',
'message': "What's your phone number",
},
{
'type': 'confirm',
'message': 'Do you want to continue?',
'name': 'continue',
'default': True,
}
]
answers = prompt(questions)
The returned answers
will be a dict containing the responses, e.g. {"phone": "0123123", "continue": False, ""}
. The questions will be prompted one after another and prompt
will return once all of them are answered.
Each configuration dictionary needs to contain the following keys:
'type'
- The type of the question.'name'
- The name of the question (will be used as key in theanswers
dictionary)'message'
- Message that will be shown to the user
Optional Keys:
'qmark'
- Question mark to use - defaults to?
.'default'
- Preselected value.'choices'
- List of choices (applies when'type': 'select'
) or function returning a list of choices.'when'
- Function checking if this question should be shown or skipped (same functionality than.skip_if()
).'validate'
- Function or Validator Class performing validation (will be performed in real time as users type).filter
- Receive the user input and return the filtered value to be used inside the program.
Advanced workflow examples
Questionary allows creating quite complex workflows when combining all of the above concepts.from questionary import Separator, prompt
questions = [
{
'type': 'confirm',
'name': 'conditional_step',
'message': 'Would you like the next question?',
'default': True,
},
{
'type': 'text',
'name': 'next_question',
'message': 'Name this library?',
# Validate if the first question was answered with yes or no
'when': lambda x: x['conditional_step'],
# Only accept questionary as answer
'validate': lambda val: val == 'questionary'
},
{
'type': 'select',
'name': 'second_question',
'message': 'Select item',
'choices': [
'item1',
'item2',
Separator(),
'other',
],
},
{
'type': 'text',
'name': 'second_question',
'message': 'Insert free text',
'when': lambda x: x['second_question'] == 'other'
},
]
prompt(questions)
The above workflow will show to the user as follows:
- Yes/No question
Would you like the next question?
. Name this library?
- only shown when the first question is answered with yes- A question to select an item from a list.
- Free text inpt if
'other'
is selected in step 3.
Depending on the route the user took, the result will look as follows:
{
'conditional_step': False,
'second_question': 'Testinput' # Free form text
}
{
'conditional_step': True,
'next_question': 'questionary',
'second_question': 'Testinput' # Free form text
}
You can test this workflow yourself by running the advanced_workflow.py example.
Styling your prompts with your favorite colors
You can customize all the colors used for the prompts. Every part of the prompt has an identifier, which you can use to style it. Let's create our own custom style:
from prompt_toolkit.styles import Style
custom_style_fancy = Style([
('qmark', 'fg:#673ab7 bold'), # token in front of the question
('question', 'bold'), # question text
('answer', 'fg:#f44336 bold'), # submitted answer text behind the question
('pointer', 'fg:#673ab7 bold'), # pointer used in select and checkbox prompts
('highlighted', 'fg:#673ab7 bold'), # pointed-at choice in select and checkbox prompts
('selected', 'fg:#cc5454'), # style for a selected item of a checkbox
('separator', 'fg:#cc5454'), # separator in lists
('instruction', ''), # user instructions for select, rawselect, checkbox
('text', ''), # plain text
('disabled', 'fg:#858585 italic') # disabled choices for select and checkbox prompts
])
To use our custom style, we need to pass it to the question type:
questionary.text("What's your phone number", style=custom_style_fancy).ask()
It is also possible to use a list of token tuples as a Choice
title. This
example assumes there is a style token named bold
in the custom style you are
using:
Choice(
title=[
('class:text', 'plain text '),
('class:bold', 'bold text')
]
)
As you can see it is possible to use custom style tokens for this purpose as
well. Note that Choices with token tuple titles will not be styled by the
selected
or highlighted
tokens. If not provided, the value
of the Choice
will be the text concatenated ('plain text bold text'
in the above example).
How to Contribute
Contributions are highly welcomed and appreciated. Every little help counts, so do not hesitate!
- Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug. There is a Contributor Friendly tag for issues that should be ideal for people who are not very familiar with the codebase yet.
- Fork the repository on GitHub to start making your changes to the master branch (or branch off of it).
- Write a test which shows that the bug was fixed or that the feature works as expected.
- Ensure your code passes running
black questionary
. - Send a pull request and bug the maintainer until it gets merged and published. 🙂
Contributors
questionary
is written and maintained by Tom Bocklisch.
It is based on the great work of Oyetoke Toby as well as the work from Mark Fink.
Changelog
unreleased (master branch)
1.5.2 (16.04.2020)
Bug fix release.
- Added
.ask_async
support for forms.
1.5.1 (22.01.2020)
Bug fix release.
- Fixed
.ask_async
for questions onprompt_toolkit==2.*
. Added tests for it.
1.5.0 (22.01.2020)
Feature release.
- Added support for prompt_toolkit 3
- All tests will be run against prompt_toolkit 2 and 3
- Removed support for python 3.5 (prompt_toolkit 3 does not support that anymore)
1.4.0 (10.11.2019)
Feature release.
- Added additional question type
autocomplete
- Allow pointer and highlight in select question type
1.3.0 (25.08.2019)
Feature release.
- Add additional options to style checkboxes and select prompts https://github.com/tmbo/questionary/pull/14
1.2.1 (19.08.2019)
Bug fix release.
- Fixed compatibility with python 3.5.2 by removing
Type
annotation (this time for real)
1.2.0 (30.07.2019)
Feature release.
- Allow a user to pass in a validator as an instance https://github.com/tmbo/questionary/pull/10
1.1.1 (21.04.2019)
Bug fix release.
- Fixed compatibility with python 3.5.2 by removing
Type
annotation
1.1.0 (10.03.2019)
Feature release.
- Added
skip_if
to questions to allow skipping questions using a flag
1.0.2 (23.01.2019)
Bug fix release.
- Fixed odd behaviour if select is created without providing any choices
instead, we will raise a
ValueError
now. (#6)
1.0.1 (12.01.2019)
Bug fix release, adding some convenience shortcuts.
1.0.0 (14.12.2018)
Initial public release of the library
- Added python interface
- Added dict style question creation
- Improved the documentation
- More tests and automatic travis test execution
Developer Info
Notes on how to do random things related to this repo
Create one of the commandline recordings
- Install
brew install asciinema
andnpm install --global asciicast2gif
- Run
asciinema rec
- Do the thing
- Convert to giv
asciicast2gif -h 7 -w 120 -s 2 <recoding> output.gif
License
Licensed under the MIT License. Copyright 2020 Tom Bocklisch. Copy of the license.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for questionary-1.5.2-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6998a1fe0639daec0da44e0a973f387e7c778bdc418d76ecfa45a7b3a0997049 |
|
MD5 | 042ea94205a0be1657ea8d9a2511fd74 |
|
BLAKE2b-256 | 057d61b7d0da15bb50e7239c870771320026447b7e2d9490ee96f49dddd3ef0d |