@@ -2111,7 +2111,7 @@ def pseudo_raw_input(self, prompt: str) -> str:
21112111 else :
21122112 line = input ()
21132113 if self .echo :
2114- sys .stdout .write ('{}{}\n ' .format (self . prompt , line ))
2114+ sys .stdout .write ('{}{}\n ' .format (prompt , line ))
21152115 except EOFError :
21162116 line = 'eof'
21172117 finally :
@@ -2121,7 +2121,7 @@ def pseudo_raw_input(self, prompt: str) -> str:
21212121 else :
21222122 if self .stdin .isatty ():
21232123 # on a tty, print the prompt first, then read the line
2124- self .poutput (self . prompt , end = '' )
2124+ self .poutput (prompt , end = '' )
21252125 self .stdout .flush ()
21262126 line = self .stdin .readline ()
21272127 if len (line ) == 0 :
@@ -2134,7 +2134,7 @@ def pseudo_raw_input(self, prompt: str) -> str:
21342134 if len (line ):
21352135 # we read something, output the prompt and the something
21362136 if self .echo :
2137- self .poutput ('{}{}' .format (self . prompt , line ))
2137+ self .poutput ('{}{}' .format (prompt , line ))
21382138 else :
21392139 line = 'eof'
21402140
@@ -3596,24 +3596,35 @@ def async_alert(self, alert_msg: str, new_prompt: Optional[str] = None) -> None:
35963596 if new_prompt is not None and new_prompt != self .prompt :
35973597 self .prompt = new_prompt
35983598
3599- # If we aren't at a continuation prompt, then redraw the prompt now
3599+ # If we aren't at a continuation prompt, then it's OK to update it
36003600 if not self .at_continuation_prompt :
36013601 rl_set_prompt (self .prompt )
36023602 update_terminal = True
36033603
36043604 if update_terminal :
3605- # Get the display width of the prompt
3606- prompt_width = utils .ansi_safe_wcswidth (current_prompt )
3607-
36083605 # Get the size of the terminal
36093606 terminal_size = shutil .get_terminal_size ()
36103607
3611- # Figure out how many lines the prompt and user input take up
3612- total_str_size = prompt_width + utils .ansi_safe_wcswidth (readline .get_line_buffer ())
3613- num_input_lines = int (total_str_size / terminal_size .columns ) + 1
3608+ # Split the prompt lines since it can contain newline characters.
3609+ prompt_lines = current_prompt .splitlines ()
3610+
3611+ # Calculate how many terminal lines are taken up by all prompt lines except for the last one.
3612+ # That will be included in the input lines calculations since that is where the cursor is.
3613+ num_prompt_terminal_lines = 0
3614+ for line in prompt_lines [:- 1 ]:
3615+ line_width = utils .ansi_safe_wcswidth (line )
3616+ num_prompt_terminal_lines += int (line_width / terminal_size .columns ) + 1
3617+
3618+ # Now calculate how many terminal lines are take up by the input
3619+ last_prompt_line = prompt_lines [- 1 ]
3620+ last_prompt_line_width = utils .ansi_safe_wcswidth (last_prompt_line )
3621+
3622+ input_width = last_prompt_line_width + utils .ansi_safe_wcswidth (readline .get_line_buffer ())
3623+
3624+ num_input_terminal_lines = int (input_width / terminal_size .columns ) + 1
36143625
36153626 # Get the cursor's offset from the beginning of the first input line
3616- cursor_input_offset = prompt_width + rl_get_point ()
3627+ cursor_input_offset = last_prompt_line_width + rl_get_point ()
36173628
36183629 # Calculate what input line the cursor is on
36193630 cursor_input_line = int (cursor_input_offset / terminal_size .columns ) + 1
@@ -3622,14 +3633,17 @@ def async_alert(self, alert_msg: str, new_prompt: Optional[str] = None) -> None:
36223633 terminal_str = ''
36233634
36243635 # Move the cursor down to the last input line
3625- if cursor_input_line != num_input_lines :
3626- terminal_str += Cursor .DOWN (num_input_lines - cursor_input_line )
3636+ if cursor_input_line != num_input_terminal_lines :
3637+ terminal_str += Cursor .DOWN (num_input_terminal_lines - cursor_input_line )
3638+
3639+ # Clear each line from the bottom up so that the cursor ends up on the first prompt line
3640+ total_lines = num_prompt_terminal_lines + num_input_terminal_lines
3641+ terminal_str += (ansi .clear_line () + Cursor .UP (1 )) * (total_lines - 1 )
36273642
3628- # Clear each input line from the bottom up so that the cursor ends up on the original first input line
3629- terminal_str += (ansi .clear_line () + Cursor .UP (1 )) * (num_input_lines - 1 )
3643+ # Clear the first prompt line
36303644 terminal_str += ansi .clear_line ()
36313645
3632- # Move the cursor to the beginning of the first input line and print the alert
3646+ # Move the cursor to the beginning of the first prompt line and print the alert
36333647 terminal_str += '\r ' + alert_msg
36343648
36353649 if rl_type == RlType .GNU :
0 commit comments