diff options
-rw-r--r-- | runtime/doc/news.txt | 3 | ||||
-rw-r--r-- | src/nvim/buffer.c | 51 | ||||
-rw-r--r-- | src/nvim/buffer.h | 11 | ||||
-rw-r--r-- | test/old/testdir/test_buffer.vim | 46 |
4 files changed, 97 insertions, 14 deletions
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index f1c241a951..604515a808 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -49,6 +49,9 @@ EDITOR now appear left of lower priority signs. • |hl-CurSearch| now behaves the same as Vim and no longer updates on every cursor movement. +• Moving in the buffer list using |:bnext| and similar commands behaves as + documented and skips help buffers if run from a non-help buffer, otherwise + it moves to another help buffer. VIM SCRIPT diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index d894844c6d..d1b7c553c3 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -942,6 +942,21 @@ static void free_buffer_stuff(buf_T *buf, int free_flags) void goto_buffer(exarg_T *eap, int start, int dir, int count) { const int save_sea = swap_exists_action; + bool skip_help_buf; + + switch (eap->cmdidx) { + case CMD_bnext: + case CMD_sbnext: + case CMD_bNext: + case CMD_bprevious: + case CMD_sbNext: + case CMD_sbprevious: + skip_help_buf = true; + break; + default: + skip_help_buf = false; + break; + } bufref_T old_curbuf; set_bufref(&old_curbuf, curbuf); @@ -949,8 +964,9 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count) if (swap_exists_action == SEA_NONE) { swap_exists_action = SEA_DIALOG; } - do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO, - start, dir, count, eap->forceit); + (void)do_buffer_ext(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO, start, dir, count, + (eap->forceit ? DOBUF_FORCEIT : 0) | + (skip_help_buf ? DOBUF_SKIPHELP : 0)); if (swap_exists_action == SEA_QUIT && *eap->cmd == 's') { cleanup_T cs; @@ -1202,10 +1218,10 @@ static int empty_curbuf(bool close_others, int forceit, int action) /// /// @param dir FORWARD or BACKWARD /// @param count buffer number or number of buffers -/// @param forceit true for :...! +/// @param flags see @ref dobuf_flags_value /// /// @return FAIL or OK. -int do_buffer(int action, int start, int dir, int count, int forceit) +static int do_buffer_ext(int action, int start, int dir, int count, int flags) { buf_T *buf; buf_T *bp; @@ -1257,8 +1273,12 @@ int do_buffer(int action, int start, int dir, int count, int forceit) buf = lastbuf; } } - // don't count unlisted buffers - if (unload || buf->b_p_bl) { + // Don't count unlisted buffers. + // Avoid non-help buffers if the starting point was a non-help buffer and + // vice-versa. + if (unload + || (buf->b_p_bl + && ((flags & DOBUF_SKIPHELP) == 0 || buf->b_help == bp->b_help))) { count--; bp = NULL; // use this buffer as new starting point } @@ -1284,7 +1304,9 @@ int do_buffer(int action, int start, int dir, int count, int forceit) return FAIL; } - if (action == DOBUF_GOTO && buf != curbuf && !check_can_set_curbuf_forceit(forceit)) { + if (action == DOBUF_GOTO + && buf != curbuf + && !check_can_set_curbuf_forceit((flags & DOBUF_FORCEIT) ? true : false)) { // disallow navigating to another buffer when 'winfixbuf' is applied return FAIL; } @@ -1310,7 +1332,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) return FAIL; } - if (!forceit && bufIsChanged(buf)) { + if ((flags & DOBUF_FORCEIT) == 0 && bufIsChanged(buf)) { if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write) { dialog_changed(buf, false); if (!bufref_valid(&bufref)) { @@ -1330,7 +1352,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) } } - if (!forceit && buf->terminal && terminal_running(buf->terminal)) { + if (!(flags & DOBUF_FORCEIT) && buf->terminal && terminal_running(buf->terminal)) { if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) { if (!dialog_close_terminal(buf)) { return FAIL; @@ -1358,7 +1380,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) } } if (bp == NULL && buf == curbuf) { - return empty_curbuf(true, forceit, action); + return empty_curbuf(true, (flags & DOBUF_FORCEIT), action); } // If the deleted buffer is the current one, close the current window @@ -1516,7 +1538,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) if (buf == NULL) { // Autocommands must have wiped out all other buffers. Only option // now is to make the current buffer empty. - return empty_curbuf(false, forceit, action); + return empty_curbuf(false, (flags & DOBUF_FORCEIT), action); } // make "buf" the current buffer @@ -1537,7 +1559,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) } // Check if the current buffer may be abandoned. - if (action == DOBUF_GOTO && !can_abandon(curbuf, forceit)) { + if (action == DOBUF_GOTO && !can_abandon(curbuf, (flags & DOBUF_FORCEIT))) { if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && p_write) { bufref_T bufref; set_bufref(&bufref, buf); @@ -1567,6 +1589,11 @@ int do_buffer(int action, int start, int dir, int count, int forceit) return OK; } +int do_buffer(int action, int start, int dir, int count, int forceit) +{ + return do_buffer_ext(action, start, dir, count, forceit ? DOBUF_FORCEIT : 0); +} + /// Set current buffer to "buf". Executes autocommands and closes current /// buffer. /// diff --git a/src/nvim/buffer.h b/src/nvim/buffer.h index 4c5023d39a..ffef4eefb6 100644 --- a/src/nvim/buffer.h +++ b/src/nvim/buffer.h @@ -39,7 +39,7 @@ enum bln_values { BLN_NOCURWIN = 128, ///< buffer is not associated with curwin }; -/// Values for action argument for do_buffer() +/// Values for action argument for do_buffer_ext() and close_buffer() enum dobuf_action_values { DOBUF_GOTO = 0, ///< go to specified buffer DOBUF_SPLIT = 1, ///< split window and go to specified buffer @@ -48,7 +48,7 @@ enum dobuf_action_values { DOBUF_WIPE = 4, ///< delete specified buffer(s) really }; -/// Values for start argument for do_buffer() +/// Values for start argument for do_buffer_ext() enum dobuf_start_values { DOBUF_CURRENT = 0, ///< "count" buffer from current buffer DOBUF_FIRST = 1, ///< "count" buffer from first buffer @@ -56,6 +56,13 @@ enum dobuf_start_values { DOBUF_MOD = 3, ///< "count" mod. buffer from current buffer }; +/// Values for flags argument of do_buffer_ext() +enum dobuf_flags_value { + DOBUF_FORCEIT = 1, ///< :cmd! + DOBUF_SKIPHELP = 4, ///< skip or keep help buffers depending on b_help of the + ///< starting buffer +}; + /// flags for buf_freeall() enum bfa_values { BFA_DEL = 1, ///< buffer is going to be deleted diff --git a/test/old/testdir/test_buffer.vim b/test/old/testdir/test_buffer.vim index bc8e5eaf7b..69d22de2ce 100644 --- a/test/old/testdir/test_buffer.vim +++ b/test/old/testdir/test_buffer.vim @@ -126,6 +126,52 @@ func Test_buflist_browse() %bwipe! endfunc +" Test for :bnext and :bprev when called from help and non-help buffers. +func Test_bnext_bprev_help() + %bwipe! + + e XHelp1 | set bt=help + let b1 = bufnr() + e Xbuf1 + let b2 = bufnr() + + " There's only one buffer of each type. + b XHelp1 + bnext | call assert_equal(b1, bufnr()) + bprev | call assert_equal(b1, bufnr()) + b Xbuf1 + bnext | call assert_equal(b2, bufnr()) + bprev | call assert_equal(b2, bufnr()) + + " Add one more buffer of each type. + e XHelp2 | set bt=help + let b3 = bufnr() + e Xbuf2 + let b4 = bufnr() + + " Help buffer jumps to help buffer. + b XHelp1 + bnext | call assert_equal(b3, bufnr()) + bnext | call assert_equal(b1, bufnr()) + bprev | call assert_equal(b3, bufnr()) + bprev | call assert_equal(b1, bufnr()) + + " Regular buffer jumps to regular buffer. + b Xbuf1 + bnext | call assert_equal(b4, bufnr()) + bnext | call assert_equal(b2, bufnr()) + bprev | call assert_equal(b4, bufnr()) + bprev | call assert_equal(b2, bufnr()) + + " :brewind and :blast are not affected by the buffer type. + b Xbuf2 + brewind | call assert_equal(b1, bufnr()) + b XHelp1 + blast | call assert_equal(b4, bufnr()) + + %bwipe! +endfunc + " Test for :bdelete func Test_bdelete_cmd() %bwipe! |