diff options
author | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2018-09-19 02:05:08 -0400 |
---|---|---|
committer | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2018-09-19 02:05:08 -0400 |
commit | bd34fee86d66a610d1e0bb392186dc73e883e2db (patch) | |
tree | aeb522388f6c28e7cfa3d5a1e2a948123c4b1ff3 /cmd2/cmd2.py | |
parent | 36d9ec82c50b037becc204f9fc05d94c4d391ccf (diff) | |
download | cmd2-git-bd34fee86d66a610d1e0bb392186dc73e883e2db.tar.gz |
Wrote function and test command to print alerts
Diffstat (limited to 'cmd2/cmd2.py')
-rw-r--r-- | cmd2/cmd2.py | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index 888d9531..874fdf6c 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -50,7 +50,7 @@ from .clipboard import can_clip, get_paste_buffer, write_to_paste_buffer from .parsing import StatementParser, Statement # Set up readline -from .rl_utils import rl_type, RlType +from .rl_utils import rl_type, RlType, rl_get_point if rl_type == RlType.NONE: # pragma: no cover rl_warning = "Readline features including tab completion have been disabled since no \n" \ "supported version of readline was found. To resolve this, install \n" \ @@ -3191,6 +3191,74 @@ Script should contain one command per line, just like command would be typed in runner = unittest.TextTestRunner() runner.run(testcase) + def print_alert(self, alert_msg: str) -> None: + """ + Used to display an important message to the user while they are at the prompt. + The current prompt and input lines are erased, then the alert is printed in their place, and + finally the prompt and input lines restored below the alert. To the user it appears as if + an alert message is printed above the prompt. + + :param alert_msg: the message to display to the user + """ + if rl_type == RlType.NONE: + return + + import shutil + import colorama.ansi as ansi + from colorama import Cursor + + visible_prompt = self.visible_prompt + + # Get the size of the terminal + terminal_size = shutil.get_terminal_size() + + # Figure out how many lines the prompt and user input take up + total_str_size = len(visible_prompt) + len(readline.get_line_buffer()) + num_input_lines = int(total_str_size / terminal_size.columns) + 1 + + # Get the cursor's offset from the beginning of the first input line + cursor_input_offset = len(visible_prompt) + rl_get_point() + + # Calculate what input line the cursor is on + cursor_input_line = int(cursor_input_offset / terminal_size.columns) + 1 + + # Create a string that will clear all input lines and print the alert + terminal_str = '' + + # Move the cursor down to the last input line + if cursor_input_line != num_input_lines: + terminal_str += Cursor.DOWN(num_input_lines - cursor_input_line) + + # Clear each input line from the bottom up so that the cursor ends up on the original first input line + terminal_str += (ansi.clear_line() + Cursor.UP(1)) * (num_input_lines - 1) + terminal_str += ansi.clear_line() + + # Print the alert + terminal_str += alert_msg + '\n' + + # Write the string to the terminal + if rl_type == RlType.GNU: + sys.stdout.write(terminal_str) + elif rl_type == RlType.PYREADLINE: + readline.rl.mode.console.write(terminal_str) + + # Redraw the prompt and input line + rl_force_redisplay() + + def worker(self): + import time + while True: + alert_msg = "\n***********************************************\n" \ + " Message failed to send\n" \ + "***********************************************" + time.sleep(5) + self.print_alert(alert_msg) + + def do_alert(self, args): + import threading + printer = threading.Thread(target=self.worker, daemon=True) + printer.start() + def cmdloop(self, intro: Optional[str]=None) -> None: """This is an outer wrapper around _cmdloop() which deals with extra features provided by cmd2. |