Skip to content

feat: add erase_when_done parameter to prompt constructors#1

Open
tobiashochguertel wants to merge 1 commit intomainfrom
fix/erase-when-done-parameter
Open

feat: add erase_when_done parameter to prompt constructors#1
tobiashochguertel wants to merge 1 commit intomainfrom
fix/erase-when-done-parameter

Conversation

@tobiashochguertel
Copy link
Copy Markdown
Owner

@tobiashochguertel tobiashochguertel commented Mar 14, 2026

Motivation

When using InquirerPy prompts inside a refresh loop (creating a new prompt instance each iteration, e.g. to rebuild a picker after a state change), the previous prompt leaves ghost/artifact lines on the terminal because Application exits without clearing its rendered output.

The underlying prompt_toolkit.Application already supports an erase_when_done attribute that, when True, wipes the rendered area on exit. However, InquirerPy does not expose this as a constructor parameter. Users are forced to reach into the private prompt._application.erase_when_done attribute after construction:

# Current workaround (fragile, undocumented)
prompt = inquirer.fuzzy(message="Pick:", choices=items)
prompt._application.erase_when_done = True
result = await prompt.execute_async()

Change

Add erase_when_done: bool = False to the constructors of all prompts that create an Application directly, and thread it through composite prompts:

File Prompt Change
prompts/fuzzy.py FuzzyPrompt Add param, store as self._erase_when_done, pass to Application()
prompts/list.py ListPrompt Same
prompts/number.py NumberPrompt Same
prompts/checkbox.py CheckboxPrompt Forward to super().__init__()
prompts/expand.py ExpandPrompt Forward to super().__init__()

Docstrings updated on all modified __init__ methods.

Usage after this change

while True:
    result = await inquirer.fuzzy(
        message="Pick:",
        choices=build_choices(),
        erase_when_done=True,   # ← clean exit, no ghost lines
    ).execute_async()
    if result == "done":
        break
    handle(result)

Testing

  • All 81 existing tests in the modified test files pass unchanged.
  • The 81 pre-existing errors in tests/prompts/test_number.py are caused by a conftest.py incompatibility with newer prompt_toolkit (create_pipe_input() returns a context manager; calling .close() on it fails). These failures exist on the unmodified master branch and are unrelated to this PR.

Upstream note

This PR is targeting the fork (tobiashochguertel/InquirerPy). Once reviewed/merged here, a corresponding PR can be opened against kazhala/InquirerPy upstream.

Summary by Sourcery

Expose a new option on interactive prompts to clear their rendered output when the underlying application exits, improving terminal behavior in refresh-loop usage.

New Features:

  • Add an erase_when_done parameter to fuzzy, list, number, checkbox, and expand prompts to control whether the prompt UI is cleared after exit.

Enhancements:

  • Thread the erase_when_done setting through to the underlying prompt_toolkit Application instances and document the new parameter in affected 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>
Copilot AI review requested due to automatic review settings March 14, 2026 16:07
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Mar 14, 2026

Reviewer's Guide

Adds an erase_when_done parameter to several InquirerPy prompt constructors and threads it through to the underlying prompt_toolkit Application so prompts can cleanly clear their rendered output when they exit, especially in refresh-loop usage.

Sequence diagram for prompt execution with erase_when_done

sequenceDiagram
    actor User
    participant InquirerFacade as InquirerPy
    participant FuzzyPrompt
    participant Application

    User->>InquirerFacade: fuzzy(message, choices, erase_when_done=True)
    InquirerFacade->>FuzzyPrompt: __init__(message, choices, erase_when_done=True)
    FuzzyPrompt->>FuzzyPrompt: set _erase_when_done = True
    FuzzyPrompt->>Application: __init__(..., erase_when_done=_erase_when_done)
    Note over Application: erase_when_done flag stored internally

    User->>FuzzyPrompt: execute_async()
    FuzzyPrompt->>Application: run_async()
    Application-->>FuzzyPrompt: result
    FuzzyPrompt-->>User: selected value

    Application->>Application: exit
    alt erase_when_done is True
        Application->>Terminal: clear rendered prompt area
    else erase_when_done is False
        Application->>Terminal: leave rendered prompt on screen
    end
