# HG changeset patch # User Bram Moolenaar # Date 1642167003 -3600 # Node ID 4fd87205ca807ddbdf65b97619099d2640617f5f # Parent 0c4b6fb98f762a0401d30e8581c55ea5814dd1c2 patch 8.2.4090: after restoring a session buffer order can be quite different Commit: https://github.com/vim/vim/commit/26ebf1f036517ebeacf571c333a83cca7e13bbe2 Author: Evgeni Chasnovski Date: Fri Jan 14 13:19:43 2022 +0000 patch 8.2.4090: after restoring a session buffer order can be quite different Problem: After restoring a session buffer order can be quite different. Solution: Create buffers first. (Evgeni Chasnovski, closes https://github.com/vim/vim/issues/9520) diff --git a/src/session.c b/src/session.c --- a/src/session.c +++ b/src/session.c @@ -690,6 +690,28 @@ makeopens( if (put_line(fd, "set shortmess=aoO") == FAIL) goto fail; + // Put all buffers into the buffer list. + // Do it very early to preserve buffer order after loading session (which + // can be disrupted by prior `edit` or `tabedit` calls). + FOR_ALL_BUFFERS(buf) + { + if (!(only_save_windows && buf->b_nwindows == 0) + && !(buf->b_help && !(ssop_flags & SSOP_HELP)) +#ifdef FEAT_TERMINAL + // Skip terminal buffers: finished ones are not useful, others + // will be resurrected and result in a new buffer. + && !bt_terminal(buf) +#endif + && buf->b_fname != NULL + && buf->b_p_bl) + { + if (fprintf(fd, "badd +%ld ", buf->b_wininfo == NULL ? 1L + : buf->b_wininfo->wi_fpos.lnum) < 0 + || ses_fname(fd, buf, &ssop_flags, TRUE) == FAIL) + goto fail; + } + } + // the global argument list if (ses_arglist(fd, "argglobal", &global_alist.al_ga, !(ssop_flags & SSOP_CURDIR), &ssop_flags) == FAIL) @@ -741,7 +763,11 @@ makeopens( // Similar to ses_win_rec() below, populate the tab pages first so // later local options won't be copied to the new tabs. FOR_ALL_TABPAGES(tp) - if (tp->tp_next != NULL && put_line(fd, "tabnew") == FAIL) + // Use `bufhidden=wipe` to remove empty "placeholder" buffers once + // they are not needed. This prevents creating extra buffers (see + // cause of patch 8.1.0829) + if (tp->tp_next != NULL + && put_line(fd, "tabnew +setlocal\\ bufhidden=wipe") == FAIL) goto fail; if (first_tabpage->tp_next != NULL && put_line(fd, "tabrewind") == FAIL) goto fail; @@ -919,29 +945,6 @@ makeopens( if (restore_stal && put_line(fd, "set stal=1") == FAIL) goto fail; - // Now put the remaining buffers into the buffer list. - // This is near the end, so that when 'hidden' is set we don't create extra - // buffers. If the buffer was already created with another command the - // ":badd" will have no effect. - FOR_ALL_BUFFERS(buf) - { - if (!(only_save_windows && buf->b_nwindows == 0) - && !(buf->b_help && !(ssop_flags & SSOP_HELP)) -#ifdef FEAT_TERMINAL - // Skip terminal buffers: finished ones are not useful, others - // will be resurrected and result in a new buffer. - && !bt_terminal(buf) -#endif - && buf->b_fname != NULL - && buf->b_p_bl) - { - if (fprintf(fd, "badd +%ld ", buf->b_wininfo == NULL ? 1L - : buf->b_wininfo->wi_fpos.lnum) < 0 - || ses_fname(fd, buf, &ssop_flags, TRUE) == FAIL) - goto fail; - } - } - // Wipe out an empty unnamed buffer we started in. if (put_line(fd, "if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0") == FAIL) diff --git a/src/testdir/test_mksession.vim b/src/testdir/test_mksession.vim --- a/src/testdir/test_mksession.vim +++ b/src/testdir/test_mksession.vim @@ -362,6 +362,31 @@ func Test_mksession_buffer_count() set hidden& endfunc +func Test_mksession_buffer_order() + %bwipe! + e Xfoo | e Xbar | e Xbaz | e Xqux + bufdo write + mksession! Xtest_mks.out + + " Verify that loading the session preserves order of buffers + %bwipe! + source Xtest_mks.out + + let s:buf_info = getbufinfo() + call assert_true(s:buf_info[0]['name'] =~# 'Xfoo$') + call assert_true(s:buf_info[1]['name'] =~# 'Xbar$') + call assert_true(s:buf_info[2]['name'] =~# 'Xbaz$') + call assert_true(s:buf_info[3]['name'] =~# 'Xqux$') + + " Clean up. + call delete('Xfoo') + call delete('Xbar') + call delete('Xbaz') + call delete('Xqux') + call delete('Xtest_mks.out') + %bwipe! +endfunc + if has('extra_search') func Test_mksession_hlsearch() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4090, +/**/ 4089, /**/ 4088,