1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
from typing import Any
from typing import Optional
from prompt_toolkit import PromptSession
from prompt_toolkit.formatted_text import to_formatted_text
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.keys import Keys
from prompt_toolkit.styles import Style
from questionary.constants import DEFAULT_QUESTION_PREFIX
from questionary.constants import NO
from questionary.constants import NO_OR_YES
from questionary.constants import YES
from questionary.constants import YES_OR_NO
from questionary.question import Question
from questionary.styles import merge_styles_default
def confirm(
message: str,
default: bool = True,
qmark: str = DEFAULT_QUESTION_PREFIX,
style: Optional[Style] = None,
auto_enter: bool = True,
instruction: Optional[str] = None,
**kwargs: Any,
) -> Question:
"""A yes or no question. The user can either confirm or deny.
This question type can be used to prompt the user for a confirmation
of a yes-or-no question. If the user just hits enter, the default
value will be returned.
Example:
>>> import questionary
>>> questionary.confirm("Are you amazed?").ask()
? Are you amazed? Yes
True
.. image:: ../images/confirm.gif
This is just a really basic example, the prompt can be customised using the
parameters.
Args:
message: Question text.
default: Default value will be returned if the user just hits
enter.
qmark: Question prefix displayed in front of the question.
By default this is a ``?``.
style: A custom color and style for the question parts. You can
configure colors as well as font types for different elements.
auto_enter: If set to `False`, the user needs to press the 'enter' key to
accept their answer. If set to `True`, a valid input will be
accepted without the need to press 'Enter'.
instruction: A message describing how to proceed through the
confirmation prompt.
Returns:
:class:`Question`: Question instance, ready to be prompted (using `.ask()`).
"""
merged_style = merge_styles_default([style])
status = {"answer": None, "complete": False}
def get_prompt_tokens():
tokens = []
tokens.append(("class:qmark", qmark))
tokens.append(("class:question", " {} ".format(message)))
if instruction is not None:
tokens.append(("class:instruction", instruction))
elif not status["complete"]:
_instruction = YES_OR_NO if default else NO_OR_YES
tokens.append(("class:instruction", "{} ".format(_instruction)))
if status["answer"] is not None:
answer = YES if status["answer"] else NO
tokens.append(("class:answer", answer))
return to_formatted_text(tokens)
def exit_with_result(event):
status["complete"] = True
event.app.exit(result=status["answer"])
bindings = KeyBindings()
@bindings.add(Keys.ControlQ, eager=True)
@bindings.add(Keys.ControlC, eager=True)
def _(event):
event.app.exit(exception=KeyboardInterrupt, style="class:aborting")
@bindings.add("n")
@bindings.add("N")
def key_n(event):
status["answer"] = False
if auto_enter:
exit_with_result(event)
@bindings.add("y")
@bindings.add("Y")
def key_y(event):
status["answer"] = True
if auto_enter:
exit_with_result(event)
@bindings.add(Keys.ControlH)
def key_backspace(event):
status["answer"] = None
@bindings.add(Keys.ControlM, eager=True)
def set_answer(event):
if status["answer"] is None:
status["answer"] = default
exit_with_result(event)
@bindings.add(Keys.Any)
def other(event):
"""Disallow inserting other text."""
return Question(
PromptSession(
get_prompt_tokens, key_bindings=bindings, style=merged_style, **kwargs
).app
)
|