diff --git a/kitty_tests/shell_integration.py b/kitty_tests/shell_integration.py index a0600746a..ec7864146 100644 --- a/kitty_tests/shell_integration.py +++ b/kitty_tests/shell_integration.py @@ -150,3 +150,23 @@ PS1="{ps1}" pty.wait_till(lambda: pty.screen_contents().count(ps1) == 3) self.ae('40', str(pty.screen.line(pty.screen.cursor.y - 1))) self.ae(ps1 + 'echo $COLUMNS', str(pty.screen.line(pty.screen.cursor.y - 2))) + + for ps1 in ('line1\\nline\\2\\prompt> ', 'line1\nprompt> ', 'line1\\nprompt> ',): + with self.subTest(ps1=ps1), self.run_shell( + shell='bash', rc=f''' + PS1="{ps1}" + ''') as pty: + ps1 = ps1.replace('\\n', '\n') + pty.wait_till(lambda: pty.screen_contents().count(ps1) == 1) + pty.send_cmd_to_child('echo test') + pty.wait_till(lambda: pty.screen_contents().count(ps1) == 2) + self.ae(pty.screen_contents(), f'{ps1}echo test\ntest\n{ps1}') + pty.write_to_child(r'echo $COLUMNS') + pty.set_window_size(rows=20, columns=40) + pty.process_input_from_child() + pty.wait_till(redrawn) + self.ae(ps1.splitlines()[-1] + 'echo $COLUMNS', str(pty.screen.line(pty.screen.cursor.y))) + pty.write_to_child('\r') + pty.wait_till(lambda: pty.screen_contents().count(ps1) == 3) + self.ae('40', str(pty.screen.line(pty.screen.cursor.y - len(ps1.splitlines())))) + self.ae(ps1.splitlines()[-1] + 'echo $COLUMNS', str(pty.screen.line(pty.screen.cursor.y - 1 - len(ps1.splitlines())))) diff --git a/shell-integration/bash/kitty.bash b/shell-integration/bash/kitty.bash index 4ad7b8249..c8991efc7 100644 --- a/shell-integration/bash/kitty.bash +++ b/shell-integration/bash/kitty.bash @@ -58,14 +58,17 @@ _ksi_main() { PS1=${PS1//\\\[\\e\]133;k;start_suffix_kitty\\a\\\]*end_suffix_kitty\\a\\\]} fi if [[ -n "${_ksi_prompt[ps1]}" ]]; then - if [[ "${_ksi_prompt[mark]}" == "y" && "${PS1}" == *"\n"* ]]; then + if [[ "${_ksi_prompt[mark]}" == "y" && ( "${PS1}" == *"\n"* || "${PS1}" == *$'\n'* ) ]]; then + local oldval=$(builtin shopt -p extglob) + builtin shopt -s extglob # bash does not redraw the leading lines in a multiline prompt so # mark the last line as a secondary prompt. Otherwise on resize the # lines before the last line will be erased by kitty. # the first part removes everything from the last \n onwards # the second part appends a newline with the secondary marking # the third part appends everything after the last newline - PS1=${PS1%'\n'*}${_ksi_prompt[secondary_prompt]}${PS1##*'\n'} + PS1=${PS1%@('\n'|$'\n')*}${_ksi_prompt[secondary_prompt]}${PS1##*@('\n'|$'\n')}; + eval "$oldval" fi PS1="${_ksi_prompt[ps1]}$PS1" fi