diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 59d21b4932..164f336c5b 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -671,18 +671,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))); @@ -821,11 +809,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)) { @@ -2076,6 +2065,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 866adbccdc..a6c198c324 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -617,7 +617,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. @@ -2118,7 +2118,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 5e318b2623..4f573c2c54 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -1018,6 +1018,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()