diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index c44166a868..aec0edbbf5 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -659,18 +659,6 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i buf->b_nwindows = nwindows; - if (buf->terminal) { - buf->b_locked_split++; - buf_close_terminal(buf); - buf->b_locked_split--; - - // Must check this before calling buf_freeall(), otherwise is_curbuf will be true - // in buf_freeall() but still false here, leading to a 0-line buffer. - if (buf == curbuf && !is_curbuf) { - return false; - } - } - buf_freeall(buf, ((del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0) + (ignore_abort ? BFA_IGNORE_ABORT : 0))); @@ -809,11 +797,12 @@ void buf_freeall(buf_T *buf, int flags) bufref_T bufref; set_bufref(&bufref, buf); - buf_updates_unload(buf, false); - if (!bufref_valid(&bufref)) { - // on_detach callback deleted the buffer. - return; + if (buf->terminal) { + buf_close_terminal(buf); } + + buf_updates_unload(buf, false); + if ((buf->b_ml.ml_mfp != NULL) && apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, false, buf) && !bufref_valid(&bufref)) { @@ -2064,6 +2053,7 @@ bool curbuf_reusable(void) return (curbuf != NULL && curbuf->b_ffname == NULL && curbuf->b_nwindows <= 1 + && !curbuf->terminal && (curbuf->b_ml.ml_mfp == NULL || buf_is_empty(curbuf)) && !bt_quickfix(curbuf) && !curbufIsChanged()); diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index c407176142..1183e446fd 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -609,7 +609,7 @@ void terminal_close(Terminal **termpp, int status) if (status == -1 || exiting) { // If this was called by buf_close_terminal() (status is -1), or if exiting, we - // must inform the buffer the terminal no longer exists so that close_buffer() + // must inform the buffer the terminal no longer exists so that buf_freeall() // won't call buf_close_terminal() again. // If inside Terminal mode event handling, setting buf_handle to 0 also // informs terminal_enter() to call the close callback before returning. @@ -2110,7 +2110,7 @@ static void refresh_terminal(Terminal *term) { buf_T *buf = handle_get_buffer(term->buf_handle); if (!buf) { - // Destroyed by `close_buffer`. Do not do anything else. + // Destroyed by `buf_freeall()`. Do not do anything else. return; } linenr_T ml_before = buf->b_ml.ml_line_count; diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index a0ddfa435a..7bae7a2fdf 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -1024,6 +1024,33 @@ describe(':terminal buffer', function() test_open_term_in_buf_with_closed_term(env) end) + + it('with nvim_open_term() channel and only 1 line is not reused by :enew', function() + command('1new') + local oldbuf = api.nvim_get_current_buf() + api.nvim_open_term(oldbuf, {}) + eq({ mode = 'nt', blocking = false }, api.nvim_get_mode()) + feed('i') + eq({ mode = 't', blocking = false }, api.nvim_get_mode()) + feed([[]]) + eq({ mode = 'nt', blocking = false }, api.nvim_get_mode()) + + command('enew') + neq(oldbuf, api.nvim_get_current_buf()) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) + feed('i') + eq({ mode = 'i', blocking = false }, api.nvim_get_mode()) + feed('') + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) + + command('buffer #') + eq(oldbuf, api.nvim_get_current_buf()) + eq({ mode = 'nt', blocking = false }, api.nvim_get_mode()) + feed('i') + eq({ mode = 't', blocking = false }, api.nvim_get_mode()) + feed([[]]) + eq({ mode = 'nt', blocking = false }, api.nvim_get_mode()) + end) end) describe('on_lines does not emit out-of-bounds line indexes when', function()