mirror of
https://github.com/vim/vim.git
synced 2025-09-29 04:34:16 -04:00
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)
This commit is contained in:
@@ -10357,8 +10357,13 @@ tabpagebuflist([{arg}]) *tabpagebuflist()*
|
|||||||
tabpagenr([{arg}]) *tabpagenr()*
|
tabpagenr([{arg}]) *tabpagenr()*
|
||||||
The result is a Number, which is the number of the current
|
The result is a Number, which is the number of the current
|
||||||
tab page. The first tab page has number 1.
|
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.
|
The number can be used with the |:tab| command.
|
||||||
|
|
||||||
|
|
||||||
|
@@ -440,6 +440,7 @@ tag char note action in Normal mode ~
|
|||||||
|<C-LeftMouse>| <C-LeftMouse> ":ta" to the keyword at the mouse click
|
|<C-LeftMouse>| <C-LeftMouse> ":ta" to the keyword at the mouse click
|
||||||
|<C-Right>| <C-Right> 1 same as "w"
|
|<C-Right>| <C-Right> 1 same as "w"
|
||||||
|<C-RightMouse>| <C-RightMouse> same as "CTRL-T"
|
|<C-RightMouse>| <C-RightMouse> same as "CTRL-T"
|
||||||
|
|<C-Tab>| <C-Tab> same as "g<Tab>"
|
||||||
|<Del>| ["x]<Del> 2 same as "x"
|
|<Del>| ["x]<Del> 2 same as "x"
|
||||||
|N<Del>| {count}<Del> remove the last digit from {count}
|
|N<Del>| {count}<Del> remove the last digit from {count}
|
||||||
|<Down>| <Down> 1 same as "j"
|
|<Down>| <Down> 1 same as "j"
|
||||||
@@ -587,6 +588,8 @@ tag command action in Normal mode ~
|
|||||||
following the file name.
|
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 next tab page
|
||||||
|CTRL-W_gT| CTRL-W g T same as `gT`: go to previous 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_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
|
|CTRL-W_i| CTRL-W i split window and jump to declaration of
|
||||||
identifier under the cursor
|
identifier under the cursor
|
||||||
@@ -805,6 +808,7 @@ tag char note action in Normal mode ~
|
|||||||
|g<LeftMouse>| g<LeftMouse> same as <C-LeftMouse>
|
|g<LeftMouse>| g<LeftMouse> same as <C-LeftMouse>
|
||||||
g<MiddleMouse> same as <C-MiddleMouse>
|
g<MiddleMouse> same as <C-MiddleMouse>
|
||||||
|g<RightMouse>| g<RightMouse> same as <C-RightMouse>
|
|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"
|
|g<Up>| g<Up> 1 same as "gk"
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
@@ -221,6 +221,8 @@ gT Go to the previous tab page. Wraps around from the first one
|
|||||||
*:tabl* *:tablast*
|
*:tabl* *:tablast*
|
||||||
:tabl[ast] Go to the last tab page.
|
: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:
|
Other commands:
|
||||||
*:tabs*
|
*:tabs*
|
||||||
|
@@ -616,6 +616,9 @@ f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv)
|
|||||||
{
|
{
|
||||||
if (STRCMP(arg, "$") == 0)
|
if (STRCMP(arg, "$") == 0)
|
||||||
nr = tabpage_index(NULL) - 1;
|
nr = tabpage_index(NULL) - 1;
|
||||||
|
else if (STRCMP(arg, "#") == 0)
|
||||||
|
nr = valid_tabpage(lastused_tabpage) ?
|
||||||
|
tabpage_index(lastused_tabpage) : 0;
|
||||||
else
|
else
|
||||||
semsg(_(e_invexpr2), arg);
|
semsg(_(e_invexpr2), arg);
|
||||||
}
|
}
|
||||||
|
@@ -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
|
* 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 *first_tabpage;
|
||||||
EXTERN tabpage_T *curtab;
|
EXTERN tabpage_T *curtab;
|
||||||
|
EXTERN tabpage_T *lastused_tabpage;
|
||||||
EXTERN int redraw_tabline INIT(= FALSE); // need to redraw tabline
|
EXTERN int redraw_tabline INIT(= FALSE); // need to redraw tabline
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
13
src/normal.c
13
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
|
static void
|
||||||
nv_pcmark(cmdarg_T *cap)
|
nv_pcmark(cmdarg_T *cap)
|
||||||
@@ -5456,6 +5456,12 @@ nv_pcmark(cmdarg_T *cap)
|
|||||||
|
|
||||||
if (!checkclearopq(cap->oap))
|
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')
|
if (cap->cmdchar == 'g')
|
||||||
pos = movechangelist((int)cap->count1);
|
pos = movechangelist((int)cap->count1);
|
||||||
else
|
else
|
||||||
@@ -6310,6 +6316,11 @@ nv_g_cmd(cmdarg_T *cap)
|
|||||||
goto_tabpage(-(int)cap->count1);
|
goto_tabpage(-(int)cap->count1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TAB:
|
||||||
|
if (!checkclearop(oap) && goto_tabpage_lastused() == FAIL)
|
||||||
|
clearopbeep(oap);
|
||||||
|
break;
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
case '-': // "g+" and "g-": undo or redo along the timeline
|
case '-': // "g+" and "g-": undo or redo along the timeline
|
||||||
if (!checkclearopq(oap))
|
if (!checkclearopq(oap))
|
||||||
|
@@ -32,6 +32,7 @@ tabpage_T *find_tabpage(int n);
|
|||||||
int tabpage_index(tabpage_T *ftp);
|
int tabpage_index(tabpage_T *ftp);
|
||||||
void goto_tabpage(int n);
|
void goto_tabpage(int n);
|
||||||
void goto_tabpage_tp(tabpage_T *tp, int trigger_enter_autocmds, int trigger_leave_autocmds);
|
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 goto_tabpage_win(tabpage_T *tp, win_T *wp);
|
||||||
void tabpage_move(int nr);
|
void tabpage_move(int nr);
|
||||||
void win_goto(win_T *wp);
|
void win_goto(win_T *wp);
|
||||||
|
@@ -130,7 +130,7 @@ function Test_tabpage()
|
|||||||
1tabmove
|
1tabmove
|
||||||
call assert_equal(2, tabpagenr())
|
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_equal(0, tabpagewinnr(-1))
|
||||||
call assert_fails("99tabmove", 'E16:')
|
call assert_fails("99tabmove", 'E16:')
|
||||||
call assert_fails("+99tabmove", 'E16:')
|
call assert_fails("+99tabmove", 'E16:')
|
||||||
@@ -777,4 +777,48 @@ func Test_tabpage_close_on_switch()
|
|||||||
%bw!
|
%bw!
|
||||||
endfunc
|
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
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -754,6 +754,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1401,
|
||||||
/**/
|
/**/
|
||||||
1400,
|
1400,
|
||||||
/**/
|
/**/
|
||||||
|
28
src/window.c
28
src/window.c
@@ -627,6 +627,11 @@ wingotofile:
|
|||||||
goto_tabpage(-(int)Prenum1);
|
goto_tabpage(-(int)Prenum1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TAB: // CTRL-W g<Tab>: go to last used tab page
|
||||||
|
if (goto_tabpage_lastused() == FAIL)
|
||||||
|
beep_flush();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
beep_flush();
|
beep_flush();
|
||||||
break;
|
break;
|
||||||
@@ -3809,6 +3814,9 @@ free_tabpage(tabpage_T *tp)
|
|||||||
unref_var_dict(tp->tp_vars);
|
unref_var_dict(tp->tp_vars);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (tp == lastused_tabpage)
|
||||||
|
lastused_tabpage = NULL;
|
||||||
|
|
||||||
vim_free(tp->tp_localdir);
|
vim_free(tp->tp_localdir);
|
||||||
vim_free(tp->tp_prevdir);
|
vim_free(tp->tp_prevdir);
|
||||||
|
|
||||||
@@ -3883,6 +3891,8 @@ win_new_tabpage(int after)
|
|||||||
newtp->tp_topframe = topframe;
|
newtp->tp_topframe = topframe;
|
||||||
last_status(FALSE);
|
last_status(FALSE);
|
||||||
|
|
||||||
|
lastused_tabpage = tp;
|
||||||
|
|
||||||
#if defined(FEAT_GUI)
|
#if defined(FEAT_GUI)
|
||||||
// When 'guioptions' includes 'L' or 'R' may have to remove or add
|
// When 'guioptions' includes 'L' or 'R' may have to remove or add
|
||||||
// scrollbars. Have to update them anyway.
|
// scrollbars. Have to update them anyway.
|
||||||
@@ -4118,6 +4128,7 @@ enter_tabpage(
|
|||||||
int row;
|
int row;
|
||||||
int old_off = tp->tp_firstwin->w_winrow;
|
int old_off = tp->tp_firstwin->w_winrow;
|
||||||
win_T *next_prevwin = tp->tp_prevwin;
|
win_T *next_prevwin = tp->tp_prevwin;
|
||||||
|
tabpage_T *last_tab = curtab;
|
||||||
|
|
||||||
curtab = tp;
|
curtab = tp;
|
||||||
firstwin = tp->tp_firstwin;
|
firstwin = tp->tp_firstwin;
|
||||||
@@ -4160,6 +4171,8 @@ enter_tabpage(
|
|||||||
if (curtab->tp_old_Columns != Columns && starting == 0)
|
if (curtab->tp_old_Columns != Columns && starting == 0)
|
||||||
shell_new_columns(); // update window widths
|
shell_new_columns(); // update window widths
|
||||||
|
|
||||||
|
lastused_tabpage = last_tab;
|
||||||
|
|
||||||
#if defined(FEAT_GUI)
|
#if defined(FEAT_GUI)
|
||||||
// When 'guioptions' includes 'L' or 'R' may have to remove or add
|
// When 'guioptions' includes 'L' or 'R' may have to remove or add
|
||||||
// scrollbars. Have to update them anyway.
|
// scrollbars. Have to update them anyway.
|
||||||
@@ -4277,6 +4290,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".
|
* Enter window "wp" in tab page "tp".
|
||||||
* Also updates the GUI tab.
|
* Also updates the GUI tab.
|
||||||
|
Reference in New Issue
Block a user