diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/ex_cmds.c | 42 | ||||
-rw-r--r-- | src/nvim/ex_cmds.h | 2 | ||||
-rw-r--r-- | src/nvim/ex_cmds.lua | 6 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 11 | ||||
-rw-r--r-- | src/nvim/ex_session.c | 16 | ||||
-rw-r--r-- | src/nvim/testdir/test_buffer.vim | 10 | ||||
-rw-r--r-- | src/nvim/testdir/test_mksession.vim | 89 |
7 files changed, 152 insertions, 24 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index ab09284c9d..a994d0d8c3 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2181,6 +2181,8 @@ theend: /// ECMD_OLDBUF: use existing buffer if it exists /// ECMD_FORCEIT: ! used for Ex command /// ECMD_ADDBUF: don't edit, just add to buffer list +/// ECMD_ALTBUF: like ECMD_ADDBUF and also set the alternate +/// file /// @param oldwin Should be "curwin" when editing a new buffer in the current /// window, NULL when splitting the window first. When not NULL /// info of the previous buffer for "oldwin" is stored. @@ -2237,8 +2239,10 @@ int do_ecmd( path_fix_case(sfname); // set correct case for sfname #endif - if ((flags & ECMD_ADDBUF) && (ffname == NULL || *ffname == NUL)) + if ((flags & (ECMD_ADDBUF | ECMD_ALTBUF)) + && (ffname == NULL || *ffname == NUL)) { goto theend; + } if (ffname == NULL) other_file = TRUE; @@ -2268,15 +2272,16 @@ int do_ecmd( // If the file was changed we may not be allowed to abandon it: // - if we are going to re-edit the same file // - or if we are the only window on this file and if ECMD_HIDE is FALSE - if ( ((!other_file && !(flags & ECMD_OLDBUF)) - || (curbuf->b_nwindows == 1 - && !(flags & (ECMD_HIDE | ECMD_ADDBUF)))) - && check_changed(curbuf, (p_awa ? CCGD_AW : 0) - | (other_file ? 0 : CCGD_MULTWIN) - | ((flags & ECMD_FORCEIT) ? CCGD_FORCEIT : 0) - | (eap == NULL ? 0 : CCGD_EXCMD))) { - if (fnum == 0 && other_file && ffname != NULL) + if (((!other_file && !(flags & ECMD_OLDBUF)) + || (curbuf->b_nwindows == 1 + && !(flags & (ECMD_HIDE | ECMD_ADDBUF | ECMD_ALTBUF)))) + && check_changed(curbuf, (p_awa ? CCGD_AW : 0) + | (other_file ? 0 : CCGD_MULTWIN) + | ((flags & ECMD_FORCEIT) ? CCGD_FORCEIT : 0) + | (eap == NULL ? 0 : CCGD_EXCMD))) { + if (fnum == 0 && other_file && ffname != NULL) { (void)setaltfname(ffname, sfname, newlnum < 0 ? 0 : newlnum); + } goto theend; } @@ -2306,17 +2311,19 @@ int do_ecmd( * Otherwise we re-use the current buffer. */ if (other_file) { - if (!(flags & ECMD_ADDBUF)) { - if (!cmdmod.keepalt) + if (!(flags & (ECMD_ADDBUF | ECMD_ALTBUF))) { + if (!cmdmod.keepalt) { curwin->w_alt_fnum = curbuf->b_fnum; - if (oldwin != NULL) + } + if (oldwin != NULL) { buflist_altfpos(oldwin); + } } if (fnum) { buf = buflist_findnr(fnum); } else { - if (flags & ECMD_ADDBUF) { + if (flags & (ECMD_ADDBUF | ECMD_ALTBUF)) { linenr_T tlnum = 1L; if (command != NULL) { @@ -2324,7 +2331,11 @@ int do_ecmd( if (tlnum <= 0) tlnum = 1L; } - (void)buflist_new(ffname, sfname, tlnum, BLN_LISTED); + const buf_T *const newbuf + = buflist_new(ffname, sfname, tlnum, BLN_LISTED); + if (newbuf != NULL && (flags & ECMD_ALTBUF)) { + curwin->w_alt_fnum = newbuf->b_fnum; + } goto theend; } buf = buflist_new(ffname, sfname, 0L, @@ -2470,8 +2481,7 @@ int do_ecmd( curwin->w_pcmark.lnum = 1; curwin->w_pcmark.col = 0; } else { // !other_file - if ((flags & ECMD_ADDBUF) - || check_fname() == FAIL) { + if ((flags & (ECMD_ADDBUF | ECMD_ALTBUF)) || check_fname() == FAIL) { goto theend; } oldbuf = (flags & ECMD_OLDBUF); diff --git a/src/nvim/ex_cmds.h b/src/nvim/ex_cmds.h index b564cde56c..1b54b3a898 100644 --- a/src/nvim/ex_cmds.h +++ b/src/nvim/ex_cmds.h @@ -16,7 +16,7 @@ #define ECMD_OLDBUF 0x04 // use existing buffer if it exists #define ECMD_FORCEIT 0x08 // ! used in Ex command #define ECMD_ADDBUF 0x10 // don't edit, just add to buffer list - +#define ECMD_ALTBUF 0x20 // like ECMD_ADDBUF and set the alternate file /* for lnum argument in do_ecmd() */ #define ECMD_LASTL (linenr_T)0 /* use last position in loaded file */ diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index e9046da800..10dd7d68ca 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -176,6 +176,12 @@ module.cmds = { func='ex_edit', }, { + command='balt', + flags=bit.bor(NEEDARG, FILE1, CMDARG, TRLBAR, CMDWIN), + addr_type='ADDR_NONE', + func='ex_edit', + }, + { command='bdelete', flags=bit.bor(BANG, RANGE, BUFNAME, COUNT, EXTRA, TRLBAR), addr_type='ADDR_BUFFERS', diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 6cc915c8c2..ef11107779 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -7271,9 +7271,7 @@ static void ex_find(exarg_T *eap) } } -/* - * ":edit", ":badd", ":visual". - */ +/// ":edit", ":badd", ":balt", ":visual". static void ex_edit(exarg_T *eap) { do_exedit(eap, NULL); @@ -7347,7 +7345,9 @@ do_exedit( else if (eap->cmdidx == CMD_enew) readonlymode = FALSE; /* 'readonly' doesn't make sense in an empty buffer */ - setpcmark(); + if (eap->cmdidx != CMD_balt && eap->cmdidx != CMD_badd) { + setpcmark(); + } if (do_ecmd(0, (eap->cmdidx == CMD_enew ? NULL : eap->arg), NULL, eap, eap->do_ecmd_lnum, (buf_hide(curbuf) ? ECMD_HIDE : 0) @@ -7355,6 +7355,7 @@ do_exedit( // After a split we can use an existing buffer. + (old_curwin != NULL ? ECMD_OLDBUF : 0) + (eap->cmdidx == CMD_badd ? ECMD_ADDBUF : 0) + + (eap->cmdidx == CMD_balt ? ECMD_ALTBUF : 0) , old_curwin == NULL ? curwin : NULL) == FAIL) { // Editing the file failed. If the window was split, close it. if (old_curwin != NULL) { @@ -8725,7 +8726,7 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen) * Evaluate cmdline variables. * * change '%' to curbuf->b_ffname - * '#' to curwin->w_altfile + * '#' to curwin->w_alt_fnum * '<cword>' to word under the cursor * '<cWORD>' to WORD under the cursor * '<cexpr>' to C-expression under the cursor diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c index 14dac9a126..63789b3981 100644 --- a/src/nvim/ex_session.c +++ b/src/nvim/ex_session.c @@ -384,6 +384,18 @@ static int put_view( xfree(fname_esc); } + if (wp->w_alt_fnum) { + buf_T *const alt = buflist_findnr(wp->w_alt_fnum); + + // Set the alternate file. + if ((flagp == &ssop_flags) && alt != NULL && alt->b_fname != NULL + && *alt->b_fname != NUL + && (fputs("balt ", fd) < 0 + || ses_fname(fd, alt, flagp, true) == FAIL)) { + return FAIL; + } + } + // // Local mappings and abbreviations. // @@ -438,9 +450,9 @@ static int put_view( "let s:l = %" PRId64 " - ((%" PRId64 " * winheight(0) + %" PRId64 ") / %" PRId64 ")\n" "if s:l < 1 | let s:l = 1 | endif\n" - "exe s:l\n" + "keepjumps exe s:l\n" "normal! zt\n" - "%" PRId64 "\n", + "keepjumps %" PRId64 "\n", (int64_t)wp->w_cursor.lnum, (int64_t)(wp->w_cursor.lnum - wp->w_topline), (int64_t)(wp->w_height_inner / 2), diff --git a/src/nvim/testdir/test_buffer.vim b/src/nvim/testdir/test_buffer.vim new file mode 100644 index 0000000000..f455b6911f --- /dev/null +++ b/src/nvim/testdir/test_buffer.vim @@ -0,0 +1,10 @@ +" Tests for Vim buffer + +func Test_balt() + new SomeNewBuffer + balt +3 OtherBuffer + e # + call assert_equal('OtherBuffer', bufname()) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim index 88320e0c22..7c7804212b 100644 --- a/src/nvim/testdir/test_mksession.vim +++ b/src/nvim/testdir/test_mksession.vim @@ -317,6 +317,20 @@ func Test_mkview_open_folds() %bwipe endfunc +func Test_mkview_no_balt() + edit Xtestfile1 + edit Xtestfile2 + + mkview! Xtestview + bdelete Xtestfile1 + + source Xtestview + call assert_equal(0, buflisted('Xtestfile1')) + + call delete('Xtestview') + %bwipe +endfunc + " Test :mkview with a file argument. func Test_mkview_file() " Create a view with line number and a fold. @@ -399,6 +413,58 @@ func Test_mkview_no_file_name() %bwipe endfunc +func Test_mkview_loadview_jumplist() + set viewdir=Xviewdir + au BufWinLeave * silent mkview + " au BufWinEnter * silent loadview + + edit Xfile1 + call setline(1, ['a', 'bbbbbbb', 'c']) + normal j3l + call assert_equal([2, 4], getcurpos()[1:2]) + write + + edit Xfile2 + call setline(1, ['d', 'eeeeeee', 'f']) + normal j5l + call assert_equal([2, 6], getcurpos()[1:2]) + write + + edit Xfile3 + call setline(1, ['g', 'h', 'iiiii']) + normal jj3l + call assert_equal([3, 4], getcurpos()[1:2]) + write + + " The commented :au above was moved here so that :mkview (on BufWinLeave) can + " run before :loadview. This is needed because Nvim's :loadview raises E484 if + " the view can't be opened, while Vim's silently fails instead. + au BufWinEnter * silent loadview + + edit Xfile1 + call assert_equal([2, 4], getcurpos()[1:2]) + edit Xfile2 + call assert_equal([2, 6], getcurpos()[1:2]) + edit Xfile3 + call assert_equal([3, 4], getcurpos()[1:2]) + + exe "normal \<C-O>" + call assert_equal('Xfile2', expand('%')) + call assert_equal([2, 6], getcurpos()[1:2]) + exe "normal \<C-O>" + call assert_equal('Xfile1', expand('%')) + call assert_equal([2, 4], getcurpos()[1:2]) + + au! BufWinLeave + au! BufWinEnter + bwipe! + call delete('Xviewdir', 'rf') + call delete('Xfile1') + call delete('Xfile2') + call delete('Xfile3') + set viewdir& +endfunc + " A clean session (one empty buffer, one window, and one tab) should not " set any error messages when sourced because no commands should fail. func Test_mksession_no_errmsg() @@ -689,4 +755,27 @@ func Test_scrolloff() set sessionoptions& endfunc +func Test_altfile() + edit Xone + split Xtwo + edit Xtwoalt + edit # + wincmd w + edit Xonealt + edit # + mksession! Xtest_altfile + only + bwipe Xonealt + bwipe Xtwoalt + bwipe! + source Xtest_altfile + call assert_equal('Xone', bufname()) + call assert_equal('Xonealt', bufname('#')) + wincmd w + call assert_equal('Xtwo', bufname()) + call assert_equal('Xtwoalt', bufname('#')) + only + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab |