summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-08-09 14:04:42 +0200
committerBram Moolenaar <Bram@vim.org>2020-08-09 14:04:42 +0200
commit62a232506d06f6d1b3b7271801c907d6294dfe84 (patch)
treed95d049e9676ef5b8a63ca9096401ca52dc8b90d /src
parent730b24833952f0f4a9a17b7815b0d9f87c609eb8 (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)
Diffstat (limited to 'src')
-rw-r--r--src/evalwindow.c3
-rw-r--r--src/globals.h4
-rw-r--r--src/normal.c13
-rw-r--r--src/proto/window.pro1
-rw-r--r--src/testdir/test_tabpage.vim46
-rw-r--r--src/version.c2
-rw-r--r--src/window.c28
7 files changed, 94 insertions, 3 deletions
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.
*/