Shell integration: Workaround bash not redrawing multiline prompts

This commit is contained in:
Kovid Goyal 2021-10-01 09:30:26 +05:30
parent eaa0ec4fc3
commit eeb02ceef4
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 12 additions and 3 deletions

View File

@ -156,6 +156,7 @@ screen_reset(Screen *self) {
if (self->overlay_line.is_active) deactivate_overlay_line(self); if (self->overlay_line.is_active) deactivate_overlay_line(self);
memset(self->main_key_encoding_flags, 0, sizeof(self->main_key_encoding_flags)); memset(self->main_key_encoding_flags, 0, sizeof(self->main_key_encoding_flags));
memset(self->alt_key_encoding_flags, 0, sizeof(self->alt_key_encoding_flags)); memset(self->alt_key_encoding_flags, 0, sizeof(self->alt_key_encoding_flags));
self->redraws_multiline_prompts = false;
self->last_graphic_char = 0; self->last_graphic_char = 0;
self->main_savepoint.is_valid = false; self->main_savepoint.is_valid = false;
self->alt_savepoint.is_valid = false; self->alt_savepoint.is_valid = false;
@ -291,6 +292,7 @@ prevent_current_prompt_from_rewrapping(Screen *self) {
y--; y--;
} }
if (y < 0) return; if (y < 0) return;
if (!self->redraws_multiline_prompts && self->cursor->y > (unsigned) y) return; // bash does not redraw multiline prompts
// we have identified a prompt at which the cursor is present, the shell // we have identified a prompt at which the cursor is present, the shell
// will redraw this prompt. However when doing so it gets confused if the // will redraw this prompt. However when doing so it gets confused if the
// cursor vertical position relative to the first prompt line changes. This // cursor vertical position relative to the first prompt line changes. This
@ -1921,8 +1923,14 @@ shell_prompt_marking(Screen *self, PyObject *data) {
if (PyUnicode_GET_LENGTH(data) > 0 && self->cursor->y < self->lines) { if (PyUnicode_GET_LENGTH(data) > 0 && self->cursor->y < self->lines) {
Py_UCS4 ch = PyUnicode_READ_CHAR(data, 0); Py_UCS4 ch = PyUnicode_READ_CHAR(data, 0);
switch (ch) { switch (ch) {
case 'A': case 'A': {
linebuf_mark_line_as_prompt_start(self->linebuf, self->cursor->y); break; linebuf_mark_line_as_prompt_start(self->linebuf, self->cursor->y);
size_t l = PyUnicode_GET_LENGTH(data);
if (l > 8) {
DECREF_AFTER_FUNCTION PyObject *q = PyUnicode_FromString(";does_not_redraw_multiline_prompt");
self->redraws_multiline_prompts = (!q || PyUnicode_Find(data, q, 1, PyUnicode_GET_LENGTH(data), 1) < 0);
} else self->redraws_multiline_prompts = true;
} break;
case 'C': case 'C':
linebuf_mark_line_as_output_start(self->linebuf, self->cursor->y); break; linebuf_mark_line_as_output_start(self->linebuf, self->cursor->y); break;
} }

View File

@ -131,6 +131,7 @@ typedef struct {
struct { struct {
monotonic_t start, duration; monotonic_t start, duration;
} ignore_bells; } ignore_bells;
bool redraws_multiline_prompts;
} Screen; } Screen;

View File

@ -40,7 +40,7 @@ _ksi_main() {
fi fi
if [[ "${_ksi_prompt[mark]}" == "y" ]]; then if [[ "${_ksi_prompt[mark]}" == "y" ]]; then
PS1="\[\e]133;A\a\]$PS1" PS1="\[\e]133;A;does_not_redraw_multiline_prompt\a\]$PS1"
PS0="\[\e]133;C\a\]$PS0" PS0="\[\e]133;C\a\]$PS0"
fi fi