aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2021-11-22 15:50:14 +0800
committerzeertzjq <zeertzjq@outlook.com>2021-11-22 15:50:14 +0800
commitd40db0edbdc7058c6096b8a389bee88d162329a9 (patch)
treeea3a5af4faa2b7c343cdf41ab4ca83b04102dcca
parent64abd7be7993ed3fa031b5d71a4482871108093a (diff)
downloadrneovim-d40db0edbdc7058c6096b8a389bee88d162329a9.tar.gz
rneovim-d40db0edbdc7058c6096b8a389bee88d162329a9.tar.bz2
rneovim-d40db0edbdc7058c6096b8a389bee88d162329a9.zip
vim-patch:8.1.1542: an OptionSet autocommand does not get enough info
Problem: An OptionSet autocommand does not get enough info. Solution: Add v:option_command, v:option_oldlocal and v:option_oldglobal. (Latrice Wilgus, closes vim/vim#4118) https://github.com/vim/vim/commit/d7c968794710f338d491072171df48f96612cf72
-rw-r--r--runtime/doc/eval.txt21
-rw-r--r--src/nvim/eval.c205
-rw-r--r--src/nvim/eval.h3
-rw-r--r--src/nvim/option.c148
-rw-r--r--src/nvim/testdir/test_autocmd.vim522
-rw-r--r--test/functional/legacy/autocmd_option_spec.lua420
6 files changed, 1131 insertions, 188 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 58d5d30146..89688b36a7 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2042,10 +2042,29 @@ v:option_new New value of the option. Valid while executing an |OptionSet|
autocommand.
*v:option_old*
v:option_old Old value of the option. Valid while executing an |OptionSet|
- autocommand.
+ autocommand. Depending on the command used for setting and the
+ kind of option this is either the local old value or the
+ global old value.
+ *v:option_oldlocal*
+v:option_oldlocal
+ Old local value of the option. Valid while executing an
+ |OptionSet| autocommand.
+ *v:option_oldglobal*
+v:option_oldglobal
+ Old global value of the option. Valid while executing an
+ |OptionSet| autocommand.
*v:option_type*
v:option_type Scope of the set command. Valid while executing an
|OptionSet| autocommand. Can be either "global" or "local"
+ *v:option_command*
+v:option_command
+ Command used to set the option. Valid while executing an
+ |OptionSet| autocommand.
+ value option was set via ~
+ "setlocal" |:setlocal| or ":let l:xxx"
+ "setglobal" |:setglobal| or ":let g:xxx"
+ "set" |:set| or |:let|
+ "modeline" |modeline|
*v:operator* *operator-variable*
v:operator The last operator given in Normal mode. This is a single
character except for commands starting with <g> or <z>,
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index d3d0121632..a09ad7924d 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -134,13 +134,15 @@ typedef struct {
.vv_flags = flags, \
}
+#define VIMVAR_KEY_LEN 16 // Maximum length of the key of v:variables
+
// Array to hold the value of v: variables.
// The value is in a dictitem, so that it can also be used in the v: scope.
// The reason to use this table anyway is for very quick access to the
// variables with the VV_ defines.
static struct vimvar {
char *vv_name; ///< Name of the variable, without v:.
- TV_DICTITEM_STRUCT(17) vv_di; ///< Value and name for key (max 16 chars).
+ TV_DICTITEM_STRUCT(VIMVAR_KEY_LEN + 1) vv_di; ///< Value and name for key (max 16 chars).
char vv_flags; ///< Flags: #VV_COMPAT, #VV_RO, #VV_RO_SBX.
} vimvars[] =
{
@@ -150,100 +152,103 @@ static struct vimvar {
// VV_SEND_SERVER "servername"
// VV_REG "register"
// VV_OP "operator"
- VV(VV_COUNT, "count", VAR_NUMBER, VV_RO),
- VV(VV_COUNT1, "count1", VAR_NUMBER, VV_RO),
- VV(VV_PREVCOUNT, "prevcount", VAR_NUMBER, VV_RO),
- VV(VV_ERRMSG, "errmsg", VAR_STRING, 0),
- VV(VV_WARNINGMSG, "warningmsg", VAR_STRING, 0),
- VV(VV_STATUSMSG, "statusmsg", VAR_STRING, 0),
- VV(VV_SHELL_ERROR, "shell_error", VAR_NUMBER, VV_RO),
- VV(VV_THIS_SESSION, "this_session", VAR_STRING, 0),
- VV(VV_VERSION, "version", VAR_NUMBER, VV_COMPAT+VV_RO),
- VV(VV_LNUM, "lnum", VAR_NUMBER, VV_RO_SBX),
- VV(VV_TERMRESPONSE, "termresponse", VAR_STRING, VV_RO),
- VV(VV_FNAME, "fname", VAR_STRING, VV_RO),
- VV(VV_LANG, "lang", VAR_STRING, VV_RO),
- VV(VV_LC_TIME, "lc_time", VAR_STRING, VV_RO),
- VV(VV_CTYPE, "ctype", VAR_STRING, VV_RO),
- VV(VV_CC_FROM, "charconvert_from", VAR_STRING, VV_RO),
- VV(VV_CC_TO, "charconvert_to", VAR_STRING, VV_RO),
- VV(VV_FNAME_IN, "fname_in", VAR_STRING, VV_RO),
- VV(VV_FNAME_OUT, "fname_out", VAR_STRING, VV_RO),
- VV(VV_FNAME_NEW, "fname_new", VAR_STRING, VV_RO),
- VV(VV_FNAME_DIFF, "fname_diff", VAR_STRING, VV_RO),
- VV(VV_CMDARG, "cmdarg", VAR_STRING, VV_RO),
- VV(VV_FOLDSTART, "foldstart", VAR_NUMBER, VV_RO_SBX),
- VV(VV_FOLDEND, "foldend", VAR_NUMBER, VV_RO_SBX),
- VV(VV_FOLDDASHES, "folddashes", VAR_STRING, VV_RO_SBX),
- VV(VV_FOLDLEVEL, "foldlevel", VAR_NUMBER, VV_RO_SBX),
- VV(VV_PROGNAME, "progname", VAR_STRING, VV_RO),
- VV(VV_SEND_SERVER, "servername", VAR_STRING, VV_RO),
- VV(VV_DYING, "dying", VAR_NUMBER, VV_RO),
- VV(VV_EXCEPTION, "exception", VAR_STRING, VV_RO),
- VV(VV_THROWPOINT, "throwpoint", VAR_STRING, VV_RO),
- VV(VV_REG, "register", VAR_STRING, VV_RO),
- VV(VV_CMDBANG, "cmdbang", VAR_NUMBER, VV_RO),
- VV(VV_INSERTMODE, "insertmode", VAR_STRING, VV_RO),
- VV(VV_VAL, "val", VAR_UNKNOWN, VV_RO),
- VV(VV_KEY, "key", VAR_UNKNOWN, VV_RO),
- VV(VV_PROFILING, "profiling", VAR_NUMBER, VV_RO),
- VV(VV_FCS_REASON, "fcs_reason", VAR_STRING, VV_RO),
- VV(VV_FCS_CHOICE, "fcs_choice", VAR_STRING, 0),
- VV(VV_BEVAL_BUFNR, "beval_bufnr", VAR_NUMBER, VV_RO),
- VV(VV_BEVAL_WINNR, "beval_winnr", VAR_NUMBER, VV_RO),
- VV(VV_BEVAL_WINID, "beval_winid", VAR_NUMBER, VV_RO),
- VV(VV_BEVAL_LNUM, "beval_lnum", VAR_NUMBER, VV_RO),
- VV(VV_BEVAL_COL, "beval_col", VAR_NUMBER, VV_RO),
- VV(VV_BEVAL_TEXT, "beval_text", VAR_STRING, VV_RO),
- VV(VV_SCROLLSTART, "scrollstart", VAR_STRING, 0),
- VV(VV_SWAPNAME, "swapname", VAR_STRING, VV_RO),
- VV(VV_SWAPCHOICE, "swapchoice", VAR_STRING, 0),
- VV(VV_SWAPCOMMAND, "swapcommand", VAR_STRING, VV_RO),
- VV(VV_CHAR, "char", VAR_STRING, 0),
- VV(VV_MOUSE_WIN, "mouse_win", VAR_NUMBER, 0),
- VV(VV_MOUSE_WINID, "mouse_winid", VAR_NUMBER, 0),
- VV(VV_MOUSE_LNUM, "mouse_lnum", VAR_NUMBER, 0),
- VV(VV_MOUSE_COL, "mouse_col", VAR_NUMBER, 0),
- VV(VV_OP, "operator", VAR_STRING, VV_RO),
- VV(VV_SEARCHFORWARD, "searchforward", VAR_NUMBER, 0),
- VV(VV_HLSEARCH, "hlsearch", VAR_NUMBER, 0),
- VV(VV_OLDFILES, "oldfiles", VAR_LIST, 0),
- VV(VV_WINDOWID, "windowid", VAR_NUMBER, VV_RO_SBX),
- VV(VV_PROGPATH, "progpath", VAR_STRING, VV_RO),
- VV(VV_COMPLETED_ITEM, "completed_item", VAR_DICT, VV_RO),
- VV(VV_OPTION_NEW, "option_new", VAR_STRING, VV_RO),
- VV(VV_OPTION_OLD, "option_old", VAR_STRING, VV_RO),
- VV(VV_OPTION_TYPE, "option_type", VAR_STRING, VV_RO),
- VV(VV_ERRORS, "errors", VAR_LIST, 0),
- VV(VV_FALSE, "false", VAR_BOOL, VV_RO),
- VV(VV_TRUE, "true", VAR_BOOL, VV_RO),
- VV(VV_NULL, "null", VAR_SPECIAL, VV_RO),
- VV(VV_NUMBERMAX, "numbermax", VAR_NUMBER, VV_RO),
- VV(VV_NUMBERMIN, "numbermin", VAR_NUMBER, VV_RO),
- VV(VV_NUMBERSIZE, "numbersize", VAR_NUMBER, VV_RO),
- VV(VV_VIM_DID_ENTER, "vim_did_enter", VAR_NUMBER, VV_RO),
- VV(VV_TESTING, "testing", VAR_NUMBER, 0),
- VV(VV_TYPE_NUMBER, "t_number", VAR_NUMBER, VV_RO),
- VV(VV_TYPE_STRING, "t_string", VAR_NUMBER, VV_RO),
- VV(VV_TYPE_FUNC, "t_func", VAR_NUMBER, VV_RO),
- VV(VV_TYPE_LIST, "t_list", VAR_NUMBER, VV_RO),
- VV(VV_TYPE_DICT, "t_dict", VAR_NUMBER, VV_RO),
- VV(VV_TYPE_FLOAT, "t_float", VAR_NUMBER, VV_RO),
- VV(VV_TYPE_BOOL, "t_bool", VAR_NUMBER, VV_RO),
- VV(VV_TYPE_BLOB, "t_blob", VAR_NUMBER, VV_RO),
- VV(VV_EVENT, "event", VAR_DICT, VV_RO),
- VV(VV_ECHOSPACE, "echospace", VAR_NUMBER, VV_RO),
- VV(VV_ARGV, "argv", VAR_LIST, VV_RO),
- VV(VV_COLLATE, "collate", VAR_STRING, VV_RO),
- VV(VV_EXITING, "exiting", VAR_NUMBER, VV_RO),
+ VV(VV_COUNT, "count", VAR_NUMBER, VV_RO),
+ VV(VV_COUNT1, "count1", VAR_NUMBER, VV_RO),
+ VV(VV_PREVCOUNT, "prevcount", VAR_NUMBER, VV_RO),
+ VV(VV_ERRMSG, "errmsg", VAR_STRING, 0),
+ VV(VV_WARNINGMSG, "warningmsg", VAR_STRING, 0),
+ VV(VV_STATUSMSG, "statusmsg", VAR_STRING, 0),
+ VV(VV_SHELL_ERROR, "shell_error", VAR_NUMBER, VV_RO),
+ VV(VV_THIS_SESSION, "this_session", VAR_STRING, 0),
+ VV(VV_VERSION, "version", VAR_NUMBER, VV_COMPAT+VV_RO),
+ VV(VV_LNUM, "lnum", VAR_NUMBER, VV_RO_SBX),
+ VV(VV_TERMRESPONSE, "termresponse", VAR_STRING, VV_RO),
+ VV(VV_FNAME, "fname", VAR_STRING, VV_RO),
+ VV(VV_LANG, "lang", VAR_STRING, VV_RO),
+ VV(VV_LC_TIME, "lc_time", VAR_STRING, VV_RO),
+ VV(VV_CTYPE, "ctype", VAR_STRING, VV_RO),
+ VV(VV_CC_FROM, "charconvert_from", VAR_STRING, VV_RO),
+ VV(VV_CC_TO, "charconvert_to", VAR_STRING, VV_RO),
+ VV(VV_FNAME_IN, "fname_in", VAR_STRING, VV_RO),
+ VV(VV_FNAME_OUT, "fname_out", VAR_STRING, VV_RO),
+ VV(VV_FNAME_NEW, "fname_new", VAR_STRING, VV_RO),
+ VV(VV_FNAME_DIFF, "fname_diff", VAR_STRING, VV_RO),
+ VV(VV_CMDARG, "cmdarg", VAR_STRING, VV_RO),
+ VV(VV_FOLDSTART, "foldstart", VAR_NUMBER, VV_RO_SBX),
+ VV(VV_FOLDEND, "foldend", VAR_NUMBER, VV_RO_SBX),
+ VV(VV_FOLDDASHES, "folddashes", VAR_STRING, VV_RO_SBX),
+ VV(VV_FOLDLEVEL, "foldlevel", VAR_NUMBER, VV_RO_SBX),
+ VV(VV_PROGNAME, "progname", VAR_STRING, VV_RO),
+ VV(VV_SEND_SERVER, "servername", VAR_STRING, VV_RO),
+ VV(VV_DYING, "dying", VAR_NUMBER, VV_RO),
+ VV(VV_EXCEPTION, "exception", VAR_STRING, VV_RO),
+ VV(VV_THROWPOINT, "throwpoint", VAR_STRING, VV_RO),
+ VV(VV_REG, "register", VAR_STRING, VV_RO),
+ VV(VV_CMDBANG, "cmdbang", VAR_NUMBER, VV_RO),
+ VV(VV_INSERTMODE, "insertmode", VAR_STRING, VV_RO),
+ VV(VV_VAL, "val", VAR_UNKNOWN, VV_RO),
+ VV(VV_KEY, "key", VAR_UNKNOWN, VV_RO),
+ VV(VV_PROFILING, "profiling", VAR_NUMBER, VV_RO),
+ VV(VV_FCS_REASON, "fcs_reason", VAR_STRING, VV_RO),
+ VV(VV_FCS_CHOICE, "fcs_choice", VAR_STRING, 0),
+ VV(VV_BEVAL_BUFNR, "beval_bufnr", VAR_NUMBER, VV_RO),
+ VV(VV_BEVAL_WINNR, "beval_winnr", VAR_NUMBER, VV_RO),
+ VV(VV_BEVAL_WINID, "beval_winid", VAR_NUMBER, VV_RO),
+ VV(VV_BEVAL_LNUM, "beval_lnum", VAR_NUMBER, VV_RO),
+ VV(VV_BEVAL_COL, "beval_col", VAR_NUMBER, VV_RO),
+ VV(VV_BEVAL_TEXT, "beval_text", VAR_STRING, VV_RO),
+ VV(VV_SCROLLSTART, "scrollstart", VAR_STRING, 0),
+ VV(VV_SWAPNAME, "swapname", VAR_STRING, VV_RO),
+ VV(VV_SWAPCHOICE, "swapchoice", VAR_STRING, 0),
+ VV(VV_SWAPCOMMAND, "swapcommand", VAR_STRING, VV_RO),
+ VV(VV_CHAR, "char", VAR_STRING, 0),
+ VV(VV_MOUSE_WIN, "mouse_win", VAR_NUMBER, 0),
+ VV(VV_MOUSE_WINID, "mouse_winid", VAR_NUMBER, 0),
+ VV(VV_MOUSE_LNUM, "mouse_lnum", VAR_NUMBER, 0),
+ VV(VV_MOUSE_COL, "mouse_col", VAR_NUMBER, 0),
+ VV(VV_OP, "operator", VAR_STRING, VV_RO),
+ VV(VV_SEARCHFORWARD, "searchforward", VAR_NUMBER, 0),
+ VV(VV_HLSEARCH, "hlsearch", VAR_NUMBER, 0),
+ VV(VV_OLDFILES, "oldfiles", VAR_LIST, 0),
+ VV(VV_WINDOWID, "windowid", VAR_NUMBER, VV_RO_SBX),
+ VV(VV_PROGPATH, "progpath", VAR_STRING, VV_RO),
+ VV(VV_COMPLETED_ITEM, "completed_item", VAR_DICT, VV_RO),
+ VV(VV_OPTION_NEW, "option_new", VAR_STRING, VV_RO),
+ VV(VV_OPTION_OLD, "option_old", VAR_STRING, VV_RO),
+ VV(VV_OPTION_OLDLOCAL, "option_oldlocal", VAR_STRING, VV_RO),
+ VV(VV_OPTION_OLDGLOBAL, "option_oldglobal", VAR_STRING, VV_RO),
+ VV(VV_OPTION_COMMAND, "option_command", VAR_STRING, VV_RO),
+ VV(VV_OPTION_TYPE, "option_type", VAR_STRING, VV_RO),
+ VV(VV_ERRORS, "errors", VAR_LIST, 0),
+ VV(VV_FALSE, "false", VAR_BOOL, VV_RO),
+ VV(VV_TRUE, "true", VAR_BOOL, VV_RO),
+ VV(VV_NULL, "null", VAR_SPECIAL, VV_RO),
+ VV(VV_NUMBERMAX, "numbermax", VAR_NUMBER, VV_RO),
+ VV(VV_NUMBERMIN, "numbermin", VAR_NUMBER, VV_RO),
+ VV(VV_NUMBERSIZE, "numbersize", VAR_NUMBER, VV_RO),
+ VV(VV_VIM_DID_ENTER, "vim_did_enter", VAR_NUMBER, VV_RO),
+ VV(VV_TESTING, "testing", VAR_NUMBER, 0),
+ VV(VV_TYPE_NUMBER, "t_number", VAR_NUMBER, VV_RO),
+ VV(VV_TYPE_STRING, "t_string", VAR_NUMBER, VV_RO),
+ VV(VV_TYPE_FUNC, "t_func", VAR_NUMBER, VV_RO),
+ VV(VV_TYPE_LIST, "t_list", VAR_NUMBER, VV_RO),
+ VV(VV_TYPE_DICT, "t_dict", VAR_NUMBER, VV_RO),
+ VV(VV_TYPE_FLOAT, "t_float", VAR_NUMBER, VV_RO),
+ VV(VV_TYPE_BOOL, "t_bool", VAR_NUMBER, VV_RO),
+ VV(VV_TYPE_BLOB, "t_blob", VAR_NUMBER, VV_RO),
+ VV(VV_EVENT, "event", VAR_DICT, VV_RO),
+ VV(VV_ECHOSPACE, "echospace", VAR_NUMBER, VV_RO),
+ VV(VV_ARGV, "argv", VAR_LIST, VV_RO),
+ VV(VV_COLLATE, "collate", VAR_STRING, VV_RO),
+ VV(VV_EXITING, "exiting", VAR_NUMBER, VV_RO),
// Neovim
- VV(VV_STDERR, "stderr", VAR_NUMBER, VV_RO),
- VV(VV_MSGPACK_TYPES, "msgpack_types", VAR_DICT, VV_RO),
- VV(VV__NULL_STRING, "_null_string", VAR_STRING, VV_RO),
- VV(VV__NULL_LIST, "_null_list", VAR_LIST, VV_RO),
- VV(VV__NULL_DICT, "_null_dict", VAR_DICT, VV_RO),
- VV(VV__NULL_BLOB, "_null_blob", VAR_BLOB, VV_RO),
- VV(VV_LUA, "lua", VAR_PARTIAL, VV_RO),
+ VV(VV_STDERR, "stderr", VAR_NUMBER, VV_RO),
+ VV(VV_MSGPACK_TYPES, "msgpack_types", VAR_DICT, VV_RO),
+ VV(VV__NULL_STRING, "_null_string", VAR_STRING, VV_RO),
+ VV(VV__NULL_LIST, "_null_list", VAR_LIST, VV_RO),
+ VV(VV__NULL_DICT, "_null_dict", VAR_DICT, VV_RO),
+ VV(VV__NULL_BLOB, "_null_blob", VAR_BLOB, VV_RO),
+ VV(VV_LUA, "lua", VAR_PARTIAL, VV_RO),
};
#undef VV
@@ -344,7 +349,7 @@ void eval_init(void)
for (size_t i = 0; i < ARRAY_SIZE(vimvars); i++) {
p = &vimvars[i];
- assert(STRLEN(p->vv_name) <= 16);
+ assert(STRLEN(p->vv_name) <= VIMVAR_KEY_LEN);
STRCPY(p->vv_di.di_key, p->vv_name);
if (p->vv_flags & VV_RO) {
p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
@@ -10446,11 +10451,15 @@ void option_last_set_msg(LastSet last_set)
}
}
-// reset v:option_new, v:option_old and v:option_type
+// reset v:option_new, v:option_old, v:option_oldlocal, v:option_oldglobal,
+// v:option_type, and v:option_command.
void reset_v_option_vars(void)
{
- set_vim_var_string(VV_OPTION_NEW, NULL, -1);
- set_vim_var_string(VV_OPTION_OLD, NULL, -1);
+ set_vim_var_string(VV_OPTION_NEW, NULL, -1);
+ set_vim_var_string(VV_OPTION_OLD, NULL, -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, NULL, -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, NULL, -1);
+ set_vim_var_string(VV_OPTION_COMMAND, NULL, -1);
set_vim_var_string(VV_OPTION_TYPE, NULL, -1);
}
diff --git a/src/nvim/eval.h b/src/nvim/eval.h
index d34348a274..986dda2408 100644
--- a/src/nvim/eval.h
+++ b/src/nvim/eval.h
@@ -138,6 +138,9 @@ typedef enum {
VV_COMPLETED_ITEM,
VV_OPTION_NEW,
VV_OPTION_OLD,
+ VV_OPTION_OLDLOCAL,
+ VV_OPTION_OLDGLOBAL,
+ VV_OPTION_COMMAND,
VV_OPTION_TYPE,
VV_ERRORS,
VV_FALSE,
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 45e2032b35..dbe90920cd 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -1301,7 +1301,11 @@ int do_set(char_u *arg, int opt_flags)
char_u *oldval = NULL; // previous value if *varp
char_u *newval;
char_u *origval = NULL;
+ char_u *origval_l = NULL;
+ char_u *origval_g = NULL;
char *saved_origval = NULL;
+ char *saved_origval_l = NULL;
+ char *saved_origval_g = NULL;
char *saved_newval = NULL;
unsigned newlen;
int comma;
@@ -1319,10 +1323,21 @@ int do_set(char_u *arg, int opt_flags)
// new value is valid.
oldval = *(char_u **)varp;
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
+ origval_l = *(char_u **)get_varp_scope(&(options[opt_idx]), OPT_LOCAL);
+ origval_g = *(char_u **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
+
+ // A global-local string option might have an empty
+ // option as value to indicate that the global
+ // value should be used.
+ if (((int)options[opt_idx].indir & PV_BOTH) && origval_l == empty_option) {
+ origval_l = origval_g;
+ }
+ }
+
// When setting the local value of a global
// option, the old value may be the global value.
- if (((int)options[opt_idx].indir & PV_BOTH) && (opt_flags
- & OPT_LOCAL)) {
+ if (((int)options[opt_idx].indir & PV_BOTH) && (opt_flags & OPT_LOCAL)) {
origval = *(char_u **)get_varp(&options[opt_idx]);
} else {
origval = oldval;
@@ -1388,6 +1403,12 @@ int do_set(char_u *arg, int opt_flags)
if (origval == oldval) {
origval = *(char_u **)varp;
}
+ if (origval_l == oldval) {
+ origval_l = *(char_u **)varp;
+ }
+ if (origval_g == oldval) {
+ origval_g = *(char_u **)varp;
+ }
oldval = *(char_u **)varp;
}
/*
@@ -1596,6 +1617,8 @@ int do_set(char_u *arg, int opt_flags)
// origval may be freed by
// did_set_string_option(), make a copy.
saved_origval = (origval != NULL) ? xstrdup((char *)origval) : 0;
+ saved_origval_l = (origval_l != NULL) ? xstrdup((char *)origval_l) : 0;
+ saved_origval_g = (origval_g != NULL) ? xstrdup((char *)origval_g) : 0;
// newval (and varp) may become invalid if the
// buffer is closed by autocommands.
@@ -1630,8 +1653,8 @@ int do_set(char_u *arg, int opt_flags)
if (errmsg == NULL) {
if (!starting) {
- trigger_optionsset_string(opt_idx, opt_flags, saved_origval,
- saved_newval);
+ trigger_optionsset_string(opt_idx, opt_flags, saved_origval, saved_origval_l,
+ saved_origval_g, saved_newval);
}
if (options[opt_idx].flags & P_UI_OPTION) {
ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
@@ -1639,6 +1662,8 @@ int do_set(char_u *arg, int opt_flags)
}
}
xfree(saved_origval);
+ xfree(saved_origval_l);
+ xfree(saved_origval_g);
xfree(saved_newval);
// If error detected, print the error message.
@@ -2233,9 +2258,19 @@ static char *set_string_option(const int opt_idx, const char *const value, const
? OPT_GLOBAL : OPT_LOCAL)
: opt_flags));
char *const oldval = *varp;
+ char *oldval_l = NULL;
+ char *oldval_g = NULL;
+
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
+ oldval_l = *(char **)get_varp_scope(&(options[opt_idx]), OPT_LOCAL);
+ oldval_g = *(char **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
+ }
+
*varp = s;
char *const saved_oldval = xstrdup(oldval);
+ char *const saved_oldval_l = (oldval_l != NULL) ? xstrdup((char *)oldval_l) : 0;
+ char *const saved_oldval_g = (oldval_g != NULL) ? xstrdup((char *)oldval_g) : 0;
char *const saved_newval = xstrdup(s);
int value_checked = false;
@@ -2249,7 +2284,8 @@ static char *set_string_option(const int opt_idx, const char *const value, const
// call autocommand after handling side effects
if (r == NULL) {
if (!starting) {
- trigger_optionsset_string(opt_idx, opt_flags, saved_oldval, saved_newval);
+ trigger_optionsset_string(opt_idx, opt_flags, saved_oldval, saved_oldval_l, saved_oldval_g,
+ saved_newval);
}
if (options[opt_idx].flags & P_UI_OPTION) {
ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
@@ -2257,6 +2293,8 @@ static char *set_string_option(const int opt_idx, const char *const value, const
}
}
xfree(saved_oldval);
+ xfree(saved_oldval_l);
+ xfree(saved_oldval_g);
xfree(saved_newval);
return r;
@@ -3851,6 +3889,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
const int opt_flags)
{
int old_value = *(int *)varp;
+ int old_global_value = 0;
// Disallow changing some options from secure mode
if ((secure || sandbox != 0)
@@ -3858,6 +3897,13 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
return (char *)e_secure;
}
+ // Save the global value before changing anything. This is needed as for
+ // a global-only option setting the "local value" in fact sets the global
+ // value (since there is only one value).
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
+ old_global_value = *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
+ }
+
*(int *)varp = value; // set the new value
// Remember where the option was set.
set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
@@ -4134,20 +4180,35 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
// Don't do this while starting up or recursively.
if (!starting && *get_vim_var_str(VV_OPTION_TYPE) == NUL) {
char buf_old[2];
+ char buf_old_global[2];
char buf_new[2];
char buf_type[7];
- vim_snprintf(buf_old, ARRAY_SIZE(buf_old), "%d",
- old_value ? true: false);
- vim_snprintf(buf_new, ARRAY_SIZE(buf_new), "%d",
- value ? true: false);
+ vim_snprintf(buf_old, ARRAY_SIZE(buf_old), "%d", old_value ? true : false);
+ vim_snprintf(buf_old_global, ARRAY_SIZE(buf_old_global), "%d", old_global_value ? true : false);
+ vim_snprintf(buf_new, ARRAY_SIZE(buf_new), "%d", value ? true : false);
vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s",
(opt_flags & OPT_LOCAL) ? "local" : "global");
set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
- apply_autocmds(EVENT_OPTIONSET,
- (char_u *)options[opt_idx].fullname,
- NULL, false, NULL);
+ if (opt_flags & OPT_LOCAL) {
+ set_vim_var_string(VV_OPTION_COMMAND, "setlocal", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ }
+ if (opt_flags & OPT_GLOBAL) {
+ set_vim_var_string(VV_OPTION_COMMAND, "setglobal", -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
+ }
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
+ set_vim_var_string(VV_OPTION_COMMAND, "set", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
+ }
+ if (opt_flags & OPT_MODELINE) {
+ set_vim_var_string(VV_OPTION_COMMAND, "modeline", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ }
+ apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname, NULL, false, NULL);
reset_v_option_vars();
}
@@ -4181,7 +4242,8 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
{
char *errmsg = NULL;
long old_value = *(long *)varp;
- long old_Rows = Rows; // remember old Rows
+ long old_global_value = 0; // only used when setting a local and global option
+ long old_Rows = Rows; // remember old Rows
long *pp = (long *)varp;
// Disallow changing some options from secure mode.
@@ -4190,6 +4252,13 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
return e_secure;
}
+ // Save the global value before changing anything. This is needed as for
+ // a global-only option setting the "local value" infact sets the global
+ // value (since there is only one value).
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
+ old_global_value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
+ }
+
// Many number options assume their value is in the signed int range.
if (value < INT_MIN || value > INT_MAX) {
return e_invarg;
@@ -4534,19 +4603,36 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
// Don't do this while starting up, failure or recursively.
if (!starting && errmsg == NULL && *get_vim_var_str(VV_OPTION_TYPE) == NUL) {
char buf_old[NUMBUFLEN];
+ char buf_old_global[NUMBUFLEN];
char buf_new[NUMBUFLEN];
char buf_type[7];
vim_snprintf(buf_old, ARRAY_SIZE(buf_old), "%ld", old_value);
+ vim_snprintf(buf_old_global, ARRAY_SIZE(buf_old_global), "%ld", old_global_value);
vim_snprintf(buf_new, ARRAY_SIZE(buf_new), "%ld", value);
vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s",
(opt_flags & OPT_LOCAL) ? "local" : "global");
set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
- apply_autocmds(EVENT_OPTIONSET,
- (char_u *)options[opt_idx].fullname,
- NULL, false, NULL);
+ if (opt_flags & OPT_LOCAL) {
+ set_vim_var_string(VV_OPTION_COMMAND, "setlocal", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ }
+ if (opt_flags & OPT_GLOBAL) {
+ set_vim_var_string(VV_OPTION_COMMAND, "setglobal", -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
+ }
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
+ set_vim_var_string(VV_OPTION_COMMAND, "set", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
+ }
+ if (opt_flags & OPT_MODELINE) {
+ set_vim_var_string(VV_OPTION_COMMAND, "modeline", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ }
+ apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname, NULL, false, NULL);
reset_v_option_vars();
}
@@ -4565,7 +4651,15 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
return (char *)errmsg;
}
-static void trigger_optionsset_string(int opt_idx, int opt_flags, char *oldval, char *newval)
+/// Trigger the OptionSet autocommand.
+/// "opt_idx" is the index of the option being set.
+/// "opt_flags" can be OPT_LOCAL etc.
+/// "oldval" the old value
+/// "oldval_l" the old local value (only non-NULL if global and local value are set)
+/// "oldval_g" the old global value (only non-NULL if global and local value are set)
+/// "newval" the new value
+static void trigger_optionsset_string(int opt_idx, int opt_flags, char *oldval, char *oldval_l,
+ char *oldval_g, char *newval)
{
// Don't do this recursively.
if (oldval != NULL
@@ -4578,8 +4672,24 @@ static void trigger_optionsset_string(int opt_idx, int opt_flags, char *oldval,
set_vim_var_string(VV_OPTION_OLD, oldval, -1);
set_vim_var_string(VV_OPTION_NEW, newval, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
- apply_autocmds(EVENT_OPTIONSET,
- (char_u *)options[opt_idx].fullname, NULL, false, NULL);
+ if (opt_flags & OPT_LOCAL) {
+ set_vim_var_string(VV_OPTION_COMMAND, "setlocal", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
+ }
+ if (opt_flags & OPT_GLOBAL) {
+ set_vim_var_string(VV_OPTION_COMMAND, "setglobal", -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1);
+ }
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
+ set_vim_var_string(VV_OPTION_COMMAND, "set", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1);
+ }
+ if (opt_flags & OPT_MODELINE) {
+ set_vim_var_string(VV_OPTION_COMMAND, "modeline", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
+ }
+ apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname, NULL, false, NULL);
reset_v_option_vars();
}
}
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 0c8b8a45d9..7835556a47 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -580,9 +580,10 @@ func Test_empty_doau()
endfunc
func s:AutoCommandOptionSet(match)
+ let template = "Option: <%s>, OldVal: <%s>, OldValLocal: <%s>, OldValGlobal: <%s>, NewVal: <%s>, Scope: <%s>, Command: <%s>\n"
let item = remove(g:options, 0)
- let expected = printf("Option: <%s>, Oldval: <%s>, NewVal: <%s>, Scope: <%s>\n", item[0], item[1], item[2], item[3])
- let actual = printf("Option: <%s>, Oldval: <%s>, NewVal: <%s>, Scope: <%s>\n", a:match, v:option_old, v:option_new, v:option_type)
+ let expected = printf(template, item[0], item[1], item[2], item[3], item[4], item[5], item[6])
+ let actual = printf(template, a:match, v:option_old, v:option_oldlocal, v:option_oldglobal, v:option_new, v:option_type, v:option_command)
let g:opt = [expected, actual]
"call assert_equal(expected, actual)
endfunc
@@ -596,130 +597,593 @@ func Test_OptionSet()
au OptionSet * :call s:AutoCommandOptionSet(expand("<amatch>"))
" 1: Setting number option"
- let g:options = [['number', 0, 1, 'global']]
+ let g:options = [['number', 0, 0, 0, 1, 'global', 'set']]
set nu
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 2: Setting local number option"
- let g:options = [['number', 1, 0, 'local']]
+ let g:options = [['number', 1, 1, '', 0, 'local', 'setlocal']]
setlocal nonu
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 3: Setting global number option"
- let g:options = [['number', 1, 0, 'global']]
+ let g:options = [['number', 1, '', 1, 0, 'global', 'setglobal']]
setglobal nonu
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 4: Setting local autoindent option"
- let g:options = [['autoindent', 0, 1, 'local']]
+ let g:options = [['autoindent', 0, 0, '', 1, 'local', 'setlocal']]
setlocal ai
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 5: Setting global autoindent option"
- let g:options = [['autoindent', 0, 1, 'global']]
+ let g:options = [['autoindent', 0, '', 0, 1, 'global', 'setglobal']]
setglobal ai
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 6: Setting global autoindent option"
- let g:options = [['autoindent', 1, 0, 'global']]
+ let g:options = [['autoindent', 1, 1, 1, 0, 'global', 'set']]
+ set ai!
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 6a: Setting global autoindent option"
+ let g:options = [['autoindent', 1, 1, 0, 0, 'global', 'set']]
+ noa setlocal ai
+ noa setglobal noai
set ai!
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" Should not print anything, use :noa
" 7: don't trigger OptionSet"
- let g:options = [['invalid', 1, 1, 'invalid']]
+ let g:options = [['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']]
noa set nonu
- call assert_equal([['invalid', 1, 1, 'invalid']], g:options)
+ call assert_equal([['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 8: Setting several global list and number option"
- let g:options = [['list', 0, 1, 'global'], ['number', 0, 1, 'global']]
+ let g:options = [['list', 0, 0, 0, 1, 'global', 'set'], ['number', 0, 0, 0, 1, 'global', 'set']]
set list nu
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 9: don't trigger OptionSet"
- let g:options = [['invalid', 1, 1, 'invalid'], ['invalid', 1, 1, 'invalid']]
+ let g:options = [['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid'], ['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']]
noa set nolist nonu
- call assert_equal([['invalid', 1, 1, 'invalid'], ['invalid', 1, 1, 'invalid']], g:options)
+ call assert_equal([['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid'], ['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 10: Setting global acd"
- let g:options = [['autochdir', 0, 1, 'local']]
+ let g:options = [['autochdir', 0, 0, '', 1, 'local', 'setlocal']]
setlocal acd
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 11: Setting global autoread (also sets local value)"
- let g:options = [['autoread', 0, 1, 'global']]
+ let g:options = [['autoread', 0, 0, 0, 1, 'global', 'set']]
set ar
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 12: Setting local autoread"
- let g:options = [['autoread', 1, 1, 'local']]
+ let g:options = [['autoread', 1, 1, '', 1, 'local', 'setlocal']]
setlocal ar
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 13: Setting global autoread"
- let g:options = [['autoread', 1, 0, 'global']]
+ let g:options = [['autoread', 1, '', 1, 0, 'global', 'setglobal']]
setglobal invar
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 14: Setting option backspace through :let"
- let g:options = [['backspace', '', 'eol,indent,start', 'global']]
+ let g:options = [['backspace', '', '', '', 'eol,indent,start', 'global', 'set']]
let &bs = "eol,indent,start"
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 15: Setting option backspace through setbufvar()"
- let g:options = [['backup', 0, 1, 'local']]
+ let g:options = [['backup', 0, 0, '', 1, 'local', 'setlocal']]
" try twice, first time, shouldn't trigger because option name is invalid,
" second time, it should trigger
- call assert_fails("call setbufvar(1, '&l:bk', 1)", "E355")
+ let bnum = bufnr('%')
+ call assert_fails("call setbufvar(bnum, '&l:bk', 1)", 'E355:')
" should trigger, use correct option name
- call setbufvar(1, '&backup', 1)
+ call setbufvar(bnum, '&backup', 1)
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 16: Setting number option using setwinvar"
- let g:options = [['number', 0, 1, 'local']]
+ let g:options = [['number', 0, 0, '', 1, 'local', 'setlocal']]
call setwinvar(0, '&number', 1)
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 17: Setting key option, shouldn't trigger"
- let g:options = [['key', 'invalid', 'invalid1', 'invalid']]
+ let g:options = [['key', 'invalid', 'invalid1', 'invalid2', 'invalid3', 'invalid4', 'invalid5']]
setlocal key=blah
setlocal key=
- call assert_equal([['key', 'invalid', 'invalid1', 'invalid']], g:options)
+ call assert_equal([['key', 'invalid', 'invalid1', 'invalid2', 'invalid3', 'invalid4', 'invalid5']], g:options)
call assert_equal(g:opt[0], g:opt[1])
- " 18: Setting string option"
+
+ " 18a: Setting string global option"
+ let oldval = &backupext
+ let g:options = [['backupext', oldval, oldval, oldval, 'foo', 'global', 'set']]
+ set backupext=foo
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 18b: Resetting string global option"
+ let g:options = [['backupext', 'foo', 'foo', 'foo', oldval, 'global', 'set']]
+ set backupext&
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 18c: Setting global string global option"
+ let g:options = [['backupext', oldval, '', oldval, 'bar', 'global', 'setglobal']]
+ setglobal backupext=bar
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 18d: Setting local string global option"
+ " As this is a global option this sets the global value even though
+ " :setlocal is used!
+ noa set backupext& " Reset global and local value (without triggering autocmd)
+ let g:options = [['backupext', oldval, oldval, '', 'baz', 'local', 'setlocal']]
+ setlocal backupext=baz
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 18e: Setting again string global option"
+ noa setglobal backupext=ext_global " Reset global and local value (without triggering autocmd)
+ noa setlocal backupext=ext_local " Sets the global(!) value!
+ let g:options = [['backupext', 'ext_local', 'ext_local', 'ext_local', 'fuu', 'global', 'set']]
+ set backupext=fuu
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 19a: Setting string local-global (to buffer) option"
let oldval = &tags
- let g:options = [['tags', oldval, 'tagpath', 'global']]
+ let g:options = [['tags', oldval, oldval, oldval, 'tagpath', 'global', 'set']]
set tags=tagpath
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
- " 1l: Resetting string option"
- let g:options = [['tags', 'tagpath', oldval, 'global']]
+ " 19b: Resetting string local-global (to buffer) option"
+ let g:options = [['tags', 'tagpath', 'tagpath', 'tagpath', oldval, 'global', 'set']]
set tags&
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
+ " 19c: Setting global string local-global (to buffer) option "
+ let g:options = [['tags', oldval, '', oldval, 'tagpath1', 'global', 'setglobal']]
+ setglobal tags=tagpath1
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 19d: Setting local string local-global (to buffer) option"
+ let g:options = [['tags', 'tagpath1', 'tagpath1', '', 'tagpath2', 'local', 'setlocal']]
+ setlocal tags=tagpath2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 19e: Setting again string local-global (to buffer) option"
+ " Note: v:option_old is the old global value for local-global string options
+ " but the old local value for all other kinds of options.
+ noa setglobal tags=tag_global " Reset global and local value (without triggering autocmd)
+ noa setlocal tags=tag_local
+ let g:options = [['tags', 'tag_global', 'tag_local', 'tag_global', 'tagpath', 'global', 'set']]
+ set tags=tagpath
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 19f: Setting string local-global (to buffer) option to an empty string"
+ " Note: v:option_old is the old global value for local-global string options
+ " but the old local value for all other kinds of options.
+ noa set tags=tag_global " Reset global and local value (without triggering autocmd)
+ noa setlocal tags= " empty string
+ let g:options = [['tags', 'tag_global', '', 'tag_global', 'tagpath', 'global', 'set']]
+ set tags=tagpath
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 20a: Setting string local (to buffer) option"
+ let oldval = &spelllang
+ let g:options = [['spelllang', oldval, oldval, oldval, 'elvish,klingon', 'global', 'set']]
+ set spelllang=elvish,klingon
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 20b: Resetting string local (to buffer) option"
+ let g:options = [['spelllang', 'elvish,klingon', 'elvish,klingon', 'elvish,klingon', oldval, 'global', 'set']]
+ set spelllang&
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 20c: Setting global string local (to buffer) option"
+ let g:options = [['spelllang', oldval, '', oldval, 'elvish', 'global', 'setglobal']]
+ setglobal spelllang=elvish
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 20d: Setting local string local (to buffer) option"
+ noa set spelllang& " Reset global and local value (without triggering autocmd)
+ let g:options = [['spelllang', oldval, oldval, '', 'klingon', 'local', 'setlocal']]
+ setlocal spelllang=klingon
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 20e: Setting again string local (to buffer) option"
+ " Note: v:option_old is the old global value for local-global string options
+ " but the old local value for all other kinds of options.
+ noa setglobal spelllang=spellglobal " Reset global and local value (without triggering autocmd)
+ noa setlocal spelllang=spelllocal
+ let g:options = [['spelllang', 'spelllocal', 'spelllocal', 'spellglobal', 'foo', 'global', 'set']]
+ set spelllang=foo
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 21a: Setting string local-global (to window) option"
+ let oldval = &statusline
+ let g:options = [['statusline', oldval, oldval, oldval, 'foo', 'global', 'set']]
+ set statusline=foo
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 21b: Resetting string local-global (to window) option"
+ " Note: v:option_old is the old global value for local-global string options
+ " but the old local value for all other kinds of options.
+ let g:options = [['statusline', 'foo', 'foo', 'foo', oldval, 'global', 'set']]
+ set statusline&
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 21c: Setting global string local-global (to window) option"
+ let g:options = [['statusline', oldval, '', oldval, 'bar', 'global', 'setglobal']]
+ setglobal statusline=bar
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 21d: Setting local string local-global (to window) option"
+ noa set statusline& " Reset global and local value (without triggering autocmd)
+ let g:options = [['statusline', oldval, oldval, '', 'baz', 'local', 'setlocal']]
+ setlocal statusline=baz
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 21e: Setting again string local-global (to window) option"
+ " Note: v:option_old is the old global value for local-global string options
+ " but the old local value for all other kinds of options.
+ noa setglobal statusline=bar " Reset global and local value (without triggering autocmd)
+ noa setlocal statusline=baz
+ let g:options = [['statusline', 'bar', 'baz', 'bar', 'foo', 'global', 'set']]
+ set statusline=foo
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 22a: Setting string local (to window) option"
+ let oldval = &foldignore
+ let g:options = [['foldignore', oldval, oldval, oldval, 'fo', 'global', 'set']]
+ set foldignore=fo
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 22b: Resetting string local (to window) option"
+ let g:options = [['foldignore', 'fo', 'fo', 'fo', oldval, 'global', 'set']]
+ set foldignore&
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 22c: Setting global string local (to window) option"
+ let g:options = [['foldignore', oldval, '', oldval, 'bar', 'global', 'setglobal']]
+ setglobal foldignore=bar
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 22d: Setting local string local (to window) option"
+ noa set foldignore& " Reset global and local value (without triggering autocmd)
+ let g:options = [['foldignore', oldval, oldval, '', 'baz', 'local', 'setlocal']]
+ setlocal foldignore=baz
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 22e: Setting again string local (to window) option"
+ noa setglobal foldignore=glob " Reset global and local value (without triggering autocmd)
+ noa setlocal foldignore=loc
+ let g:options = [['foldignore', 'loc', 'loc', 'glob', 'fo', 'global', 'set']]
+ set foldignore=fo
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 23a: Setting global number local option"
+ noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
+ noa setlocal cmdheight=1 " Sets the global(!) value!
+ let g:options = [['cmdheight', '1', '', '1', '2', 'global', 'setglobal']]
+ setglobal cmdheight=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 23b: Setting local number global option"
+ noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
+ noa setlocal cmdheight=1 " Sets the global(!) value!
+ let g:options = [['cmdheight', '1', '1', '', '2', 'local', 'setlocal']]
+ setlocal cmdheight=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 23c: Setting again number global option"
+ noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
+ noa setlocal cmdheight=1 " Sets the global(!) value!
+ let g:options = [['cmdheight', '1', '1', '1', '2', 'global', 'set']]
+ set cmdheight=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 23d: Setting again number global option"
+ noa set cmdheight=8 " Reset global and local value (without triggering autocmd)
+ let g:options = [['cmdheight', '8', '8', '8', '2', 'global', 'set']]
+ set cmdheight=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 24a: Setting global number global-local (to buffer) option"
+ noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd)
+ noa setlocal undolevels=1
+ let g:options = [['undolevels', '8', '', '8', '2', 'global', 'setglobal']]
+ setglobal undolevels=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 24b: Setting local number global-local (to buffer) option"
+ noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd)
+ noa setlocal undolevels=1
+ let g:options = [['undolevels', '1', '1', '', '2', 'local', 'setlocal']]
+ setlocal undolevels=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 24c: Setting again number global-local (to buffer) option"
+ noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd)
+ noa setlocal undolevels=1
+ let g:options = [['undolevels', '1', '1', '8', '2', 'global', 'set']]
+ set undolevels=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 24d: Setting again global number global-local (to buffer) option"
+ noa set undolevels=8 " Reset global and local value (without triggering autocmd)
+ let g:options = [['undolevels', '8', '8', '8', '2', 'global', 'set']]
+ set undolevels=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 25a: Setting global number local (to buffer) option"
+ noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd)
+ noa setlocal wrapmargin=1
+ let g:options = [['wrapmargin', '8', '', '8', '2', 'global', 'setglobal']]
+ setglobal wrapmargin=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 25b: Setting local number local (to buffer) option"
+ noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd)
+ noa setlocal wrapmargin=1
+ let g:options = [['wrapmargin', '1', '1', '', '2', 'local', 'setlocal']]
+ setlocal wrapmargin=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 25c: Setting again number local (to buffer) option"
+ noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd)
+ noa setlocal wrapmargin=1
+ let g:options = [['wrapmargin', '1', '1', '8', '2', 'global', 'set']]
+ set wrapmargin=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 25d: Setting again global number local (to buffer) option"
+ noa set wrapmargin=8 " Reset global and local value (without triggering autocmd)
+ let g:options = [['wrapmargin', '8', '8', '8', '2', 'global', 'set']]
+ set wrapmargin=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 26: Setting number global-local (to window) option.
+ " Such option does currently not exist.
+
+
+ " 27a: Setting global number local (to window) option"
+ noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd)
+ noa setlocal foldcolumn=1
+ let g:options = [['foldcolumn', '8', '', '8', '2', 'global', 'setglobal']]
+ setglobal foldcolumn=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 27b: Setting local number local (to window) option"
+ noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd)
+ noa setlocal foldcolumn=1
+ let g:options = [['foldcolumn', '1', '1', '', '2', 'local', 'setlocal']]
+ setlocal foldcolumn=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 27c: Setting again number local (to window) option"
+ noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd)
+ noa setlocal foldcolumn=1
+ let g:options = [['foldcolumn', '1', '1', '8', '2', 'global', 'set']]
+ set foldcolumn=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 27d: Ssettin again global number local (to window) option"
+ noa set foldcolumn=8 " Reset global and local value (without triggering autocmd)
+ let g:options = [['foldcolumn', '8', '8', '8', '2', 'global', 'set']]
+ set foldcolumn=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 28a: Setting global boolean global option"
+ noa setglobal nowrapscan " Reset global and local value (without triggering autocmd)
+ noa setlocal wrapscan " Sets the global(!) value!
+ let g:options = [['wrapscan', '1', '', '1', '0', 'global', 'setglobal']]
+ setglobal nowrapscan
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 28b: Setting local boolean global option"
+ noa setglobal nowrapscan " Reset global and local value (without triggering autocmd)
+ noa setlocal wrapscan " Sets the global(!) value!
+ let g:options = [['wrapscan', '1', '1', '', '0', 'local', 'setlocal']]
+ setlocal nowrapscan
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 28c: Setting again boolean global option"
+ noa setglobal nowrapscan " Reset global and local value (without triggering autocmd)
+ noa setlocal wrapscan " Sets the global(!) value!
+ let g:options = [['wrapscan', '1', '1', '1', '0', 'global', 'set']]
+ set nowrapscan
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 28d: Setting again global boolean global option"
+ noa set nowrapscan " Reset global and local value (without triggering autocmd)
+ let g:options = [['wrapscan', '0', '0', '0', '1', 'global', 'set']]
+ set wrapscan
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 29a: Setting global boolean global-local (to buffer) option"
+ noa setglobal noautoread " Reset global and local value (without triggering autocmd)
+ noa setlocal autoread
+ let g:options = [['autoread', '0', '', '0', '1', 'global', 'setglobal']]
+ setglobal autoread
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 29b: Setting local boolean global-local (to buffer) option"
+ noa setglobal noautoread " Reset global and local value (without triggering autocmd)
+ noa setlocal autoread
+ let g:options = [['autoread', '1', '1', '', '0', 'local', 'setlocal']]
+ setlocal noautoread
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 29c: Setting again boolean global-local (to buffer) option"
+ noa setglobal noautoread " Reset global and local value (without triggering autocmd)
+ noa setlocal autoread
+ let g:options = [['autoread', '1', '1', '0', '1', 'global', 'set']]
+ set autoread
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 29d: Setting again global boolean global-local (to buffer) option"
+ noa set noautoread " Reset global and local value (without triggering autocmd)
+ let g:options = [['autoread', '0', '0', '0', '1', 'global', 'set']]
+ set autoread
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 30a: Setting global boolean local (to buffer) option"
+ noa setglobal nocindent " Reset global and local value (without triggering autocmd)
+ noa setlocal cindent
+ let g:options = [['cindent', '0', '', '0', '1', 'global', 'setglobal']]
+ setglobal cindent
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 30b: Setting local boolean local (to buffer) option"
+ noa setglobal nocindent " Reset global and local value (without triggering autocmd)
+ noa setlocal cindent
+ let g:options = [['cindent', '1', '1', '', '0', 'local', 'setlocal']]
+ setlocal nocindent
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 30c: Setting again boolean local (to buffer) option"
+ noa setglobal nocindent " Reset global and local value (without triggering autocmd)
+ noa setlocal cindent
+ let g:options = [['cindent', '1', '1', '0', '1', 'global', 'set']]
+ set cindent
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 30d: Setting again global boolean local (to buffer) option"
+ noa set nocindent " Reset global and local value (without triggering autocmd)
+ let g:options = [['cindent', '0', '0', '0', '1', 'global', 'set']]
+ set cindent
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 31: Setting boolean global-local (to window) option
+ " Currently no such option exists.
+
+
+ " 32a: Setting global boolean local (to window) option"
+ noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd)
+ noa setlocal cursorcolumn
+ let g:options = [['cursorcolumn', '0', '', '0', '1', 'global', 'setglobal']]
+ setglobal cursorcolumn
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 32b: Setting local boolean local (to window) option"
+ noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd)
+ noa setlocal cursorcolumn
+ let g:options = [['cursorcolumn', '1', '1', '', '0', 'local', 'setlocal']]
+ setlocal nocursorcolumn
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 32c: Setting again boolean local (to window) option"
+ noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd)
+ noa setlocal cursorcolumn
+ let g:options = [['cursorcolumn', '1', '1', '0', '1', 'global', 'set']]
+ set cursorcolumn
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+ " 32d: Setting again global boolean local (to window) option"
+ noa set nocursorcolumn " Reset global and local value (without triggering autocmd)
+ let g:options = [['cursorcolumn', '0', '0', '0', '1', 'global', 'set']]
+ set cursorcolumn
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
+ " 33: Test autocommands when an option value is converted internally.
+ noa set backspace=1 " Reset global and local value (without triggering autocmd)
+ let g:options = [['backspace', 'indent,eol', 'indent,eol', 'indent,eol', '2', 'global', 'set']]
+ set backspace=2
+ call assert_equal([], g:options)
+ call assert_equal(g:opt[0], g:opt[1])
+
+
" Cleanup
au! OptionSet
" set tags&
- for opt in ['nu', 'ai', 'acd', 'ar', 'bs', 'backup', 'cul', 'cp', 'tags']
+ for opt in ['nu', 'ai', 'acd', 'ar', 'bs', 'backup', 'cul', 'cp', 'backupext', 'tags', 'spelllang', 'statusline', 'foldignore', 'cmdheight', 'undolevels', 'wrapmargin', 'foldcolumn', 'wrapscan', 'autoread', 'cindent', 'cursorcolumn']
exe printf(":set %s&vim", opt)
endfor
call test_override('starting', 0)
diff --git a/test/functional/legacy/autocmd_option_spec.lua b/test/functional/legacy/autocmd_option_spec.lua
index 1914818215..5e586d3a6a 100644
--- a/test/functional/legacy/autocmd_option_spec.lua
+++ b/test/functional/legacy/autocmd_option_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local nvim = helpers.meths
-local clear, eq, neq = helpers.clear, helpers.eq, helpers.neq
+local clear, eq, neq, eval = helpers.clear, helpers.eq, helpers.neq, helpers.eval
local curbuf, buf = helpers.curbuf, helpers.bufmeths
local curwin = helpers.curwin
local exec_capture = helpers.exec_capture
@@ -10,11 +10,14 @@ local function declare_hook_function()
source([[
fu! AutoCommand(match, bufnr, winnr)
let l:acc = {
- \ 'option' : a:match,
- \ 'oldval' : v:option_old,
- \ 'newval' : v:option_new,
- \ 'scope' : v:option_type,
- \ 'attr' : {
+ \ 'option' : a:match,
+ \ 'oldval' : v:option_old,
+ \ 'oldval_l' : v:option_oldlocal,
+ \ 'oldval_g' : v:option_oldglobal,
+ \ 'newval' : v:option_new,
+ \ 'scope' : v:option_type,
+ \ 'cmd' : v:option_command,
+ \ 'attr' : {
\ 'bufnr' : a:bufnr,
\ 'winnr' : a:winnr,
\ }
@@ -42,13 +45,16 @@ local function get_result()
return ret
end
-local function expected_table(option, oldval, newval, scope, attr)
+local function expected_table(option, oldval, oldval_l, oldval_g, newval, scope, cmd, attr)
return {
- option = option,
- oldval = tostring(oldval),
- newval = tostring(newval),
- scope = scope,
- attr = attr,
+ option = option,
+ oldval = tostring(oldval),
+ oldval_l = tostring(oldval_l),
+ oldval_g = tostring(oldval_g),
+ newval = tostring(newval),
+ scope = scope,
+ cmd = cmd,
+ attr = attr,
}
end
@@ -66,7 +72,7 @@ local function expected_combination(...)
end
for i, v in ipairs(args) do
- local attr = v[5]
+ local attr = v[8]
if not attr then
-- remove attr entries
ret[i].attr = nil
@@ -112,7 +118,7 @@ local function get_new_window_number()
end
describe('au OptionSet', function()
- describe('with any opton (*)', function()
+ describe('with any option (*)', function()
before_each(function()
clear()
@@ -123,44 +129,44 @@ describe('au OptionSet', function()
it('should be called in setting number option', function()
command('set nu')
- expected_combination({'number', 0, 1, 'global'})
+ expected_combination({'number', 0, 0, 0, 1, 'global', 'set'})
command('setlocal nonu')
- expected_combination({'number', 1, 0, 'local'})
+ expected_combination({'number', 1, 1, '', 0, 'local', 'setlocal'})
command('setglobal nonu')
- expected_combination({'number', 1, 0, 'global'})
+ expected_combination({'number', 1, '', 1, 0, 'global', 'setglobal'})
end)
it('should be called in setting autoindent option',function()
command('setlocal ai')
- expected_combination({'autoindent', 0, 1, 'local'})
+ expected_combination({'autoindent', 0, 0, '', 1, 'local', 'setlocal'})
command('setglobal ai')
- expected_combination({'autoindent', 0, 1, 'global'})
+ expected_combination({'autoindent', 0, '', 0, 1, 'global', 'setglobal'})
command('set noai')
- expected_combination({'autoindent', 1, 0, 'global'})
+ expected_combination({'autoindent', 1, 1, 1, 0, 'global', 'set'})
end)
it('should be called in inverting global autoindent option',function()
command('set ai!')
- expected_combination({'autoindent', 0, 1, 'global'})
+ expected_combination({'autoindent', 0, 0, 0, 1, 'global', 'set'})
end)
it('should be called in being unset local autoindent option',function()
command('setlocal ai')
- expected_combination({'autoindent', 0, 1, 'local'})
+ expected_combination({'autoindent', 0, 0, '', 1, 'local', 'setlocal'})
command('setlocal ai<')
- expected_combination({'autoindent', 1, 0, 'local'})
+ expected_combination({'autoindent', 1, 1, '', 0, 'local', 'setlocal'})
end)
it('should be called in setting global list and number option at the same time',function()
command('set list nu')
expected_combination(
- {'list', 0, 1, 'global'},
- {'number', 0, 1, 'global'}
+ {'list', 0, 0, 0, 1, 'global', 'set'},
+ {'number', 0, 0, 0, 1, 'global', 'set'}
)
end)
@@ -171,25 +177,27 @@ describe('au OptionSet', function()
it('should be called in setting local acd', function()
command('setlocal acd')
- expected_combination({'autochdir', 0, 1, 'local'})
+ expected_combination({'autochdir', 0, 0, '', 1, 'local', 'setlocal'})
end)
it('should be called in setting autoread', function()
command('set noar')
- expected_combination({'autoread', 1, 0, 'global'})
+ expected_combination({'autoread', 1, 1, 1, 0, 'global', 'set'})
command('setlocal ar')
- expected_combination({'autoread', 0, 1, 'local'})
+ expected_combination({'autoread', 0, 0, '', 1, 'local', 'setlocal'})
end)
it('should be called in inverting global autoread', function()
command('setglobal invar')
- expected_combination({'autoread', 1, 0, 'global'})
+ expected_combination({'autoread', 1, '', 1, 0, 'global', 'setglobal'})
end)
it('should be called in setting backspace option through :let', function()
+ local oldval = eval('&backspace')
+
command('let &bs=""')
- expected_combination({'backspace', 'indent,eol,start', '', 'global'})
+ expected_combination({'backspace', oldval, oldval, oldval, '', 'global', 'set'})
end)
describe('being set by setbufvar()', function()
@@ -200,7 +208,7 @@ describe('au OptionSet', function()
it('should trigger using correct option name', function()
command('call setbufvar(1, "&backup", 1)')
- expected_combination({'backup', 0, 1, 'local'})
+ expected_combination({'backup', 0, 0, '', 1, 'local', 'setlocal'})
end)
it('should trigger if the current buffer is different from the targetted buffer', function()
@@ -208,9 +216,339 @@ describe('au OptionSet', function()
local new_bufnr = buf.get_number(new_buffer)
command('call setbufvar(' .. new_bufnr .. ', "&buftype", "nofile")')
- expected_combination({'buftype', '', 'nofile', 'local', {bufnr = new_bufnr}})
+ expected_combination({'buftype', '', '', '', 'nofile', 'local', 'setlocal', {bufnr = new_bufnr}})
end)
end)
+
+ it('with string global option', function()
+ local oldval = eval('&backupext')
+
+ command('set backupext=foo')
+ expected_combination({'backupext', oldval, oldval, oldval, 'foo', 'global', 'set'})
+
+ command('set backupext&')
+ expected_combination({'backupext', 'foo', 'foo', 'foo', oldval, 'global', 'set'})
+
+ command('setglobal backupext=bar')
+ expected_combination({'backupext', oldval, '', oldval, 'bar', 'global', 'setglobal'})
+
+ command('noa set backupext&')
+ -- As this is a global option this sets the global value even though :setlocal is used!
+ command('setlocal backupext=baz')
+ expected_combination({'backupext', oldval, oldval, '', 'baz', 'local', 'setlocal'})
+
+ command('noa setglobal backupext=ext_global')
+ command('noa setlocal backupext=ext_local') -- Sets the global(!) value
+ command('set backupext=foo')
+ expected_combination({
+ 'backupext', 'ext_local', 'ext_local', 'ext_local', 'foo', 'global', 'set'
+ })
+ end)
+
+ it('with string global-local (to buffer) option', function()
+ local oldval = eval('&tags')
+
+ command('set tags=tagpath')
+ expected_combination({'tags', oldval, oldval, oldval, 'tagpath', 'global', 'set'})
+
+ command('set tags&')
+ expected_combination({'tags', 'tagpath', 'tagpath', 'tagpath', oldval, 'global', 'set'})
+
+ command('setglobal tags=tagpath1')
+ expected_combination({'tags', oldval, '', oldval, 'tagpath1', 'global', 'setglobal'})
+
+ command('setlocal tags=tagpath2')
+ expected_combination({'tags', 'tagpath1', 'tagpath1', '', 'tagpath2', 'local', 'setlocal'})
+
+ -- Note: v:option_old is the old global value for global-local string options
+ -- but the old local value for all other kinds of options.
+ command('noa setglobal tags=tag_global')
+ command('noa setlocal tags=tag_local')
+ command('set tags=tagpath')
+ expected_combination({
+ 'tags', 'tag_global', 'tag_local', 'tag_global', 'tagpath', 'global', 'set'
+ })
+
+ -- Note: v:option_old is the old global value for global-local string options
+ -- but the old local value for all other kinds of options.
+ command('noa set tags=tag_global')
+ command('noa setlocal tags=')
+ command('set tags=tagpath')
+ expected_combination({'tags', 'tag_global', '', 'tag_global', 'tagpath', 'global', 'set'})
+ end)
+
+ it('with string local (to buffer) option', function()
+ local oldval = eval('&spelllang')
+
+ command('set spelllang=elvish,klingon')
+ expected_combination({'spelllang', oldval, oldval, oldval, 'elvish,klingon', 'global', 'set'})
+
+ command('set spelllang&')
+ expected_combination({
+ 'spelllang', 'elvish,klingon', 'elvish,klingon', 'elvish,klingon', oldval, 'global', 'set'
+ })
+
+ command('setglobal spelllang=elvish')
+ expected_combination({'spelllang', oldval, '', oldval, 'elvish', 'global', 'setglobal'})
+
+ command('noa set spelllang&')
+ command('setlocal spelllang=klingon')
+ expected_combination({'spelllang', oldval, oldval, '', 'klingon', 'local', 'setlocal'})
+
+ -- Note: v:option_old is the old global value for global-local string options
+ -- but the old local value for all other kinds of options.
+ command('noa setglobal spelllang=spellglobal')
+ command('noa setlocal spelllang=spelllocal')
+ command('set spelllang=foo')
+ expected_combination({
+ 'spelllang', 'spelllocal', 'spelllocal', 'spellglobal', 'foo', 'global', 'set'
+ })
+ end)
+
+ it('with string global-local (to window) option', function()
+ local oldval = eval('&statusline')
+
+ command('set statusline=foo')
+ expected_combination({'statusline', oldval, oldval, '', 'foo', 'global', 'set'})
+
+ -- Note: v:option_old is the old global value for global-local string options
+ -- but the old local value for all other kinds of options.
+ command('set statusline&')
+ expected_combination({'statusline', 'foo', 'foo', 'foo', oldval, 'global', 'set'})
+
+ command('setglobal statusline=bar')
+ expected_combination({'statusline', oldval, '', oldval, 'bar', 'global', 'setglobal'})
+
+ command('noa set statusline&')
+ command('setlocal statusline=baz')
+ expected_combination({'statusline', oldval, oldval, '', 'baz', 'local', 'setlocal'})
+
+ -- Note: v:option_old is the old global value for global-local string options
+ -- but the old local value for all other kinds of options.
+ command('noa setglobal statusline=bar')
+ command('noa setlocal statusline=baz')
+ command('set statusline=foo')
+ expected_combination({'statusline', 'bar', 'baz', 'bar', 'foo', 'global', 'set'})
+ end)
+
+ it('with string local (to window) option', function()
+ local oldval = eval('&foldignore')
+
+ command('set foldignore=fo')
+ expected_combination({'foldignore', oldval, oldval, oldval, 'fo', 'global', 'set'})
+
+ command('set foldignore&')
+ expected_combination({'foldignore', 'fo', 'fo', 'fo', oldval, 'global', 'set'})
+
+ command('setglobal foldignore=bar')
+ expected_combination({'foldignore', oldval, '', oldval, 'bar', 'global', 'setglobal'})
+
+ command('noa set foldignore&')
+ command('setlocal foldignore=baz')
+ expected_combination({'foldignore', oldval, oldval, '', 'baz', 'local', 'setlocal'})
+
+ command('noa setglobal foldignore=glob')
+ command('noa setlocal foldignore=loc')
+ command('set foldignore=fo')
+ expected_combination({'foldignore', 'loc', 'loc', 'glob', 'fo', 'global', 'set'})
+ end)
+
+ it('with number global option', function()
+ command('noa setglobal cmdheight=8')
+ command('noa setlocal cmdheight=1') -- Sets the global(!) value
+ command('setglobal cmdheight=2')
+ expected_combination({'cmdheight', 1, '', 1, 2, 'global', 'setglobal'})
+
+ command('noa setglobal cmdheight=8')
+ command('noa setlocal cmdheight=1') -- Sets the global(!) value
+ command('setlocal cmdheight=2')
+ expected_combination({'cmdheight', 1, 1, '', 2, 'local', 'setlocal'})
+
+ command('noa setglobal cmdheight=8')
+ command('noa setlocal cmdheight=1') -- Sets the global(!) value
+ command('set cmdheight=2')
+ expected_combination({'cmdheight', 1, 1, 1, 2, 'global', 'set'})
+
+ command('noa set cmdheight=8')
+ command('set cmdheight=2')
+ expected_combination({'cmdheight', 8, 8, 8, 2, 'global', 'set'})
+ end)
+
+ it('with number global-local (to buffer) option', function()
+ command('noa setglobal undolevels=8')
+ command('noa setlocal undolevels=1')
+ command('setglobal undolevels=2')
+ expected_combination({'undolevels', 8, '', 8, 2, 'global', 'setglobal'})
+
+ command('noa setglobal undolevels=8')
+ command('noa setlocal undolevels=1')
+ command('setlocal undolevels=2')
+ expected_combination({'undolevels', 1, 1, '', 2, 'local', 'setlocal'})
+
+ command('noa setglobal undolevels=8')
+ command('noa setlocal undolevels=1')
+ command('set undolevels=2')
+ expected_combination({'undolevels', 1, 1, 8, 2, 'global', 'set'})
+
+ command('noa set undolevels=8')
+ command('set undolevels=2')
+ expected_combination({'undolevels', 8, 8, 8, 2, 'global', 'set'})
+ end)
+
+ it('with number local (to buffer) option', function()
+ command('noa setglobal wrapmargin=8')
+ command('noa setlocal wrapmargin=1')
+ command('setglobal wrapmargin=2')
+ expected_combination({'wrapmargin', 8, '', 8, 2, 'global', 'setglobal'})
+
+ command('noa setglobal wrapmargin=8')
+ command('noa setlocal wrapmargin=1')
+ command('setlocal wrapmargin=2')
+ expected_combination({'wrapmargin', 1, 1, '', 2, 'local', 'setlocal'})
+
+ command('noa setglobal wrapmargin=8')
+ command('noa setlocal wrapmargin=1')
+ command('set wrapmargin=2')
+ expected_combination({'wrapmargin', 1, 1, 8, 2, 'global', 'set'})
+
+ command('noa set wrapmargin=8')
+ command('set wrapmargin=2')
+ expected_combination({'wrapmargin', 8, 8, 8, 2, 'global', 'set'})
+ end)
+
+ it('with number global-local (to window) option', function()
+ command('noa setglobal scrolloff=8')
+ command('noa setlocal scrolloff=1')
+ command('setglobal scrolloff=2')
+ expected_combination({'scrolloff', 8, '', 8, 2, 'global', 'setglobal'})
+
+ command('noa setglobal scrolloff=8')
+ command('noa setlocal scrolloff=1')
+ command('setlocal scrolloff=2')
+ expected_combination({'scrolloff', 1, 1, '', 2, 'local', 'setlocal'})
+
+ command('noa setglobal scrolloff=8')
+ command('noa setlocal scrolloff=1')
+ command('set scrolloff=2')
+ expected_combination({'scrolloff', 1, 1, 8, 2, 'global', 'set'})
+
+ command('noa set scrolloff=8')
+ command('set scrolloff=2')
+ expected_combination({'scrolloff', 8, 8, 8, 2, 'global', 'set'})
+ end)
+
+ it('with number local (to window) option', function()
+ command('noa setglobal foldcolumn=8')
+ command('noa setlocal foldcolumn=1')
+ command('setglobal foldcolumn=2')
+ expected_combination({'foldcolumn', 8, '', 8, 2, 'global', 'setglobal'})
+
+ command('noa setglobal foldcolumn=8')
+ command('noa setlocal foldcolumn=1')
+ command('setlocal foldcolumn=2')
+ expected_combination({'foldcolumn', 1, 1, '', 2, 'local', 'setlocal'})
+
+ command('noa setglobal foldcolumn=8')
+ command('noa setlocal foldcolumn=1')
+ command('set foldcolumn=2')
+ expected_combination({'foldcolumn', 1, 1, 8, 2, 'global', 'set'})
+
+ command('noa set foldcolumn=8')
+ command('set foldcolumn=2')
+ expected_combination({'foldcolumn', 8, 8, 8, 2, 'global', 'set'})
+ end)
+
+ it('with boolean global option', function()
+ command('noa setglobal nowrapscan')
+ command('noa setlocal wrapscan') -- Sets the global(!) value
+ command('setglobal nowrapscan')
+ expected_combination({'wrapscan', 1, '', 1, 0, 'global', 'setglobal'})
+
+ command('noa setglobal nowrapscan')
+ command('noa setlocal wrapscan') -- Sets the global(!) value
+ command('setlocal nowrapscan')
+ expected_combination({'wrapscan', 1, 1, '', 0, 'local', 'setlocal'})
+
+ command('noa setglobal nowrapscan')
+ command('noa setlocal wrapscan') -- Sets the global(!) value
+ command('set nowrapscan')
+ expected_combination({'wrapscan', 1, 1, 1, 0, 'global', 'set'})
+
+ command('noa set nowrapscan')
+ command('set wrapscan')
+ expected_combination({'wrapscan', 0, 0, 0, 1, 'global', 'set'})
+ end)
+
+ it('with boolean global-local (to buffer) option', function()
+ command('noa setglobal noautoread')
+ command('noa setlocal autoread')
+ command('setglobal autoread')
+ expected_combination({'autoread', 0, '', 0, 1, 'global', 'setglobal'})
+
+ command('noa setglobal noautoread')
+ command('noa setlocal autoread')
+ command('setlocal noautoread')
+ expected_combination({'autoread', 1, 1, '', 0, 'local', 'setlocal'})
+
+ command('noa setglobal noautoread')
+ command('noa setlocal autoread')
+ command('set autoread')
+ expected_combination({'autoread', 1, 1, 0, 1, 'global', 'set'})
+
+ command('noa set noautoread')
+ command('set autoread')
+ expected_combination({'autoread', 0, 0, 0, 1, 'global', 'set'})
+ end)
+
+ it('with boolean local (to buffer) option', function()
+ command('noa setglobal nocindent')
+ command('noa setlocal cindent')
+ command('setglobal cindent')
+ expected_combination({'cindent', 0, '', 0, 1, 'global', 'setglobal'})
+
+ command('noa setglobal nocindent')
+ command('noa setlocal cindent')
+ command('setlocal nocindent')
+ expected_combination({'cindent', 1, 1, '', 0, 'local', 'setlocal'})
+
+ command('noa setglobal nocindent')
+ command('noa setlocal cindent')
+ command('set cindent')
+ expected_combination({'cindent', 1, 1, 0, 1, 'global', 'set'})
+
+ command('noa set nocindent')
+ command('set cindent')
+ expected_combination({'cindent', 0, 0, 0, 1, 'global', 'set'})
+ end)
+
+ it('with boolean local (to window) option', function()
+ command('noa setglobal nocursorcolumn')
+ command('noa setlocal cursorcolumn')
+ command('setglobal cursorcolumn')
+ expected_combination({'cursorcolumn', 0, '', 0, 1, 'global', 'setglobal'})
+
+ command('noa setglobal nocursorcolumn')
+ command('noa setlocal cursorcolumn')
+ command('setlocal nocursorcolumn')
+ expected_combination({'cursorcolumn', 1, 1, '', 0, 'local', 'setlocal'})
+
+ command('noa setglobal nocursorcolumn')
+ command('noa setlocal cursorcolumn')
+ command('set cursorcolumn')
+ expected_combination({'cursorcolumn', 1, 1, 0, 1, 'global', 'set'})
+
+ command('noa set nocursorcolumn')
+ command('set cursorcolumn')
+ expected_combination({'cursorcolumn', 0, 0, 0, 1, 'global', 'set'})
+ end)
+
+ it('with option value converted internally', function()
+ command('noa set backspace=1')
+ command('set backspace=2')
+ expected_combination(({
+ 'backspace', 'indent,eol', 'indent,eol', 'indent,eol', '2', 'global', 'set'
+ }))
+ end)
end)
describe('with specific option', function()
@@ -228,13 +566,13 @@ describe('au OptionSet', function()
expected_empty()
command('setlocal ro')
- expected_combination({'readonly', 0, 1, 'local'})
+ expected_combination({'readonly', 0, 0, '', 1, 'local', 'setlocal'})
command('setglobal ro')
- expected_combination({'readonly', 0, 1, 'global'})
+ expected_combination({'readonly', 0, '', 0, 1, 'global', 'setglobal'})
command('set noro')
- expected_combination({'readonly', 1, 0, 'global'})
+ expected_combination({'readonly', 1, 1, 1, 0, 'global', 'set'})
end)
describe('being set by setbufvar()', function()
@@ -249,7 +587,7 @@ describe('au OptionSet', function()
set_hook('backup')
command('call setbufvar(1, "&backup", 1)')
- expected_combination({'backup', 0, 1, 'local'})
+ expected_combination({'backup', 0, 0, '', 1, 'local', 'setlocal'})
end)
it('should trigger if the current buffer is different from the targetted buffer', function()
@@ -259,7 +597,7 @@ describe('au OptionSet', function()
local new_bufnr = buf.get_number(new_buffer)
command('call setbufvar(' .. new_bufnr .. ', "&buftype", "nofile")')
- expected_combination({'buftype', '', 'nofile', 'local', {bufnr = new_bufnr}})
+ expected_combination({'buftype', '', '', '', 'nofile', 'local', 'setlocal', {bufnr = new_bufnr}})
end)
end)
@@ -275,7 +613,7 @@ describe('au OptionSet', function()
set_hook('backup')
command('call setwinvar(1, "&backup", 1)')
- expected_combination({'backup', 0, 1, 'local'})
+ expected_combination({'backup', 0, 0, '', 1, 'local', 'setlocal'})
end)
it('should not trigger if the current window is different from the targetted window', function()
@@ -295,7 +633,7 @@ describe('au OptionSet', function()
nvim.set_option('autochdir', true)
eq(true, nvim.get_option('autochdir'))
- expected_combination({'autochdir', '0', '1', 'global'})
+ expected_combination({'autochdir', 0, '', 0, 1, 'global', 'setglobal'})
end)
it('should trigger if a number option be set globally', function()
@@ -303,7 +641,7 @@ describe('au OptionSet', function()
nvim.set_option('cmdheight', 5)
eq(5, nvim.get_option('cmdheight'))
- expected_combination({'cmdheight', 1, 5, 'global'})
+ expected_combination({'cmdheight', 1, '', 1, 5, 'global', 'setglobal'})
end)
it('should trigger if a string option be set globally', function()
@@ -311,7 +649,7 @@ describe('au OptionSet', function()
nvim.set_option('ambiwidth', 'double')
eq('double', nvim.get_option('ambiwidth'))
- expected_combination({'ambiwidth', 'single', 'double', 'global'})
+ expected_combination({'ambiwidth', 'single', '', 'single', 'double', 'global', 'setglobal'})
end)
end)
end)