From 54f22a8f01c0feb27a531b52aedf5cdbd5e51b24 Mon Sep 17 00:00:00 2001 From: glepnir Date: Sun, 17 May 2026 00:25:18 +0800 Subject: [PATCH] fix(excmd): :bufdelete may fail from floating window #39800 Problem: with a float focused and the target buf only shown in the last non-float window, do_buffer_ext goes down the buf != curbuf path. close_windows can't touch the last non-float, b_nwindows stays > 0, close_buffer is skipped, returns OK silently. Solution: if a non-float still holds buf after close_windows, jump into it and recurse. Then buf == curbuf and the existing replacement path takes over. --- src/nvim/buffer.c | 8 ++++++++ test/functional/ui/float_spec.lua | 9 +++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 1f860a305b..b125bdc77f 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1462,6 +1462,14 @@ static int do_buffer_ext(int action, int start, int dir, int count, int flags) } close_windows(buf, false); + // close_windows keeps the last non-float window. If it still + // shows buf, jump there and retry so curbuf gets replaced. + if (bufref_valid(&bufref) && buf->b_nwindows > 0) { + win_T *holder = buf_jump_open_win(buf); + if (holder != NULL && !holder->w_floating) { + return do_buffer_ext(action, start, dir, count, flags); + } + } if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows <= 0) { close_buffer(NULL, buf, action, false, false, false); diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index fded55e30a..7c4387ed6e 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -761,8 +761,7 @@ describe('float window', function() eq(old_win, eval('g:win_enter')) eq(old_win, curwin()) end) - -- TODO: this case is too hard to deal with - pending('if called from floating window with another buffer', function() + it('if called from floating window with another buffer', function() api.nvim_set_current_win(other_buf_float) api.nvim_buf_delete(old_buf, { force = true }) end) @@ -794,8 +793,7 @@ describe('float window', function() eq(old_win, eval('g:win_enter')) eq(old_win, curwin()) end) - -- TODO: this case is too hard to deal with - pending('if called from floating window with an unlisted buffer', function() + it('if called from floating window with an unlisted buffer', function() api.nvim_set_current_win(unlisted_buf_float) api.nvim_buf_delete(old_buf, { force = true }) end) @@ -963,8 +961,7 @@ describe('float window', function() api.nvim_set_current_win(same_buf_float) api.nvim_buf_delete(old_buf, { force = false }) end) - -- TODO: this case is too hard to deal with - pending('if called from floating window with another buffer', function() + it('if called from floating window with another buffer', function() api.nvim_set_current_win(other_buf_float) api.nvim_buf_delete(old_buf, { force = false }) end)