diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-08-09 14:04:42 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-08-09 14:04:42 +0200 |
commit | 62a232506d06f6d1b3b7271801c907d6294dfe84 (patch) | |
tree | d95d049e9676ef5b8a63ca9096401ca52dc8b90d | |
parent | 730b24833952f0f4a9a17b7815b0d9f87c609eb8 (diff) |
patch 8.2.1401: cannot jump to the last used tabpagev8.2.1401
Problem: Cannot jump to the last used tabpage.
Solution: Add g<Tab> and tabpagnr('#'). (Yegappan Lakshmanan, closes #6661,
neovim #11626)
-rw-r--r-- | runtime/doc/eval.txt | 9 | ||||
-rw-r--r-- | runtime/doc/index.txt | 4 | ||||
-rw-r--r-- | runtime/doc/tabpage.txt | 2 | ||||
-rw-r--r-- | src/evalwindow.c | 3 | ||||
-rw-r--r-- | src/globals.h | 4 | ||||
-rw-r--r-- | src/normal.c | 13 | ||||
-rw-r--r-- | src/proto/window.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_tabpage.vim | 46 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/window.c | 28 |
10 files changed, 107 insertions, 5 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 5bb763a4a4..c579ed2faa 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -10357,8 +10357,13 @@ tabpagebuflist([{arg}]) *tabpagebuflist()* tabpagenr([{arg}]) *tabpagenr()* The result is a Number, which is the number of the current tab page. The first tab page has number 1. - When the optional argument is "$", the number of the last tab - page is returned (the tab page count). + + The optional argument {arg} supports the following values: + $ the number of the last tab page (the tab page + count). + # the number of the last accessed tab page + (where |g<Tab>| goes to). if there is no + previous tab page 0 is returned. The number can be used with the |:tab| command. diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index 83c6c176c8..ed6916f62e 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -440,6 +440,7 @@ tag char note action in Normal mode ~ |<C-LeftMouse>| <C-LeftMouse> ":ta" to the keyword at the mouse click |<C-Right>| <C-Right> 1 same as "w" |<C-RightMouse>| <C-RightMouse> same as "CTRL-T" +|<C-Tab>| <C-Tab> same as "g<Tab>" |<Del>| ["x]<Del> 2 same as "x" |N<Del>| {count}<Del> remove the last digit from {count} |<Down>| <Down> 1 same as "j" @@ -587,6 +588,8 @@ tag command action in Normal mode ~ following the file name. |CTRL-W_gt| CTRL-W g t same as `gt`: go to next tab page |CTRL-W_gT| CTRL-W g T same as `gT`: go to previous tab page +|CTRL-W_g<Tab>| CTRL-W g <Tab> same as |g<Tab>|: go to last accessed tab + page. |CTRL-W_h| CTRL-W h go to Nth left window (stop at first window) |CTRL-W_i| CTRL-W i split window and jump to declaration of identifier under the cursor @@ -805,6 +808,7 @@ tag char note action in Normal mode ~ |g<LeftMouse>| g<LeftMouse> same as <C-LeftMouse> g<MiddleMouse> same as <C-MiddleMouse> |g<RightMouse>| g<RightMouse> same as <C-RightMouse> +|g<Tab>| g<Tab> go to the last accessed tab page. |g<Up>| g<Up> 1 same as "gk" ============================================================================== diff --git a/runtime/doc/tabpage.txt b/runtime/doc/tabpage.txt index 75070b5fe7..1d8c2082f2 100644 --- a/runtime/doc/tabpage.txt +++ b/runtime/doc/tabpage.txt @@ -221,6 +221,8 @@ gT Go to the previous tab page. Wraps around from the first one *:tabl* *:tablast* :tabl[ast] Go to the last tab page. + *g<Tab>* *CTRL-W_g<Tab>* *<C-Tab>* +g<Tab> Go to the last accessed tab page. Other commands: *:tabs* diff --git a/src/evalwindow.c b/src/evalwindow.c index 0b3052c241..b50776d74d 100644 --- a/src/evalwindow.c +++ b/src/evalwindow.c @@ -616,6 +616,9 @@ f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv) { if (STRCMP(arg, "$") == 0) nr = tabpage_index(NULL) - 1; + else if (STRCMP(arg, "#") == 0) + nr = valid_tabpage(lastused_tabpage) ? + tabpage_index(lastused_tabpage) : 0; else semsg(_(e_invexpr2), arg); } diff --git a/src/globals.h b/src/globals.h index cc01ac2508..72b8a1e460 100644 --- a/src/globals.h +++ b/src/globals.h @@ -725,10 +725,12 @@ EXTERN frame_T *topframe; // top of the window frame tree /* * Tab pages are alternative topframes. "first_tabpage" points to the first - * one in the list, "curtab" is the current one. + * one in the list, "curtab" is the current one. "lastused_tabpage" is the + * last used one. */ EXTERN tabpage_T *first_tabpage; EXTERN tabpage_T *curtab; +EXTERN tabpage_T *lastused_tabpage; EXTERN int redraw_tabline INIT(= FALSE); // need to redraw tabline /* diff --git a/src/normal.c b/src/normal.c index dd79a43aac..cb8e736368 100644 --- a/src/normal.c +++ b/src/normal.c @@ -5442,7 +5442,7 @@ nv_gomark(cmdarg_T *cap) } /* - * Handle CTRL-O, CTRL-I, "g;" and "g," commands. + * Handle CTRL-O, CTRL-I, "g;", "g," and "CTRL-Tab" commands. */ static void nv_pcmark(cmdarg_T *cap) @@ -5456,6 +5456,12 @@ nv_pcmark(cmdarg_T *cap) if (!checkclearopq(cap->oap)) { + if (cap->cmdchar == TAB && mod_mask == MOD_MASK_CTRL) + { + if (goto_tabpage_lastused() == FAIL) + clearopbeep(cap->oap); + return; + } if (cap->cmdchar == 'g') pos = movechangelist((int)cap->count1); else @@ -6310,6 +6316,11 @@ nv_g_cmd(cmdarg_T *cap) goto_tabpage(-(int)cap->count1); break; + case TAB: + if (!checkclearop(oap) && goto_tabpage_lastused() == FAIL) + clearopbeep(oap); + break; + case '+': case '-': // "g+" and "g-": undo or redo along the timeline if (!checkclearopq(oap)) diff --git a/src/proto/window.pro b/src/proto/window.pro index ab62c0a096..4c9bddd281 100644 --- a/src/proto/window.pro +++ b/src/proto/window.pro @@ -32,6 +32,7 @@ tabpage_T *find_tabpage(int n); int tabpage_index(tabpage_T *ftp); void goto_tabpage(int n); void goto_tabpage_tp(tabpage_T *tp, int trigger_enter_autocmds, int trigger_leave_autocmds); +int goto_tabpage_lastused(void); void goto_tabpage_win(tabpage_T *tp, win_T *wp); void tabpage_move(int nr); void win_goto(win_T *wp); diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim index bbcafa8eb6..67469718f2 100644 --- a/src/testdir/test_tabpage.vim +++ b/src/testdir/test_tabpage.vim @@ -130,7 +130,7 @@ function Test_tabpage() 1tabmove call assert_equal(2, tabpagenr()) - call assert_fails('let t = tabpagenr("#")', 'E15:') + call assert_fails('let t = tabpagenr("@")', 'E15:') call assert_equal(0, tabpagewinnr(-1)) call assert_fails("99tabmove", 'E16:') call assert_fails("+99tabmove", 'E16:') @@ -777,4 +777,48 @@ func Test_tabpage_close_on_switch() %bw! endfunc +" Test for jumping to last accessed tabpage +func Test_lastused_tabpage() + tabonly! + call assert_equal(0, tabpagenr('#')) + call assert_beeps('call feedkeys("g\<Tab>", "xt")') + call assert_beeps('call feedkeys("\<C-Tab>", "xt")') + call assert_beeps('call feedkeys("\<C-W>g\<Tab>", "xt")') + + " open four tab pages + tabnew + tabnew + tabnew + + 2tabnext + + " Test for g<Tab> + call assert_equal(4, tabpagenr('#')) + call feedkeys("g\<Tab>", "xt") + call assert_equal(4, tabpagenr()) + call assert_equal(2, tabpagenr('#')) + + " Test for <C-Tab> + call feedkeys("\<C-Tab>", "xt") + call assert_equal(2, tabpagenr()) + call assert_equal(4, tabpagenr('#')) + + " Test for <C-W>g<Tab> + call feedkeys("\<C-W>g\<Tab>", "xt") + call assert_equal(4, tabpagenr()) + call assert_equal(2, tabpagenr('#')) + + " Try to jump to a closed tab page + tabclose 2 + call assert_equal(0, tabpagenr('#')) + call feedkeys("g\<Tab>", "xt") + call assert_equal(3, tabpagenr()) + call feedkeys("\<C-Tab>", "xt") + call assert_equal(3, tabpagenr()) + call feedkeys("\<C-W>g\<Tab>", "xt") + call assert_equal(3, tabpagenr()) + + tabclose! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 20e8b36b81..15f4c061d2 100644 --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1401, +/**/ 1400, /**/ 1399, diff --git a/src/window.c b/src/window.c index 4b2ff4b523..7d8122efdd 100644 --- a/src/window.c +++ b/src/window.c @@ -627,6 +627,11 @@ wingotofile: goto_tabpage(-(int)Prenum1); break; + case TAB: // CTRL-W g<Tab>: go to last used tab page + if (goto_tabpage_lastused() == FAIL) + beep_flush(); + break; + default: beep_flush(); break; @@ -3809,6 +3814,9 @@ free_tabpage(tabpage_T *tp) unref_var_dict(tp->tp_vars); #endif + if (tp == lastused_tabpage) + lastused_tabpage = NULL; + vim_free(tp->tp_localdir); vim_free(tp->tp_prevdir); @@ -3883,6 +3891,8 @@ win_new_tabpage(int after) newtp->tp_topframe = topframe; last_status(FALSE); + lastused_tabpage = tp; + #if defined(FEAT_GUI) // When 'guioptions' includes 'L' or 'R' may have to remove or add // scrollbars. Have to update them anyway. @@ -4118,6 +4128,7 @@ enter_tabpage( int row; int old_off = tp->tp_firstwin->w_winrow; win_T *next_prevwin = tp->tp_prevwin; + tabpage_T *last_tab = curtab; curtab = tp; firstwin = tp->tp_firstwin; @@ -4160,6 +4171,8 @@ enter_tabpage( if (curtab->tp_old_Columns != Columns && starting == 0) shell_new_columns(); // update window widths + lastused_tabpage = last_tab; + #if defined(FEAT_GUI) // When 'guioptions' includes 'L' or 'R' may have to remove or add // scrollbars. Have to update them anyway. @@ -4278,6 +4291,21 @@ goto_tabpage_tp( } /* + * Go to the last accessed tab page, if there is one. + * Return OK or FAIL + */ + int +goto_tabpage_lastused(void) +{ + if (valid_tabpage(lastused_tabpage)) + { + goto_tabpage_tp(lastused_tabpage, TRUE, TRUE); + return OK; + } + return FAIL; +} + +/* * Enter window "wp" in tab page "tp". * Also updates the GUI tab. */ |