diff options
-rw-r--r-- | src/nvim/edit.c | 2 | ||||
-rw-r--r-- | src/nvim/terminal.c | 15 | ||||
-rw-r--r-- | test/functional/terminal/buffer_spec.lua | 40 |
3 files changed, 51 insertions, 6 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 8b2ac1943f..c60d987ddd 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -246,7 +246,7 @@ edit ( ) { if (curbuf->terminal) { - terminal_enter(curbuf->terminal, true); + terminal_enter(true); return false; } diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index daba7b943f..9f4d81be19 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -353,8 +353,11 @@ void terminal_resize(Terminal *term, uint16_t width, uint16_t height) invalidate_terminal(term, -1, -1); } -void terminal_enter(Terminal *term, bool process_deferred) +void terminal_enter(bool process_deferred) { + Terminal *term = curbuf->terminal; + assert(term && "should only be called when curbuf has a terminal"); + checkpcmark(); setpcmark(); int save_state = State; @@ -373,7 +376,7 @@ void terminal_enter(Terminal *term, bool process_deferred) int c; bool close = false; - for (;;) { + while (term->buf == curbuf) { if (process_deferred) { event_enable_deferred(); } @@ -431,7 +434,7 @@ end: invalidate_terminal(term, term->cursor.row, term->cursor.row + 1); mapped_ctrl_c = save_mapped_ctrl_c; unshowmode(true); - redraw(false); + redraw(term->buf != curbuf); ui_busy_stop(); if (close) { term->opts.close_cb(term->opts.data); @@ -1018,6 +1021,11 @@ static void refresh_screen(Terminal *term) static void redraw(bool restore_cursor) { + Terminal *term = curbuf->terminal; + if (!term) { + restore_cursor = true; + } + int save_row, save_col; if (restore_cursor) { // save the current row/col to restore after updating screen when not @@ -1040,7 +1048,6 @@ static void redraw(bool restore_cursor) showruler(false); - Terminal *term = curbuf->terminal; if (term && is_focused(term)) { curwin->w_wrow = term->cursor.row; curwin->w_wcol = term->cursor.col + win_col_off(curwin); diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index 857679c4b3..0756508a4c 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -2,7 +2,9 @@ local helpers = require('test.functional.helpers') local Screen = require('test.functional.ui.screen') local thelpers = require('test.functional.terminal.helpers') local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim -local wait, execute, eq = helpers.wait, helpers.execute, helpers.eq +local wait = helpers.wait +local eval, execute, source = helpers.eval, helpers.execute, helpers.source +local eq, neq = helpers.eq, helpers.neq describe('terminal buffer', function() @@ -155,5 +157,41 @@ describe('terminal buffer', function() :bnext | ]]) end) + + it('handles loss of focus gracefully', function() + -- Temporarily change the statusline to avoid printing the file name, which + -- varies be where the test is run. + nvim('set_option', 'statusline', '==========') + execute('set laststatus=0') + + -- Save the buffer number of the terminal for later testing. + local tbuf = eval('bufnr("%")') + + source([[ + function! SplitWindow() + new + endfunction + + startinsert + call jobstart(['sh', '-c', 'exit'], {'on_exit': function("SplitWindow")}) + ]]) + + -- We should be in a new buffer now. + screen:expect([[ + ^ | + ~ | + ========== | + rows: 2, cols: 50 | + {2: } | + {1:========== }| + | + ]]) + + neq(tbuf, eval('bufnr("%")')) + execute('quit') -- Should exit the new window, not the terminal. + eq(tbuf, eval('bufnr("%")')) + + execute('set laststatus=1') -- Restore laststatus to the default. + end) end) |