Bram et al., I noticed this week that Ctrl-^ and Ctrl-W-Ctrl-^ are not consistent in their behavior when the alternate file is not named. The former works as expected, and the latter fails. This was a tad annoying.
Example: vim --clean :e Xfoo :enew <C-^><C-^><C-^> " works fine <C-W><C-^> " fails to split window on other buffer With this patch, <C-W><C-^> will work just like <C-^> but it will split a window first (with some sanity/error checking before it does so). I also included MANY test cases. Before these patches, these commands weren't tested very well at all. Best, Jason Franklin -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
>From 999a274db45d754979ed0fdaf3a747beafdcbf6f Mon Sep 17 00:00:00 2001 From: Jason Franklin <[email protected]> Date: Fri, 9 Nov 2018 13:56:07 -0500 Subject: [PATCH 1/7] Improve the test for the "<C-^>" command The test that was in use did not use 'tx' in the "feedkeys()" function calls. This meant that the functionality of interest wasn't being tested. I also added a couple of cases that weren't examined previously. --- src/testdir/test_normal.vim | 42 ++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index a06426e8e..de6c25808 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -1260,20 +1260,34 @@ func! Test_normal20_exmode() endfunc func! Test_normal21_nv_hat() - set hidden - new - " to many buffers opened already, will not work - "call assert_fails(":b#", 'E23') - "call assert_equal('', @#) - e Xfoobar - e Xfile2 - call feedkeys("\<c-^>", 't') - call assert_equal("Xfile2", fnamemodify(bufname('%'), ':t')) - call feedkeys("f\<c-^>", 't') - call assert_equal("Xfile2", fnamemodify(bufname('%'), ':t')) - " clean up - set nohidden - bw! + + " Edit a fresh file and wipe the buffer list so that there is no alternate + " file present. Next, check for the expected command failures. + edit Xfoo | %bw + call assert_fails(':buffer #', 'E86') + call assert_fails(':execute "normal! \<C-^>"', 'E23') + + " Test for the expected behavior when switching between two named buffers. + edit Xfoo | edit Xbar + call feedkeys("\<C-^>", 'tx') + call assert_equal('Xfoo', fnamemodify(bufname('%'), ':t')) + call feedkeys("\<C-^>", 'tx') + call assert_equal('Xbar', fnamemodify(bufname('%'), ':t')) + + " Test for the expected behavior when only one buffer is named. + enew | let l:nr = bufnr('%') + call feedkeys("\<C-^>", 'tx') + call assert_equal('Xbar', fnamemodify(bufname('%'), ':t')) + call feedkeys("\<C-^>", 'tx') + call assert_equal('', bufname('%')) + call assert_equal(l:nr, bufnr('%')) + + " Test that no action is taken by "<C-^>" when an operator is pending. + edit Xfoo + call feedkeys("ci\<C-^>", 'tx') + call assert_equal('Xfoo', fnamemodify(bufname('%'), ':t')) + + %bw! endfunc func! Test_normal22_zet() -- 2.17.1 >From 1f40cc9f17226b7dfec7d9512235f306f60fc178 Mon Sep 17 00:00:00 2001 From: Jason Franklin <[email protected]> Date: Fri, 9 Nov 2018 14:48:54 -0500 Subject: [PATCH 2/7] Add a failing test for ":wincmd ^" The test for ":wincmd ^" now fails for the case where the alternate buffer is not named. This is the case that will be addressed in the next commit. --- src/testdir/test_window_cmd.vim | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index 423d6f8d2..c1e3d0a1b 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -104,14 +104,26 @@ func Test_window_vertical_split() endfunc func Test_window_split_edit_alternate() - e Xa - e Xb + " Test for failure when the alternate buffer/file no longer exists. + edit Xfoo | %bw + call assert_fails(':wincmd ^', 'E23') + + " Test for the expected behavior when we have two named buffers. + edit Xfoo | edit Xbar wincmd ^ - call assert_equal('Xa', bufname(winbufnr(1))) - call assert_equal('Xb', bufname(winbufnr(2))) + call assert_equal('Xfoo', bufname(winbufnr(1))) + call assert_equal('Xbar', bufname(winbufnr(2))) + only - bw Xa Xb + " Test for the expected behavior when the alternate buffer is not named. + enew | let l:nr1 = bufnr('%') + edit Xfoo | let l:nr2 = bufnr('%') + wincmd ^ + call assert_equal(l:nr1, winbufnr(1)) + call assert_equal(l:nr2, winbufnr(2)) + + %bw! endfunc func Test_window_preview() @@ -322,7 +334,7 @@ func Test_equalalways_on_close() set equalalways vsplit windo split - split + split wincmd J " now we have a frame top-left with two windows, a frame top-right with two " windows and a frame at the bottom, full-width. -- 2.17.1 >From 874815d2de6445700130ae7dd58944122b64810d Mon Sep 17 00:00:00 2001 From: Jason Franklin <[email protected]> Date: Fri, 9 Nov 2018 15:04:07 -0500 Subject: [PATCH 3/7] Allow ":wincmd ^" to work with a [No Name] buffer --- src/normal.c | 3 ++- src/window.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/normal.c b/src/normal.c index 4c157004a..a0683b207 100644 --- a/src/normal.c +++ b/src/normal.c @@ -5496,7 +5496,8 @@ nv_ctrlo(cmdarg_T *cap) } /* - * CTRL-^ command, short for ":e #" + * CTRL-^ command, short for ":e #". Works even when the alternate buffer is + * not named. */ static void nv_hat(cmdarg_T *cap) diff --git a/src/window.c b/src/window.c index e16570f4e..be942884d 100644 --- a/src/window.c +++ b/src/window.c @@ -151,8 +151,16 @@ do_window( case '^': CHECK_CMDWIN; reset_VIsual_and_resel(); /* stop Visual mode */ - cmd_with_count("split #", cbuf, sizeof(cbuf), Prenum); - do_cmdline_cmd(cbuf); + + if (buflist_findnr(curwin->w_alt_fnum) == NULL) + { + EMSG(_(e_noalt)); + break; + } + + if (!curbuf_locked() && win_split(0, 0) == OK) + (void) buflist_getfile(curwin->w_alt_fnum, (linenr_T) 0, GETF_ALT, FALSE); + break; /* open new window */ -- 2.17.1 >From 2fb244b47d2ffef3647512bc80ad97e5703a90e4 Mon Sep 17 00:00:00 2001 From: Jason Franklin <[email protected]> Date: Sat, 10 Nov 2018 06:55:24 -0500 Subject: [PATCH 4/7] Add a test for the [count]<C-^> command --- src/testdir/test_normal.vim | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index de6c25808..e5b06a94c 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -2461,7 +2461,7 @@ func! Test_normal53_digraph() bw! endfunc -func Test_normal54_Ctrl_bsl() +func! Test_normal54_Ctrl_bsl() new call setline(1, 'abcdefghijklmn') exe "norm! df\<c-\>\<c-n>" @@ -2485,7 +2485,7 @@ func Test_normal54_Ctrl_bsl() bw! endfunc -func Test_normal_large_count() +func! Test_normal_large_count() " This may fail with 32bit long, how do we detect that? new normal o @@ -2493,7 +2493,7 @@ func Test_normal_large_count() bwipe! endfunc -func Test_delete_until_paragraph() +func! Test_delete_until_paragraph() if !has('multi_byte') return endif @@ -2507,7 +2507,7 @@ endfunc " Test for the gr (virtual replace) command " Test for the bug fixed by 7.4.387 -func Test_gr_command() +func! Test_gr_command() enew! let save_cpo = &cpo call append(0, ['First line', 'Second line', 'Third line']) @@ -2527,7 +2527,7 @@ endfunc " When splitting a window the changelist position is wrong. " Test the changelist position after splitting a window. " Test for the bug fixed by 7.4.386 -func Test_changelist() +func! Test_changelist() let save_ul = &ul enew! call append('$', ['1', '2']) @@ -2546,3 +2546,27 @@ func Test_changelist() %bwipe! let &ul = save_ul endfunc + +func! Test_nv_hat_count() + + %bwipeout! + let l:nr = bufnr('%') + 1 + call assert_fails(':execute "normal! ' . l:nr . '\<C-^>"', 'E92') + + edit Xfoo + let l:foo_nr = bufnr('Xfoo') + + edit Xbar + let l:bar_nr = bufnr('Xbar') + + " Make sure we are not just using the alternate file. + edit Xbaz + + call feedkeys(l:foo_nr . "\<C-^>", 'tx') + call assert_equal('Xfoo', fnamemodify(bufname('%'), ':t')) + + call feedkeys(l:bar_nr . "\<C-^>", 'tx') + call assert_equal('Xbar', fnamemodify(bufname('%'), ':t')) + + %bwipeout! +endfunc -- 2.17.1 >From 39e24747628bcd33be4b676839323dfd14ee2d2e Mon Sep 17 00:00:00 2001 From: Jason Franklin <[email protected]> Date: Sat, 10 Nov 2018 07:37:06 -0500 Subject: [PATCH 5/7] Add tests for :[count]wincmd ^ and [count]<C-W>^ --- src/testdir/test_window_cmd.vim | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index c1e3d0a1b..a60986810 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -103,6 +103,7 @@ func Test_window_vertical_split() bw endfunc +" Test the ":wincmd ^" and "<C-W>^" commands. func Test_window_split_edit_alternate() " Test for failure when the alternate buffer/file no longer exists. @@ -122,6 +123,43 @@ func Test_window_split_edit_alternate() wincmd ^ call assert_equal(l:nr1, winbufnr(1)) call assert_equal(l:nr2, winbufnr(2)) + only + + " Test the Normal mode command. + call feedkeys("\<C-W>\<C-^>", 'tx') + call assert_equal(l:nr2, winbufnr(1)) + call assert_equal(l:nr1, winbufnr(2)) + + %bw! +endfunc + +" Test the ":[count]wincmd ^" and "[count]<C-W>^" commands. +func Test_window_split_edit_bufnr() + + %bwipeout + let l:nr = bufnr('%') + 1 + call assert_fails(':execute "normal! ' . l:nr . '\<C-W>\<C-^>"', 'E92') + call assert_fails(':' . l:nr . 'wincmd ^', 'E16') + call assert_fails(':0wincmd ^', 'E16') + + edit Xfoo | edit Xbar | edit Xbaz + let l:foo_nr = bufnr('Xfoo') + let l:bar_nr = bufnr('Xbar') + let l:baz_nr = bufnr('Xbaz') + + call feedkeys(l:foo_nr . "\<C-W>\<C-^>", 'tx') + call assert_equal('Xfoo', bufname(winbufnr(1))) + call assert_equal('Xbaz', bufname(winbufnr(2))) + only + + call feedkeys(l:bar_nr . "\<C-W>\<C-^>", 'tx') + call assert_equal('Xbar', bufname(winbufnr(1))) + call assert_equal('Xfoo', bufname(winbufnr(2))) + only + + execute l:baz_nr . 'wincmd ^' + call assert_equal('Xbaz', bufname(winbufnr(1))) + call assert_equal('Xbar', bufname(winbufnr(2))) %bw! endfunc -- 2.17.1 >From d6103602a13561264cdfa679e0a29cd4212e908a Mon Sep 17 00:00:00 2001 From: Jason Franklin <[email protected]> Date: Sat, 10 Nov 2018 07:42:30 -0500 Subject: [PATCH 6/7] Restore the functionality of [count]<C-W>^ --- src/window.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/window.c b/src/window.c index be942884d..3f854dff4 100644 --- a/src/window.c +++ b/src/window.c @@ -152,14 +152,18 @@ do_window( CHECK_CMDWIN; reset_VIsual_and_resel(); /* stop Visual mode */ - if (buflist_findnr(curwin->w_alt_fnum) == NULL) + if (buflist_findnr(Prenum == 0 ? curwin->w_alt_fnum : Prenum) == NULL) { - EMSG(_(e_noalt)); + if (Prenum == 0) + EMSG(_(e_noalt)); + if (Prenum != 0) + EMSGN(_("E92: Buffer %ld not found"), Prenum); break; } if (!curbuf_locked() && win_split(0, 0) == OK) - (void) buflist_getfile(curwin->w_alt_fnum, (linenr_T) 0, GETF_ALT, FALSE); + (void) buflist_getfile(Prenum == 0 ? curwin->w_alt_fnum : Prenum, + (linenr_T) 0, GETF_ALT, FALSE); break; -- 2.17.1 >From a876b24407500a93c4751fff0c15a6b852e974e9 Mon Sep 17 00:00:00 2001 From: Jason Franklin <[email protected]> Date: Sat, 10 Nov 2018 07:53:23 -0500 Subject: [PATCH 7/7] Update the documentation --- runtime/doc/windows.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt index 824efe709..90a178900 100644 --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -222,9 +222,11 @@ CTRL-W CTRL_N *CTRL-W_CTRL-N* |:find|. Doesn't split if {file} is not found. CTRL-W CTRL-^ *CTRL-W_CTRL-^* *CTRL-W_^* -CTRL-W ^ Does ":split #", split window in two and edit alternate file. - When a count is given, it becomes ":split #N", split window - and edit buffer N. +CTRL-W ^ Split the current window in two and edit the alternate file. + When a count N is given, split the current window and edit + buffer N. Similar to ":sp #" and ":sp #N", but it allows the + other buffer to be unnamed. This command matches the behavior + of |CTRL-^|, except that it splits a window first. *CTRL-W_:* CTRL-W : Does the same as typing |:| - enter a command line. Useful in a -- 2.17.1
