134 lines
4.0 KiB
Python
134 lines
4.0 KiB
Python
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
|
|
)
|