patch 9.1.0572: cannot specify tab page closing behaviour
Problem: cannot specify tab page closing behaviour
(Gianluca Pacchiella)
Solution: Add the 'tabclose' option (LemonBoy).
fixes: #5967
closes: #15204
Signed-off-by: LemonBoy <thatlemon@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/option.h b/src/option.h
index 630d7bf..e84f7f9 100644
--- a/src/option.h
+++ b/src/option.h
@@ -955,7 +955,6 @@
EXTERN char_u *p_su; // 'suffixes'
EXTERN char_u *p_sws; // 'swapsync'
EXTERN char_u *p_swb; // 'switchbuf'
-EXTERN char_u *p_spk; // 'splitkeep'
EXTERN unsigned swb_flags;
// Keep in sync with p_swb_values in optionstr.c
#define SWB_USEOPEN 0x001
@@ -964,9 +963,14 @@
#define SWB_NEWTAB 0x008
#define SWB_VSPLIT 0x010
#define SWB_USELAST 0x020
+EXTERN char_u *p_spk; // 'splitkeep'
#ifdef FEAT_SYN_HL
EXTERN char_u *p_syn; // 'syntax'
#endif
+EXTERN char_u *p_tcl; // 'tabclose'
+EXTERN unsigned tcl_flags; // flags from 'tabclose'
+#define TCL_LEFT 0x001
+#define TCL_USELAST 0x002
EXTERN long p_ts; // 'tabstop'
EXTERN int p_tbs; // 'tagbsearch'
EXTERN char_u *p_tc; // 'tagcase'
diff --git a/src/optiondefs.h b/src/optiondefs.h
index 617f3ce..bf3ed35 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -2462,6 +2462,9 @@
{(char_u *)0L, (char_u *)0L}
#endif
SCTX_INIT},
+ {"tabclose", "tcl", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
+ (char_u *)&p_tcl, PV_NONE, did_set_tabclose, expand_set_tabclose,
+ {(char_u *)"", (char_u *)0L} SCTX_INIT},
{"tabline", "tal", P_STRING|P_VI_DEF|P_RALL|P_MLE,
#ifdef FEAT_STL_OPT
(char_u *)&p_tal, PV_NONE, did_set_tabline, NULL,
diff --git a/src/optionstr.c b/src/optionstr.c
index 417f785..b6249a2 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -81,6 +81,8 @@
static char *(p_swb_values[]) = {"useopen", "usetab", "split", "newtab", "vsplit", "uselast", NULL};
static char *(p_spk_values[]) = {"cursor", "screen", "topline", NULL};
static char *(p_tc_values[]) = {"followic", "ignore", "match", "followscs", "smart", NULL};
+// Keep in sync with TCL_ flags in option.h
+static char *(p_tcl_values[]) = {"left", "uselast", NULL};
#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)
static char *(p_toolbar_values[]) = {"text", "icons", "tooltips", "horiz", NULL};
#endif
@@ -166,6 +168,7 @@
(void)opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE);
#endif
(void)opt_strings_flags(p_swb, p_swb_values, &swb_flags, TRUE);
+ (void)opt_strings_flags(p_tcl, p_tcl_values, &tcl_flags, TRUE);
}
#if defined(FEAT_EVAL) || defined(PROTO)
@@ -3669,6 +3672,26 @@
matches);
}
+/*
+ * The 'tabclose' option is changed.
+ */
+ char *
+did_set_tabclose(optset_T *args UNUSED)
+{
+ return did_set_opt_flags(p_tcl, p_tcl_values, &tcl_flags, TRUE);
+}
+
+ int
+expand_set_tabclose(optexpand_T *args, int *numMatches, char_u ***matches)
+{
+ return expand_set_opt_string(
+ args,
+ p_tcl_values,
+ ARRAY_LENGTH(p_tcl_values) - 1,
+ numMatches,
+ matches);
+}
+
#if defined(FEAT_STL_OPT) || defined(PROTO)
/*
* The 'tabline' option is changed.
diff --git a/src/proto/option.pro b/src/proto/option.pro
index 69463d4..1659131 100644
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -69,6 +69,7 @@
char *did_set_smoothscroll(optset_T *args);
char *did_set_spell(optset_T *args);
char *did_set_swapfile(optset_T *args);
+char *did_set_tabclose(optset_T *args);
char *did_set_termguicolors(optset_T *args);
char *did_set_terse(optset_T *args);
char *did_set_textauto(optset_T *args);
diff --git a/src/proto/optionstr.pro b/src/proto/optionstr.pro
index 340ffc4..39c40f3 100644
--- a/src/proto/optionstr.pro
+++ b/src/proto/optionstr.pro
@@ -156,6 +156,7 @@
int expand_set_swapsync(optexpand_T *args, int *numMatches, char_u ***matches);
char *did_set_switchbuf(optset_T *args);
int expand_set_switchbuf(optexpand_T *args, int *numMatches, char_u ***matches);
+int expand_set_tabclose(optexpand_T *args, int *numMatches, char_u ***matches);
char *did_set_tabline(optset_T *args);
char *did_set_tagcase(optset_T *args);
int expand_set_tagcase(optexpand_T *args, int *numMatches, char_u ***matches);
diff --git a/src/testdir/gen_opt_test.vim b/src/testdir/gen_opt_test.vim
index 8cca2b9..7674714 100644
--- a/src/testdir/gen_opt_test.vim
+++ b/src/testdir/gen_opt_test.vim
@@ -144,6 +144,7 @@
\ 'splitkeep': [['cursor', 'screen', 'topline'], ['xxx']],
\ 'swapsync': [['', 'sync', 'fsync'], ['xxx']],
\ 'switchbuf': [['', 'useopen', 'split,newtab'], ['xxx']],
+ \ 'tabclose': [['', 'left', 'left,uselast'], ['xxx']],
\ 'tagcase': [['smart', 'match'], ['', 'xxx', 'smart,match']],
\ 'term': [[], []],
\ 'termguicolors': [[], []],
diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim
index fbfbaae..02f5d7e 100644
--- a/src/testdir/test_options.vim
+++ b/src/testdir/test_options.vim
@@ -548,6 +548,9 @@
call assert_equal('sync', getcompletion('set swapsync=', 'cmdline')[1])
call assert_equal('usetab', getcompletion('set switchbuf=', 'cmdline')[1])
call assert_equal('ignore', getcompletion('set tagcase=', 'cmdline')[1])
+ if exists('+tabclose')
+ call assert_equal('left uselast', join(sort(getcompletion('set tabclose=', 'cmdline'))), ' ')
+ endif
if exists('+termwintype')
call assert_equal('conpty', getcompletion('set termwintype=', 'cmdline')[1])
endif
@@ -1407,7 +1410,8 @@
set nowrite
call assert_fails('write Xwrfile', 'E142:')
set write
- close!
+ " close swapfile
+ bw!
endfunc
" Test for 'buftype' option
diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim
index 3624790..1a40567 100644
--- a/src/testdir/test_tabpage.vim
+++ b/src/testdir/test_tabpage.vim
@@ -965,6 +965,64 @@
call assert_equal(1, tabpagenr('$'))
endfunc
+func Test_tabpage_tabclose()
+ " Default behaviour, move to the right.
+ call s:reconstruct_tabpage_for_test(6)
+ norm! 4gt
+ setl tcl=
+ tabclose
+ call assert_equal("n3", bufname())
+
+ " Move to the left.
+ call s:reconstruct_tabpage_for_test(6)
+ norm! 4gt
+ setl tcl=left
+ tabclose
+ call assert_equal("n1", bufname())
+
+ " Move to the last used tab page.
+ call s:reconstruct_tabpage_for_test(6)
+ norm! 5gt
+ norm! 2gt
+ setl tcl=uselast
+ tabclose
+ call assert_equal("n3", bufname())
+
+ " Same, but the last used tab page is invalid. Move to the right.
+ call s:reconstruct_tabpage_for_test(6)
+ norm! 5gt
+ norm! 3gt
+ setl tcl=uselast
+ tabclose 5
+ tabclose!
+ call assert_equal("n2", bufname())
+
+ " Same, but the last used tab page is invalid. Move to the left.
+ call s:reconstruct_tabpage_for_test(6)
+ norm! 5gt
+ norm! 3gt
+ setl tcl=uselast,left
+ tabclose 5
+ tabclose!
+ call assert_equal("n0", bufname())
+
+ " Move left when moving right is not possible.
+ call s:reconstruct_tabpage_for_test(6)
+ setl tcl=
+ norm! 6gt
+ tabclose
+ call assert_equal("n3", bufname())
+
+ " Move right when moving left is not possible.
+ call s:reconstruct_tabpage_for_test(6)
+ setl tcl=left
+ norm! 1gt
+ tabclose
+ call assert_equal("n0", bufname())
+
+ setl tcl&
+endfunc
+
" this was giving ml_get errors
func Test_tabpage_last_line()
enew
diff --git a/src/version.c b/src/version.c
index 194099b..fc1fb24 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 572,
+/**/
571,
/**/
570,
diff --git a/src/window.c b/src/window.c
index 7322905..c87cce0 100644
--- a/src/window.c
+++ b/src/window.c
@@ -3782,15 +3782,23 @@
static tabpage_T *
alt_tabpage(void)
{
- tabpage_T *tp;
+ tabpage_T *tp = NULL;
+ int forward;
- // Use the next tab page if possible.
- if (curtab->tp_next != NULL)
- return curtab->tp_next;
+ // Use the last accessed tab page, if possible.
+ if ((tcl_flags & TCL_USELAST) && valid_tabpage(lastused_tabpage))
+ return lastused_tabpage;
- // Find the last but one tab page.
- for (tp = first_tabpage; tp->tp_next != curtab; tp = tp->tp_next)
- ;
+ // Use the previous tab page, if possible.
+ forward = curtab->tp_next != NULL &&
+ ((tcl_flags & TCL_LEFT) == 0 || curtab == first_tabpage);
+
+ if (forward)
+ tp = curtab->tp_next;
+ else
+ for (tp = first_tabpage; tp->tp_next != curtab; tp = tp->tp_next)
+ ;
+
return tp;
}