124
124
)
125
125
from .rl_utils import (
126
126
RlType ,
127
+ rl_escape_prompt ,
127
128
rl_get_point ,
128
- rl_make_safe_prompt ,
129
+ rl_get_prompt ,
129
130
rl_set_prompt ,
130
131
rl_type ,
131
132
rl_warning ,
@@ -2982,11 +2983,11 @@ def restore_readline() -> None:
2982
2983
if sys .stdin .isatty ():
2983
2984
try :
2984
2985
# Deal with the vagaries of readline and ANSI escape codes
2985
- safe_prompt = rl_make_safe_prompt (prompt )
2986
+ escaped_prompt = rl_escape_prompt (prompt )
2986
2987
2987
2988
with self .sigint_protection :
2988
2989
configure_readline ()
2989
- line = input (safe_prompt )
2990
+ line = input (escaped_prompt )
2990
2991
finally :
2991
2992
with self .sigint_protection :
2992
2993
restore_readline ()
@@ -5013,42 +5014,44 @@ def async_alert(self, alert_msg: str, new_prompt: Optional[str] = None) -> None:
5013
5014
Raises a `RuntimeError` if called while another thread holds `terminal_lock`.
5014
5015
5015
5016
IMPORTANT: This function will not print an alert unless it can acquire self.terminal_lock to ensure
5016
- a prompt is onscreen. Therefore it is best to acquire the lock before calling this function
5017
+ a prompt is onscreen. Therefore it is best to acquire the lock before calling this function
5017
5018
to guarantee the alert prints and to avoid raising a RuntimeError.
5018
5019
5019
5020
:param alert_msg: the message to display to the user
5020
- :param new_prompt: if you also want to change the prompt that is displayed, then include it here
5021
- see async_update_prompt() docstring for guidance on updating a prompt
5021
+ :param new_prompt: If you also want to change the prompt that is displayed, then include it here.
5022
+ See async_update_prompt() docstring for guidance on updating a prompt.
5022
5023
"""
5023
5024
if not (vt100_support and self .use_rawinput ):
5024
5025
return
5025
5026
5026
5027
# Sanity check that can't fail if self.terminal_lock was acquired before calling this function
5027
5028
if self .terminal_lock .acquire (blocking = False ):
5028
5029
5029
- # Only update terminal if there are changes
5030
+ # Windows terminals tend to flicker when we redraw the prompt and input lines.
5031
+ # To reduce how often this occurs, only update terminal if there are changes.
5030
5032
update_terminal = False
5031
5033
5032
5034
if alert_msg :
5033
5035
alert_msg += '\n '
5034
5036
update_terminal = True
5035
5037
5036
- # Set the prompt if it's changed
5037
- if new_prompt is not None and new_prompt != self .prompt :
5038
+ if new_prompt is not None :
5038
5039
self .prompt = new_prompt
5039
5040
5040
- # If we aren't at a continuation prompt, then it's OK to update it
5041
- if not self ._at_continuation_prompt :
5042
- rl_set_prompt (self .prompt )
5043
- update_terminal = True
5041
+ # Check if the prompt to display has changed from what's currently displayed
5042
+ cur_onscreen_prompt = rl_get_prompt ()
5043
+ new_onscreen_prompt = self .continuation_prompt if self ._at_continuation_prompt else self .prompt
5044
+
5045
+ if new_onscreen_prompt != cur_onscreen_prompt :
5046
+ update_terminal = True
5044
5047
5045
5048
if update_terminal :
5046
5049
import shutil
5047
5050
5048
- current_prompt = self . continuation_prompt if self . _at_continuation_prompt else self . prompt
5051
+ # Generate the string which will replace the current prompt and input lines with the alert
5049
5052
terminal_str = ansi .async_alert_str (
5050
5053
terminal_columns = shutil .get_terminal_size ().columns ,
5051
- prompt = current_prompt ,
5054
+ prompt = cur_onscreen_prompt ,
5052
5055
line = readline .get_line_buffer (),
5053
5056
cursor_offset = rl_get_point (),
5054
5057
alert_msg = alert_msg ,
@@ -5060,7 +5063,10 @@ def async_alert(self, alert_msg: str, new_prompt: Optional[str] = None) -> None:
5060
5063
# noinspection PyUnresolvedReferences
5061
5064
readline .rl .mode .console .write (terminal_str )
5062
5065
5063
- # Redraw the prompt and input lines
5066
+ # Update Readline's prompt before we redraw it
5067
+ rl_set_prompt (new_onscreen_prompt )
5068
+
5069
+ # Redraw the prompt and input lines below the alert
5064
5070
rl_force_redisplay ()
5065
5071
5066
5072
self .terminal_lock .release ()
@@ -5079,7 +5085,7 @@ def async_update_prompt(self, new_prompt: str) -> None: # pragma: no cover
5079
5085
Raises a `RuntimeError` if called while another thread holds `terminal_lock`.
5080
5086
5081
5087
IMPORTANT: This function will not update the prompt unless it can acquire self.terminal_lock to ensure
5082
- a prompt is onscreen. Therefore it is best to acquire the lock before calling this function
5088
+ a prompt is onscreen. Therefore it is best to acquire the lock before calling this function
5083
5089
to guarantee the prompt changes and to avoid raising a RuntimeError.
5084
5090
5085
5091
If user is at a continuation prompt while entering a multiline command, the onscreen prompt will
0 commit comments