Loading

Updated class diagram for prompt constructors with erase_when_done

classDiagram
    class Application {
        +bool erase_when_done
        +__init__(layout, style, key_bindings, after_render, editing_mode, erase_when_done)
    }

    class BaseListPrompt {
        <<abstract>>
        +message
        +choices
        +execute()
        +execute_async()
    }

    class BaseComplexPrompt {
        <<abstract>>
        +message
        +execute()
        +execute_async()
    }

    class ListPrompt {
        +bool _show_cursor
        +bool _erase_when_done
        +__init__(message, choices, style, default, height, max_height, keybindings, show_cursor, instruction, transformer, filter, validate, invalid_message, multiselect, keybind_help, show_cursor, vi_mode, mandatory, mandatory_message, session_result, erase_when_done)
    }

    class FuzzyPrompt {
        +bool _erase_when_done
        +__init__(message, choices, style, default, keybindings, vi_mode, instruction, long_instruction, separator, transformer, filter, validate, invalid_message, mandatory, mandatory_message, session_result, erase_when_done)
    }

    class CheckboxPrompt {
        +__init__(message, choices, style, default, height, max_height, keybindings, instruction, transformer, filter, validate, invalid_message, keybind_help, show_cursor, vi_mode, mandatory, mandatory_message, session_result, erase_when_done)
    }

    class ExpandPrompt {
        +__init__(message, choices, style, default, height, max_height, keybindings, instruction, expand_pointer, expand_selected, expand_help, help_msg, keybind_help, show_cursor, vi_mode, mandatory, mandatory_message, session_result, erase_when_done)
    }

    class NumberPrompt {
        +bool _erase_when_done
        +__init__(message, style, default, float_allowed, min_allowed, max_allowed, step, precision, keybindings, instruction, transformer, filter, validate, invalid_message, show_cursor, border, vi_mode, mandatory, mandatory_message, session_result, erase_when_done)
    }

    BaseListPrompt <|-- ListPrompt
    BaseListPrompt <|-- FuzzyPrompt
    ListPrompt <|-- CheckboxPrompt
    ListPrompt <|-- ExpandPrompt
    BaseComplexPrompt <|-- NumberPrompt

    ListPrompt --> Application : creates
    FuzzyPrompt --> Application : creates
    CheckboxPrompt --> Application : creates via super
    ExpandPrompt --> Application : creates via super
    NumberPrompt --> Application : creates

    ListPrompt ..> Application : pass erase_when_done
    FuzzyPrompt ..> Application : pass erase_when_done
    CheckboxPrompt ..> Application : pass erase_when_done
    ExpandPrompt ..> Application : pass erase_when_done
    NumberPrompt ..> Application : pass erase_when_done
Loading

File-Level Changes

Change Details Files
Expose erase_when_done option on fuzzy, list, and number prompts and wire it to prompt_toolkit Application.
  • Extend FuzzyPrompt.init to accept erase_when_done, store it on the instance, and pass it to Application(...) when constructing the prompt_toolkit Application.
  • Extend ListPrompt.init to accept erase_when_done, store it on the instance, and pass it to Application(...) when constructing the prompt_toolkit Application.
  • Extend NumberPrompt.init to accept erase_when_done, store it on the instance, and pass it to Application(...) when constructing the prompt_toolkit Application.
  • Update init docstrings for FuzzyPrompt, ListPrompt, and NumberPrompt to document erase_when_done and its refresh-loop usage.
InquirerPy/prompts/fuzzy.py
InquirerPy/prompts/list.py
InquirerPy/prompts/number.py
Thread erase_when_done through composite prompts so they inherit the new behavior from ListPrompt/Base prompts.
  • Add erase_when_done parameter to CheckboxPrompt.init and forward it to the ListPrompt super().init call so checkbox prompts can control Application erasure.
  • Add erase_when_done parameter to ExpandPrompt.init and forward it to the ListPrompt super().init call so expand prompts can control Application erasure.
  • Update init docstrings for CheckboxPrompt and ExpandPrompt to document erase_when_done and its refresh-loop usage.
InquirerPy/prompts/checkbox.py
InquirerPy/prompts/expand.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 14, 2026

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants