diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2017-02-21 15:06:44 +0100 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2017-02-26 13:00:01 +0100 |
commit | 4ceec30cd0b48f865ffae05811c4862cef4a548a (patch) | |
tree | df0b5272e1560bdd4af78c0697c68a58303242d7 | |
parent | e7bbd35c812d338918d1c23692c70b403205fb30 (diff) | |
download | rneovim-4ceec30cd0b48f865ffae05811c4862cef4a548a.tar.gz rneovim-4ceec30cd0b48f865ffae05811c4862cef4a548a.tar.bz2 rneovim-4ceec30cd0b48f865ffae05811c4862cef4a548a.zip |
terminal: Follow output only if cursor is at end.
Closes #2257
Closes #2636
References #2683
-rw-r--r-- | src/nvim/terminal.c | 26 | ||||
-rw-r--r-- | test/functional/terminal/edit_spec.lua | 3 | ||||
-rw-r--r-- | test/functional/terminal/ex_terminal_spec.lua | 12 |
3 files changed, 27 insertions, 14 deletions
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index f156cd6abf..b8ae2da913 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -370,8 +370,7 @@ void terminal_enter(void) State = TERM_FOCUS; mapped_ctrl_c |= TERM_FOCUS; // Always map CTRL-C to avoid interrupt. RedrawingDisabled = false; - // go to the bottom when the terminal is focused - adjust_topline(s->term, buf, false); + adjust_topline(s->term, buf, 0); // scroll to end // erase the unfocused cursor invalidate_terminal(s->term, s->term->cursor.row, s->term->cursor.row + 1); showmode(); @@ -966,14 +965,15 @@ static void refresh_terminal(Terminal *term) } return; } - bool pending_resize = term->pending_resize; + long ml_before = buf->b_ml.ml_line_count; WITH_BUFFER(buf, { refresh_size(term, buf); refresh_scrollback(term, buf); refresh_screen(term, buf); 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. static void refresh_timer_cb(TimeWatcher *watcher, void *data) @@ -1153,21 +1153,21 @@ static void redraw(bool restore_cursor) 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; vterm_get_size(term->vt, &height, &width); FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (wp->w_buffer == buf) { - // for every window that displays a terminal, ensure the cursor is in a - // valid line - wp->w_cursor.lnum = MIN(wp->w_cursor.lnum, buf->b_ml.ml_line_count); - if (force || curbuf != buf || is_focused(term)) { - // if the terminal is not in the current window or if it's focused, - // adjust topline/cursor so the window will "follow" the terminal - // output - wp->w_cursor.lnum = buf->b_ml.ml_line_count; + linenr_T ml_end = buf->b_ml.ml_line_count; + bool following = ml_end == wp->w_cursor.lnum + added; // cursor at end? + if (following || (wp == curwin && is_focused(term))) { + // "Follow" the terminal output + wp->w_cursor.lnum = ml_end; 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); } } } diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua index 9795e7957d..42a5c768bb 100644 --- a/test/functional/terminal/edit_spec.lua +++ b/test/functional/terminal/edit_spec.lua @@ -38,7 +38,8 @@ describe(':edit term://*', function() meths.set_option('shellcmdflag', 'REP ' .. rep) local rep_size = rep:byte() -- 'a' => 97 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') local bufcontents = {} diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua index dc2535bade..7a9d2a9b36 100644 --- a/test/functional/terminal/ex_terminal_spec.lua +++ b/test/functional/terminal/ex_terminal_spec.lua @@ -36,6 +36,18 @@ describe(':terminal', function() ]]) 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) describe(':terminal (with fake shell)', function() |