mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-28 13:53:10 +00:00
Make sure initial indentation is done using cursor move, not spaces.
The goal to allow a terminal to reliably distinguish user input from indentation and prompts, in the context of shell integration.
This commit is contained in:
parent
7448e7825f
commit
e05a0716e5
2 changed files with 27 additions and 7 deletions
|
@ -388,9 +388,12 @@ static void s_desired_append_char(screen_t *s, wchar_t b, highlight_spec_t c, in
|
||||||
// Current line is definitely hard wrapped.
|
// Current line is definitely hard wrapped.
|
||||||
s->desired.create_line(s->desired.line_count());
|
s->desired.create_line(s->desired.line_count());
|
||||||
s->desired.line(s->desired.cursor.y).is_soft_wrapped = false;
|
s->desired.line(s->desired.cursor.y).is_soft_wrapped = false;
|
||||||
s->desired.cursor.y++;
|
int line_no = ++s->desired.cursor.y;
|
||||||
s->desired.cursor.x = 0;
|
s->desired.cursor.x = 0;
|
||||||
for (size_t i = 0; i < prompt_width + indent * INDENT_STEP; i++) {
|
size_t indentation = prompt_width + indent * INDENT_STEP;
|
||||||
|
line_t &line = s->desired.line(line_no);
|
||||||
|
line.indentation = indentation;
|
||||||
|
for (size_t i = 0; i < indentation; i++) {
|
||||||
s_desired_append_char(s, L' ', highlight_spec_t{}, indent, prompt_width, 1);
|
s_desired_append_char(s, L' ', highlight_spec_t{}, indent, prompt_width, 1);
|
||||||
}
|
}
|
||||||
} else if (b == L'\r') {
|
} else if (b == L'\r') {
|
||||||
|
@ -650,6 +653,7 @@ static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring
|
||||||
line_t &s_line = scr->actual.create_line(i);
|
line_t &s_line = scr->actual.create_line(i);
|
||||||
size_t start_pos = i == 0 ? left_prompt_width : 0;
|
size_t start_pos = i == 0 ? left_prompt_width : 0;
|
||||||
int current_width = 0;
|
int current_width = 0;
|
||||||
|
bool has_cleared_line = false;
|
||||||
|
|
||||||
// If this is the last line, maybe we should clear the screen.
|
// If this is the last line, maybe we should clear the screen.
|
||||||
const bool should_clear_screen_this_line =
|
const bool should_clear_screen_this_line =
|
||||||
|
@ -659,13 +663,28 @@ static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring
|
||||||
size_t skip_remaining = start_pos;
|
size_t skip_remaining = start_pos;
|
||||||
|
|
||||||
const size_t shared_prefix = line_shared_prefix(o_line, s_line);
|
const size_t shared_prefix = line_shared_prefix(o_line, s_line);
|
||||||
|
size_t skip_prefix = shared_prefix;
|
||||||
|
if (shared_prefix < o_line.indentation) {
|
||||||
|
if (o_line.indentation > s_line.indentation
|
||||||
|
&& s_line.indentation != s_line.size()
|
||||||
|
&& !has_cleared_screen && clr_eol && clr_eos) {
|
||||||
|
s_set_color(scr, vars, highlight_spec_t{});
|
||||||
|
s_move(scr, 0, (int)i);
|
||||||
|
s_write_mbs(scr,
|
||||||
|
should_clear_screen_this_line ? clr_eos : clr_eol);
|
||||||
|
has_cleared_screen = should_clear_screen_this_line;
|
||||||
|
has_cleared_line = true;
|
||||||
|
}
|
||||||
|
skip_prefix = o_line.indentation;
|
||||||
|
}
|
||||||
if (!should_clear_screen_this_line) {
|
if (!should_clear_screen_this_line) {
|
||||||
// Compute how much we should skip. At a minimum we skip over the prompt. But also skip
|
// Compute how much we should skip. At a minimum we skip over the prompt. But also skip
|
||||||
// over the shared prefix of what we want to output now, and what we output before, to
|
// over the shared prefix of what we want to output now, and what we output before, to
|
||||||
// avoid repeatedly outputting it.
|
// avoid repeatedly outputting it.
|
||||||
if (shared_prefix > 0) {
|
if (skip_prefix > 0) {
|
||||||
size_t prefix_width = fish_wcswidth(&o_line.text.at(0), shared_prefix);
|
size_t skip_width = shared_prefix < skip_prefix ? skip_prefix
|
||||||
if (prefix_width > skip_remaining) skip_remaining = prefix_width;
|
: fish_wcswidth(&o_line.text.at(0), shared_prefix);
|
||||||
|
if (skip_width > skip_remaining) skip_remaining = skip_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're soft wrapped, and if we're going to change the first character of the next
|
// If we're soft wrapped, and if we're going to change the first character of the next
|
||||||
|
@ -727,7 +746,7 @@ static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring
|
||||||
// Clear the remainder of the line if we need to clear and if we didn't write to the end of
|
// Clear the remainder of the line if we need to clear and if we didn't write to the end of
|
||||||
// the line. If we did write to the end of the line, the "sticky right edge" (as part of
|
// the line. If we did write to the end of the line, the "sticky right edge" (as part of
|
||||||
// auto_right_margin) means that we'll be clearing the last character we wrote!
|
// auto_right_margin) means that we'll be clearing the last character we wrote!
|
||||||
if (has_cleared_screen) {
|
if (has_cleared_screen || has_cleared_line) {
|
||||||
// Already cleared everything.
|
// Already cleared everything.
|
||||||
clear_remainder = false;
|
clear_remainder = false;
|
||||||
} else if (need_clear_lines && current_width < screen_width) {
|
} else if (need_clear_lines && current_width < screen_width) {
|
||||||
|
|
|
@ -32,8 +32,9 @@ struct line_t {
|
||||||
std::vector<wchar_t> text;
|
std::vector<wchar_t> text;
|
||||||
std::vector<highlight_spec_t> colors;
|
std::vector<highlight_spec_t> colors;
|
||||||
bool is_soft_wrapped;
|
bool is_soft_wrapped;
|
||||||
|
size_t indentation;
|
||||||
|
|
||||||
line_t() : text(), colors(), is_soft_wrapped(false) {}
|
line_t() : text(), colors(), is_soft_wrapped(false), indentation(0) {}
|
||||||
|
|
||||||
void clear(void) {
|
void clear(void) {
|
||||||
text.clear();
|
text.clear();
|
||||||
|
|
Loading…
Reference in a new issue