Skip to content

Commit 63d53de

Browse files
seandewarchrisbra
authored andcommitted
patch 9.1.2068: :bd/bw may try to switch to a closing buffer
Problem: :bdelete/bunload/bwipeout may attempt to switch to a closing buffer, which fails. (after 9.1.2058) Solution: don't consider switching to closing buffers (Sean Dewar) closes: #19107 Signed-off-by: Sean Dewar <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent 335aecd commit 63d53de

3 files changed

Lines changed: 158 additions & 7 deletions

File tree

src/buffer.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,11 +1542,12 @@ do_buffer_ext(
15421542
* Then prefer the buffer we most recently visited.
15431543
* Else try to find one that is loaded, after the current buffer,
15441544
* then before the current buffer.
1545-
* Finally use any buffer.
1545+
* Finally use any buffer. Skip buffers that are closing throughout.
15461546
*/
15471547
buf = NULL; // selected buffer
15481548
bp = NULL; // used when no loaded buffer found
1549-
if (au_new_curbuf.br_buf != NULL && bufref_valid(&au_new_curbuf))
1549+
if (au_new_curbuf.br_buf != NULL && bufref_valid(&au_new_curbuf)
1550+
&& !au_new_curbuf.br_buf->b_locked_split)
15501551
buf = au_new_curbuf.br_buf;
15511552
else if (curwin->w_jumplistlen > 0)
15521553
{
@@ -1563,8 +1564,9 @@ do_buffer_ext(
15631564
if (buf != NULL)
15641565
{
15651566
// Skip current and unlisted bufs. Also skip a quickfix
1566-
// buffer, it might be deleted soon.
1567-
if (buf == curbuf || !buf->b_p_bl || bt_quickfix(buf))
1567+
// or closing buffer, it might be deleted soon.
1568+
if (buf == curbuf || !buf->b_p_bl || bt_quickfix(buf)
1569+
|| buf->b_locked_split)
15681570
buf = NULL;
15691571
else if (buf->b_ml.ml_mfp == NULL)
15701572
{
@@ -1602,7 +1604,7 @@ do_buffer_ext(
16021604
}
16031605
// in non-help buffer, try to skip help buffers, and vv
16041606
if (buf->b_help == curbuf->b_help && buf->b_p_bl
1605-
&& !bt_quickfix(buf))
1607+
&& !bt_quickfix(buf) && !buf->b_locked_split)
16061608
{
16071609
if (buf->b_ml.ml_mfp != NULL) // found loaded buffer
16081610
break;
@@ -1620,7 +1622,8 @@ do_buffer_ext(
16201622
if (buf == NULL) // No loaded buffer, find listed one
16211623
{
16221624
FOR_ALL_BUFFERS(buf)
1623-
if (buf->b_p_bl && buf != curbuf && !bt_quickfix(buf))
1625+
if (buf->b_p_bl && buf != curbuf && !bt_quickfix(buf)
1626+
&& !buf->b_locked_split)
16241627
break;
16251628
}
16261629
if (buf == NULL) // Still no buffer, just take one
@@ -1629,7 +1632,7 @@ do_buffer_ext(
16291632
buf = curbuf->b_next;
16301633
else
16311634
buf = curbuf->b_prev;
1632-
if (bt_quickfix(buf))
1635+
if (bt_quickfix(buf) || (buf != curbuf && buf->b_locked_split))
16331636
buf = NULL;
16341637
}
16351638
}

src/testdir/test_buffer.vim

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,4 +734,150 @@ func Test_switch_to_previously_viewed_buffer()
734734
set startofline&
735735
endfunc
736736

737+
func Test_bdelete_skip_closing_bufs()
738+
set hidden
739+
let s:fired = 0
740+
741+
edit foo
742+
edit bar
743+
let s:next_new_bufnr = bufnr('$') + 1
744+
augroup SkipClosing
745+
autocmd!
746+
" Only window and other buffer is closing.
747+
" No choice but to switch to a new, empty buffer.
748+
autocmd BufDelete * ++once let s:fired += 1
749+
\| call assert_equal(1, winnr('$'))
750+
\| call assert_equal('bar', bufname())
751+
\| bdelete
752+
\| call assert_equal('', bufname())
753+
\| call assert_equal(s:next_new_bufnr, bufnr())
754+
augroup END
755+
bdelete foo
756+
call assert_equal(1, s:fired)
757+
unlet! s:next_new_bufnr
758+
%bw!
759+
760+
edit baz
761+
edit bar
762+
edit fleb
763+
edit foo
764+
augroup SkipClosing
765+
autocmd!
766+
" Only window, au_new_curbuf is NOT closing; should end up there.
767+
autocmd BufDelete * ++once let s:fired += 1
768+
\| call assert_equal(1, winnr('$'))
769+
\| call assert_equal('foo', bufname())
770+
\| bwipeout
771+
\| call assert_equal('bar', bufname())
772+
augroup END
773+
buffer baz
774+
buffer foo
775+
augroup SkipClosing
776+
autocmd BufLeave * ++once ++nested bdelete baz
777+
augroup END
778+
edit bar
779+
call assert_equal(2, s:fired)
780+
%bw!
781+
782+
edit baz
783+
edit bar
784+
edit fleb
785+
edit foo
786+
augroup SkipClosing
787+
autocmd!
788+
" Like above, but au_new_curbuf IS closing.
789+
" Should use the most recent jumplist buffer instead.
790+
autocmd BufDelete * ++once let s:fired += 1
791+
\| call assert_equal(1, winnr('$'))
792+
\| call assert_equal('foo', bufname())
793+
\| bwipeout
794+
\| call assert_equal('baz', bufname())
795+
augroup END
796+
buffer baz
797+
buffer foo
798+
augroup SkipClosing
799+
autocmd BufLeave * ++once ++nested bdelete bar
800+
augroup END
801+
edit bar
802+
call assert_equal(3, s:fired)
803+
%bw!
804+
805+
edit foo
806+
edit floob
807+
edit baz
808+
edit bar
809+
augroup SkipClosing
810+
autocmd!
811+
" Only window, most recent buffer in jumplist is closing.
812+
" Should switch to the next most-recent buffer in the jumplist instead.
813+
autocmd BufDelete * ++once let s:fired += 1
814+
\| call assert_equal(1, winnr('$'))
815+
\| call assert_equal('bar', bufname())
816+
\| bdelete
817+
\| call assert_equal('floob', bufname())
818+
augroup END
819+
buffer baz
820+
buffer floob
821+
buffer foo
822+
buffer bar
823+
bdelete foo
824+
call assert_equal(4, s:fired)
825+
%bw!
826+
827+
edit foo
828+
edit baz
829+
edit bar
830+
edit floob
831+
edit bazinga
832+
augroup SkipClosing
833+
autocmd!
834+
" Only window, most recent jumplist buffer is gone, next most-recent is
835+
" closing. Should switch to the 3rd most-recent jumplist buffer.
836+
autocmd BufDelete * ++once let s:fired += 1
837+
\| call assert_equal(1, winnr('$'))
838+
\| call assert_equal('bar', bufname())
839+
\| bwipeout
840+
\| call assert_equal('baz', bufname())
841+
augroup END
842+
buffer bazinga
843+
buffer baz
844+
buffer floob
845+
buffer foo
846+
buffer bar
847+
noautocmd bdelete foo
848+
bdelete floob
849+
call assert_equal(5, s:fired)
850+
%bw!
851+
852+
edit foo
853+
edit baz
854+
edit floob
855+
edit bazinga
856+
edit bar
857+
augroup SkipClosing
858+
autocmd!
859+
" Like above, but jumplist cleared, no next buffer in the buffer list and
860+
" previous buffer is closing. Should switch to the buffer before previous.
861+
autocmd BufDelete * ++once let s:fired += 1
862+
\| call assert_equal(1, winnr('$'))
863+
\| call assert_equal('bar', bufname())
864+
\| bunload
865+
\| call assert_equal('floob', bufname())
866+
augroup END
867+
buffer bazinga
868+
buffer baz
869+
buffer floob
870+
buffer foo
871+
buffer bar
872+
noautocmd bdelete foo
873+
clearjumps
874+
bdelete bazinga
875+
call assert_equal(6, s:fired)
876+
877+
unlet! s:fired
878+
autocmd! SkipClosing
879+
set hidden&
880+
%bw!
881+
endfunc
882+
737883
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,8 @@ static char *(features[]) =
734734

735735
static int included_patches[] =
736736
{ /* Add new patch number below this line */
737+
/**/
738+
2068,
737739
/**/
738740
2067,
739741
/**/

0 commit comments

Comments
 (0)