Skip to content

Commit 45a260d

Browse files
committed
Added ability to use Rich renderables as alert messages.
1 parent 29ace9c commit 45a260d

1 file changed

Lines changed: 30 additions & 5 deletions

File tree

cmd2/cmd2.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -313,14 +313,18 @@ class AsyncAlert:
313313
"""Contents of an asynchronous alert which display while user is at prompt.
314314
315315
:param msg: an optional message to be printed above the prompt.
316+
:param soft_wrap: Enable soft wrap mode. This only applies with msg is not None.
317+
Defaults to True. See print_to() docstring for more details on
318+
this parameter.
316319
:param prompt: an optional string to dynamically replace the current prompt.
317320
318321
:ivar timestamp: monotonic creation time of the alert. If an alert was created
319322
before the current prompt was rendered, its prompt data is ignored
320323
to avoid a stale display, but its msg data will still be displayed.
321324
"""
322325

323-
msg: str | None = None
326+
msg: RenderableType | None = None
327+
soft_wrap: bool = True
324328
prompt: str | None = None
325329
timestamp: float = field(default_factory=time.monotonic, init=False)
326330

@@ -3657,7 +3661,19 @@ def _process_alerts(self) -> None:
36573661
# prevents async alerts from printing once a command starts.
36583662

36593663
# Print all alerts at once to reduce flicker.
3660-
alert_text = "\n".join(alert.msg for alert in self._alert_queue if alert.msg)
3664+
console = self._get_core_print_console(
3665+
file=self.stdout,
3666+
emoji=False,
3667+
markup=False,
3668+
highlight=False,
3669+
)
3670+
3671+
with console.capture() as capture:
3672+
for alert in self._alert_queue:
3673+
if alert.msg is not None:
3674+
console.print(alert.msg, soft_wrap=alert.soft_wrap)
3675+
3676+
alert_text = capture.get()
36613677

36623678
# Find the latest prompt update among all pending alerts.
36633679
latest_prompt = None
@@ -3681,7 +3697,7 @@ def _process_alerts(self) -> None:
36813697
if alert_text:
36823698
# Print the alert messages above the prompt.
36833699
with patch_stdout():
3684-
print_formatted_text(pt_filter_style(alert_text))
3700+
print_formatted_text(ANSI(alert_text), end="")
36853701

36863702
elif latest_prompt is not None:
36873703
# Refresh UI immediately to show the new prompt
@@ -5616,7 +5632,13 @@ def do__relative_run_script(self, args: argparse.Namespace) -> bool | None:
56165632
# self.last_result will be set by do_run_script()
56175633
return self.do_run_script(su.quote(relative_path))
56185634

5619-
def add_alert(self, *, msg: str | None = None, prompt: str | None = None) -> None:
5635+
def add_alert(
5636+
self,
5637+
*,
5638+
msg: RenderableType | None = None,
5639+
soft_wrap: bool = True,
5640+
prompt: str | None = None,
5641+
) -> None:
56205642
"""Queue an asynchronous alert to be displayed when the prompt is active.
56215643
56225644
Examples:
@@ -5625,14 +5647,17 @@ def add_alert(self, *, msg: str | None = None, prompt: str | None = None) -> Non
56255647
add_alert(msg="Done", prompt="> ") # Update both
56265648
56275649
:param msg: an optional message to be printed above the prompt.
5650+
:param soft_wrap: Enable soft wrap mode. This only applies with msg is not None.
5651+
Defaults to True. See print_to() docstring for more details on
5652+
this parameter.
56285653
:param prompt: an optional string to dynamically replace the current prompt.
56295654
56305655
"""
56315656
if msg is None and prompt is None:
56325657
return
56335658

56345659
with self._alert_condition:
5635-
alert = AsyncAlert(msg=msg, prompt=prompt)
5660+
alert = AsyncAlert(msg=msg, soft_wrap=soft_wrap, prompt=prompt)
56365661
self._alert_queue.append(alert)
56375662
self._alert_condition.notify_all()
56385663

0 commit comments

Comments
 (0)