@@ -2153,7 +2153,7 @@ def pseudo_raw_input(self, prompt: str) -> str:
21532153 else :
21542154 line = input ()
21552155 if self .echo :
2156- sys .stdout .write ('{}{}\n ' .format (self . prompt , line ))
2156+ sys .stdout .write ('{}{}\n ' .format (prompt , line ))
21572157 except EOFError :
21582158 line = 'eof'
21592159 finally :
@@ -2163,7 +2163,7 @@ def pseudo_raw_input(self, prompt: str) -> str:
21632163 else :
21642164 if self .stdin .isatty ():
21652165 # on a tty, print the prompt first, then read the line
2166- self .poutput (self . prompt , end = '' )
2166+ self .poutput (prompt , end = '' )
21672167 self .stdout .flush ()
21682168 line = self .stdin .readline ()
21692169 if len (line ) == 0 :
@@ -2176,7 +2176,7 @@ def pseudo_raw_input(self, prompt: str) -> str:
21762176 if len (line ):
21772177 # we read something, output the prompt and the something
21782178 if self .echo :
2179- self .poutput ('{}{}' .format (self . prompt , line ))
2179+ self .poutput ('{}{}' .format (prompt , line ))
21802180 else :
21812181 line = 'eof'
21822182
@@ -3652,24 +3652,35 @@ def async_alert(self, alert_msg: str, new_prompt: Optional[str] = None) -> None:
36523652 if new_prompt is not None and new_prompt != self .prompt :
36533653 self .prompt = new_prompt
36543654
3655- # If we aren't at a continuation prompt, then redraw the prompt now
3655+ # If we aren't at a continuation prompt, then it's OK to update it
36563656 if not self .at_continuation_prompt :
36573657 rl_set_prompt (self .prompt )
36583658 update_terminal = True
36593659
36603660 if update_terminal :
3661- # Get the display width of the prompt
3662- prompt_width = utils .ansi_safe_wcswidth (current_prompt )
3663-
36643661 # Get the size of the terminal
36653662 terminal_size = shutil .get_terminal_size ()
36663663
3667- # Figure out how many lines the prompt and user input take up
3668- total_str_size = prompt_width + utils .ansi_safe_wcswidth (readline .get_line_buffer ())
3669- num_input_lines = int (total_str_size / terminal_size .columns ) + 1
3664+ # Split the prompt lines since it can contain newline characters.
3665+ prompt_lines = current_prompt .splitlines ()
3666+
3667+ # Calculate how many terminal lines are taken up by all prompt lines except for the last one.
3668+ # That will be included in the input lines calculations since that is where the cursor is.
3669+ num_prompt_terminal_lines = 0
3670+ for line in prompt_lines [:- 1 ]:
3671+ line_width = utils .ansi_safe_wcswidth (line )
3672+ num_prompt_terminal_lines += int (line_width / terminal_size .columns ) + 1
3673+
3674+ # Now calculate how many terminal lines are take up by the input
3675+ last_prompt_line = prompt_lines [- 1 ]
3676+ last_prompt_line_width = utils .ansi_safe_wcswidth (last_prompt_line )
3677+
3678+ input_width = last_prompt_line_width + utils .ansi_safe_wcswidth (readline .get_line_buffer ())
3679+
3680+ num_input_terminal_lines = int (input_width / terminal_size .columns ) + 1
36703681
36713682 # Get the cursor's offset from the beginning of the first input line
3672- cursor_input_offset = prompt_width + rl_get_point ()
3683+ cursor_input_offset = last_prompt_line_width + rl_get_point ()
36733684
36743685 # Calculate what input line the cursor is on
36753686 cursor_input_line = int (cursor_input_offset / terminal_size .columns ) + 1
@@ -3678,14 +3689,17 @@ def async_alert(self, alert_msg: str, new_prompt: Optional[str] = None) -> None:
36783689 terminal_str = ''
36793690
36803691 # Move the cursor down to the last input line
3681- if cursor_input_line != num_input_lines :
3682- terminal_str += Cursor .DOWN (num_input_lines - cursor_input_line )
3692+ if cursor_input_line != num_input_terminal_lines :
3693+ terminal_str += Cursor .DOWN (num_input_terminal_lines - cursor_input_line )
3694+
3695+ # Clear each line from the bottom up so that the cursor ends up on the first prompt line
3696+ total_lines = num_prompt_terminal_lines + num_input_terminal_lines
3697+ terminal_str += (ansi .clear_line () + Cursor .UP (1 )) * (total_lines - 1 )
36833698
3684- # Clear each input line from the bottom up so that the cursor ends up on the original first input line
3685- terminal_str += (ansi .clear_line () + Cursor .UP (1 )) * (num_input_lines - 1 )
3699+ # Clear the first prompt line
36863700 terminal_str += ansi .clear_line ()
36873701
3688- # Move the cursor to the beginning of the first input line and print the alert
3702+ # Move the cursor to the beginning of the first prompt line and print the alert
36893703 terminal_str += '\r ' + alert_msg
36903704
36913705 if rl_type == RlType .GNU :
0 commit comments