From 3edfd4bb180e6ac943e2ad20f45d540b7a036ebb Mon Sep 17 00:00:00 2001 From: Kevin Zhuang Date: Tue, 3 Aug 2021 12:46:21 +1000 Subject: [PATCH] feat: enable instruction for non-list type prompts #7 --- InquirerPy/base.py | 23 +++++++++++++---------- InquirerPy/prompts/confirm.py | 14 ++++++++++---- InquirerPy/prompts/filepath.py | 3 +++ InquirerPy/prompts/input.py | 10 ++++++++-- InquirerPy/prompts/secret.py | 23 +++++++++++++---------- examples/example_confirm.py | 2 +- examples/example_secret.py | 3 ++- 7 files changed, 50 insertions(+), 28 deletions(-) diff --git a/InquirerPy/base.py b/InquirerPy/base.py index d7bf61d..2ffecbe 100644 --- a/InquirerPy/base.py +++ b/InquirerPy/base.py @@ -55,7 +55,8 @@ class BaseSimplePrompt(ABC): :param style: The style dictionary to apply. :param vi_mode: Use vi kb for the prompt. :param qmark: The custom symbol to display infront of the question before its answered. - :param amark: THe custom symbol to display infront of the question after its answered. + :param amark: The custom symbol to display infront of the question after its answered. + :param instruction: Instruction to display after the question message. :param validate: A callable or Validator instance to validate user input. :param invalid_message: The message to display when input is invalid. :param transformer: A callable to transform the result, this is visual effect only. @@ -73,6 +74,7 @@ def __init__( vi_mode: bool = False, qmark: str = "?", amark: str = "?", + instruction: str = "", validate: Union[Callable[[Any], bool], Validator] = None, invalid_message: str = "Invalid input", transformer: Callable[[Any], Any] = None, @@ -84,6 +86,7 @@ def __init__( """Construct the base class for simple prompts.""" self._result = session_result or {} self._message = message if not isinstance(message, Callable) else message(self._result) # type: ignore + self._instruction = instruction self._default = ( default if not isinstance(default, Callable) else default(self._result) ) @@ -222,6 +225,14 @@ def execute(self) -> Any: """ pass + @property + def instruction(self) -> str: + """Instruction to display next to question. + + :return: Instruction text + """ + return self._instruction + class InquirerPyUIControl(FormattedTextControl): """A UIControl class intended to be consumed by `prompt_toolkit` window. @@ -457,6 +468,7 @@ def __init__( vi_mode=vi_mode, qmark=qmark, amark=amark, + instruction=instruction, transformer=transformer, filter=filter, invalid_message=invalid_message, @@ -465,7 +477,6 @@ def __init__( session_result=session_result, ) self._content_control: InquirerPyUIControl - self._instruction = instruction self._invalid_message = invalid_message self._multiselect = multiselect self._rendered = False @@ -613,14 +624,6 @@ def execute(self, raise_keyboard_interrupt: bool = True) -> Any: return result return self._filter(result) - @property - def instruction(self) -> str: - """Instruction to display next to question. - - :return: Instruction text - """ - return self._instruction - @property def content_control(self) -> InquirerPyUIControl: """Get the content controller object. diff --git a/InquirerPy/prompts/confirm.py b/InquirerPy/prompts/confirm.py index 33b351a..8513e87 100644 --- a/InquirerPy/prompts/confirm.py +++ b/InquirerPy/prompts/confirm.py @@ -22,6 +22,7 @@ class ConfirmPrompt(BaseSimplePrompt): :param default: Set default answer value. :param qmark: The custom symbol to display infront of the question before its answered. :param amark: THe custom symbol to display infront of the question after its answered. + :param instruction: Instruction to display after the question message. :param transformer: A callable to transform the result, this is visual effect only. :param filter: A callable to filter the result, updating the user input before returning the result. :param wrap_lines: Soft wrap question lines when question exceeds the terminal width. @@ -34,6 +35,7 @@ def __init__( default: Union[bool, Callable[[Dict[str, Any]], bool]] = False, qmark: str = "?", amark: str = "?", + instruction: str = "", transformer: Callable[[bool], Any] = None, filter: Callable[[bool], Any] = None, wrap_lines: bool = True, @@ -46,6 +48,7 @@ def __init__( vi_mode=False, qmark=qmark, amark=amark, + instruction=instruction, transformer=transformer, filter=filter, default=default, @@ -104,10 +107,13 @@ def _get_prompt_message(self) -> List[Tuple[str, str]]: :return: A list of formatted message to be consumed by PromptSession. """ - pre_answer = ( - "class:instruction", - "%s" % " (Y/n)" if self._default else " (y/N)", - ) + if not self.instruction: + pre_answer = ( + "class:instruction", + " (Y/n)" if self._default else " (y/N)", + ) + 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) diff --git a/InquirerPy/prompts/filepath.py b/InquirerPy/prompts/filepath.py index 792feda..3307a2a 100644 --- a/InquirerPy/prompts/filepath.py +++ b/InquirerPy/prompts/filepath.py @@ -86,6 +86,7 @@ class FilePathPrompt(InputPrompt): :param default: The default result. :param qmark: The custom symbol to display infront of the question before its answered. :param amark: The custom symbol to display infront of the question after its answered. + :param instruction: Instruction to display after the question message. :param multicolumn_complete: Complete in multi column. :param validate: A callable or a validation class to validate user input. :param invalid_message: The error message to display when input is invalid. @@ -104,6 +105,7 @@ def __init__( default: Union[str, Callable[[SessionResult], str]] = "", qmark: str = "?", amark: str = "?", + instruction: str = "", multicolumn_complete: bool = False, validate: Union[Callable[[str], bool], Validator] = None, invalid_message: str = "Invalid input", @@ -126,6 +128,7 @@ def __init__( default=default, qmark=qmark, amark=amark, + instruction=instruction, completer=ThreadedCompleter( FilePathCompleter( only_directories=only_directories, only_files=only_files diff --git a/InquirerPy/prompts/input.py b/InquirerPy/prompts/input.py index 8a0bc05..8fadc5c 100644 --- a/InquirerPy/prompts/input.py +++ b/InquirerPy/prompts/input.py @@ -29,6 +29,7 @@ class InputPrompt(BaseSimplePrompt): :param default: The default result. :param qmark: The custom symbol to display infront of the question before its answered. :param amark: The custom symbol to display infront of the question after its answered. + :param instruction: Instruction to display after the question message. :param completer: Add auto completer to user input. :param multicolumn_complete: Complete in multi column. :param multiline: Enable multiline mode. @@ -47,6 +48,7 @@ def __init__( default: Union[str, Callable[[SessionResult], str]] = "", qmark: str = "?", amark: str = "?", + instruction: str = "", completer: Union[Dict[str, Optional[str]], Completer] = None, multicolumn_complete: bool = False, multiline: bool = False, @@ -64,6 +66,7 @@ def __init__( vi_mode=vi_mode, qmark=qmark, amark=amark, + instruction=instruction, validate=validate, invalid_message=invalid_message, transformer=transformer, @@ -159,10 +162,13 @@ def _get_prompt_message( :return: The formatted text for PromptSession. """ if not pre_answer: - if self._multiline: + if self._multiline and not self._instruction: pre_answer = ("class:instruction", " ESC + Enter to finish input") else: - pre_answer = ("class:instruction", " ") + pre_answer = ( + "class:instruction", + " %s " % self.instruction if self.instruction else " ", + ) if not post_answer: if self._multiline and self.status["result"]: lines = self.status["result"].split("\n") diff --git a/InquirerPy/prompts/secret.py b/InquirerPy/prompts/secret.py index c5baf09..1b3d350 100644 --- a/InquirerPy/prompts/secret.py +++ b/InquirerPy/prompts/secret.py @@ -18,6 +18,7 @@ class SecretPrompt(InputPrompt): :param default: The default value. :param qmark: The custom symbol to display infront of the question before its answered. :param amark: The custom symbol to display infront of the question after its answered. + :param instruction: Instruction to display after the question message. :param vi_mode: Use vi kb for the prompt. :param validate: A callable to validate the user input. :param invalid_message: The error message to display when validator failed. @@ -33,6 +34,7 @@ def __init__( default: Union[str, Callable[[SessionResult], str]] = "", qmark: str = "?", amark: str = "?", + instruction: str = "", vi_mode: bool = False, validate: Union[Validator, Callable[[str], bool]] = None, invalid_message: str = "Invalid input", @@ -54,6 +56,7 @@ def __init__( default=default, qmark=qmark, amark=amark, + instruction=instruction, validate=validate, invalid_message=invalid_message, is_password=True, @@ -69,14 +72,14 @@ def _get_prompt_message(self) -> List[Tuple[str, str]]: :return: A list of formatted message. """ - pre_answer = ("class:instruction", " ") - if not self._transformer: - post_answer = ( - "class:answer", - "" - if not self.status["result"] - else " %s" % "".join(["*" for _ in self.status["result"]]), - ) - else: - post_answer = ("class:answer", " %s" % self.status["result"]) + pre_answer = ( + "class:instruction", + " %s " % self.instruction if self.instruction else " ", + ) + post_answer = ( + "class:answer", + "" + if not self.status["result"] + else " %s" % "".join(["*" for _ in self.status["result"]]), + ) return super()._get_prompt_message(pre_answer, post_answer) diff --git a/examples/example_confirm.py b/examples/example_confirm.py index fa90b53..f584538 100644 --- a/examples/example_confirm.py +++ b/examples/example_confirm.py @@ -1,4 +1,4 @@ -from InquirerPy import prompt, inquirer +from InquirerPy import inquirer, prompt def classic(): diff --git a/examples/example_secret.py b/examples/example_secret.py index 3ee63e0..a62c484 100644 --- a/examples/example_secret.py +++ b/examples/example_secret.py @@ -1,4 +1,4 @@ -from InquirerPy import prompt, inquirer +from InquirerPy import inquirer, prompt from InquirerPy.validator import PasswordValidator original_password = "InquirerPy45@" @@ -33,6 +33,7 @@ def alternate(): transformer=lambda _: "[hidden]", validate=lambda text: text == original_password, invalid_message="Wrong password", + instruction="(abc)", ).execute() new_password = inquirer.secret( message="New password:",