summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Van Brunt <kmvanbrunt@gmail.com>2018-09-21 21:21:21 -0400
committerKevin Van Brunt <kmvanbrunt@gmail.com>2018-09-21 21:21:21 -0400
commit3f57b97df8cd5576547bddea98cc72238f0c6072 (patch)
tree2f6179bc03213d5087240a7e6812aee5823d814b
parentd10badce0e9c12aa341c2de247523b7a494761fc (diff)
downloadcmd2-git-3f57b97df8cd5576547bddea98cc72238f0c6072.tar.gz
Updating prompt in example app
-rw-r--r--cmd2/cmd2.py29
-rwxr-xr-xexamples/async_printing.py50
2 files changed, 59 insertions, 20 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index dae934b8..3063068d 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -3221,7 +3221,7 @@ Script should contain one command per line, just like command would be typed in
return terminal_str
- def async_alert(self, alert_msg: str, new_prompt: Optional[str] = None) -> None:
+ def _async_alert(self, alert_msg: str, new_prompt: Optional[str] = None) -> None:
"""
Used to display an important message to the user while they are at the prompt in between commands.
To the user it appears as if an alert message is printed above the prompt and their current input
@@ -3237,24 +3237,25 @@ Script should contain one command per line, just like command would be typed in
if not (vt100_support and self.use_rawinput):
return
- # Clear the prompt and input lines and replace with the alert
+ # Generate a string to clear the prompt and input lines and replace with the alert
terminal_str = self._clear_input_lines_str()
terminal_str += alert_msg + '\n'
+ # Set the new prompt now that _clear_input_lines_str is done using the old prompt
+ if new_prompt is not None:
+ self.prompt = new_prompt
+ rl_set_prompt(self.prompt)
+
+ # Print terminal_str to erase the lines
if rl_type == RlType.GNU:
sys.stderr.write(terminal_str)
elif rl_type == RlType.PYREADLINE:
readline.rl.mode.console.write(terminal_str)
- # Set the new prompt
- if new_prompt is not None:
- self.prompt = new_prompt
- rl_set_prompt(self.prompt)
-
# Redraw the prompt and input lines
rl_force_redisplay()
- def async_update_prompt(self, new_prompt: str) -> None:
+ def _async_update_prompt(self, new_prompt: str) -> None:
"""
Updates the prompt while the user is still typing at it. This is good for alerting the user to system
changes dynamically in between commands. For instance you could alter the color of the prompt to indicate
@@ -3270,17 +3271,19 @@ Script should contain one command per line, just like command would be typed in
if not (vt100_support and self.use_rawinput):
return
- # Clear the prompt and input lines
+ # Generate a string to clear the prompt and input lines
terminal_str = self._clear_input_lines_str()
+
+ # Set the new prompt now that _clear_input_lines_str is done using the old prompt
+ self.prompt = new_prompt
+ rl_set_prompt(self.prompt)
+
+ # Print terminal_str to erase the lines
if rl_type == RlType.GNU:
sys.stderr.write(terminal_str)
elif rl_type == RlType.PYREADLINE:
readline.rl.mode.console.write(terminal_str)
- # Set the new prompt
- self.prompt = new_prompt
- rl_set_prompt(self.prompt)
-
# Redraw the prompt and input lines
rl_force_redisplay()
diff --git a/examples/async_printing.py b/examples/async_printing.py
index 65e83bbe..69880ee7 100755
--- a/examples/async_printing.py
+++ b/examples/async_printing.py
@@ -8,6 +8,7 @@ import time
from typing import List
import cmd2
+from colorama import Fore
ALERTS = ["Mail server is down",
"Blockage detected in sector 4",
@@ -23,8 +24,10 @@ ALERTS = ["Mail server is down",
def get_alerts() -> List[str]:
- """ Randomly generates alerts for testing purposes """
-
+ """
+ Randomly reports alerts
+ :return: the list of alerts
+ """
rand_num = random.randint(1, 20)
if rand_num > 3:
return []
@@ -40,7 +43,7 @@ def get_alerts() -> List[str]:
return alerts
-def get_alert_str() -> str:
+def generate_alert_str() -> str:
"""
Combines alerts into one string that can be printed to the terminal
:return: the alert string
@@ -72,7 +75,12 @@ class AlerterApp(cmd2.Cmd):
super().__init__(*args, **kwargs)
- self.prompt = "(APR)> "
+ self._orig_prompt = "(APR)> "
+ self.prompt = self._orig_prompt
+
+ self.intro = "\nWatch as this application prints alerts and updates the prompt.\n"
+ self.intro += "This will only happen when the prompt is present. Notice how it doesn't\n"
+ self.intro += "interfere with your typing.\n"
# The thread that will asynchronously alert the user of events
self._stop_thread = False
@@ -96,6 +104,28 @@ class AlerterApp(cmd2.Cmd):
if self._alerter_thread.is_alive():
self._alerter_thread.join()
+ def _generate_new_prompt(self) -> str:
+ """
+ Randomly generates a new prompt
+ :return: the new prompt
+ """
+ rand_num = random.randint(1, 20)
+
+ status_color = Fore.RESET
+
+ if rand_num == 1:
+ status_color = Fore.LIGHTRED_EX
+ elif rand_num == 2:
+ status_color = Fore.LIGHTYELLOW_EX
+ elif rand_num == 3:
+ status_color = Fore.CYAN
+ elif rand_num == 4:
+ status_color = Fore.LIGHTGREEN_EX
+ elif rand_num == 5:
+ status_color = Fore.LIGHTBLUE_EX
+
+ return status_color + self._orig_prompt + Fore.RESET
+
def _alerter_thread_func(self) -> None:
""" Prints alerts and updates the prompt any time the prompt is showing """
@@ -104,11 +134,16 @@ class AlerterApp(cmd2.Cmd):
# To keep the app responsive, do not block on this call
if self._terminal_lock.acquire(blocking=False):
- # We have the terminal lock. See if any alerts need to be printed.
- alert_str = get_alert_str()
+ # Get any alerts that need to be printed
+ alert_str = generate_alert_str()
+
+ # Generate a new prompt
+ new_prompt = self._generate_new_prompt()
if alert_str:
- self.async_alert(alert_str)
+ self._async_alert(alert_str, new_prompt)
+ elif new_prompt != self.prompt:
+ self._async_update_prompt(new_prompt)
# Don't forget to release the lock
self._terminal_lock.release()
@@ -118,4 +153,5 @@ class AlerterApp(cmd2.Cmd):
if __name__ == '__main__':
app = AlerterApp()
+ app.set_window_title("Asynchronous Printer Test")
app.cmdloop()