Skip to content

Commit 62a2325

Browse files
committed
patch 8.2.1401: cannot jump to the last used tabpage
Problem: Cannot jump to the last used tabpage. Solution: Add g<Tab> and tabpagnr('#'). (Yegappan Lakshmanan, closes #6661, neovim #11626)
1 parent 730b248 commit 62a2325

10 files changed

Lines changed: 107 additions & 5 deletions

File tree

runtime/doc/eval.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10357,8 +10357,13 @@ tabpagebuflist([{arg}]) *tabpagebuflist()*
1035710357
tabpagenr([{arg}]) *tabpagenr()*
1035810358
The result is a Number, which is the number of the current
1035910359
tab page. The first tab page has number 1.
10360-
When the optional argument is "$", the number of the last tab
10361-
page is returned (the tab page count).
10360+
10361+
The optional argument {arg} supports the following values:
10362+
$ the number of the last tab page (the tab page
10363+
count).
10364+
# the number of the last accessed tab page
10365+
(where |g<Tab>| goes to). if there is no
10366+
previous tab page 0 is returned.
1036210367
The number can be used with the |:tab| command.
1036310368

1036410369

runtime/doc/index.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ tag char note action in Normal mode ~
440440
|<C-LeftMouse>| <C-LeftMouse> ":ta" to the keyword at the mouse click
441441
|<C-Right>| <C-Right> 1 same as "w"
442442
|<C-RightMouse>| <C-RightMouse> same as "CTRL-T"
443+
|<C-Tab>| <C-Tab> same as "g<Tab>"
443444
|<Del>| ["x]<Del> 2 same as "x"
444445
|N<Del>| {count}<Del> remove the last digit from {count}
445446
|<Down>| <Down> 1 same as "j"
@@ -587,6 +588,8 @@ tag command action in Normal mode ~
587588
following the file name.
588589
|CTRL-W_gt| CTRL-W g t same as `gt`: go to next tab page
589590
|CTRL-W_gT| CTRL-W g T same as `gT`: go to previous tab page
591+
|CTRL-W_g<Tab>| CTRL-W g <Tab> same as |g<Tab>|: go to last accessed tab
592+
page.
590593
|CTRL-W_h| CTRL-W h go to Nth left window (stop at first window)
591594
|CTRL-W_i| CTRL-W i split window and jump to declaration of
592595
identifier under the cursor
@@ -805,6 +808,7 @@ tag char note action in Normal mode ~
805808
|g<LeftMouse>| g<LeftMouse> same as <C-LeftMouse>
806809
g<MiddleMouse> same as <C-MiddleMouse>
807810
|g<RightMouse>| g<RightMouse> same as <C-RightMouse>
811+
|g<Tab>| g<Tab> go to the last accessed tab page.
808812
|g<Up>| g<Up> 1 same as "gk"
809813

810814
==============================================================================

runtime/doc/tabpage.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ gT Go to the previous tab page. Wraps around from the first one
221221
*:tabl* *:tablast*
222222
:tabl[ast] Go to the last tab page.
223223

224+
*g<Tab>* *CTRL-W_g<Tab>* *<C-Tab>*
225+
g<Tab> Go to the last accessed tab page.
224226

225227
Other commands:
226228
*:tabs*

src/evalwindow.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,9 @@ f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv)
616616
{
617617
if (STRCMP(arg, "$") == 0)
618618
nr = tabpage_index(NULL) - 1;
619+
else if (STRCMP(arg, "#") == 0)
620+
nr = valid_tabpage(lastused_tabpage) ?
621+
tabpage_index(lastused_tabpage) : 0;
619622
else
620623
semsg(_(e_invexpr2), arg);
621624
}

src/globals.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,10 +725,12 @@ EXTERN frame_T *topframe; // top of the window frame tree
725725

726726
/*
727727
* Tab pages are alternative topframes. "first_tabpage" points to the first
728-
* one in the list, "curtab" is the current one.
728+
* one in the list, "curtab" is the current one. "lastused_tabpage" is the
729+
* last used one.
729730
*/
730731
EXTERN tabpage_T *first_tabpage;
731732
EXTERN tabpage_T *curtab;
733+
EXTERN tabpage_T *lastused_tabpage;
732734
EXTERN int redraw_tabline INIT(= FALSE); // need to redraw tabline
733735

734736
/*

src/normal.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5442,7 +5442,7 @@ nv_gomark(cmdarg_T *cap)
54425442
}
54435443

54445444
/*
5445-
* Handle CTRL-O, CTRL-I, "g;" and "g," commands.
5445+
* Handle CTRL-O, CTRL-I, "g;", "g," and "CTRL-Tab" commands.
54465446
*/
54475447
static void
54485448
nv_pcmark(cmdarg_T *cap)
@@ -5456,6 +5456,12 @@ nv_pcmark(cmdarg_T *cap)
54565456

54575457
if (!checkclearopq(cap->oap))
54585458
{
5459+
if (cap->cmdchar == TAB && mod_mask == MOD_MASK_CTRL)
5460+
{
5461+
if (goto_tabpage_lastused() == FAIL)
5462+
clearopbeep(cap->oap);
5463+
return;
5464+
}
54595465
if (cap->cmdchar == 'g')
54605466
pos = movechangelist((int)cap->count1);
54615467
else
@@ -6310,6 +6316,11 @@ nv_g_cmd(cmdarg_T *cap)
63106316
goto_tabpage(-(int)cap->count1);
63116317
break;
63126318

6319+
case TAB:
6320+
if (!checkclearop(oap) && goto_tabpage_lastused() == FAIL)
6321+
clearopbeep(oap);
6322+
break;
6323+
63136324
case '+':
63146325
case '-': // "g+" and "g-": undo or redo along the timeline
63156326
if (!checkclearopq(oap))

src/proto/window.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ tabpage_T *find_tabpage(int n);
3232
int tabpage_index(tabpage_T *ftp);
3333
void goto_tabpage(int n);
3434
void goto_tabpage_tp(tabpage_T *tp, int trigger_enter_autocmds, int trigger_leave_autocmds);
35+
int goto_tabpage_lastused(void);
3536
void goto_tabpage_win(tabpage_T *tp, win_T *wp);
3637
void tabpage_move(int nr);
3738
void win_goto(win_T *wp);

src/testdir/test_tabpage.vim

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ function Test_tabpage()
130130
1tabmove
131131
call assert_equal(2, tabpagenr())
132132

133-
call assert_fails('let t = tabpagenr("#")', 'E15:')
133+
call assert_fails('let t = tabpagenr("@")', 'E15:')
134134
call assert_equal(0, tabpagewinnr(-1))
135135
call assert_fails("99tabmove", 'E16:')
136136
call assert_fails("+99tabmove", 'E16:')
@@ -777,4 +777,48 @@ func Test_tabpage_close_on_switch()
777777
%bw!
778778
endfunc
779779

780+
" Test for jumping to last accessed tabpage
781+
func Test_lastused_tabpage()
782+
tabonly!
783+
call assert_equal(0, tabpagenr('#'))
784+
call assert_beeps('call feedkeys("g\<Tab>", "xt")')
785+
call assert_beeps('call feedkeys("\<C-Tab>", "xt")')
786+
call assert_beeps('call feedkeys("\<C-W>g\<Tab>", "xt")')
787+
788+
" open four tab pages
789+
tabnew
790+
tabnew
791+
tabnew
792+
793+
2tabnext
794+
795+
" Test for g<Tab>
796+
call assert_equal(4, tabpagenr('#'))
797+
call feedkeys("g\<Tab>", "xt")
798+
call assert_equal(4, tabpagenr())
799+
call assert_equal(2, tabpagenr('#'))
800+
801+
" Test for <C-Tab>
802+
call feedkeys("\<C-Tab>", "xt")
803+
call assert_equal(2, tabpagenr())
804+
call assert_equal(4, tabpagenr('#'))
805+
806+
" Test for <C-W>g<Tab>
807+
call feedkeys("\<C-W>g\<Tab>", "xt")
808+
call assert_equal(4, tabpagenr())
809+
call assert_equal(2, tabpagenr('#'))
810+
811+
" Try to jump to a closed tab page
812+
tabclose 2
813+
call assert_equal(0, tabpagenr('#'))
814+
call feedkeys("g\<Tab>", "xt")
815+
call assert_equal(3, tabpagenr())
816+
call feedkeys("\<C-Tab>", "xt")
817+
call assert_equal(3, tabpagenr())
818+
call feedkeys("\<C-W>g\<Tab>", "xt")
819+
call assert_equal(3, tabpagenr())
820+
821+
tabclose!
822+
endfunc
823+
780824
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,8 @@ static char *(features[]) =
754754

755755
static int included_patches[] =
756756
{ /* Add new patch number below this line */
757+
/**/
758+
1401,
757759
/**/
758760
1400,
759761
/**/

src/window.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,11 @@ do_window(
627627
goto_tabpage(-(int)Prenum1);
628628
break;
629629

630+
case TAB: // CTRL-W g<Tab>: go to last used tab page
631+
if (goto_tabpage_lastused() == FAIL)
632+
beep_flush();
633+
break;
634+
630635
default:
631636
beep_flush();
632637
break;
@@ -3809,6 +3814,9 @@ free_tabpage(tabpage_T *tp)
38093814
unref_var_dict(tp->tp_vars);
38103815
#endif
38113816

3817+
if (tp == lastused_tabpage)
3818+
lastused_tabpage = NULL;
3819+
38123820
vim_free(tp->tp_localdir);
38133821
vim_free(tp->tp_prevdir);
38143822

@@ -3883,6 +3891,8 @@ win_new_tabpage(int after)
38833891
newtp->tp_topframe = topframe;
38843892
last_status(FALSE);
38853893

3894+
lastused_tabpage = tp;
3895+
38863896
#if defined(FEAT_GUI)
38873897
// When 'guioptions' includes 'L' or 'R' may have to remove or add
38883898
// scrollbars. Have to update them anyway.
@@ -4118,6 +4128,7 @@ enter_tabpage(
41184128
int row;
41194129
int old_off = tp->tp_firstwin->w_winrow;
41204130
win_T *next_prevwin = tp->tp_prevwin;
4131+
tabpage_T *last_tab = curtab;
41214132

41224133
curtab = tp;
41234134
firstwin = tp->tp_firstwin;
@@ -4160,6 +4171,8 @@ enter_tabpage(
41604171
if (curtab->tp_old_Columns != Columns && starting == 0)
41614172
shell_new_columns(); // update window widths
41624173

4174+
lastused_tabpage = last_tab;
4175+
41634176
#if defined(FEAT_GUI)
41644177
// When 'guioptions' includes 'L' or 'R' may have to remove or add
41654178
// scrollbars. Have to update them anyway.
@@ -4277,6 +4290,21 @@ goto_tabpage_tp(
42774290
}
42784291
}
42794292

4293+
/*
4294+
* Go to the last accessed tab page, if there is one.
4295+
* Return OK or FAIL
4296+
*/
4297+
int
4298+
goto_tabpage_lastused(void)
4299+
{
4300+
if (valid_tabpage(lastused_tabpage))
4301+
{
4302+
goto_tabpage_tp(lastused_tabpage, TRUE, TRUE);
4303+
return OK;
4304+
}
4305+
return FAIL;
4306+
}
4307+
42804308
/*
42814309
* Enter window "wp" in tab page "tp".
42824310
* Also updates the GUI tab.

0 commit comments

Comments
 (0)