diff options
author | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2018-09-21 21:21:21 -0400 |
---|---|---|
committer | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2018-09-21 21:21:21 -0400 |
commit | 3f57b97df8cd5576547bddea98cc72238f0c6072 (patch) | |
tree | 2f6179bc03213d5087240a7e6812aee5823d814b | |
parent | d10badce0e9c12aa341c2de247523b7a494761fc (diff) | |
download | cmd2-git-3f57b97df8cd5576547bddea98cc72238f0c6072.tar.gz |
Updating prompt in example app
-rw-r--r-- | cmd2/cmd2.py | 29 | ||||
-rwxr-xr-x | examples/async_printing.py | 50 |
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() |