aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/ex_cmds.c42
-rw-r--r--src/nvim/ex_cmds.h2
-rw-r--r--src/nvim/ex_cmds.lua6
-rw-r--r--src/nvim/ex_docmd.c11
-rw-r--r--src/nvim/ex_session.c16
-rw-r--r--src/nvim/testdir/test_buffer.vim10
-rw-r--r--src/nvim/testdir/test_mksession.vim89
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