fix(terminal): keep last cursor if it's on the last row

This commit is contained in:
zeertzjq
2025-10-28 08:10:58 +08:00
parent a2d4a0fda9
commit a6d8f40b64
4 changed files with 182 additions and 83 deletions

View File

@@ -774,7 +774,7 @@ bool terminal_enter(void)
set_terminal_winopts(s);
s->term->pending.cursor = true; // Update the cursor shape table
adjust_topline(s->term, buf, 0); // scroll to end
adjust_topline_cursor(s->term, buf, 0); // scroll to end
showmode();
ui_cursor_shape();
@@ -2109,7 +2109,7 @@ static void refresh_terminal(Terminal *term)
refresh_screen(term, buf);
int ml_added = buf->b_ml.ml_line_count - ml_before;
adjust_topline(term, buf, ml_added);
adjust_topline_cursor(term, buf, ml_added);
// Copy pending events back to the main event queue
multiqueue_move_events(main_loop.events, term->pending.events);
@@ -2325,8 +2325,10 @@ static void refresh_screen(Terminal *term, buf_T *buf)
term->invalid_end = -1;
}
static void adjust_topline(Terminal *term, buf_T *buf, int added)
static void adjust_topline_cursor(Terminal *term, buf_T *buf, int added)
{
linenr_T ml_end = buf->b_ml.ml_line_count;
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->w_buffer == buf) {
if (wp == curwin && is_focused(term)) {
@@ -2335,9 +2337,7 @@ static void adjust_topline(Terminal *term, buf_T *buf, int added)
continue;
}
linenr_T ml_end = buf->b_ml.ml_line_count;
bool following = ml_end == wp->w_cursor.lnum + added; // cursor at end?
if (following) {
// "Follow" the terminal output
wp->w_cursor.lnum = ml_end;
@@ -2349,6 +2349,17 @@ static void adjust_topline(Terminal *term, buf_T *buf, int added)
mb_check_adjust_col(wp);
}
}
if (ml_end == buf->b_last_cursor.mark.lnum + added) {
buf->b_last_cursor.mark.lnum = ml_end;
}
for (size_t i = 0; i < kv_size(buf->b_wininfo); i++) {
WinInfo *wip = kv_A(buf->b_wininfo, i);
if (ml_end == wip->wi_mark.mark.lnum + added) {
wip->wi_mark.mark.lnum = ml_end;
}
}
}
static int row_to_linenr(Terminal *term, int row)