From 51c62c4c5e964a4d5b54976a049db1503e85aaff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Hochg=C3=BCrtel?= Date: Sat, 14 Mar 2026 17:05:49 +0100 Subject: [PATCH] feat: add erase_when_done parameter to prompt constructors Expose prompt_toolkit's Application.erase_when_done as a first-class parameter on all prompts that create an Application instance directly (FuzzyPrompt, ListPrompt, NumberPrompt) and forward it through composite prompts that delegate to them (CheckboxPrompt, ExpandPrompt). When True, the rendered prompt UI is erased from the terminal when the application exits. This is useful when prompts are used in a loop (e.g. rebuilding a fuzzy picker after a state change) to avoid ghost/artifact lines accumulating in the terminal output. Without this parameter, users must reach into the private prompt._application.erase_when_done attribute after construction, which is fragile and undocumented. This change gives them a supported, documented path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- InquirerPy/prompts/checkbox.py | 5 +++++ InquirerPy/prompts/expand.py | 5 +++++ InquirerPy/prompts/fuzzy.py | 6 ++++++ InquirerPy/prompts/list.py | 6 ++++++ InquirerPy/prompts/number.py | 6 ++++++ 5 files changed, 28 insertions(+) diff --git a/InquirerPy/prompts/checkbox.py b/InquirerPy/prompts/checkbox.py index d6bca33..19ff759 100644 --- a/InquirerPy/prompts/checkbox.py +++ b/InquirerPy/prompts/checkbox.py @@ -157,6 +157,9 @@ class CheckboxPrompt(ListPrompt): 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)`. + erase_when_done: Clear the rendered prompt from the terminal after the application exits. + Useful when looping over multiple prompt instances (e.g. a refresh loop) to avoid + leaving ghost output from previous iterations on screen. Examples: >>> from InquirerPy import inquirer @@ -194,6 +197,7 @@ def __init__( mandatory: bool = True, mandatory_message: str = "Mandatory prompt", session_result: Optional[InquirerPySessionResult] = None, + erase_when_done: bool = False, ) -> None: self.content_control = InquirerPyCheckboxControl( choices=choices, @@ -228,6 +232,7 @@ def __init__( mandatory=mandatory, mandatory_message=mandatory_message, session_result=session_result, + erase_when_done=erase_when_done, ) def _handle_enter(self, event) -> None: diff --git a/InquirerPy/prompts/expand.py b/InquirerPy/prompts/expand.py index 80a2db4..98f9fc8 100644 --- a/InquirerPy/prompts/expand.py +++ b/InquirerPy/prompts/expand.py @@ -262,6 +262,9 @@ class ExpandPrompt(ListPrompt): 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)`. + erase_when_done: Clear the rendered prompt from the terminal after the application exits. + Useful when looping over multiple prompt instances (e.g. a refresh loop) to avoid + leaving ghost output from previous iterations on screen. Examples: >>> from InquirerPy import inquirer @@ -304,6 +307,7 @@ def __init__( mandatory: bool = True, mandatory_message: str = "Mandatory prompt", session_result: Optional[InquirerPySessionResult] = None, + erase_when_done: bool = False, ) -> None: if expand_help is None: expand_help = ExpandHelp(message=help_msg) @@ -345,6 +349,7 @@ def __init__( mandatory=mandatory, mandatory_message=mandatory_message, session_result=session_result, + erase_when_done=erase_when_done, ) def _on_rendered(self, _) -> None: diff --git a/InquirerPy/prompts/fuzzy.py b/InquirerPy/prompts/fuzzy.py index 83be9b8..feb66fb 100644 --- a/InquirerPy/prompts/fuzzy.py +++ b/InquirerPy/prompts/fuzzy.py @@ -325,6 +325,9 @@ class FuzzyPrompt(BaseListPrompt): 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)`. + erase_when_done: Clear the rendered prompt from the terminal after the application exits. + Useful when looping over multiple prompt instances (e.g. a refresh loop) to avoid + leaving ghost output from previous iterations on screen. Examples: >>> from InquirerPy import inquirer @@ -366,6 +369,7 @@ def __init__( mandatory: bool = True, mandatory_message: str = "Mandatory prompt", session_result: Optional[InquirerPySessionResult] = None, + erase_when_done: bool = False, ) -> None: if not keybindings: keybindings = {} @@ -374,6 +378,7 @@ def __init__( self._task = None self._rendered = False self._exact_symbol = exact_symbol + self._erase_when_done = erase_when_done keybindings = { "up": [{"key": "up"}, {"key": "c-p"}], @@ -498,6 +503,7 @@ def __init__( key_bindings=self._kb, editing_mode=self._editing_mode, after_render=self._after_render, + erase_when_done=self._erase_when_done, ) def _toggle_exact(self, _, value: Optional[bool] = None) -> None: diff --git a/InquirerPy/prompts/list.py b/InquirerPy/prompts/list.py index d1f4a09..4b3abb2 100644 --- a/InquirerPy/prompts/list.py +++ b/InquirerPy/prompts/list.py @@ -154,6 +154,9 @@ class ListPrompt(BaseListPrompt): 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)`. + erase_when_done: Clear the rendered prompt from the terminal after the application exits. + Useful when looping over multiple prompt instances (e.g. a refresh loop) to avoid + leaving ghost output from previous iterations on screen. Examples: >>> from InquirerPy import inquirer @@ -192,6 +195,7 @@ def __init__( mandatory: bool = True, mandatory_message: str = "Mandatory prompt", session_result: Optional[InquirerPySessionResult] = None, + erase_when_done: bool = False, ) -> None: if not hasattr(self, "_content_control"): self.content_control = InquirerPyListControl( @@ -226,6 +230,7 @@ def __init__( session_result=session_result, ) self._show_cursor = show_cursor + self._erase_when_done = erase_when_done self._dimmension_height, self._dimmension_max_height = calculate_height( height, max_height, height_offset=self.height_offset ) @@ -282,6 +287,7 @@ def __init__( style=self._style, key_bindings=self._kb, after_render=self._after_render, + erase_when_done=self._erase_when_done, ) def _get_prompt_message_with_cursor(self) -> List[Tuple[str, str]]: diff --git a/InquirerPy/prompts/number.py b/InquirerPy/prompts/number.py index d42a4ce..3dd2afe 100644 --- a/InquirerPy/prompts/number.py +++ b/InquirerPy/prompts/number.py @@ -95,6 +95,9 @@ class NumberPrompt(BaseComplexPrompt): 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)`. + erase_when_done: Clear the rendered prompt from the terminal after the application exits. + Useful when looping over multiple prompt instances (e.g. a refresh loop) to avoid + leaving ghost output from previous iterations on screen. Examples: >>> from InquirerPy import inquirer @@ -128,6 +131,7 @@ def __init__( mandatory: bool = True, mandatory_message: str = "Mandatory prompt", session_result: Optional[InquirerPySessionResult] = None, + erase_when_done: bool = False, ) -> None: super().__init__( message=message, @@ -157,6 +161,7 @@ def __init__( self._whole_replace = False self._integral_replace = False self._replace_mode = replace_mode + self._erase_when_done = erase_when_done self._leading_zero_pattern = re.compile(r"^(0*)[0-9]+.*") self._sn_pattern = re.compile(r"^.*E-.*") @@ -329,6 +334,7 @@ def _(_): key_bindings=self._kb, after_render=self._after_render, editing_mode=self._editing_mode, + erase_when_done=self._erase_when_done, ) def _fix_sn(self, value: str) -> Tuple[str, str]: