mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-28 13:53:10 +00:00
Switch screen.h free functions to member functions on screen_t
Refactoring only, no functional change here.
This commit is contained in:
parent
26f3cee86c
commit
8878672014
3 changed files with 258 additions and 242 deletions
|
@ -1092,9 +1092,9 @@ void reader_data_t::paint_layout(const wchar_t *reason) {
|
|||
indents.resize(full_line.size(), 0);
|
||||
|
||||
// Prepend the mode prompt to the left prompt.
|
||||
s_write(&screen, mode_prompt_buff + left_prompt_buff, right_prompt_buff, full_line,
|
||||
cmd_line->size(), colors, indents, data.position, pager, current_page_rendering,
|
||||
data.focused_on_pager);
|
||||
screen.write(mode_prompt_buff + left_prompt_buff, right_prompt_buff, full_line,
|
||||
cmd_line->size(), colors, indents, data.position, pager, current_page_rendering,
|
||||
data.focused_on_pager);
|
||||
}
|
||||
|
||||
/// Internal helper function for handling killing parts of text.
|
||||
|
@ -2618,7 +2618,7 @@ void reader_pop() {
|
|||
reader_interactive_destroy();
|
||||
*commandline_state_snapshot() = commandline_state_t{};
|
||||
} else {
|
||||
s_reset_abandoning_line(&new_reader->screen, termsize_last().width);
|
||||
new_reader->screen.reset_abandoning_line(termsize_last().width);
|
||||
new_reader->update_commandline_state();
|
||||
}
|
||||
}
|
||||
|
@ -3000,7 +3000,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
|
|||
outp.push_back('\n');
|
||||
|
||||
set_command_line_and_position(&command_line, L"", 0);
|
||||
s_reset_abandoning_line(&screen, termsize_last().width - command_line.size());
|
||||
screen.reset_abandoning_line(termsize_last().width - command_line.size());
|
||||
|
||||
// Post fish_cancel.
|
||||
event_fire_generic(parser(), L"fish_cancel");
|
||||
|
@ -3038,7 +3038,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
|
|||
parser().libdata().is_repaint = true;
|
||||
exec_mode_prompt();
|
||||
if (!mode_prompt_buff.empty()) {
|
||||
s_reset_line(&screen, true /* redraw prompt */);
|
||||
screen.reset_line(true /* redraw prompt */);
|
||||
if (this->is_repaint_needed()) this->layout_and_repaint(L"mode");
|
||||
parser().libdata().is_repaint = false;
|
||||
break;
|
||||
|
@ -3050,7 +3050,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
|
|||
case rl::repaint: {
|
||||
parser().libdata().is_repaint = true;
|
||||
exec_prompt();
|
||||
s_reset_line(&screen, true /* redraw prompt */);
|
||||
screen.reset_line(true /* redraw prompt */);
|
||||
this->layout_and_repaint(L"readline");
|
||||
force_exec_prompt_and_repaint = false;
|
||||
parser().libdata().is_repaint = false;
|
||||
|
@ -3370,7 +3370,7 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
|
|||
// already be printed, all we need to do is repaint.
|
||||
wcstring_list_t argv(1, el->text());
|
||||
event_fire_generic(parser(), L"fish_posterror", &argv);
|
||||
s_reset_abandoning_line(&screen, termsize_last().width);
|
||||
screen.reset_abandoning_line(termsize_last().width);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3950,7 +3950,7 @@ maybe_t<wcstring> reader_data_t::readline(int nchars_or_0) {
|
|||
//
|
||||
// I can't see a good way around this.
|
||||
if (!first_prompt) {
|
||||
s_reset_abandoning_line(&screen, termsize_last().width);
|
||||
screen.reset_abandoning_line(termsize_last().width);
|
||||
}
|
||||
first_prompt = false;
|
||||
|
||||
|
|
367
src/screen.cpp
367
src/screen.cpp
|
@ -46,10 +46,8 @@
|
|||
/// The number of characters to indent new blocks.
|
||||
#define INDENT_STEP 4u
|
||||
|
||||
static void invalidate_soft_wrap(screen_t *scr);
|
||||
|
||||
/// RAII class to begin and end buffering around stdoutput().
|
||||
class scoped_buffer_t {
|
||||
class screen_t::scoped_buffer_t {
|
||||
screen_t &screen_;
|
||||
|
||||
public:
|
||||
|
@ -466,17 +464,14 @@ static size_t calc_prompt_lines(const wcstring &prompt) {
|
|||
|
||||
/// Stat stdout and stderr and save result. This should be done before calling a function that may
|
||||
/// cause output.
|
||||
void s_save_status(screen_t *s) {
|
||||
fstat(STDOUT_FILENO, &s->prev_buff_1);
|
||||
fstat(STDERR_FILENO, &s->prev_buff_2);
|
||||
void screen_t::save_status() {
|
||||
fstat(STDOUT_FILENO, &this->prev_buff_1);
|
||||
fstat(STDERR_FILENO, &this->prev_buff_2);
|
||||
}
|
||||
|
||||
/// Stat stdout and stderr and compare result to previous result in reader_save_status. Repaint if
|
||||
/// modification time has changed.
|
||||
///
|
||||
/// Unfortunately, for some reason this call seems to give a lot of false positives, at least under
|
||||
/// Linux.
|
||||
static void s_check_status(screen_t *s) {
|
||||
void screen_t::check_status() {
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
if (!has_working_tty_timestamps) {
|
||||
|
@ -491,15 +486,16 @@ static void s_check_status(screen_t *s) {
|
|||
fstat(STDOUT_FILENO, &post_buff_1);
|
||||
fstat(STDERR_FILENO, &post_buff_2);
|
||||
|
||||
bool changed = (s->prev_buff_1.st_mtime != post_buff_1.st_mtime) ||
|
||||
(s->prev_buff_2.st_mtime != post_buff_2.st_mtime);
|
||||
bool changed = (this->prev_buff_1.st_mtime != post_buff_1.st_mtime) ||
|
||||
(this->prev_buff_2.st_mtime != post_buff_2.st_mtime);
|
||||
|
||||
#if defined HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
|
||||
changed = changed || s->prev_buff_1.st_mtimespec.tv_nsec != post_buff_1.st_mtimespec.tv_nsec ||
|
||||
s->prev_buff_2.st_mtimespec.tv_nsec != post_buff_2.st_mtimespec.tv_nsec;
|
||||
changed = changed ||
|
||||
this->prev_buff_1.st_mtimespec.tv_nsec != post_buff_1.st_mtimespec.tv_nsec ||
|
||||
this->prev_buff_2.st_mtimespec.tv_nsec != post_buff_2.st_mtimespec.tv_nsec;
|
||||
#elif defined HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
|
||||
changed = changed || s->prev_buff_1.st_mtim.tv_nsec != post_buff_1.st_mtim.tv_nsec ||
|
||||
s->prev_buff_2.st_mtim.tv_nsec != post_buff_2.st_mtim.tv_nsec;
|
||||
changed = changed || this->prev_buff_1.st_mtim.tv_nsec != post_buff_1.st_mtim.tv_nsec ||
|
||||
this->prev_buff_2.st_mtim.tv_nsec != post_buff_2.st_mtim.tv_nsec;
|
||||
#endif
|
||||
|
||||
if (changed) {
|
||||
|
@ -507,99 +503,91 @@ static void s_check_status(screen_t *s) {
|
|||
// know where the cursor is. It is our best bet that we are still on the same line, so we
|
||||
// move to the beginning of the line, reset the modelled screen contents, and then set the
|
||||
// modeled cursor y-pos to its earlier value.
|
||||
int prev_line = s->actual.cursor.y;
|
||||
s_reset_line(s, true /* repaint prompt */);
|
||||
s->actual.cursor.y = prev_line;
|
||||
int prev_line = this->actual.cursor.y;
|
||||
this->reset_line(true /* repaint prompt */);
|
||||
this->actual.cursor.y = prev_line;
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends a character to the end of the line that the output cursor is on. This function
|
||||
/// automatically handles linebreaks and lines longer than the screen width.
|
||||
static void s_desired_append_char(screen_t *s, wchar_t b, highlight_spec_t c, int indent,
|
||||
size_t prompt_width, size_t bwidth) {
|
||||
int line_no = s->desired.cursor.y;
|
||||
void screen_t::desired_append_char(wchar_t b, highlight_spec_t c, int indent, size_t prompt_width,
|
||||
size_t bwidth) {
|
||||
int line_no = this->desired.cursor.y;
|
||||
|
||||
if (b == L'\n') {
|
||||
// Current line is definitely hard wrapped.
|
||||
// Create the next line.
|
||||
s->desired.create_line(s->desired.cursor.y + 1);
|
||||
s->desired.line(s->desired.cursor.y).is_soft_wrapped = false;
|
||||
int line_no = ++s->desired.cursor.y;
|
||||
s->desired.cursor.x = 0;
|
||||
this->desired.create_line(this->desired.cursor.y + 1);
|
||||
this->desired.line(this->desired.cursor.y).is_soft_wrapped = false;
|
||||
int line_no = ++this->desired.cursor.y;
|
||||
this->desired.cursor.x = 0;
|
||||
size_t indentation = prompt_width + indent * INDENT_STEP;
|
||||
line_t &line = s->desired.line(line_no);
|
||||
line_t &line = this->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);
|
||||
desired_append_char(L' ', highlight_spec_t{}, indent, prompt_width, 1);
|
||||
}
|
||||
} else if (b == L'\r') {
|
||||
line_t ¤t = s->desired.line(line_no);
|
||||
line_t ¤t = this->desired.line(line_no);
|
||||
current.clear();
|
||||
s->desired.cursor.x = 0;
|
||||
this->desired.cursor.x = 0;
|
||||
} else {
|
||||
int screen_width = s->desired.screen_width;
|
||||
int screen_width = this->desired.screen_width;
|
||||
int cw = bwidth;
|
||||
|
||||
s->desired.create_line(line_no);
|
||||
this->desired.create_line(line_no);
|
||||
|
||||
// Check if we are at the end of the line. If so, continue on the next line.
|
||||
if ((s->desired.cursor.x + cw) > screen_width) {
|
||||
if ((this->desired.cursor.x + cw) > screen_width) {
|
||||
// Current line is soft wrapped (assuming we support it).
|
||||
s->desired.line(s->desired.cursor.y).is_soft_wrapped = true;
|
||||
this->desired.line(this->desired.cursor.y).is_soft_wrapped = true;
|
||||
|
||||
line_no = static_cast<int>(s->desired.line_count());
|
||||
s->desired.add_line();
|
||||
s->desired.cursor.y++;
|
||||
s->desired.cursor.x = 0;
|
||||
line_no = static_cast<int>(this->desired.line_count());
|
||||
this->desired.add_line();
|
||||
this->desired.cursor.y++;
|
||||
this->desired.cursor.x = 0;
|
||||
}
|
||||
|
||||
line_t &line = s->desired.line(line_no);
|
||||
line_t &line = this->desired.line(line_no);
|
||||
line.append(b, c);
|
||||
s->desired.cursor.x += cw;
|
||||
this->desired.cursor.x += cw;
|
||||
|
||||
// Maybe wrap the cursor to the next line, even if the line itself did not wrap. This
|
||||
// avoids wonkiness in the last column.
|
||||
if (s->desired.cursor.x >= screen_width) {
|
||||
if (this->desired.cursor.x >= screen_width) {
|
||||
line.is_soft_wrapped = true;
|
||||
s->desired.cursor.x = 0;
|
||||
s->desired.cursor.y++;
|
||||
this->desired.cursor.x = 0;
|
||||
this->desired.cursor.y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Write the bytes needed to move screen cursor to the specified position to the specified buffer.
|
||||
/// The actual_cursor field of the specified screen_t will be updated.
|
||||
///
|
||||
/// \param s the screen to operate on
|
||||
/// \param new_x the new x position
|
||||
/// \param new_y the new y position
|
||||
static void s_move(screen_t *s, int new_x, int new_y) {
|
||||
if (s->actual.cursor.x == new_x && s->actual.cursor.y == new_y) return;
|
||||
void screen_t::move(int new_x, int new_y) {
|
||||
if (this->actual.cursor.x == new_x && this->actual.cursor.y == new_y) return;
|
||||
|
||||
const scoped_buffer_t buffering(*s);
|
||||
const scoped_buffer_t buffering(*this);
|
||||
|
||||
// If we are at the end of our window, then either the cursor stuck to the edge or it didn't. We
|
||||
// don't know! We can fix it up though.
|
||||
if (s->actual.cursor.x == s->actual.screen_width) {
|
||||
if (this->actual.cursor.x == this->actual.screen_width) {
|
||||
// Either issue a cr to go back to the beginning of this line, or a nl to go to the
|
||||
// beginning of the next one, depending on what we think is more efficient.
|
||||
if (new_y <= s->actual.cursor.y) {
|
||||
s->outp().push_back('\r');
|
||||
if (new_y <= this->actual.cursor.y) {
|
||||
this->outp().push_back('\r');
|
||||
} else {
|
||||
s->outp().push_back('\n');
|
||||
s->actual.cursor.y++;
|
||||
this->outp().push_back('\n');
|
||||
this->actual.cursor.y++;
|
||||
}
|
||||
// Either way we're not in the first column.
|
||||
s->actual.cursor.x = 0;
|
||||
this->actual.cursor.x = 0;
|
||||
}
|
||||
|
||||
int i;
|
||||
int x_steps, y_steps;
|
||||
|
||||
const char *str;
|
||||
auto &outp = s->outp();
|
||||
auto &outp = this->outp();
|
||||
|
||||
y_steps = new_y - s->actual.cursor.y;
|
||||
y_steps = new_y - this->actual.cursor.y;
|
||||
|
||||
if (y_steps < 0) {
|
||||
str = cursor_up;
|
||||
|
@ -613,7 +601,7 @@ static void s_move(screen_t *s, int new_x, int new_y) {
|
|||
// We could do:
|
||||
// if (std::strcmp(cursor_up, "\x1B[A") == 0) str = "\x1B[B";
|
||||
// else ... but that doesn't work for unknown reasons.
|
||||
s->actual.cursor.x = 0;
|
||||
this->actual.cursor.x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -621,7 +609,7 @@ static void s_move(screen_t *s, int new_x, int new_y) {
|
|||
writembs(outp, str);
|
||||
}
|
||||
|
||||
x_steps = new_x - s->actual.cursor.x;
|
||||
x_steps = new_x - this->actual.cursor.x;
|
||||
|
||||
if (x_steps && new_x == 0) {
|
||||
outp.push_back('\r');
|
||||
|
@ -650,32 +638,32 @@ static void s_move(screen_t *s, int new_x, int new_y) {
|
|||
}
|
||||
}
|
||||
|
||||
s->actual.cursor.x = new_x;
|
||||
s->actual.cursor.y = new_y;
|
||||
this->actual.cursor.x = new_x;
|
||||
this->actual.cursor.y = new_y;
|
||||
}
|
||||
|
||||
/// Convert a wide character to a multibyte string and append it to the buffer.
|
||||
static void s_write_char(screen_t *s, wchar_t c, size_t width) {
|
||||
scoped_buffer_t outp(*s);
|
||||
s->actual.cursor.x += width;
|
||||
s->outp().writech(c);
|
||||
if (s->actual.cursor.x == s->actual.screen_width && allow_soft_wrap()) {
|
||||
s->soft_wrap_location = screen_data_t::cursor_t{0, s->actual.cursor.y + 1};
|
||||
void screen_t::write_char(wchar_t c, size_t width) {
|
||||
scoped_buffer_t outp(*this);
|
||||
this->actual.cursor.x += width;
|
||||
this->outp().writech(c);
|
||||
if (this->actual.cursor.x == this->actual.screen_width && allow_soft_wrap()) {
|
||||
this->soft_wrap_location = screen_data_t::cursor_t{0, this->actual.cursor.y + 1};
|
||||
|
||||
// Note that our cursor position may be a lie: Apple Terminal makes the right cursor stick
|
||||
// to the margin, while Ubuntu makes it "go off the end" (but still doesn't wrap). We rely
|
||||
// on s_move to fix this up.
|
||||
} else {
|
||||
invalidate_soft_wrap(s);
|
||||
this->soft_wrap_location = none();
|
||||
}
|
||||
}
|
||||
|
||||
/// Send the specified string through tputs and append the output to the screen's outputter.
|
||||
static void s_write_mbs(screen_t *screen, const char *s) { writembs(screen->outp(), s); }
|
||||
void screen_t::write_mbs(const char *s) { writembs(this->outp(), s); }
|
||||
|
||||
/// Convert a wide string to a multibyte string and append it to the buffer.
|
||||
static void s_write_str(screen_t *screen, const wchar_t *s) { screen->outp().writestr(s); }
|
||||
static void s_write_str(screen_t *screen, const wcstring &s) { screen->outp().writestr(s); }
|
||||
void screen_t::write_str(const wchar_t *s) { this->outp().writestr(s); }
|
||||
void screen_t::write_str(const wcstring &s) { this->outp().writestr(s); }
|
||||
|
||||
/// Returns the length of the "shared prefix" of the two lines, which is the run of matching text
|
||||
/// and colors. If the prefix ends on a combining character, do not include the previous character
|
||||
|
@ -714,37 +702,34 @@ static size_t line_shared_prefix(const line_t &a, const line_t &b) {
|
|||
// end of previous line, and the previous line is marked as soft wrapping, then tweak the screen so
|
||||
// we believe we are already in the target position. This lets the terminal take care of wrapping,
|
||||
// which means that if you copy and paste the text, it won't have an embedded newline.
|
||||
static bool perform_any_impending_soft_wrap(screen_t *scr, int x, int y) {
|
||||
if (scr->soft_wrap_location && x == scr->soft_wrap_location->x &&
|
||||
y == scr->soft_wrap_location->y) { //!OCLINT
|
||||
bool screen_t::handle_soft_wrap(int x, int y) {
|
||||
if (this->soft_wrap_location && x == this->soft_wrap_location->x &&
|
||||
y == this->soft_wrap_location->y) { //!OCLINT
|
||||
// We can soft wrap; but do we want to?
|
||||
if (scr->desired.line(y - 1).is_soft_wrapped && allow_soft_wrap()) {
|
||||
if (this->desired.line(y - 1).is_soft_wrapped && allow_soft_wrap()) {
|
||||
// Yes. Just update the actual cursor; that will cause us to elide emitting the commands
|
||||
// to move here, so we will just output on "one big line" (which the terminal soft
|
||||
// wraps.
|
||||
scr->actual.cursor = scr->soft_wrap_location.value();
|
||||
this->actual.cursor = this->soft_wrap_location.value();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Make sure we don't soft wrap.
|
||||
static void invalidate_soft_wrap(screen_t *scr) { scr->soft_wrap_location = none(); }
|
||||
|
||||
/// Update the screen to match the desired output.
|
||||
static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring &right_prompt) {
|
||||
void screen_t::update(const wcstring &left_prompt, const wcstring &right_prompt) {
|
||||
// TODO: this should be passed in.
|
||||
const environment_t &vars = env_stack_t::principal();
|
||||
|
||||
// Helper function to set a resolved color, using the caching resolver.
|
||||
highlight_color_resolver_t color_resolver{};
|
||||
auto set_color = [&](highlight_spec_t c) {
|
||||
scr->outp().set_color(color_resolver.resolve_spec(c, false, vars),
|
||||
color_resolver.resolve_spec(c, true, vars));
|
||||
this->outp().set_color(color_resolver.resolve_spec(c, false, vars),
|
||||
color_resolver.resolve_spec(c, true, vars));
|
||||
};
|
||||
|
||||
layout_cache_t &cached_layouts = layout_cache_t::shared;
|
||||
const scoped_buffer_t buffering(*scr);
|
||||
const scoped_buffer_t buffering(*this);
|
||||
|
||||
// Determine size of left and right prompt. Note these have already been truncated.
|
||||
const prompt_layout_t left_prompt_layout = cached_layouts.calc_prompt_layout(left_prompt);
|
||||
|
@ -753,56 +738,56 @@ static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring
|
|||
cached_layouts.calc_prompt_layout(right_prompt).last_line_width;
|
||||
|
||||
// Figure out how many following lines we need to clear (probably 0).
|
||||
size_t actual_lines_before_reset = scr->actual_lines_before_reset;
|
||||
scr->actual_lines_before_reset = 0;
|
||||
size_t actual_lines_before_reset = this->actual_lines_before_reset;
|
||||
this->actual_lines_before_reset = 0;
|
||||
|
||||
bool need_clear_lines = scr->need_clear_lines;
|
||||
bool need_clear_screen = scr->need_clear_screen;
|
||||
bool need_clear_lines = this->need_clear_lines;
|
||||
bool need_clear_screen = this->need_clear_screen;
|
||||
bool has_cleared_screen = false;
|
||||
|
||||
const int screen_width = scr->desired.screen_width;
|
||||
const int screen_width = this->desired.screen_width;
|
||||
|
||||
if (scr->actual.screen_width != screen_width) {
|
||||
if (this->actual.screen_width != screen_width) {
|
||||
// Ensure we don't issue a clear screen for the very first output, to avoid issue #402.
|
||||
if (scr->actual.screen_width > 0) {
|
||||
if (this->actual.screen_width > 0) {
|
||||
need_clear_screen = true;
|
||||
s_move(scr, 0, 0);
|
||||
s_reset_line(scr);
|
||||
this->move(0, 0);
|
||||
this->reset_line();
|
||||
|
||||
need_clear_lines = need_clear_lines || scr->need_clear_lines;
|
||||
need_clear_screen = need_clear_screen || scr->need_clear_screen;
|
||||
need_clear_lines = need_clear_lines || this->need_clear_lines;
|
||||
need_clear_screen = need_clear_screen || this->need_clear_screen;
|
||||
}
|
||||
scr->actual.screen_width = screen_width;
|
||||
this->actual.screen_width = screen_width;
|
||||
}
|
||||
|
||||
scr->need_clear_lines = false;
|
||||
scr->need_clear_screen = false;
|
||||
this->need_clear_lines = false;
|
||||
this->need_clear_screen = false;
|
||||
|
||||
// Determine how many lines have stuff on them; we need to clear lines with stuff that we don't
|
||||
// want.
|
||||
const size_t lines_with_stuff = std::max(actual_lines_before_reset, scr->actual.line_count());
|
||||
if (scr->desired.line_count() < lines_with_stuff) need_clear_screen = true;
|
||||
const size_t lines_with_stuff = std::max(actual_lines_before_reset, this->actual.line_count());
|
||||
if (this->desired.line_count() < lines_with_stuff) need_clear_screen = true;
|
||||
|
||||
// Output the left prompt if it has changed.
|
||||
if (left_prompt != scr->actual_left_prompt) {
|
||||
s_move(scr, 0, 0);
|
||||
if (left_prompt != this->actual_left_prompt) {
|
||||
this->move(0, 0);
|
||||
size_t start = 0;
|
||||
for (const size_t line_break : left_prompt_layout.line_breaks) {
|
||||
s_write_str(scr, left_prompt.substr(start, line_break - start));
|
||||
this->write_str(left_prompt.substr(start, line_break - start));
|
||||
if (clr_eol) {
|
||||
s_write_mbs(scr, clr_eol);
|
||||
this->write_mbs(clr_eol);
|
||||
}
|
||||
start = line_break;
|
||||
}
|
||||
s_write_str(scr, left_prompt.substr(start));
|
||||
scr->actual_left_prompt = left_prompt;
|
||||
scr->actual.cursor.x = static_cast<int>(left_prompt_width);
|
||||
this->write_str(left_prompt.substr(start));
|
||||
this->actual_left_prompt = left_prompt;
|
||||
this->actual.cursor.x = static_cast<int>(left_prompt_width);
|
||||
}
|
||||
|
||||
// Output all lines.
|
||||
for (size_t i = 0; i < scr->desired.line_count(); i++) {
|
||||
const line_t &o_line = scr->desired.line(i);
|
||||
line_t &s_line = scr->actual.create_line(i);
|
||||
for (size_t i = 0; i < this->desired.line_count(); i++) {
|
||||
const line_t &o_line = this->desired.line(i);
|
||||
line_t &s_line = this->actual.create_line(i);
|
||||
size_t start_pos = i == 0 ? left_prompt_width : 0;
|
||||
int current_width = 0;
|
||||
bool has_cleared_line = false;
|
||||
|
@ -810,9 +795,9 @@ static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring
|
|||
// If this is the last line, maybe we should clear the screen.
|
||||
// Don't issue clr_eos if we think the cursor will end up in the last column - see #6951.
|
||||
const bool should_clear_screen_this_line =
|
||||
need_clear_screen && i + 1 == scr->desired.line_count() && clr_eos != nullptr &&
|
||||
!(scr->desired.cursor.x == 0 &&
|
||||
scr->desired.cursor.y == static_cast<int>(scr->desired.line_count()));
|
||||
need_clear_screen && i + 1 == this->desired.line_count() && clr_eos != nullptr &&
|
||||
!(this->desired.cursor.x == 0 &&
|
||||
this->desired.cursor.y == static_cast<int>(this->desired.line_count()));
|
||||
|
||||
// skip_remaining is how many columns are unchanged on this line.
|
||||
// Note that skip_remaining is a width, not a character count.
|
||||
|
@ -824,8 +809,8 @@ static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring
|
|||
if (o_line.indentation > s_line.indentation && !has_cleared_screen && clr_eol &&
|
||||
clr_eos) {
|
||||
set_color(highlight_spec_t{});
|
||||
s_move(scr, 0, static_cast<int>(i));
|
||||
s_write_mbs(scr, should_clear_screen_this_line ? clr_eos : clr_eol);
|
||||
this->move(0, static_cast<int>(i));
|
||||
this->write_mbs(should_clear_screen_this_line ? clr_eos : clr_eol);
|
||||
has_cleared_screen = should_clear_screen_this_line;
|
||||
has_cleared_line = true;
|
||||
}
|
||||
|
@ -844,16 +829,17 @@ static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring
|
|||
if (!should_clear_screen_this_line) {
|
||||
// If we're soft wrapped, and if we're going to change the first character of the next
|
||||
// line, don't skip over the last two characters so that we maintain soft-wrapping.
|
||||
if (o_line.is_soft_wrapped && i + 1 < scr->desired.line_count()) {
|
||||
if (o_line.is_soft_wrapped && i + 1 < this->desired.line_count()) {
|
||||
bool next_line_will_change = true;
|
||||
if (i + 1 < scr->actual.line_count()) { //!OCLINT
|
||||
if (line_shared_prefix(scr->desired.line(i + 1), scr->actual.line(i + 1)) > 0) {
|
||||
if (i + 1 < this->actual.line_count()) { //!OCLINT
|
||||
if (line_shared_prefix(this->desired.line(i + 1), this->actual.line(i + 1)) >
|
||||
0) {
|
||||
next_line_will_change = false;
|
||||
}
|
||||
}
|
||||
if (next_line_will_change) {
|
||||
skip_remaining =
|
||||
std::min(skip_remaining, static_cast<size_t>(scr->actual.screen_width - 2));
|
||||
skip_remaining = std::min(skip_remaining,
|
||||
static_cast<size_t>(this->actual.screen_width - 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -884,17 +870,17 @@ static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring
|
|||
if (should_clear_screen_this_line && !has_cleared_screen &&
|
||||
(done || j + 1 == static_cast<size_t>(screen_width))) {
|
||||
set_color(highlight_spec_t{});
|
||||
s_move(scr, current_width, static_cast<int>(i));
|
||||
s_write_mbs(scr, clr_eos);
|
||||
this->move(current_width, static_cast<int>(i));
|
||||
this->write_mbs(clr_eos);
|
||||
has_cleared_screen = true;
|
||||
}
|
||||
if (done) break;
|
||||
|
||||
perform_any_impending_soft_wrap(scr, current_width, static_cast<int>(i));
|
||||
s_move(scr, current_width, static_cast<int>(i));
|
||||
this->handle_soft_wrap(current_width, static_cast<int>(i));
|
||||
this->move(current_width, static_cast<int>(i));
|
||||
set_color(o_line.color_at(j));
|
||||
auto width = fish_wcwidth_visible(o_line.char_at(j));
|
||||
s_write_char(scr, o_line.char_at(j), width);
|
||||
this->write_char(o_line.char_at(j), width);
|
||||
current_width += width;
|
||||
}
|
||||
|
||||
|
@ -907,7 +893,7 @@ static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring
|
|||
clear_remainder = false;
|
||||
} else if (need_clear_lines && current_width < screen_width) {
|
||||
clear_remainder = true;
|
||||
} else if (right_prompt_width < scr->last_right_prompt_width) {
|
||||
} else if (right_prompt_width < this->last_right_prompt_width) {
|
||||
clear_remainder = true;
|
||||
} else {
|
||||
// This wcswidth shows up strong in the profile.
|
||||
|
@ -920,19 +906,19 @@ static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring
|
|||
}
|
||||
if (clear_remainder && clr_eol) {
|
||||
set_color(highlight_spec_t{});
|
||||
s_move(scr, current_width, static_cast<int>(i));
|
||||
s_write_mbs(scr, clr_eol);
|
||||
this->move(current_width, static_cast<int>(i));
|
||||
this->write_mbs(clr_eol);
|
||||
}
|
||||
|
||||
// Output any rprompt if this is the first line.
|
||||
if (i == 0 && right_prompt_width > 0) { //!OCLINT(Use early exit/continue)
|
||||
// Move the cursor to the beginning of the line first to be independent of the width.
|
||||
// This helps prevent staircase effects if fish and the terminal disagree.
|
||||
s_move(scr, 0, 0);
|
||||
s_move(scr, static_cast<int>(screen_width - right_prompt_width), static_cast<int>(i));
|
||||
this->move(0, 0);
|
||||
this->move(static_cast<int>(screen_width - right_prompt_width), static_cast<int>(i));
|
||||
set_color(highlight_spec_t{});
|
||||
s_write_str(scr, right_prompt);
|
||||
scr->actual.cursor.x += right_prompt_width;
|
||||
this->write_str(right_prompt);
|
||||
this->actual.cursor.x += right_prompt_width;
|
||||
|
||||
// We output in the last column. Some terms (Linux) push the cursor further right, past
|
||||
// the window. Others make it "stick." Since we don't really know which is which, issue
|
||||
|
@ -942,33 +928,33 @@ static void s_update(screen_t *scr, const wcstring &left_prompt, const wcstring
|
|||
// wrapped. If so, then a cr will go to the beginning of the following line! So instead
|
||||
// issue a bunch of "move left" commands to get back onto the line, and then jump to the
|
||||
// front of it.
|
||||
s_move(scr, scr->actual.cursor.x - static_cast<int>(right_prompt_width),
|
||||
scr->actual.cursor.y);
|
||||
s_write_str(scr, L"\r");
|
||||
scr->actual.cursor.x = 0;
|
||||
this->move(this->actual.cursor.x - static_cast<int>(right_prompt_width),
|
||||
this->actual.cursor.y);
|
||||
this->write_str(L"\r");
|
||||
this->actual.cursor.x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Also move the cursor to the beginning of the line here,
|
||||
// in case we're wrong about the width anywhere.
|
||||
s_move(scr, 0, 0);
|
||||
this->move(0, 0);
|
||||
|
||||
// Clear remaining lines (if any) if we haven't cleared the screen.
|
||||
if (!has_cleared_screen && need_clear_screen && clr_eol) {
|
||||
set_color(highlight_spec_t{});
|
||||
for (size_t i = scr->desired.line_count(); i < lines_with_stuff; i++) {
|
||||
s_move(scr, 0, static_cast<int>(i));
|
||||
s_write_mbs(scr, clr_eol);
|
||||
for (size_t i = this->desired.line_count(); i < lines_with_stuff; i++) {
|
||||
this->move(0, static_cast<int>(i));
|
||||
this->write_mbs(clr_eol);
|
||||
}
|
||||
}
|
||||
|
||||
s_move(scr, scr->desired.cursor.x, scr->desired.cursor.y);
|
||||
this->move(this->desired.cursor.x, this->desired.cursor.y);
|
||||
set_color(highlight_spec_t{});
|
||||
|
||||
// We have now synced our actual screen against our desired screen. Note that this is a big
|
||||
// assignment!
|
||||
scr->actual = scr->desired;
|
||||
scr->last_right_prompt_width = right_prompt_width;
|
||||
this->actual = this->desired;
|
||||
this->last_right_prompt_width = right_prompt_width;
|
||||
}
|
||||
|
||||
/// Returns true if we are using a dumb terminal.
|
||||
|
@ -1156,11 +1142,11 @@ static screen_layout_t compute_layout(screen_t *s, size_t screen_width,
|
|||
return result;
|
||||
}
|
||||
|
||||
void s_write(screen_t *s, const wcstring &left_prompt, const wcstring &right_prompt,
|
||||
const wcstring &commandline, size_t explicit_len,
|
||||
const std::vector<highlight_spec_t> &colors, const std::vector<int> &indent,
|
||||
size_t cursor_pos, pager_t &pager, page_rendering_t &page_rendering,
|
||||
bool cursor_is_within_pager) {
|
||||
void screen_t::write(const wcstring &left_prompt, const wcstring &right_prompt,
|
||||
const wcstring &commandline, size_t explicit_len,
|
||||
const std::vector<highlight_spec_t> &colors, const std::vector<int> &indent,
|
||||
size_t cursor_pos, pager_t &pager, page_rendering_t &page_rendering,
|
||||
bool cursor_is_within_pager) {
|
||||
termsize_t curr_termsize = termsize_last();
|
||||
int screen_width = curr_termsize.width;
|
||||
static relaxed_atomic_t<uint32_t> s_repaints{0};
|
||||
|
@ -1184,7 +1170,7 @@ void s_write(screen_t *s, const wcstring &left_prompt, const wcstring &right_pro
|
|||
return;
|
||||
}
|
||||
|
||||
s_check_status(s);
|
||||
this->check_status();
|
||||
|
||||
// Completely ignore impossibly small screens.
|
||||
if (screen_width < 4) {
|
||||
|
@ -1192,21 +1178,21 @@ void s_write(screen_t *s, const wcstring &left_prompt, const wcstring &right_pro
|
|||
}
|
||||
|
||||
// Compute a layout.
|
||||
const screen_layout_t layout = compute_layout(s, screen_width, left_prompt, right_prompt,
|
||||
const screen_layout_t layout = compute_layout(this, screen_width, left_prompt, right_prompt,
|
||||
explicit_command_line, autosuggestion);
|
||||
|
||||
// Determine whether, if we have an autosuggestion, it was truncated.
|
||||
s->autosuggestion_is_truncated =
|
||||
this->autosuggestion_is_truncated =
|
||||
!autosuggestion.empty() && autosuggestion != layout.autosuggestion;
|
||||
|
||||
// Clear the desired screen and set its width.
|
||||
s->desired.screen_width = screen_width;
|
||||
s->desired.resize(0);
|
||||
s->desired.cursor.x = s->desired.cursor.y = 0;
|
||||
this->desired.screen_width = screen_width;
|
||||
this->desired.resize(0);
|
||||
this->desired.cursor.x = this->desired.cursor.y = 0;
|
||||
|
||||
// Append spaces for the left prompt.
|
||||
for (size_t i = 0; i < layout.left_prompt_space; i++) {
|
||||
s_desired_append_char(s, L' ', highlight_spec_t{}, 0, layout.left_prompt_space, 1);
|
||||
desired_append_char(L' ', highlight_spec_t{}, 0, layout.left_prompt_space, 1);
|
||||
}
|
||||
|
||||
// If overflowing, give the prompt its own line to improve the situation.
|
||||
|
@ -1220,25 +1206,25 @@ void s_write(screen_t *s, const wcstring &left_prompt, const wcstring &right_pro
|
|||
for (i = 0; i < effective_commandline.size(); i++) {
|
||||
// Grab the current cursor's x,y position if this character matches the cursor's offset.
|
||||
if (!cursor_is_within_pager && i == cursor_pos) {
|
||||
cursor_arr = s->desired.cursor;
|
||||
cursor_arr = this->desired.cursor;
|
||||
}
|
||||
s_desired_append_char(s, effective_commandline.at(i), colors[i], indent[i],
|
||||
first_line_prompt_space,
|
||||
fish_wcwidth_visible(effective_commandline.at(i)));
|
||||
desired_append_char(effective_commandline.at(i), colors[i], indent[i],
|
||||
first_line_prompt_space,
|
||||
fish_wcwidth_visible(effective_commandline.at(i)));
|
||||
}
|
||||
|
||||
// Cursor may have been at the end too.
|
||||
if (!cursor_is_within_pager && i == cursor_pos) {
|
||||
cursor_arr = s->desired.cursor;
|
||||
cursor_arr = this->desired.cursor;
|
||||
}
|
||||
|
||||
// Now that we've output everything, set the cursor to the position that we saved in the loop
|
||||
// above.
|
||||
s->desired.cursor = cursor_arr;
|
||||
this->desired.cursor = cursor_arr;
|
||||
|
||||
if (cursor_is_within_pager) {
|
||||
s->desired.cursor.x = static_cast<int>(cursor_pos);
|
||||
s->desired.cursor.y = static_cast<int>(s->desired.line_count());
|
||||
this->desired.cursor.x = static_cast<int>(cursor_pos);
|
||||
this->desired.cursor.y = static_cast<int>(this->desired.line_count());
|
||||
}
|
||||
|
||||
// Re-render our completions page if necessary. Limit the term size of the pager to the true
|
||||
|
@ -1248,48 +1234,45 @@ void s_write(screen_t *s, const wcstring &left_prompt, const wcstring &right_pro
|
|||
std::max(1, curr_termsize.height - full_line_count)});
|
||||
pager.update_rendering(&page_rendering);
|
||||
// Append pager_data (none if empty).
|
||||
s->desired.append_lines(page_rendering.screen_data);
|
||||
this->desired.append_lines(page_rendering.screen_data);
|
||||
|
||||
s_update(s, layout.left_prompt, layout.right_prompt);
|
||||
s_save_status(s);
|
||||
this->update(layout.left_prompt, layout.right_prompt);
|
||||
this->save_status();
|
||||
}
|
||||
|
||||
void s_reset_line(screen_t *s, bool repaint_prompt) {
|
||||
assert(s && "Null screen");
|
||||
|
||||
void screen_t::reset_line(bool repaint_prompt) {
|
||||
// Remember how many lines we had output to, so we can clear the remaining lines in the next
|
||||
// call to s_update. This prevents leaving junk underneath the cursor when resizing a window
|
||||
// wider such that it reduces our desired line count.
|
||||
s->actual_lines_before_reset = std::max(s->actual_lines_before_reset, s->actual.line_count());
|
||||
this->actual_lines_before_reset =
|
||||
std::max(this->actual_lines_before_reset, this->actual.line_count());
|
||||
|
||||
if (repaint_prompt) {
|
||||
// If the prompt is multi-line, we need to move up to the prompt's initial line. We do this
|
||||
// by lying to ourselves and claiming that we're really below what we consider "line 0"
|
||||
// (which is the last line of the prompt). This will cause us to move up to try to get back
|
||||
// to line 0, but really we're getting back to the initial line of the prompt.
|
||||
const size_t prompt_line_count = calc_prompt_lines(s->actual_left_prompt);
|
||||
const size_t prompt_line_count = calc_prompt_lines(this->actual_left_prompt);
|
||||
assert(prompt_line_count >= 1);
|
||||
s->actual.cursor.y += (prompt_line_count - 1);
|
||||
s->actual_left_prompt.clear();
|
||||
this->actual.cursor.y += (prompt_line_count - 1);
|
||||
this->actual_left_prompt.clear();
|
||||
}
|
||||
s->actual.resize(0);
|
||||
s->need_clear_lines = true;
|
||||
this->actual.resize(0);
|
||||
this->need_clear_lines = true;
|
||||
|
||||
// This should prevent resetting the cursor position during the next repaint.
|
||||
write_loop(STDOUT_FILENO, "\r", 1);
|
||||
s->actual.cursor.x = 0;
|
||||
this->actual.cursor.x = 0;
|
||||
|
||||
fstat(STDOUT_FILENO, &s->prev_buff_1);
|
||||
fstat(STDERR_FILENO, &s->prev_buff_2);
|
||||
fstat(STDOUT_FILENO, &this->prev_buff_1);
|
||||
fstat(STDERR_FILENO, &this->prev_buff_2);
|
||||
}
|
||||
|
||||
void s_reset_abandoning_line(screen_t *s, int screen_width) {
|
||||
assert(s && "Null screen");
|
||||
|
||||
s->actual.cursor.y = 0;
|
||||
s->actual.resize(0);
|
||||
s->actual_left_prompt.clear();
|
||||
s->need_clear_lines = true;
|
||||
void screen_t::reset_abandoning_line(int screen_width) {
|
||||
this->actual.cursor.y = 0;
|
||||
this->actual.resize(0);
|
||||
this->actual_left_prompt.clear();
|
||||
this->need_clear_lines = true;
|
||||
|
||||
// Do the PROMPT_SP hack.
|
||||
wcstring abandon_line_string;
|
||||
|
@ -1358,10 +1341,10 @@ void s_reset_abandoning_line(screen_t *s, int screen_width) {
|
|||
const std::string narrow_abandon_line_string = wcs2string(abandon_line_string);
|
||||
write_loop(STDOUT_FILENO, narrow_abandon_line_string.c_str(),
|
||||
narrow_abandon_line_string.size());
|
||||
s->actual.cursor.x = 0;
|
||||
this->actual.cursor.x = 0;
|
||||
|
||||
fstat(STDOUT_FILENO, &s->prev_buff_1);
|
||||
fstat(STDERR_FILENO, &s->prev_buff_2);
|
||||
fstat(STDOUT_FILENO, &this->prev_buff_1);
|
||||
fstat(STDERR_FILENO, &this->prev_buff_2);
|
||||
}
|
||||
|
||||
void screen_force_clear_to_end() {
|
||||
|
|
115
src/screen.h
115
src/screen.h
|
@ -136,6 +136,76 @@ class screen_t {
|
|||
public:
|
||||
screen_t();
|
||||
|
||||
/// This is the main function for the screen output library. It is used to define the desired
|
||||
/// contents of the screen. The screen command will use its knowledge of the current contents of
|
||||
/// the screen in order to render the desired output using as few terminal commands as possible.
|
||||
///
|
||||
/// \param left_prompt the prompt to prepend to the command line
|
||||
/// \param right_prompt the right prompt, or NULL if none
|
||||
/// \param commandline the command line
|
||||
/// \param explicit_len the number of characters of the "explicit" (non-autosuggestion) portion
|
||||
/// of the command line \param colors the colors to use for the comand line \param indent the
|
||||
/// indent to use for the command line \param cursor_pos where the cursor is \param pager the
|
||||
/// pager to render below the command line \param page_rendering to cache the current pager view
|
||||
/// \param cursor_is_within_pager whether the position is within the pager line (first line)
|
||||
void write(const wcstring &left_prompt, const wcstring &right_prompt,
|
||||
const wcstring &commandline, size_t explicit_len,
|
||||
const std::vector<highlight_spec_t> &colors, const std::vector<int> &indent,
|
||||
size_t cursor_pos, pager_t &pager, page_rendering_t &page_rendering,
|
||||
bool cursor_is_within_pager);
|
||||
|
||||
/// Resets the screen buffer's internal knowledge about the contents of the screen,
|
||||
/// optionally repainting the prompt as well.
|
||||
/// This function assumes that the current line is still valid.
|
||||
void reset_line(bool repaint_prompt = false);
|
||||
|
||||
/// Resets the screen buffer's internal knowldge about the contents of the screen,
|
||||
/// abandoning the current line and going to the next line.
|
||||
/// If clear_to_eos is set,
|
||||
/// The screen width must be provided for the PROMPT_SP hack.
|
||||
void reset_abandoning_line(int screen_width);
|
||||
|
||||
/// Stat stdout and stderr and save result as the current timestamp.
|
||||
/// This is used to avoid reacting to changes that we ourselves made to the screen.
|
||||
void save_status();
|
||||
|
||||
/// \return whether we believe the cursor is wrapped onto the last line, and that line is
|
||||
/// otherwise empty. This includes both soft and hard wrapping.
|
||||
bool cursor_is_wrapped_to_own_line() const;
|
||||
|
||||
/// Whether the last-drawn autosuggestion (if any) is truncated, or hidden entirely.
|
||||
bool autosuggestion_is_truncated{false};
|
||||
|
||||
private:
|
||||
/// Appends a character to the end of the line that the output cursor is on. This function
|
||||
/// automatically handles linebreaks and lines longer than the screen width.
|
||||
void desired_append_char(wchar_t b, highlight_spec_t c, int indent, size_t prompt_width,
|
||||
size_t bwidth);
|
||||
|
||||
/// Stat stdout and stderr and compare result to previous result in reader_save_status. Repaint
|
||||
/// if modification time has changed.
|
||||
void check_status();
|
||||
|
||||
/// Write the bytes needed to move screen cursor to the specified position to the specified
|
||||
/// buffer. The actual_cursor field of the specified screen_t will be updated.
|
||||
///
|
||||
/// \param new_x the new x position
|
||||
/// \param new_y the new y position
|
||||
void move(int new_x, int new_y);
|
||||
|
||||
/// Convert a wide character to a multibyte string and append it to the buffer.
|
||||
void write_char(wchar_t c, size_t width);
|
||||
|
||||
/// Send the specified string through tputs and append the output to the screen's outputter.
|
||||
void write_mbs(const char *s);
|
||||
|
||||
/// Convert a wide string to a multibyte string and append it to the buffer.
|
||||
void write_str(const wchar_t *s);
|
||||
void write_str(const wcstring &s);
|
||||
|
||||
/// Update the cursor as if soft wrapping had been performed.
|
||||
bool handle_soft_wrap(int x, int y);
|
||||
|
||||
/// The internal representation of the desired screen contents.
|
||||
screen_data_t desired{};
|
||||
/// The internal representation of the actual screen contents.
|
||||
|
@ -146,8 +216,6 @@ class screen_t {
|
|||
size_t last_right_prompt_width{0};
|
||||
/// If we support soft wrapping, we can output to this location without any cursor motion.
|
||||
maybe_t<screen_data_t::cursor_t> soft_wrap_location{};
|
||||
/// Whether the last-drawn autosuggestion (if any) is truncated, or hidden entirely.
|
||||
bool autosuggestion_is_truncated{false};
|
||||
/// This flag is set to true when there is reason to suspect that the parts of the screen lines
|
||||
/// where the actual content is not filled in may be non-empty. This means that a clr_eol
|
||||
/// command has to be sent to the terminal at the end of each line, including
|
||||
|
@ -167,47 +235,12 @@ class screen_t {
|
|||
/// \return the outputter for this screen.
|
||||
outputter_t &outp() { return outp_; }
|
||||
|
||||
/// \return whether we believe the cursor is wrapped onto the last line, and that line is
|
||||
/// otherwise empty. This includes both soft and hard wrapping.
|
||||
bool cursor_is_wrapped_to_own_line() const;
|
||||
/// Update the screen to match the desired output.
|
||||
void update(const wcstring &left_prompt, const wcstring &right_prompt);
|
||||
|
||||
class scoped_buffer_t;
|
||||
};
|
||||
|
||||
/// This is the main function for the screen putput library. It is used to define the desired
|
||||
/// contents of the screen. The screen command will use its knowledge of the current contents of the
|
||||
/// screen in order to render the desired output using as few terminal commands as possible.
|
||||
///
|
||||
/// \param s the screen on which to write
|
||||
/// \param left_prompt the prompt to prepend to the command line
|
||||
/// \param right_prompt the right prompt, or NULL if none
|
||||
/// \param commandline the command line
|
||||
/// \param explicit_len the number of characters of the "explicit" (non-autosuggestion) portion of
|
||||
/// the command line
|
||||
/// \param colors the colors to use for the comand line
|
||||
/// \param indent the indent to use for the command line
|
||||
/// \param cursor_pos where the cursor is
|
||||
/// \param pager the pager to render below the command line
|
||||
/// \param page_rendering to cache the current pager view
|
||||
/// \param cursor_is_within_pager whether the position is within the pager line (first line)
|
||||
void s_write(screen_t *s, const wcstring &left_prompt, const wcstring &right_prompt,
|
||||
const wcstring &commandline, size_t explicit_len,
|
||||
const std::vector<highlight_spec_t> &colors, const std::vector<int> &indent,
|
||||
size_t cursor_pos, pager_t &pager, page_rendering_t &page_rendering,
|
||||
bool cursor_is_within_pager);
|
||||
|
||||
/// Resets the screen buffer's internal knowledge about the contents of the screen,
|
||||
/// optionally repainting the prompt as well.
|
||||
/// This function assumes that the current line is still valid.
|
||||
void s_reset_line(screen_t *s, bool repaint_prompt = false);
|
||||
|
||||
/// Resets the screen buffer's internal knowldge about the contents of the screen,
|
||||
/// abandoning the current line and going to the next line.
|
||||
/// If clear_to_eos is set,
|
||||
/// The screen width must be provided for the PROMPT_SP hack.
|
||||
void s_reset_abandoning_line(screen_t *s, int screen_width);
|
||||
|
||||
/// Stat stdout and stderr and save result as the current timestamp.
|
||||
void s_save_status(screen_t *s);
|
||||
|
||||
/// Issues an immediate clr_eos.
|
||||
void screen_force_clear_to_end();
|
||||
|
||||
|
|
Loading…
Reference in a new issue