|
16 | 16 | from prompt_toolkit.application import Application, create_app_session |
17 | 17 | from prompt_toolkit.enums import EditingMode |
18 | 18 | from prompt_toolkit.filters import Condition, to_filter |
| 19 | +from prompt_toolkit.formatted_text import ANSI |
19 | 20 | from prompt_toolkit.input.typeahead import get_typeahead, store_typeahead |
20 | 21 | from prompt_toolkit.key_binding import KeyBindings, merge_key_bindings |
21 | 22 | from prompt_toolkit.key_binding.key_processor import KeyPress, KeyPressEvent |
|
28 | 29 |
|
29 | 30 | if TYPE_CHECKING: |
30 | 31 | from prompt_toolkit.buffer import Buffer |
31 | | - from prompt_toolkit.formatted_text import ANSI |
32 | 32 |
|
33 | 33 | from .cmd2 import Cmd |
34 | 34 |
|
@@ -425,7 +425,10 @@ def _accept_line(self, buff: "Buffer") -> bool: |
425 | 425 | """Hand an accepted line to the waiting command thread without ending the run.""" |
426 | 426 | if self._line is not None and not self._line.done(): |
427 | 427 | self._line.set_result(buff.document.text) |
428 | | - return True # Keep the text; read_line() resets the buffer itself. |
| 428 | + # Discard the text so the live prompt region stops showing the accepted line. |
| 429 | + # _echo_accepted() is what commits it, and leaving it here too would draw it |
| 430 | + # twice. validate_and_handle() still records history before resetting. |
| 431 | + return False |
429 | 432 |
|
430 | 433 | def _fail_line(self, error: BaseException) -> None: |
431 | 434 | """Abort the pending read_line() with Ctrl-C's or Ctrl-D's exception.""" |
@@ -471,11 +474,28 @@ def enter() -> None: |
471 | 474 | raise |
472 | 475 | self._check_running() |
473 | 476 | else: |
| 477 | + self._echo_accepted(message, text) |
474 | 478 | return text |
475 | 479 | finally: |
476 | 480 | self._line = None |
477 | 481 | session.default_buffer.accept_handler = self._session_accept |
478 | 482 |
|
| 483 | + @staticmethod |
| 484 | + def _resolve_message(message: "PromptMessage") -> str: |
| 485 | + """Render the prompt to text for the scrollback echo.""" |
| 486 | + resolved = message() if callable(message) else message |
| 487 | + return resolved.value if isinstance(resolved, ANSI) else resolved |
| 488 | + |
| 489 | + def _echo_accepted(self, message: "PromptMessage", text: str) -> None: |
| 490 | + """Commit the accepted line above the toolbar. |
| 491 | +
|
| 492 | + prompt-toolkit normally leaves the prompt line in the scrollback when its run |
| 493 | + ends. Prompt mode never ends a run, so write the line through the same stdout |
| 494 | + proxy that keeps command output above the toolbar. |
| 495 | + """ |
| 496 | + self.cmd.stdout.write(f"{self._resolve_message(message)}{text}\n") |
| 497 | + self.cmd.stdout.flush() |
| 498 | + |
479 | 499 | def page(self, text: str, *, chop: bool) -> None: |
480 | 500 | """Show a pager above the same toolbar without starting another input reader.""" |
481 | 501 | size = self.app.output.get_size() |
|
0 commit comments