To: vim_dev@googlegroups.com Subject: Patch 8.2.1401 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.1401 Problem: Cannot jump to the last used tabpage. Solution: Add g and tabpagnr('#'). (Yegappan Lakshmanan, closes #6661, neovim #11626) Files: runtime/doc/eval.txt, runtime/doc/index.txt, runtime/doc/tabpage.txt, src/evalwindow.c, src/globals.h, src/normal.c, src/proto/window.pro, src/testdir/test_tabpage.vim, src/window.c *** ../vim-8.2.1400/runtime/doc/eval.txt 2020-08-02 16:10:02.355921894 +0200 --- runtime/doc/eval.txt 2020-08-09 13:43:52.244438702 +0200 *************** *** 10314,10321 **** 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 number can be used with the |:tab| command. --- 10357,10369 ---- tabpagenr([{arg}]) *tabpagenr()* The result is a Number, which is the number of the current tab page. The first tab page has number 1. ! ! 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| goes to). if there is no ! previous tab page 0 is returned. The number can be used with the |:tab| command. *************** *** 10913,10928 **** GetWinid()->win_screenpos() < win_splitmove({nr}, {target} [, {options}]) *win_splitmove()* ! Move the window {nr} to a new split of the window {target}. This is similar to moving to {target}, creating a new window using |:split| but having the same contents as window {nr}, and then closing {nr}. Both {nr} and {target} can be window numbers or |window-ID|s. Returns zero for success, non-zero for failure. ! {options} is a Dictionary with the following optional entries: "vertical" When TRUE, the split is created vertically, like with |:vsplit|. "rightbelow" When TRUE, the split is made below or to the --- 10961,10977 ---- GetWinid()->win_screenpos() < win_splitmove({nr}, {target} [, {options}]) *win_splitmove()* ! Move the window {nr} to a new split of the window {target}. This is similar to moving to {target}, creating a new window using |:split| but having the same contents as window {nr}, and then closing {nr}. Both {nr} and {target} can be window numbers or |window-ID|s. + Both must be in the current tab page. Returns zero for success, non-zero for failure. ! {options} is a |Dictionary| with the following optional entries: "vertical" When TRUE, the split is created vertically, like with |:vsplit|. "rightbelow" When TRUE, the split is made below or to the *** ../vim-8.2.1400/runtime/doc/index.txt 2019-12-12 12:49:06.000000000 +0100 --- runtime/doc/index.txt 2020-08-09 13:43:52.244438702 +0200 *************** *** 437,442 **** --- 440,446 ---- || ":ta" to the keyword at the mouse click || 1 same as "w" || same as "CTRL-T" + || same as "g" || ["x] 2 same as "x" |N| {count} remove the last digit from {count} || 1 same as "j" *************** *** 584,589 **** --- 588,595 ---- 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| CTRL-W g same as |g|: 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 *************** *** 802,807 **** --- 808,814 ---- |g| g same as g same as |g| g same as + |g| g go to the last accessed tab page. |g| g 1 same as "gk" ============================================================================== *** ../vim-8.2.1400/runtime/doc/tabpage.txt 2019-12-12 12:49:06.000000000 +0100 --- runtime/doc/tabpage.txt 2020-08-09 13:43:52.244438702 +0200 *************** *** 138,144 **** :+tabclose " close the next tab page :1tabclose " close the first tab page :$tabclose " close the last tab page ! :tabclose -2 " close the two previous tab page :tabclose + " close the next tab page :tabclose 3 " close the third tab page :tabclose $ " close the last tab page --- 138,144 ---- :+tabclose " close the next tab page :1tabclose " close the first tab page :$tabclose " close the last tab page ! :tabclose -2 " close the 2nd previous tab page :tabclose + " close the next tab page :tabclose 3 " close the third tab page :tabclose $ " close the last tab page *************** *** 221,226 **** --- 221,228 ---- *:tabl* *:tablast* :tabl[ast] Go to the last tab page. + *g* *CTRL-W_g* ** + g Go to the last accessed tab page. Other commands: *:tabs* *** ../vim-8.2.1400/src/evalwindow.c 2020-06-17 21:41:31.969819222 +0200 --- src/evalwindow.c 2020-08-09 13:43:52.244438702 +0200 *************** *** 616,621 **** --- 616,624 ---- { 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); } *** ../vim-8.2.1400/src/globals.h 2020-08-01 22:16:39.724599474 +0200 --- src/globals.h 2020-08-09 13:43:52.244438702 +0200 *************** *** 725,734 **** /* * Tab pages are alternative topframes. "first_tabpage" points to the first ! * one in the list, "curtab" is the current one. */ EXTERN tabpage_T *first_tabpage; EXTERN tabpage_T *curtab; EXTERN int redraw_tabline INIT(= FALSE); // need to redraw tabline /* --- 725,736 ---- /* * Tab pages are alternative topframes. "first_tabpage" points to the first ! * 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 /* *** ../vim-8.2.1400/src/normal.c 2020-07-20 23:10:52.989054043 +0200 --- src/normal.c 2020-08-09 14:01:55.305665675 +0200 *************** *** 5442,5448 **** } /* ! * Handle CTRL-O, CTRL-I, "g;" and "g," commands. */ static void nv_pcmark(cmdarg_T *cap) --- 5442,5448 ---- } /* ! * Handle CTRL-O, CTRL-I, "g;", "g," and "CTRL-Tab" commands. */ static void nv_pcmark(cmdarg_T *cap) *************** *** 5456,5461 **** --- 5456,5467 ---- 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,6315 **** --- 6316,6326 ---- 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)) *** ../vim-8.2.1400/src/proto/window.pro 2019-12-12 12:55:37.000000000 +0100 --- src/proto/window.pro 2020-08-09 13:50:54.743357476 +0200 *************** *** 32,37 **** --- 32,38 ---- 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); *** ../vim-8.2.1400/src/testdir/test_tabpage.vim 2020-07-30 20:08:46.840890218 +0200 --- src/testdir/test_tabpage.vim 2020-08-09 13:43:52.248438694 +0200 *************** *** 130,136 **** 1tabmove call assert_equal(2, tabpagenr()) ! call assert_fails('let t = tabpagenr("#")', 'E15:') call assert_equal(0, tabpagewinnr(-1)) call assert_fails("99tabmove", 'E16:') call assert_fails("+99tabmove", 'E16:') --- 130,136 ---- 1tabmove call assert_equal(2, tabpagenr()) ! call assert_fails('let t = tabpagenr("@")', 'E15:') call assert_equal(0, tabpagewinnr(-1)) call assert_fails("99tabmove", 'E16:') call assert_fails("+99tabmove", 'E16:') *************** *** 777,780 **** --- 777,824 ---- %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\", "xt")') + call assert_beeps('call feedkeys("\", "xt")') + call assert_beeps('call feedkeys("\g\", "xt")') + + " open four tab pages + tabnew + tabnew + tabnew + + 2tabnext + + " Test for g + call assert_equal(4, tabpagenr('#')) + call feedkeys("g\", "xt") + call assert_equal(4, tabpagenr()) + call assert_equal(2, tabpagenr('#')) + + " Test for + call feedkeys("\", "xt") + call assert_equal(2, tabpagenr()) + call assert_equal(4, tabpagenr('#')) + + " Test for g + call feedkeys("\g\", "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\", "xt") + call assert_equal(3, tabpagenr()) + call feedkeys("\", "xt") + call assert_equal(3, tabpagenr()) + call feedkeys("\g\", "xt") + call assert_equal(3, tabpagenr()) + + tabclose! + endfunc + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.1400/src/window.c 2020-06-26 20:41:35.632844686 +0200 --- src/window.c 2020-08-09 13:50:51.399366009 +0200 *************** *** 627,632 **** --- 627,637 ---- goto_tabpage(-(int)Prenum1); break; + case TAB: // CTRL-W g: go to last used tab page + if (goto_tabpage_lastused() == FAIL) + beep_flush(); + break; + default: beep_flush(); break; *************** *** 3809,3814 **** --- 3814,3822 ---- 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,3888 **** --- 3891,3898 ---- 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,4123 **** --- 4128,4134 ---- 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,4165 **** --- 4171,4178 ---- 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,4283 **** --- 4291,4311 ---- } /* + * 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. */ *** ../vim-8.2.1400/src/version.c 2020-08-09 13:02:06.486620402 +0200 --- src/version.c 2020-08-09 13:48:13.535770075 +0200 *************** *** 756,757 **** --- 756,759 ---- { /* Add new patch number below this line */ + /**/ + 1401, /**/ -- hundred-and-one symptoms of being an internet addict: 161. You get up before the sun rises to check your e-mail, and you find yourself in the very same chair long after the sun has set. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///