mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
vim-patch:9.1.0572: cannot specify tab page closing behaviour (#29682)
Problem: cannot specify tab page closing behaviour
(Gianluca Pacchiella)
Solution: Add the 'tabclose' option (LemonBoy).
fixes: vim/vim#5967
closes: vim/vim#15204
5247b0b92e
Co-authored-by: LemonBoy <thatlemon@gmail.com>
This commit is contained in:
parent
10256bb760
commit
b1aa8f5eb8
@ -141,6 +141,7 @@ LUA
|
|||||||
OPTIONS
|
OPTIONS
|
||||||
|
|
||||||
• 'completeopt' flag "fuzzy" enables |fuzzy-matching| during |ins-completion|.
|
• 'completeopt' flag "fuzzy" enables |fuzzy-matching| during |ins-completion|.
|
||||||
|
• 'tabclose' controls which tab page to focus when closing a tab page.
|
||||||
|
|
||||||
PERFORMANCE
|
PERFORMANCE
|
||||||
|
|
||||||
|
@ -6343,6 +6343,19 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
'S' flag in 'cpoptions'.
|
'S' flag in 'cpoptions'.
|
||||||
Only normal file name characters can be used, `/\*?[|<>` are illegal.
|
Only normal file name characters can be used, `/\*?[|<>` are illegal.
|
||||||
|
|
||||||
|
*'tabclose'* *'tcl'*
|
||||||
|
'tabclose' 'tcl' string (default "")
|
||||||
|
global
|
||||||
|
This option controls the behavior when closing tab pages (e.g., using
|
||||||
|
|:tabclose|). When empty Vim goes to the next (right) tab page.
|
||||||
|
|
||||||
|
Possible values (comma-separated list):
|
||||||
|
left If included, go to the previous tab page instead of
|
||||||
|
the next one.
|
||||||
|
uselast If included, go to the previously used tab page if
|
||||||
|
possible. This option takes precedence over the
|
||||||
|
others.
|
||||||
|
|
||||||
*'tabline'* *'tal'*
|
*'tabline'* *'tal'*
|
||||||
'tabline' 'tal' string (default "")
|
'tabline' 'tal' string (default "")
|
||||||
global
|
global
|
||||||
|
@ -886,6 +886,7 @@ Short explanation of each option: *option-list*
|
|||||||
'switchbuf' 'swb' sets behavior when switching to another buffer
|
'switchbuf' 'swb' sets behavior when switching to another buffer
|
||||||
'synmaxcol' 'smc' maximum column to find syntax items
|
'synmaxcol' 'smc' maximum column to find syntax items
|
||||||
'syntax' 'syn' syntax to be loaded for current buffer
|
'syntax' 'syn' syntax to be loaded for current buffer
|
||||||
|
'tabclose' 'tcl' which tab page to focus when closing a tab
|
||||||
'tabline' 'tal' custom format for the console tab pages line
|
'tabline' 'tal' custom format for the console tab pages line
|
||||||
'tabpagemax' 'tpm' maximum number of tab pages for |-p| and "tab all"
|
'tabpagemax' 'tpm' maximum number of tab pages for |-p| and "tab all"
|
||||||
'tabstop' 'ts' number of spaces that <Tab> in file uses
|
'tabstop' 'ts' number of spaces that <Tab> in file uses
|
||||||
|
@ -135,7 +135,8 @@ something else.
|
|||||||
:tabclose $ " close the last tab page
|
:tabclose $ " close the last tab page
|
||||||
:tabclose # " close the last accessed tab page
|
:tabclose # " close the last accessed tab page
|
||||||
|
|
||||||
When a tab is closed the next tab page will become the current one.
|
When a tab is closed the next tab page will become the current one. This
|
||||||
|
behaviour can be customized using the 'tabclose' option.
|
||||||
|
|
||||||
*:tabo* *:tabonly*
|
*:tabo* *:tabonly*
|
||||||
:tabo[nly][!] Close all other tab pages.
|
:tabo[nly][!] Close all other tab pages.
|
||||||
|
16
runtime/lua/vim/_meta/options.lua
generated
16
runtime/lua/vim/_meta/options.lua
generated
@ -6837,6 +6837,22 @@ vim.o.syn = vim.o.syntax
|
|||||||
vim.bo.syntax = vim.o.syntax
|
vim.bo.syntax = vim.o.syntax
|
||||||
vim.bo.syn = vim.bo.syntax
|
vim.bo.syn = vim.bo.syntax
|
||||||
|
|
||||||
|
--- This option controls the behavior when closing tab pages (e.g., using
|
||||||
|
--- `:tabclose`). When empty Vim goes to the next (right) tab page.
|
||||||
|
---
|
||||||
|
--- Possible values (comma-separated list):
|
||||||
|
--- left If included, go to the previous tab page instead of
|
||||||
|
--- the next one.
|
||||||
|
--- uselast If included, go to the previously used tab page if
|
||||||
|
--- possible. This option takes precedence over the
|
||||||
|
--- others.
|
||||||
|
---
|
||||||
|
--- @type string
|
||||||
|
vim.o.tabclose = ""
|
||||||
|
vim.o.tcl = vim.o.tabclose
|
||||||
|
vim.go.tabclose = vim.o.tabclose
|
||||||
|
vim.go.tcl = vim.go.tabclose
|
||||||
|
|
||||||
--- When non-empty, this option determines the content of the tab pages
|
--- When non-empty, this option determines the content of the tab pages
|
||||||
--- line at the top of the Vim window. When empty Vim will use a default
|
--- line at the top of the Vim window. When empty Vim will use a default
|
||||||
--- tab pages line. See `setting-tabline` for more info.
|
--- tab pages line. See `setting-tabline` for more info.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
" These commands create the option window.
|
" These commands create the option window.
|
||||||
"
|
"
|
||||||
" Maintainer: The Vim Project <https://github.com/vim/vim>
|
" Maintainer: The Vim Project <https://github.com/vim/vim>
|
||||||
" Last Change: 2024 Jun 05
|
" Last Change: 2024 Jul 12
|
||||||
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
|
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||||
|
|
||||||
" If there already is an option window, jump to that one.
|
" If there already is an option window, jump to that one.
|
||||||
@ -507,6 +507,8 @@ endif
|
|||||||
call <SID>Header(gettext("multiple tab pages"))
|
call <SID>Header(gettext("multiple tab pages"))
|
||||||
call <SID>AddOption("showtabline", gettext("0, 1 or 2; when to use a tab pages line"))
|
call <SID>AddOption("showtabline", gettext("0, 1 or 2; when to use a tab pages line"))
|
||||||
call append("$", " \tset stal=" . &stal)
|
call append("$", " \tset stal=" . &stal)
|
||||||
|
call <SID>AddOption("tabclose", gettext("behaviour when closing tab pages: left, uselast or empty"))
|
||||||
|
call append("$", " \tset tcl=" . &tcl)
|
||||||
call <SID>AddOption("tabpagemax", gettext("maximum number of tab pages to open for -p and \"tab all\""))
|
call <SID>AddOption("tabpagemax", gettext("maximum number of tab pages to open for -p and \"tab all\""))
|
||||||
call append("$", " \tset tpm=" . &tpm)
|
call append("$", " \tset tpm=" . &tpm)
|
||||||
call <SID>AddOption("tabline", gettext("custom tab pages line"))
|
call <SID>AddOption("tabline", gettext("custom tab pages line"))
|
||||||
|
@ -694,7 +694,6 @@ EXTERN unsigned tpf_flags; ///< flags from 'termpastefilter'
|
|||||||
EXTERN char *p_tfu; ///< 'tagfunc'
|
EXTERN char *p_tfu; ///< 'tagfunc'
|
||||||
EXTERN char *p_spc; ///< 'spellcapcheck'
|
EXTERN char *p_spc; ///< 'spellcapcheck'
|
||||||
EXTERN char *p_spf; ///< 'spellfile'
|
EXTERN char *p_spf; ///< 'spellfile'
|
||||||
EXTERN char *p_spk; ///< 'splitkeep'
|
|
||||||
EXTERN char *p_spl; ///< 'spelllang'
|
EXTERN char *p_spl; ///< 'spelllang'
|
||||||
EXTERN char *p_spo; ///< 'spelloptions'
|
EXTERN char *p_spo; ///< 'spelloptions'
|
||||||
EXTERN unsigned spo_flags;
|
EXTERN unsigned spo_flags;
|
||||||
@ -711,7 +710,12 @@ EXTERN unsigned swb_flags;
|
|||||||
#define SWB_NEWTAB 0x008
|
#define SWB_NEWTAB 0x008
|
||||||
#define SWB_VSPLIT 0x010
|
#define SWB_VSPLIT 0x010
|
||||||
#define SWB_USELAST 0x020
|
#define SWB_USELAST 0x020
|
||||||
|
EXTERN char *p_spk; ///< 'splitkeep'
|
||||||
EXTERN char *p_syn; ///< 'syntax'
|
EXTERN char *p_syn; ///< 'syntax'
|
||||||
|
EXTERN char *p_tcl; ///< 'tabclose'
|
||||||
|
EXTERN unsigned tcl_flags; ///< flags from 'tabclose'
|
||||||
|
#define TCL_LEFT 0x001
|
||||||
|
#define TCL_USELAST 0x002
|
||||||
EXTERN OptInt p_ts; ///< 'tabstop'
|
EXTERN OptInt p_ts; ///< 'tabstop'
|
||||||
EXTERN int p_tbs; ///< 'tagbsearch'
|
EXTERN int p_tbs; ///< 'tagbsearch'
|
||||||
EXTERN char *p_tc; ///< 'tagcase'
|
EXTERN char *p_tc; ///< 'tagcase'
|
||||||
|
@ -8506,6 +8506,30 @@ return {
|
|||||||
type = 'string',
|
type = 'string',
|
||||||
varname = 'p_syn',
|
varname = 'p_syn',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
abbreviation = 'tcl',
|
||||||
|
cb = 'did_set_tabclose',
|
||||||
|
defaults = { if_true = '' },
|
||||||
|
deny_duplicates = true,
|
||||||
|
desc = [=[
|
||||||
|
This option controls the behavior when closing tab pages (e.g., using
|
||||||
|
|:tabclose|). When empty Vim goes to the next (right) tab page.
|
||||||
|
|
||||||
|
Possible values (comma-separated list):
|
||||||
|
left If included, go to the previous tab page instead of
|
||||||
|
the next one.
|
||||||
|
uselast If included, go to the previously used tab page if
|
||||||
|
possible. This option takes precedence over the
|
||||||
|
others.
|
||||||
|
]=],
|
||||||
|
expand_cb = 'expand_set_tabclose',
|
||||||
|
full_name = 'tabclose',
|
||||||
|
list = 'onecomma',
|
||||||
|
scope = { 'global' },
|
||||||
|
short_desc = N_('which tab page to focus when closing a tab'),
|
||||||
|
type = 'string',
|
||||||
|
varname = 'p_tcl',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
abbreviation = 'tal',
|
abbreviation = 'tal',
|
||||||
cb = 'did_set_tabline',
|
cb = 'did_set_tabline',
|
||||||
|
@ -98,11 +98,13 @@ static char *(p_ssop_values[]) = { "buffers", "winpos", "resize", "winsize", "lo
|
|||||||
"options", "help", "blank", "globals", "slash", "unix", "sesdir",
|
"options", "help", "blank", "globals", "slash", "unix", "sesdir",
|
||||||
"curdir", "folds", "cursor", "tabpages", "terminal", "skiprtp",
|
"curdir", "folds", "cursor", "tabpages", "terminal", "skiprtp",
|
||||||
NULL };
|
NULL };
|
||||||
// Keep in sync with SWB_ flags in option_defs.h
|
// Keep in sync with SWB_ flags in option_vars.h
|
||||||
static char *(p_swb_values[]) = { "useopen", "usetab", "split", "newtab", "vsplit", "uselast",
|
static char *(p_swb_values[]) = { "useopen", "usetab", "split", "newtab", "vsplit", "uselast",
|
||||||
NULL };
|
NULL };
|
||||||
static char *(p_spk_values[]) = { "cursor", "screen", "topline", NULL };
|
static char *(p_spk_values[]) = { "cursor", "screen", "topline", NULL };
|
||||||
static char *(p_tc_values[]) = { "followic", "ignore", "match", "followscs", "smart", NULL };
|
static char *(p_tc_values[]) = { "followic", "ignore", "match", "followscs", "smart", NULL };
|
||||||
|
// Keep in sync with TCL_ flags in option_vars.h
|
||||||
|
static char *(p_tcl_values[]) = { "left", "uselast", NULL };
|
||||||
static char *(p_ve_values[]) = { "block", "insert", "all", "onemore", "none", "NONE", NULL };
|
static char *(p_ve_values[]) = { "block", "insert", "all", "onemore", "none", "NONE", NULL };
|
||||||
// Note: Keep this in sync with check_opt_wim()
|
// Note: Keep this in sync with check_opt_wim()
|
||||||
static char *(p_wim_values[]) = { "full", "longest", "list", "lastused", NULL };
|
static char *(p_wim_values[]) = { "full", "longest", "list", "lastused", NULL };
|
||||||
@ -169,6 +171,7 @@ void didset_string_options(void)
|
|||||||
opt_strings_flags(p_tpf, p_tpf_values, &tpf_flags, true);
|
opt_strings_flags(p_tpf, p_tpf_values, &tpf_flags, true);
|
||||||
opt_strings_flags(p_ve, p_ve_values, &ve_flags, true);
|
opt_strings_flags(p_ve, p_ve_values, &ve_flags, true);
|
||||||
opt_strings_flags(p_swb, p_swb_values, &swb_flags, true);
|
opt_strings_flags(p_swb, p_swb_values, &swb_flags, true);
|
||||||
|
opt_strings_flags(p_tcl, p_tcl_values, &tcl_flags, true);
|
||||||
opt_strings_flags(p_wop, p_wop_values, &wop_flags, true);
|
opt_strings_flags(p_wop, p_wop_values, &wop_flags, true);
|
||||||
opt_strings_flags(p_cb, p_cb_values, &cb_flags, true);
|
opt_strings_flags(p_cb, p_cb_values, &cb_flags, true);
|
||||||
}
|
}
|
||||||
@ -2207,6 +2210,21 @@ int expand_set_switchbuf(optexpand_T *args, int *numMatches, char ***matches)
|
|||||||
matches);
|
matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The 'tabclose' option is changed.
|
||||||
|
const char *did_set_tabclose(optset_T *args FUNC_ATTR_UNUSED)
|
||||||
|
{
|
||||||
|
return did_set_opt_flags(p_tcl, p_tcl_values, &tcl_flags, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int expand_set_tabclose(optexpand_T *args, int *numMatches, char ***matches)
|
||||||
|
{
|
||||||
|
return expand_set_opt_string(args,
|
||||||
|
p_tcl_values,
|
||||||
|
ARRAY_SIZE(p_tcl_values) - 1,
|
||||||
|
numMatches,
|
||||||
|
matches);
|
||||||
|
}
|
||||||
|
|
||||||
/// The 'tabline' option is changed.
|
/// The 'tabline' option is changed.
|
||||||
const char *did_set_tabline(optset_T *args)
|
const char *did_set_tabline(optset_T *args)
|
||||||
{
|
{
|
||||||
|
@ -3456,14 +3456,22 @@ static frame_T *win_altframe(win_T *win, tabpage_T *tp)
|
|||||||
// Return the tabpage that will be used if the current one is closed.
|
// Return the tabpage that will be used if the current one is closed.
|
||||||
static tabpage_T *alt_tabpage(void)
|
static tabpage_T *alt_tabpage(void)
|
||||||
{
|
{
|
||||||
// Use the next tab page if possible.
|
// Use the last accessed tab page, if possible.
|
||||||
if (curtab->tp_next != NULL) {
|
if ((tcl_flags & TCL_USELAST) && valid_tabpage(lastused_tabpage)) {
|
||||||
return curtab->tp_next;
|
return lastused_tabpage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the last but one tab page.
|
// Use the previous tab page, if possible.
|
||||||
|
bool forward = curtab->tp_next != NULL
|
||||||
|
&& ((tcl_flags & TCL_LEFT) == 0 || curtab == first_tabpage);
|
||||||
|
|
||||||
tabpage_T *tp;
|
tabpage_T *tp;
|
||||||
for (tp = first_tabpage; tp->tp_next != curtab; tp = tp->tp_next) {}
|
if (forward) {
|
||||||
|
tp = curtab->tp_next;
|
||||||
|
} else {
|
||||||
|
for (tp = first_tabpage; tp->tp_next != curtab; tp = tp->tp_next) {}
|
||||||
|
}
|
||||||
|
|
||||||
return tp;
|
return tp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,6 +558,9 @@ func Test_set_completion_string_values()
|
|||||||
" call assert_equal('sync', getcompletion('set swapsync=', 'cmdline')[1])
|
" call assert_equal('sync', getcompletion('set swapsync=', 'cmdline')[1])
|
||||||
call assert_equal('usetab', getcompletion('set switchbuf=', 'cmdline')[1])
|
call assert_equal('usetab', getcompletion('set switchbuf=', 'cmdline')[1])
|
||||||
call assert_equal('ignore', getcompletion('set tagcase=', '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')
|
if exists('+termwintype')
|
||||||
call assert_equal('conpty', getcompletion('set termwintype=', 'cmdline')[1])
|
call assert_equal('conpty', getcompletion('set termwintype=', 'cmdline')[1])
|
||||||
endif
|
endif
|
||||||
@ -1377,9 +1380,10 @@ func Test_write()
|
|||||||
new
|
new
|
||||||
call setline(1, ['L1'])
|
call setline(1, ['L1'])
|
||||||
set nowrite
|
set nowrite
|
||||||
call assert_fails('write Xfile', 'E142:')
|
call assert_fails('write Xwrfile', 'E142:')
|
||||||
set write
|
set write
|
||||||
close!
|
" close swapfile
|
||||||
|
bw!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Test for 'buftype' option
|
" Test for 'buftype' option
|
||||||
|
@ -967,6 +967,64 @@ func Test_tabpage_alloc_failure()
|
|||||||
call assert_equal(1, tabpagenr('$'))
|
call assert_equal(1, tabpagenr('$'))
|
||||||
endfunc
|
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
|
" this was giving ml_get errors
|
||||||
func Test_tabpage_last_line()
|
func Test_tabpage_last_line()
|
||||||
enew
|
enew
|
||||||
|
Loading…
Reference in New Issue
Block a user