aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/getchar.c34
-rw-r--r--src/nvim/lua/executor.c5
-rw-r--r--src/nvim/option_vars.h6
-rw-r--r--src/nvim/options.lua24
-rw-r--r--src/nvim/optionstr.c20
-rw-r--r--src/nvim/window.c18
6 files changed, 81 insertions, 26 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index ce2c85f174..20c53703da 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -105,10 +105,10 @@ static buffheader_T readbuf1 = { { NULL, { NUL } }, NULL, 0, 0 };
static buffheader_T readbuf2 = { { NULL, { NUL } }, NULL, 0, 0 };
/// Buffer used to store typed characters for vim.on_key().
-static kvec_withinit_t(char, MAXMAPLEN) on_key_buf = KVI_INITIAL_VALUE(on_key_buf);
+static kvec_withinit_t(char, MAXMAPLEN + 1) on_key_buf = KVI_INITIAL_VALUE(on_key_buf);
/// Number of following bytes that should not be stored for vim.on_key().
-static size_t no_on_key_len = 0;
+static size_t on_key_ignore_len = 0;
static int typeahead_char = 0; ///< typeahead char that's not flushed
@@ -1010,18 +1010,18 @@ int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent)
/// Uses cmd_silent, KeyTyped and KeyNoremap to restore the flags belonging to
/// the char.
///
-/// @param no_on_key don't store these bytes for vim.on_key()
+/// @param on_key_ignore don't store these bytes for vim.on_key()
///
/// @return the length of what was inserted
-int ins_char_typebuf(int c, int modifiers, bool no_on_key)
+int ins_char_typebuf(int c, int modifiers, bool on_key_ignore)
{
char buf[MB_MAXBYTES * 3 + 4];
unsigned len = special_to_buf(c, modifiers, true, buf);
assert(len < sizeof(buf));
buf[len] = NUL;
ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent);
- if (KeyTyped && no_on_key) {
- no_on_key_len += len;
+ if (KeyTyped && on_key_ignore) {
+ on_key_ignore_len += len;
}
return (int)len;
}
@@ -1189,22 +1189,21 @@ static void gotchars(const uint8_t *chars, size_t len)
updatescript(state.buf[i]);
}
- state.buf[state.buflen] = NUL;
+ if (state.buflen > on_key_ignore_len) {
+ kvi_concat_len(on_key_buf, (char *)state.buf + on_key_ignore_len,
+ state.buflen - on_key_ignore_len);
+ on_key_ignore_len = 0;
+ } else {
+ on_key_ignore_len -= state.buflen;
+ }
if (reg_recording != 0) {
+ state.buf[state.buflen] = NUL;
add_buff(&recordbuff, (char *)state.buf, (ptrdiff_t)state.buflen);
// remember how many chars were last recorded
last_recorded_len += state.buflen;
}
- if (state.buflen > no_on_key_len) {
- vim_unescape_ks((char *)state.buf + no_on_key_len);
- kvi_concat(on_key_buf, (char *)state.buf + no_on_key_len);
- no_on_key_len = 0;
- } else {
- no_on_key_len -= state.buflen;
- }
-
state.buflen = 0;
}
@@ -1222,7 +1221,7 @@ static void gotchars(const uint8_t *chars, size_t len)
void gotchars_ignore(void)
{
uint8_t nop_buf[3] = { K_SPECIAL, KS_EXTRA, KE_IGNORE };
- no_on_key_len += 3;
+ on_key_ignore_len += 3;
gotchars(nop_buf, 3);
}
@@ -1770,7 +1769,8 @@ int vgetc(void)
may_garbage_collect = false;
// Execute Lua on_key callbacks.
- nlua_execute_on_key(c, on_key_buf.items, on_key_buf.size);
+ kvi_push(on_key_buf, NUL);
+ nlua_execute_on_key(c, on_key_buf.items);
kvi_destroy(on_key_buf);
kvi_init(on_key_buf);
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index c29e670c33..4d5b2c3698 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -2057,10 +2057,11 @@ char *nlua_register_table_as_callable(const typval_T *const arg)
return name;
}
-void nlua_execute_on_key(int c, char *typed_buf, size_t typed_len)
+void nlua_execute_on_key(int c, char *typed_buf)
{
char buf[MB_MAXBYTES * 3 + 4];
size_t buf_len = special_to_buf(c, mod_mask, false, buf);
+ vim_unescape_ks(typed_buf);
lua_State *const lstate = global_lstate;
@@ -2079,7 +2080,7 @@ void nlua_execute_on_key(int c, char *typed_buf, size_t typed_len)
lua_pushlstring(lstate, buf, buf_len);
// [ vim, vim._on_key, buf, typed_buf ]
- lua_pushlstring(lstate, typed_buf, typed_len);
+ lua_pushstring(lstate, typed_buf);
int save_got_int = got_int;
got_int = false; // avoid interrupts when the key typed is Ctrl-C
diff --git a/src/nvim/option_vars.h b/src/nvim/option_vars.h
index 3326c0879a..b6b307befb 100644
--- a/src/nvim/option_vars.h
+++ b/src/nvim/option_vars.h
@@ -694,7 +694,6 @@ EXTERN unsigned tpf_flags; ///< flags from 'termpastefilter'
EXTERN char *p_tfu; ///< 'tagfunc'
EXTERN char *p_spc; ///< 'spellcapcheck'
EXTERN char *p_spf; ///< 'spellfile'
-EXTERN char *p_spk; ///< 'splitkeep'
EXTERN char *p_spl; ///< 'spelllang'
EXTERN char *p_spo; ///< 'spelloptions'
EXTERN unsigned spo_flags;
@@ -711,7 +710,12 @@ EXTERN unsigned swb_flags;
#define SWB_NEWTAB 0x008
#define SWB_VSPLIT 0x010
#define SWB_USELAST 0x020
+EXTERN char *p_spk; ///< 'splitkeep'
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 int p_tbs; ///< 'tagbsearch'
EXTERN char *p_tc; ///< 'tagcase'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 6e317a426c..6345ef5ada 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -8507,6 +8507,30 @@ return {
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',
cb = 'did_set_tabline',
defaults = { if_true = '' },
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index 1a4c142fdd..8e853b6ee0 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -98,11 +98,13 @@ static char *(p_ssop_values[]) = { "buffers", "winpos", "resize", "winsize", "lo
"options", "help", "blank", "globals", "slash", "unix", "sesdir",
"curdir", "folds", "cursor", "tabpages", "terminal", "skiprtp",
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",
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_vars.h
+static char *(p_tcl_values[]) = { "left", "uselast", NULL };
static char *(p_ve_values[]) = { "block", "insert", "all", "onemore", "none", "NONE", NULL };
// Note: Keep this in sync with check_opt_wim()
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_ve, p_ve_values, &ve_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_cb, p_cb_values, &cb_flags, true);
}
@@ -2207,6 +2210,21 @@ int expand_set_switchbuf(optexpand_T *args, int *numMatches, char ***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.
const char *did_set_tabline(optset_T *args)
{
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 9203dd1bdb..132bf9ee60 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -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.
static tabpage_T *alt_tabpage(void)
{
- // 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.
+ // Use the previous tab page, if possible.
+ bool forward = curtab->tp_next != NULL
+ && ((tcl_flags & TCL_LEFT) == 0 || curtab == first_tabpage);
+
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;
}