Spaces:
Sleeping
Sleeping
File size: 8,522 Bytes
2d876d1 |
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 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
"""Module contains the class to create a confirm prompt."""
from typing import TYPE_CHECKING, Any, Callable, List, Optional, Tuple
from prompt_toolkit.buffer import ValidationState
from prompt_toolkit.keys import Keys
from prompt_toolkit.shortcuts import PromptSession
from prompt_toolkit.validation import ValidationError
from InquirerPy.base import BaseSimplePrompt
from InquirerPy.exceptions import InvalidArgument
from InquirerPy.utils import (
InquirerPyDefault,
InquirerPyKeybindings,
InquirerPyMessage,
InquirerPySessionResult,
InquirerPyStyle,
)
if TYPE_CHECKING:
from prompt_toolkit.input.base import Input
from prompt_toolkit.key_binding.key_processor import KeyPressEvent
from prompt_toolkit.output.base import Output
__all__ = ["ConfirmPrompt"]
class ConfirmPrompt(BaseSimplePrompt):
"""Create a prompt that provides 2 options (confirm/deny) and controlled via single keypress.
A wrapper class around :class:`~prompt_toolkit.shortcuts.PromptSession`.
Args:
message: The question to ask the user.
Refer to :ref:`pages/dynamic:message` documentation for more details.
style: An :class:`InquirerPyStyle` instance.
Refer to :ref:`Style <pages/style:Alternate Syntax>` documentation for more details.
vi_mode: Used for compatibility .
default: Set the default value of the prompt, should be either `True` or `False`.
This affects the value returned when user directly hit `enter` key.
Refer to :ref:`pages/dynamic:default` documentation for more details.
qmark: Question mark symbol. Custom symbol that will be displayed infront of the question before its answered.
amark: Answer mark symbol. Custom symbol that will be displayed infront of the question after its answered.
instruction: Short instruction to display next to the question.
long_instruction: Long instructions to display at the bottom of the prompt.
transformer: A function which performs additional transformation on the value that gets printed to the terminal.
Different than `filter` parameter, this is only visual effect and won’t affect the actual value returned by :meth:`~InquirerPy.base.simple.BaseSimplePrompt.execute`.
Refer to :ref:`pages/dynamic:transformer` documentation for more details.
filter: A function which performs additional transformation on the result.
This affects the actual value returned by :meth:`~InquirerPy.base.simple.BaseSimplePrompt.execute`.
Refer to :ref:`pages/dynamic:filter` documentation for more details.
keybindings: Customise the builtin keybindings.
Refer to :ref:`pages/kb:Keybindings` for more details.
wrap_lines: Soft wrap question lines when question exceeds the terminal width.
confirm_letter: Letter used to confirm the prompt. A keybinding will be created for this letter.
Default is `y` and pressing `y` will answer the prompt with value `True`.
reject_letter: Letter used to reject the prompt. A keybinding will be created for this letter.
Default is `n` and pressing `n` will answer the prompt with value `False`.
raise_keyboard_interrupt: Raise the :class:`KeyboardInterrupt` exception when `ctrl-c` is pressed. If false, the result
will be `None` and the question is skiped.
mandatory: Indicate if the prompt is mandatory. If True, then the question cannot be skipped.
mandatory_message: Error message to show when user attempts to skip mandatory prompt.
session_result: Used internally for :ref:`index:Classic Syntax (PyInquirer)`.
input: Used internally and will be removed in future updates.
output: Used internally and will be removed in future updates.
Examples:
>>> from InquirerPy import inquirer
>>> result = inquirer.confirm(message="Confirm?").execute()
>>> print(result)
True
"""
def __init__(
self,
message: InquirerPyMessage,
style: Optional[InquirerPyStyle] = None,
default: InquirerPyDefault = False,
vi_mode: bool = False,
qmark: str = "?",
amark: str = "?",
instruction: str = "",
long_instruction: str = "",
transformer: Optional[Callable[[bool], Any]] = None,
filter: Optional[Callable[[bool], Any]] = None,
keybindings: Optional[InquirerPyKeybindings] = None,
wrap_lines: bool = True,
confirm_letter: str = "y",
reject_letter: str = "n",
raise_keyboard_interrupt: bool = True,
mandatory: bool = True,
mandatory_message: str = "Mandatory prompt",
session_result: Optional[InquirerPySessionResult] = None,
input: Optional["Input"] = None,
output: Optional["Output"] = None,
) -> None:
vi_mode = False
super().__init__(
message=message,
style=style,
vi_mode=vi_mode,
qmark=qmark,
amark=amark,
instruction=instruction,
transformer=transformer,
filter=filter,
default=default,
wrap_lines=wrap_lines,
raise_keyboard_interrupt=raise_keyboard_interrupt,
mandatory=mandatory,
mandatory_message=mandatory_message,
session_result=session_result,
)
if not isinstance(self._default, bool):
raise InvalidArgument(
f"{type(self).__name__} argument default should be type of bool"
)
self._confirm_letter = confirm_letter
self._reject_letter = reject_letter
if not keybindings:
keybindings = {}
self.kb_maps = {
"confirm": [
{"key": self._confirm_letter},
{"key": self._confirm_letter.upper()},
],
"reject": [
{"key": self._reject_letter},
{"key": self._reject_letter.upper()},
],
"any": [{"key": Keys.Any}],
**keybindings,
}
self.kb_func_lookup = {
"confirm": [{"func": self._handle_confirm}],
"reject": [{"func": self._handle_reject}],
"any": [{"func": lambda _: None}],
}
self._keybinding_factory()
self._session = PromptSession(
message=self._get_prompt_message,
key_bindings=self._kb,
style=self._style,
wrap_lines=self._wrap_lines,
bottom_toolbar=[("class:long_instruction", long_instruction)]
if long_instruction
else None,
input=input,
output=output,
)
def _set_error(self, message: str) -> None:
self._session.default_buffer.validation_state = ValidationState.INVALID
self._session.default_buffer.validation_error = ValidationError(message=message)
def _handle_reject(self, event) -> None:
self._session.default_buffer.text = ""
self.status["answered"] = True
self.status["result"] = False
event.app.exit(result=False)
def _handle_confirm(self, event) -> None:
self._session.default_buffer.text = ""
self.status["answered"] = True
self.status["result"] = True
event.app.exit(result=True)
def _handle_enter(self, event: "KeyPressEvent") -> None:
self.status["answered"] = True
self.status["result"] = self._default
event.app.exit(result=self._default)
def _get_prompt_message(self) -> List[Tuple[str, str]]:
"""Get message to display infront of the input buffer.
Returns:
Formatted text in list of tuple format.
"""
if not self.instruction:
pre_answer = (
"class:instruction",
" (%s/%s) " % (self._confirm_letter.upper(), self._reject_letter)
if self._default
else " (%s/%s) " % (self._confirm_letter, self._reject_letter.upper()),
)
else:
pre_answer = ("class:instruction", " %s " % self.instruction)
post_answer = ("class:answer", " Yes" if self.status["result"] else " No")
return super()._get_prompt_message(pre_answer, post_answer)
def _run(self) -> bool:
return self._session.prompt()
async def _run_async(self) -> Any:
return await self._session.prompt_async()
|