mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
terminal: Follow output only if cursor is at end.
Closes #2257 Closes #2636 References #2683
This commit is contained in:
parent
e7bbd35c81
commit
4ceec30cd0
@ -370,8 +370,7 @@ void terminal_enter(void)
|
|||||||
State = TERM_FOCUS;
|
State = TERM_FOCUS;
|
||||||
mapped_ctrl_c |= TERM_FOCUS; // Always map CTRL-C to avoid interrupt.
|
mapped_ctrl_c |= TERM_FOCUS; // Always map CTRL-C to avoid interrupt.
|
||||||
RedrawingDisabled = false;
|
RedrawingDisabled = false;
|
||||||
// go to the bottom when the terminal is focused
|
adjust_topline(s->term, buf, 0); // scroll to end
|
||||||
adjust_topline(s->term, buf, false);
|
|
||||||
// erase the unfocused cursor
|
// erase the unfocused cursor
|
||||||
invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1);
|
invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1);
|
||||||
showmode();
|
showmode();
|
||||||
@ -966,14 +965,15 @@ static void refresh_terminal(Terminal *term)
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool pending_resize = term->pending_resize;
|
long ml_before = buf->b_ml.ml_line_count;
|
||||||
WITH_BUFFER(buf, {
|
WITH_BUFFER(buf, {
|
||||||
refresh_size(term, buf);
|
refresh_size(term, buf);
|
||||||
refresh_scrollback(term, buf);
|
refresh_scrollback(term, buf);
|
||||||
refresh_screen(term, buf);
|
refresh_screen(term, buf);
|
||||||
redraw_buf_later(buf, NOT_VALID);
|
redraw_buf_later(buf, NOT_VALID);
|
||||||
});
|
});
|
||||||
adjust_topline(term, buf, pending_resize);
|
long ml_added = buf->b_ml.ml_line_count - ml_before;
|
||||||
|
adjust_topline(term, buf, ml_added);
|
||||||
}
|
}
|
||||||
// Calls refresh_terminal() on all invalidated_terminals.
|
// Calls refresh_terminal() on all invalidated_terminals.
|
||||||
static void refresh_timer_cb(TimeWatcher *watcher, void *data)
|
static void refresh_timer_cb(TimeWatcher *watcher, void *data)
|
||||||
@ -1153,21 +1153,21 @@ static void redraw(bool restore_cursor)
|
|||||||
ui_flush();
|
ui_flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adjust_topline(Terminal *term, buf_T *buf, bool force)
|
static void adjust_topline(Terminal *term, buf_T *buf, long added)
|
||||||
{
|
{
|
||||||
int height, width;
|
int height, width;
|
||||||
vterm_get_size(term->vt, &height, &width);
|
vterm_get_size(term->vt, &height, &width);
|
||||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||||
if (wp->w_buffer == buf) {
|
if (wp->w_buffer == buf) {
|
||||||
// for every window that displays a terminal, ensure the cursor is in a
|
linenr_T ml_end = buf->b_ml.ml_line_count;
|
||||||
// valid line
|
bool following = ml_end == wp->w_cursor.lnum + added; // cursor at end?
|
||||||
wp->w_cursor.lnum = MIN(wp->w_cursor.lnum, buf->b_ml.ml_line_count);
|
if (following || (wp == curwin && is_focused(term))) {
|
||||||
if (force || curbuf != buf || is_focused(term)) {
|
// "Follow" the terminal output
|
||||||
// if the terminal is not in the current window or if it's focused,
|
wp->w_cursor.lnum = ml_end;
|
||||||
// adjust topline/cursor so the window will "follow" the terminal
|
|
||||||
// output
|
|
||||||
wp->w_cursor.lnum = buf->b_ml.ml_line_count;
|
|
||||||
set_topline(wp, MAX(wp->w_cursor.lnum - height + 1, 1));
|
set_topline(wp, MAX(wp->w_cursor.lnum - height + 1, 1));
|
||||||
|
} else {
|
||||||
|
// Ensure valid cursor for each window displaying this terminal.
|
||||||
|
wp->w_cursor.lnum = MIN(wp->w_cursor.lnum, ml_end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,8 @@ describe(':edit term://*', function()
|
|||||||
meths.set_option('shellcmdflag', 'REP ' .. rep)
|
meths.set_option('shellcmdflag', 'REP ' .. rep)
|
||||||
local rep_size = rep:byte() -- 'a' => 97
|
local rep_size = rep:byte() -- 'a' => 97
|
||||||
local sb = 10
|
local sb = 10
|
||||||
command('autocmd TermOpen * :setlocal scrollback='..tostring(sb))
|
command('autocmd TermOpen * :setlocal scrollback='..tostring(sb)
|
||||||
|
..'|call feedkeys("G", "n")')
|
||||||
command('edit term://foobar')
|
command('edit term://foobar')
|
||||||
|
|
||||||
local bufcontents = {}
|
local bufcontents = {}
|
||||||
|
@ -36,6 +36,18 @@ describe(':terminal', function()
|
|||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("in normal-mode :split does not move cursor", function()
|
||||||
|
execute([[terminal while true; do echo foo; sleep .1; done]])
|
||||||
|
helpers.feed([[<C-\><C-N>M]]) -- move cursor away from last line
|
||||||
|
wait()
|
||||||
|
eq(3, eval("line('$')")) -- window height
|
||||||
|
eq(2, eval("line('.')")) -- cursor is in the middle
|
||||||
|
execute('vsplit')
|
||||||
|
eq(2, eval("line('.')")) -- cursor stays where we put it
|
||||||
|
execute('split')
|
||||||
|
eq(2, eval("line('.')")) -- cursor stays where we put it
|
||||||
|
end)
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe(':terminal (with fake shell)', function()
|
describe(':terminal (with fake shell)', function()
|
||||||
|
Loading…
Reference in New Issue
Block a user