aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/option.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/option.c')
-rw-r--r--src/nvim/option.c2078
1 files changed, 976 insertions, 1102 deletions
diff --git a/src/nvim/option.c b/src/nvim/option.c
index ff0c0e2acf..bb86d10425 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -176,7 +176,7 @@ static int p_paste_dep_opts[] = {
void set_init_tablocal(void)
{
// susy baka: cmdheight calls itself OPT_GLOBAL but is really tablocal!
- p_ch = options[kOptCmdheight].def_val.number;
+ p_ch = options[kOptCmdheight].def_val.data.number;
}
/// Initialize the 'shell' option to a default value.
@@ -291,8 +291,8 @@ static void set_init_default_cdpath(void)
}
}
buf[j] = NUL;
- options[kOptCdpath].def_val.string = buf;
- options[kOptCdpath].flags |= P_DEF_ALLOCED;
+ change_option_default(kOptCdpath, CSTR_AS_OPTVAL(buf));
+
xfree(cdpath);
}
@@ -301,29 +301,22 @@ static void set_init_default_cdpath(void)
/// only happen for non-indirect options.
/// Also set the default to the expanded value, so ":set" does not list
/// them.
-/// Don't set the P_ALLOCED flag, because we don't want to free the
-/// default.
static void set_init_expand_env(void)
{
- for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) {
vimoption_T *opt = &options[opt_idx];
- if (opt->flags & P_NO_DEF_EXP) {
+ if (opt->flags & kOptFlagNoDefExp) {
continue;
}
char *p;
- if ((opt->flags & P_GETTEXT) && opt->var != NULL) {
+ if ((opt->flags & kOptFlagGettext) && opt->var != NULL) {
p = _(*(char **)opt->var);
} else {
p = option_expand(opt_idx, NULL);
}
if (p != NULL) {
- p = xstrdup(p);
- *(char **)opt->var = p;
- if (opt->flags & P_DEF_ALLOCED) {
- xfree(opt->def_val.string);
- }
- opt->def_val.string = p;
- opt->flags |= P_DEF_ALLOCED;
+ set_option_varp(opt_idx, opt->var, CSTR_TO_OPTVAL(p), true);
+ change_option_default(opt_idx, CSTR_TO_OPTVAL(p));
}
}
}
@@ -354,6 +347,9 @@ void set_init_1(bool clean_arg)
{
langmap_init();
+ // Allocate the default option values.
+ alloc_options_default();
+
set_init_default_shell();
set_init_default_backupskip();
set_init_default_cdpath();
@@ -430,71 +426,73 @@ void set_init_1(bool clean_arg)
set_helplang_default(get_mess_lang());
}
-/// Set an option to its default value.
-/// This does not take care of side effects!
+/// Get default value for option, based on the option's type and scope.
///
-/// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL.
+/// @param opt_idx Option index in options[] table.
+/// @param opt_flags Option flags.
///
-/// TODO(famiu): Refactor this when def_val uses OptVal.
-static void set_option_default(const OptIndex opt_idx, int opt_flags)
+/// @return Default value of option for the scope specified in opt_flags.
+static OptVal get_option_default(const OptIndex opt_idx, int opt_flags)
{
- bool both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
-
- // pointer to variable for current option
vimoption_T *opt = &options[opt_idx];
- void *varp = get_varp_scope(opt, both ? OPT_LOCAL : opt_flags);
- uint32_t flags = opt->flags;
- if (varp != NULL) { // skip hidden option, nothing to do for it
- if (option_has_type(opt_idx, kOptValTypeString)) {
- // Use set_option_direct() for local options to handle freeing and allocating the value.
- if (opt->indir != PV_NONE) {
- set_option_direct(opt_idx, CSTR_AS_OPTVAL(opt->def_val.string), opt_flags, 0);
- } else {
- if (flags & P_ALLOCED) {
- free_string_option(*(char **)(varp));
- }
- *(char **)varp = opt->def_val.string;
- opt->flags &= ~P_ALLOCED;
- }
- } else if (option_has_type(opt_idx, kOptValTypeNumber)) {
- if (opt->indir == PV_SCROLL) {
- win_comp_scroll(curwin);
- } else {
- OptInt def_val = opt->def_val.number;
- if ((OptInt *)varp == &curwin->w_p_so
- || (OptInt *)varp == &curwin->w_p_siso) {
- // 'scrolloff' and 'sidescrolloff' local values have a
- // different default value than the global default.
- *(OptInt *)varp = -1;
- } else {
- *(OptInt *)varp = def_val;
- }
- // May also set global value for local option.
- if (both) {
- *(OptInt *)get_varp_scope(opt, OPT_GLOBAL) = def_val;
- }
- }
- } else { // boolean
- *(int *)varp = opt->def_val.boolean;
+ bool is_global_local_option = option_is_global_local(opt_idx);
+
#ifdef UNIX
- // 'modeline' defaults to off for root
- if (opt->indir == PV_ML && getuid() == ROOT_UID) {
- *(int *)varp = false;
- }
+ if (opt_idx == kOptModeline && getuid() == ROOT_UID) {
+ // 'modeline' defaults to off for root.
+ return BOOLEAN_OPTVAL(false);
+ }
#endif
- // May also set global value for local option.
- if (both) {
- *(int *)get_varp_scope(opt, OPT_GLOBAL) =
- *(int *)varp;
- }
- }
- // The default value is not insecure.
- uint32_t *flagsp = insecure_flag(curwin, opt_idx, opt_flags);
- *flagsp = *flagsp & ~P_INSECURE;
+ if ((opt_flags & OPT_LOCAL) && is_global_local_option) {
+ // Use unset local value instead of default value for local scope of global-local options.
+ return get_option_unset_value(opt_idx);
+ } else if (option_has_type(opt_idx, kOptValTypeString) && !(opt->flags & kOptFlagNoDefExp)) {
+ // For string options, expand environment variables and ~ since the default value was already
+ // expanded, only required when an environment variable was set later.
+ char *s = option_expand(opt_idx, opt->def_val.data.string.data);
+ return s == NULL ? opt->def_val : CSTR_AS_OPTVAL(s);
+ } else {
+ return opt->def_val;
}
+}
- set_option_sctx(opt_idx, opt_flags, current_sctx);
+/// Allocate the default values for all options by copying them from the stack.
+/// This ensures that we don't need to always check if the option default is allocated or not.
+static void alloc_options_default(void)
+{
+ for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) {
+ options[opt_idx].def_val = optval_copy(options[opt_idx].def_val);
+ }
+}
+
+/// Change the default value for an option.
+///
+/// @param opt_idx Option index in options[] table.
+/// @param value New default value. Must be allocated.
+static void change_option_default(const OptIndex opt_idx, OptVal value)
+{
+ optval_free(options[opt_idx].def_val);
+ options[opt_idx].def_val = value;
+}
+
+/// Set an option to its default value.
+/// This does not take care of side effects!
+///
+/// @param opt_idx Option index in options[] table.
+/// @param opt_flags Option flags.
+static void set_option_default(const OptIndex opt_idx, int opt_flags)
+{
+ OptVal def_val = get_option_default(opt_idx, opt_flags);
+ set_option_direct(opt_idx, def_val, opt_flags, current_sctx.sc_sid);
+
+ if (opt_idx == kOptScroll) {
+ win_comp_scroll(curwin);
+ }
+
+ // The default value is not insecure.
+ uint32_t *flagsp = insecure_flag(curwin, opt_idx, opt_flags);
+ *flagsp = *flagsp & ~(unsigned)kOptFlagInsecure;
}
/// Set all options (except terminal options) to their default value.
@@ -502,8 +500,8 @@ static void set_option_default(const OptIndex opt_idx, int opt_flags)
/// @param opt_flags Option flags.
static void set_options_default(int opt_flags)
{
- for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
- if (!(options[opt_idx].flags & P_NODEFAULT)) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) {
+ if (!(options[opt_idx].flags & kOptFlagNoDefault)) {
set_option_default(opt_idx, opt_flags);
}
}
@@ -522,20 +520,13 @@ static void set_options_default(int opt_flags)
/// @param opt_idx Option index in options[] table.
/// @param val The value of the option.
/// @param allocated If true, do not copy default as it was already allocated.
+///
+/// TODO(famiu): Remove this.
static void set_string_default(OptIndex opt_idx, char *val, bool allocated)
FUNC_ATTR_NONNULL_ALL
{
- if (opt_idx == kOptInvalid) {
- return;
- }
-
- vimoption_T *opt = &options[opt_idx];
- if (opt->flags & P_DEF_ALLOCED) {
- xfree(opt->def_val.string);
- }
-
- opt->def_val.string = allocated ? val : xstrdup(val);
- opt->flags |= P_DEF_ALLOCED;
+ assert(opt_idx != kOptInvalid);
+ change_option_default(opt_idx, CSTR_AS_OPTVAL(allocated ? val : xstrdup(val)));
}
/// For an option value that contains comma separated items, find "newval" in
@@ -551,9 +542,9 @@ static char *find_dup_item(char *origval, const char *newval, const size_t newva
int bs = 0;
for (char *s = origval; *s != NUL; s++) {
- if ((!(flags & P_COMMA) || s == origval || (s[-1] == ',' && !(bs & 1)))
+ if ((!(flags & kOptFlagComma) || s == origval || (s[-1] == ',' && !(bs & 1)))
&& strncmp(s, newval, newvallen) == 0
- && (!(flags & P_COMMA) || s[newvallen] == ',' || s[newvallen] == NUL)) {
+ && (!(flags & kOptFlagComma) || s[newvallen] == ',' || s[newvallen] == NUL)) {
return s;
}
// Count backslashes. Only a comma with an even number of backslashes
@@ -569,35 +560,28 @@ static char *find_dup_item(char *origval, const char *newval, const size_t newva
return NULL;
}
-/// Set the Vi-default value of a number option.
-/// Used for 'lines' and 'columns'.
-void set_number_default(OptIndex opt_idx, OptInt val)
-{
- if (opt_idx != kOptInvalid) {
- options[opt_idx].def_val.number = val;
- }
-}
-
#if defined(EXITFREE)
/// Free all options.
void free_all_options(void)
{
- for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
- if (options[opt_idx].indir == PV_NONE) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) {
+ bool hidden = is_option_hidden(opt_idx);
+
+ if (option_is_global_only(opt_idx) || hidden) {
// global option: free value and default value.
- if ((options[opt_idx].flags & P_ALLOCED) && options[opt_idx].var != NULL) {
+ // hidden option: free default value only.
+ if (!hidden) {
optval_free(optval_from_varp(opt_idx, options[opt_idx].var));
}
- if (options[opt_idx].flags & P_DEF_ALLOCED) {
- optval_free(optval_from_varp(opt_idx, &options[opt_idx].def_val));
- }
- } else if (options[opt_idx].var != VAR_WIN) {
- // buffer-local option: free global value
+ } else if (!option_is_window_local(opt_idx)) {
+ // buffer-local option: free global value.
optval_free(optval_from_varp(opt_idx, options[opt_idx].var));
}
+ optval_free(options[opt_idx].def_val);
}
free_operatorfunc_option();
free_tagfunc_option();
+ free_findfunc_option();
XFREE_CLEAR(fenc_default);
XFREE_CLEAR(p_term);
XFREE_CLEAR(p_ttytype);
@@ -612,7 +596,7 @@ void set_init_2(bool headless)
// 'scroll' defaults to half the window height. The stored default is zero,
// which results in the actual value computed from the window height.
- if (!(options[kOptScroll].flags & P_WAS_SET)) {
+ if (!(options[kOptScroll].flags & kOptFlagWasSet)) {
set_option_default(kOptScroll, OPT_LOCAL);
}
comp_col();
@@ -622,7 +606,7 @@ void set_init_2(bool headless)
if (!option_was_set(kOptWindow)) {
p_window = Rows - 1;
}
- set_number_default(kOptWindow, Rows - 1);
+ change_option_default(kOptWindow, NUMBER_OPTVAL(Rows - 1));
}
/// Initialize the options, part three: After reading the .vimrc
@@ -633,56 +617,40 @@ void set_init_3(void)
// Set 'shellpipe' and 'shellredir', depending on the 'shell' option.
// This is done after other initializations, where 'shell' might have been
// set, but only if they have not been set before.
- bool do_srr = !(options[kOptShellredir].flags & P_WAS_SET);
- bool do_sp = !(options[kOptShellpipe].flags & P_WAS_SET);
+ bool do_srr = !(options[kOptShellredir].flags & kOptFlagWasSet);
+ bool do_sp = !(options[kOptShellpipe].flags & kOptFlagWasSet);
size_t len = 0;
char *p = (char *)invocation_path_tail(p_sh, &len);
p = xmemdupz(p, len);
- {
- //
- // Default for p_sp is "| tee", for p_srr is ">".
- // For known shells it is changed here to include stderr.
- //
- if (path_fnamecmp(p, "csh") == 0
- || path_fnamecmp(p, "tcsh") == 0) {
- if (do_sp) {
- p_sp = "|& tee";
- options[kOptShellpipe].def_val.string = p_sp;
- }
- if (do_srr) {
- p_srr = ">&";
- options[kOptShellredir].def_val.string = p_srr;
- }
- } else if (path_fnamecmp(p, "sh") == 0
- || path_fnamecmp(p, "ksh") == 0
- || path_fnamecmp(p, "mksh") == 0
- || path_fnamecmp(p, "pdksh") == 0
- || path_fnamecmp(p, "zsh") == 0
- || path_fnamecmp(p, "zsh-beta") == 0
- || path_fnamecmp(p, "bash") == 0
- || path_fnamecmp(p, "fish") == 0
- || path_fnamecmp(p, "ash") == 0
- || path_fnamecmp(p, "dash") == 0) {
- // Always use POSIX shell style redirection if we reach this
- if (do_sp) {
- p_sp = "2>&1| tee";
- options[kOptShellpipe].def_val.string = p_sp;
- }
- if (do_srr) {
- p_srr = ">%s 2>&1";
- options[kOptShellredir].def_val.string = p_srr;
- }
+ bool is_csh = path_fnamecmp(p, "csh") == 0 || path_fnamecmp(p, "tcsh") == 0;
+ bool is_known_shell = path_fnamecmp(p, "sh") == 0 || path_fnamecmp(p, "ksh") == 0
+ || path_fnamecmp(p, "mksh") == 0 || path_fnamecmp(p, "pdksh") == 0
+ || path_fnamecmp(p, "zsh") == 0 || path_fnamecmp(p, "zsh-beta") == 0
+ || path_fnamecmp(p, "bash") == 0 || path_fnamecmp(p, "fish") == 0
+ || path_fnamecmp(p, "ash") == 0 || path_fnamecmp(p, "dash") == 0;
+
+ // Default for p_sp is "| tee", for p_srr is ">".
+ // For known shells it is changed here to include stderr.
+ if (is_csh || is_known_shell) {
+ if (do_sp) {
+ const OptVal sp =
+ is_csh ? STATIC_CSTR_AS_OPTVAL("|& tee") : STATIC_CSTR_AS_OPTVAL("2>&1| tee");
+ set_option_direct(kOptShellpipe, sp, 0, SID_NONE);
+ change_option_default(kOptShellpipe, optval_copy(sp));
+ }
+ if (do_srr) {
+ const OptVal srr = is_csh ? STATIC_CSTR_AS_OPTVAL(">&") : STATIC_CSTR_AS_OPTVAL(">%s 2>&1");
+ set_option_direct(kOptShellredir, srr, 0, SID_NONE);
+ change_option_default(kOptShellredir, optval_copy(srr));
}
- xfree(p);
}
+ xfree(p);
if (buf_is_empty(curbuf)) {
- int idx_ffs = find_option("ffs");
-
// Apply the first entry of 'fileformats' to the initial buffer.
- if (idx_ffs >= 0 && (options[idx_ffs].flags & P_WAS_SET)) {
+ if (options[kOptFileformats].flags & kOptFlagWasSet) {
set_fileformat(default_fileformat(), OPT_LOCAL);
}
}
@@ -702,13 +670,11 @@ void set_helplang_default(const char *lang)
if (lang_len < 2) { // safety check
return;
}
- if (options[kOptHelplang].flags & P_WAS_SET) {
+ if (options[kOptHelplang].flags & kOptFlagWasSet) {
return;
}
- if (options[kOptHelplang].flags & P_ALLOCED) {
- free_string_option(p_hlg);
- }
+ free_string_option(p_hlg);
p_hlg = xmemdupz(lang, lang_len);
// zh_CN becomes "cn", zh_TW becomes "tw".
if (STRNICMP(p_hlg, "zh_", 3) == 0 && lang_len >= 5) {
@@ -720,7 +686,6 @@ void set_helplang_default(const char *lang)
p_hlg[1] = 'n';
}
p_hlg[2] = NUL;
- options[kOptHelplang].flags |= P_ALLOCED;
}
/// 'title' and 'icon' only default to true if they have not been set or reset
@@ -733,13 +698,13 @@ void set_title_defaults(void)
// If GUI is (going to be) used, we can always set the window title and
// icon name. Saves a bit of time, because the X11 display server does
// not need to be contacted.
- if (!(options[kOptTitle].flags & P_WAS_SET)) {
- options[kOptTitle].def_val.boolean = false;
- p_title = false;
+ if (!(options[kOptTitle].flags & kOptFlagWasSet)) {
+ change_option_default(kOptTitle, BOOLEAN_OPTVAL(false));
+ p_title = 0;
}
- if (!(options[kOptIcon].flags & P_WAS_SET)) {
- options[kOptIcon].def_val.boolean = false;
- p_icon = false;
+ if (!(options[kOptIcon].flags & kOptFlagWasSet)) {
+ change_option_default(kOptIcon, BOOLEAN_OPTVAL(false));
+ p_icon = 0;
}
}
@@ -758,27 +723,6 @@ void ex_set(exarg_T *eap)
do_set(eap->arg, flags);
}
-/// Get the default value for a string option.
-static char *stropt_get_default_val(OptIndex opt_idx, uint64_t flags)
-{
- char *newval = options[opt_idx].def_val.string;
- // expand environment variables and ~ since the default value was
- // already expanded, only required when an environment variable was set
- // later
- if (newval == NULL) {
- newval = empty_string_option;
- } else if (!(options[opt_idx].flags & P_NO_DEF_EXP)) {
- char *s = option_expand(opt_idx, newval);
- if (s == NULL) {
- s = newval;
- }
- newval = xstrdup(s);
- } else {
- newval = xstrdup(newval);
- }
- return newval;
-}
-
/// Copy the new string value into allocated memory for the option.
/// Can't use set_option_direct(), because we need to remove the backslashes.
static char *stropt_copy_value(char *origval, char **argp, set_op_T op,
@@ -802,7 +746,7 @@ static char *stropt_copy_value(char *origval, char **argp, set_op_T op,
while (*arg != NUL && !ascii_iswhite(*arg)) {
if (*arg == '\\' && arg[1] != NUL
#ifdef BACKSLASH_IN_FILENAME
- && !((flags & P_EXPAND)
+ && !((flags & kOptFlagExpand)
&& vim_isfilec((uint8_t)arg[1])
&& !ascii_iswhite(arg[1])
&& (arg[1] != '\\'
@@ -851,12 +795,12 @@ static char *stropt_expand_envvar(OptIndex opt_idx, char *origval, char *newval,
static void stropt_concat_with_comma(char *origval, char *newval, set_op_T op, uint32_t flags)
{
int len = 0;
- int comma = ((flags & P_COMMA) && *origval != NUL && *newval != NUL);
+ int comma = ((flags & kOptFlagComma) && *origval != NUL && *newval != NUL);
if (op == OP_ADDING) {
len = (int)strlen(origval);
// Strip a trailing comma, would get 2.
if (comma && len > 1
- && (flags & P_ONECOMMA) == P_ONECOMMA
+ && (flags & kOptFlagOneComma) == kOptFlagOneComma
&& origval[len - 1] == ','
&& origval[len - 2] != '\\') {
len--;
@@ -881,7 +825,7 @@ static void stropt_remove_val(char *origval, char *newval, uint32_t flags, char
STRCPY(newval, origval);
if (*strval) {
// may need to remove a comma
- if (flags & P_COMMA) {
+ if (flags & kOptFlagComma) {
if (strval == origval) {
// include comma after string
if (strval[len] == ',') {
@@ -903,8 +847,8 @@ static void stropt_remove_dupflags(char *newval, uint32_t flags)
char *s = newval;
// Remove flags that appear twice.
for (s = newval; *s;) {
- // if options have P_FLAGLIST and P_ONECOMMA such as 'whichwrap'
- if (flags & P_ONECOMMA) {
+ // if options have kOptFlagFlagList and kOptFlagOneComma such as 'whichwrap'
+ if (flags & kOptFlagOneComma) {
if (*s != ',' && *(s + 1) == ','
&& vim_strchr(s + 2, (uint8_t)(*s)) != NULL) {
// Remove the duplicated value and the next comma.
@@ -912,7 +856,7 @@ static void stropt_remove_dupflags(char *newval, uint32_t flags)
continue;
}
} else {
- if ((!(flags & P_COMMA) || *s != ',')
+ if ((!(flags & kOptFlagComma) || *s != ',')
&& vim_strchr(s + 1, (uint8_t)(*s)) != NULL) {
STRMOVE(s, s + 1);
continue;
@@ -922,10 +866,7 @@ static void stropt_remove_dupflags(char *newval, uint32_t flags)
}
}
-/// Get the string value specified for a ":set" command. The following set
-/// options are supported:
-/// set {opt}&
-/// set {opt}<
+/// Get the string value specified for a ":set" command. The following set options are supported:
/// set {opt}={val}
/// set {opt}:{val}
static char *stropt_get_newval(int nextchar, OptIndex opt_idx, char **argp, void *varp,
@@ -936,61 +877,56 @@ static char *stropt_get_newval(int nextchar, OptIndex opt_idx, char **argp, void
char *save_arg = NULL;
char *newval;
char *s = NULL;
- if (nextchar == '&') { // set to default val
- newval = stropt_get_default_val(opt_idx, flags);
- } else if (nextchar == '<') { // set to global val
- newval = xstrdup(*(char **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL));
- } else {
- arg++; // jump to after the '=' or ':'
- // Set 'keywordprg' to ":help" if an empty
- // value was passed to :set by the user.
- if (varp == &p_kp && (*arg == NUL || *arg == ' ')) {
- save_arg = arg;
- arg = ":help";
- }
+ arg++; // jump to after the '=' or ':'
- // Copy the new string into allocated memory.
- newval = stropt_copy_value(origval, &arg, op, flags);
+ // Set 'keywordprg' to ":help" if an empty
+ // value was passed to :set by the user.
+ if (varp == &p_kp && (*arg == NUL || *arg == ' ')) {
+ save_arg = arg;
+ arg = ":help";
+ }
- // Expand environment variables and ~.
- // Don't do it when adding without inserting a comma.
- if (op == OP_NONE || (flags & P_COMMA)) {
- newval = stropt_expand_envvar(opt_idx, origval, newval, op);
- }
+ // Copy the new string into allocated memory.
+ newval = stropt_copy_value(origval, &arg, op, flags);
- // locate newval[] in origval[] when removing it
- // and when adding to avoid duplicates
- int len = 0;
- if (op == OP_REMOVING || (flags & P_NODUP)) {
- len = (int)strlen(newval);
- s = find_dup_item(origval, newval, (size_t)len, flags);
+ // Expand environment variables and ~.
+ // Don't do it when adding without inserting a comma.
+ if (op == OP_NONE || (flags & kOptFlagComma)) {
+ newval = stropt_expand_envvar(opt_idx, origval, newval, op);
+ }
- // do not add if already there
- if ((op == OP_ADDING || op == OP_PREPENDING) && s != NULL) {
- op = OP_NONE;
- STRCPY(newval, origval);
- }
+ // locate newval[] in origval[] when removing it
+ // and when adding to avoid duplicates
+ int len = 0;
+ if (op == OP_REMOVING || (flags & kOptFlagNoDup)) {
+ len = (int)strlen(newval);
+ s = find_dup_item(origval, newval, (size_t)len, flags);
- // if no duplicate, move pointer to end of original value
- if (s == NULL) {
- s = origval + (int)strlen(origval);
- }
+ // do not add if already there
+ if ((op == OP_ADDING || op == OP_PREPENDING) && s != NULL) {
+ op = OP_NONE;
+ STRCPY(newval, origval);
}
- // concatenate the two strings; add a ',' if needed
- if (op == OP_ADDING || op == OP_PREPENDING) {
- stropt_concat_with_comma(origval, newval, op, flags);
- } else if (op == OP_REMOVING) {
- // Remove newval[] from origval[]. (Note: "len" has been set above
- // and is used here).
- stropt_remove_val(origval, newval, flags, s, len);
+ // if no duplicate, move pointer to end of original value
+ if (s == NULL) {
+ s = origval + (int)strlen(origval);
}
+ }
- if (flags & P_FLAGLIST) {
- // Remove flags that appear twice.
- stropt_remove_dupflags(newval, flags);
- }
+ // concatenate the two strings; add a ',' if needed
+ if (op == OP_ADDING || op == OP_PREPENDING) {
+ stropt_concat_with_comma(origval, newval, op, flags);
+ } else if (op == OP_REMOVING) {
+ // Remove newval[] from origval[]. (Note: "len" has been set above
+ // and is used here).
+ stropt_remove_val(origval, newval, flags, s, len);
+ }
+
+ if (flags & kOptFlagFlagList) {
+ // Remove flags that appear twice.
+ stropt_remove_dupflags(newval, flags);
}
if (save_arg != NULL) {
@@ -1041,38 +977,35 @@ static int validate_opt_idx(win_T *win, OptIndex opt_idx, int opt_flags, uint32_
// Skip all options that are not window-local (used when showing
// an already loaded buffer in a window).
- if ((opt_flags & OPT_WINONLY) && (opt_idx == kOptInvalid || options[opt_idx].var != VAR_WIN)) {
+ if ((opt_flags & OPT_WINONLY) && (opt_idx == kOptInvalid || !option_is_window_local(opt_idx))) {
return FAIL;
}
// Skip all options that are window-local (used for :vimgrep).
- if ((opt_flags & OPT_NOWIN) && opt_idx != kOptInvalid && options[opt_idx].var == VAR_WIN) {
+ if ((opt_flags & OPT_NOWIN) && opt_idx != kOptInvalid && option_is_window_local(opt_idx)) {
return FAIL;
}
// Disallow changing some options from modelines.
if (opt_flags & OPT_MODELINE) {
- if (flags & (P_SECURE | P_NO_ML)) {
+ if (flags & (kOptFlagSecure | kOptFlagNoML)) {
*errmsg = e_not_allowed_in_modeline;
return FAIL;
}
- if ((flags & P_MLE) && !p_mle) {
+ if ((flags & kOptFlagMLE) && !p_mle) {
*errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off;
return FAIL;
}
// In diff mode some options are overruled. This avoids that
// 'foldmethod' becomes "marker" instead of "diff" and that
// "wrap" gets set.
- if (win->w_p_diff
- && opt_idx != kOptInvalid // shut up coverity warning
- && (options[opt_idx].indir == PV_FDM
- || options[opt_idx].indir == PV_WRAP)) {
+ if (win->w_p_diff && (opt_idx == kOptFoldmethod || opt_idx == kOptWrap)) {
return FAIL;
}
}
// Disallow changing some options in the sandbox
- if (sandbox != 0 && (flags & P_SECURE)) {
+ if (sandbox != 0 && (flags & kOptFlagSecure)) {
*errmsg = e_sandbox;
return FAIL;
}
@@ -1152,6 +1085,7 @@ const char *find_option_end(const char *arg, OptIndex *opt_idxp)
}
/// Get new option value from argp. Allocated OptVal must be freed by caller.
+/// Can unset local value of an option when ":set {option}<" is used.
static OptVal get_option_newval(OptIndex opt_idx, int opt_flags, set_prefix_T prefix, char **argp,
int nextchar, set_op_T op, uint32_t flags, void *varp, char *errbuf,
const size_t errbuflen, const char **errmsg)
@@ -1162,10 +1096,24 @@ static OptVal get_option_newval(OptIndex opt_idx, int opt_flags, set_prefix_T pr
vimoption_T *opt = &options[opt_idx];
char *arg = *argp;
// When setting the local value of a global option, the old value may be the global value.
- const bool oldval_is_global = ((int)opt->indir & PV_BOTH) && (opt_flags & OPT_LOCAL);
+ const bool oldval_is_global = option_is_global_local(opt_idx) && (opt_flags & OPT_LOCAL);
OptVal oldval = optval_from_varp(opt_idx, oldval_is_global ? get_varp(opt) : varp);
OptVal newval = NIL_OPTVAL;
+ if (nextchar == '&') {
+ // ":set opt&": Reset to default value.
+ // NOTE: Use OPT_GLOBAL instead of opt_flags to ensure we don't use the unset local value for
+ // global-local options when OPT_LOCAL is used.
+ return optval_copy(get_option_default(opt_idx, OPT_GLOBAL));
+ } else if (nextchar == '<') {
+ // ":set opt<": Reset to global value.
+ // ":setlocal opt<": Copy global value to local value.
+ if (option_is_global_local(opt_idx) && !(opt_flags & OPT_LOCAL)) {
+ unset_option_local_value(opt_idx);
+ }
+ return get_option_value(opt_idx, OPT_GLOBAL);
+ }
+
switch (oldval.type) {
case kOptValTypeNil:
abort();
@@ -1173,8 +1121,6 @@ static OptVal get_option_newval(OptIndex opt_idx, int opt_flags, set_prefix_T pr
TriState newval_bool;
// ":set opt!": invert
- // ":set opt&": reset to default value
- // ":set opt<": reset to global value
if (nextchar == '!') {
switch (oldval.data.boolean) {
case kNone:
@@ -1187,15 +1133,6 @@ static OptVal get_option_newval(OptIndex opt_idx, int opt_flags, set_prefix_T pr
newval_bool = kTrue;
break;
}
- } else if (nextchar == '&') {
- newval_bool = TRISTATE_FROM_INT(options[opt_idx].def_val.boolean);
- } else if (nextchar == '<') {
- // For 'autoread', kNone means to use global value.
- if ((int *)varp == &curbuf->b_p_ar && opt_flags == OPT_LOCAL) {
- newval_bool = kNone;
- } else {
- newval_bool = TRISTATE_FROM_INT(*(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL));
- }
} else {
// ":set invopt": invert
// ":set opt" or ":set noopt": set or reset
@@ -1214,31 +1151,15 @@ static OptVal get_option_newval(OptIndex opt_idx, int opt_flags, set_prefix_T pr
OptInt newval_num;
// Different ways to set a number option:
- // & set to default value
- // < set to global value
// <xx> accept special key codes for 'wildchar' or 'wildcharm'
// ^x accept ctrl key codes for 'wildchar' or 'wildcharm'
// c accept any non-digit for 'wildchar' or 'wildcharm'
// [-]0-9 set number
// other error
arg++;
- if (nextchar == '&') {
- newval_num = options[opt_idx].def_val.number;
- } else if (nextchar == '<') {
- if ((OptInt *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL) {
- // for 'undolevels' NO_LOCAL_UNDOLEVEL means using the global newval_num
- newval_num = NO_LOCAL_UNDOLEVEL;
- } else if (opt_flags == OPT_LOCAL
- && ((OptInt *)varp == &curwin->w_p_siso || (OptInt *)varp == &curwin->w_p_so)) {
- // for 'scrolloff'/'sidescrolloff' -1 means using the global newval_num
- newval_num = -1;
- } else {
- newval_num = *(OptInt *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
- }
- } else if (((OptInt *)varp == &p_wc || (OptInt *)varp == &p_wcm)
- && (*arg == '<' || *arg == '^'
- || (*arg != NUL && (!arg[1] || ascii_iswhite(arg[1]))
- && !ascii_isdigit(*arg)))) {
+ if (((OptInt *)varp == &p_wc || (OptInt *)varp == &p_wcm)
+ && (*arg == '<' || *arg == '^'
+ || (*arg != NUL && (!arg[1] || ascii_iswhite(arg[1])) && !ascii_isdigit(*arg)))) {
newval_num = string_to_key(arg);
if (newval_num == 0) {
*errmsg = e_invarg;
@@ -1318,21 +1239,10 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char *
}
uint8_t nextchar = (uint8_t)(*p); // next non-white char after option name
- uint32_t flags = 0; // flags for current option
- void *varp = NULL; // pointer to variable for current option
-
- if (options[opt_idx].var == NULL) { // hidden option: skip
- // Only give an error message when requesting the value of
- // a hidden option, ignore setting it.
- if (vim_strchr("=:!&<", nextchar) == NULL
- && (!option_has_type(opt_idx, kOptValTypeBoolean) || nextchar == '?')) {
- *errmsg = e_unsupportedoption;
- }
- return;
- }
-
- flags = options[opt_idx].flags;
- varp = get_varp_scope(&(options[opt_idx]), opt_flags);
+ // flags for current option
+ uint32_t flags = options[opt_idx].flags;
+ // pointer to variable for current option
+ void *varp = get_varp_scope(&(options[opt_idx]), opt_flags);
if (validate_opt_idx(curwin, opt_idx, opt_flags, flags, prefix, errmsg) == FAIL) {
return;
@@ -1372,10 +1282,10 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char *
// Mention where the option was last set.
if (varp == options[opt_idx].var) {
option_last_set_msg(options[opt_idx].last_set);
- } else if ((int)options[opt_idx].indir & PV_WIN) {
- option_last_set_msg(curwin->w_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]);
- } else if ((int)options[opt_idx].indir & PV_BUF) {
- option_last_set_msg(curbuf->b_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]);
+ } else if (option_has_scope(opt_idx, kOptScopeWin)) {
+ option_last_set_msg(curwin->w_p_script_ctx[option_scope_idx(opt_idx, kOptScopeWin)]);
+ } else if (option_has_scope(opt_idx, kOptScopeBuf)) {
+ option_last_set_msg(curbuf->b_p_script_ctx[option_scope_idx(opt_idx, kOptScopeBuf)]);
}
}
@@ -1402,11 +1312,6 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char *
}
}
- // Don't try to change hidden option.
- if (varp == NULL) {
- return;
- }
-
OptVal newval = get_option_newval(opt_idx, opt_flags, prefix, argp, nextchar, op, flags, varp,
errbuf, errbuflen, errmsg);
@@ -1414,8 +1319,7 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char *
return;
}
- *errmsg = set_option(opt_idx, varp, newval, opt_flags, 0, false, op == OP_NONE, errbuf,
- errbuflen);
+ *errmsg = set_option(opt_idx, newval, opt_flags, 0, false, op == OP_NONE, errbuf, errbuflen);
}
/// Parse 'arg' for option settings.
@@ -1664,7 +1568,7 @@ char *find_shada_parameter(int type)
static char *option_expand(OptIndex opt_idx, char *val)
{
// if option doesn't need expansion nothing to do
- if (!(options[opt_idx].flags & P_EXPAND) || options[opt_idx].var == NULL) {
+ if (!(options[opt_idx].flags & kOptFlagExpand) || is_option_hidden(opt_idx)) {
return NULL;
}
@@ -1705,7 +1609,7 @@ static void didset_options(void)
spell_check_msm();
spell_check_sps();
compile_cap_prog(curwin->w_s);
- did_set_spell_option(true);
+ did_set_spell_option();
// set cedit_key
did_set_cedit(NULL);
// initialize the table for 'breakat'.
@@ -1736,7 +1640,7 @@ static void didset_options2(void)
/// Check for string options that are NULL (normally only termcap options).
void check_options(void)
{
- for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) {
if ((option_has_type(opt_idx, kOptValTypeString)) && options[opt_idx].var != NULL) {
check_string_option((char **)get_varp(&(options[opt_idx])));
}
@@ -1755,10 +1659,10 @@ int was_set_insecurely(win_T *const wp, OptIndex opt_idx, int opt_flags)
assert(opt_idx != kOptInvalid);
uint32_t *flagp = insecure_flag(wp, opt_idx, opt_flags);
- return (*flagp & P_INSECURE) != 0;
+ return (*flagp & kOptFlagInsecure) != 0;
}
-/// Get a pointer to the flags used for the P_INSECURE flag of option
+/// Get a pointer to the flags used for the kOptFlagInsecure flag of option
/// "opt_idx". For some local options a local flags field is used.
/// NOTE: Caller must make sure that "wp" is set to the window from which
/// the option is used.
@@ -1766,24 +1670,25 @@ uint32_t *insecure_flag(win_T *const wp, OptIndex opt_idx, int opt_flags)
{
if (opt_flags & OPT_LOCAL) {
assert(wp != NULL);
- switch ((int)options[opt_idx].indir) {
- case PV_STL:
+ switch (opt_idx) {
+ case kOptStatusline:
return &wp->w_p_stl_flags;
- case PV_WBR:
+ case kOptWinbar:
return &wp->w_p_wbr_flags;
- case PV_FDE:
+ case kOptFoldexpr:
return &wp->w_p_fde_flags;
- case PV_FDT:
+ case kOptFoldtext:
return &wp->w_p_fdt_flags;
- case PV_INDE:
+ case kOptIndentexpr:
return &wp->w_buffer->b_p_inde_flags;
- case PV_FEX:
+ case kOptFormatexpr:
return &wp->w_buffer->b_p_fex_flags;
- case PV_INEX:
+ case kOptIncludeexpr:
return &wp->w_buffer->b_p_inex_flags;
+ default:
+ break;
}
}
-
// Nothing special, return global flags field.
return &options[opt_idx].flags;
}
@@ -1816,12 +1721,22 @@ void check_blending(win_T *wp)
}
/// Handle setting `winhighlight' in window "wp"
-bool parse_winhl_opt(win_T *wp)
+///
+/// @param winhl when NULL: use "wp->w_p_winhl"
+/// @param wp when NULL: only parse "winhl"
+///
+/// @return whether the option value is valid.
+bool parse_winhl_opt(const char *winhl, win_T *wp)
{
- const char *p = wp->w_p_winhl;
+ const char *p = empty_string_option;
+ if (winhl != NULL) {
+ p = winhl;
+ } else if (wp != NULL) {
+ p = wp->w_p_winhl;
+ }
if (!*p) {
- if (wp->w_ns_hl_winhl && wp->w_ns_hl == wp->w_ns_hl_winhl) {
+ if (wp != NULL && wp->w_ns_hl_winhl && wp->w_ns_hl == wp->w_ns_hl_winhl) {
wp->w_ns_hl = 0;
wp->w_hl_needs_update = true;
}
@@ -1829,39 +1744,49 @@ bool parse_winhl_opt(win_T *wp)
return true;
}
- if (wp->w_ns_hl_winhl == 0) {
- wp->w_ns_hl_winhl = (int)nvim_create_namespace(NULL_STRING);
- } else {
- // namespace already exist. invalidate existing items
- DecorProvider *dp = get_decor_provider(wp->w_ns_hl_winhl, true);
- dp->hl_valid++;
+ int ns_hl = 0;
+ if (wp != NULL) {
+ if (wp->w_ns_hl_winhl == 0) {
+ wp->w_ns_hl_winhl = (int)nvim_create_namespace(NULL_STRING);
+ } else {
+ // Namespace already exists. Invalidate existing items.
+ DecorProvider *dp = get_decor_provider(wp->w_ns_hl_winhl, true);
+ dp->hl_valid++;
+ }
+ wp->w_ns_hl = wp->w_ns_hl_winhl;
+ ns_hl = wp->w_ns_hl;
}
- wp->w_ns_hl = wp->w_ns_hl_winhl;
- int ns_hl = wp->w_ns_hl;
while (*p) {
- char *colon = strchr(p, ':');
+ const char *colon = strchr(p, ':');
if (!colon) {
return false;
}
size_t nlen = (size_t)(colon - p);
- char *hi = colon + 1;
- char *commap = xstrchrnul(hi, ',');
+ const char *hi = colon + 1;
+ const char *commap = xstrchrnul(hi, ',');
size_t len = (size_t)(commap - hi);
int hl_id = len ? syn_check_group(hi, len) : -1;
if (hl_id == 0) {
return false;
}
int hl_id_link = nlen ? syn_check_group(p, nlen) : 0;
+ if (hl_id_link == 0) {
+ return false;
+ }
- HlAttrs attrs = HLATTRS_INIT;
- attrs.rgb_ae_attr |= HL_GLOBAL;
- ns_hl_def(ns_hl, hl_id_link, attrs, hl_id, NULL);
+ if (wp != NULL) {
+ HlAttrs attrs = HLATTRS_INIT;
+ attrs.rgb_ae_attr |= HL_GLOBAL;
+ ns_hl_def(ns_hl, hl_id_link, attrs, hl_id, NULL);
+ }
p = *commap ? commap + 1 : "";
}
- wp->w_hl_needs_update = true;
+ if (wp != NULL) {
+ wp->w_hl_needs_update = true;
+ }
return true;
}
@@ -1877,7 +1802,6 @@ sctx_T *get_option_sctx(OptIndex opt_idx)
void set_option_sctx(OptIndex opt_idx, int opt_flags, sctx_T script_ctx)
{
bool both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
- int indir = (int)options[opt_idx].indir;
nlua_set_sctx(&script_ctx);
LastSet last_set = {
.script_ctx = script_ctx,
@@ -1891,17 +1815,17 @@ void set_option_sctx(OptIndex opt_idx, int opt_flags, sctx_T script_ctx)
// Remember where the option was set. For local options need to do that
// in the buffer or window structure.
- if (both || (opt_flags & OPT_GLOBAL) || (indir & (PV_BUF|PV_WIN)) == 0) {
+ if (both || (opt_flags & OPT_GLOBAL) || option_is_global_only(opt_idx)) {
options[opt_idx].last_set = last_set;
}
if (both || (opt_flags & OPT_LOCAL)) {
- if (indir & PV_BUF) {
- curbuf->b_p_script_ctx[indir & PV_MASK] = last_set;
- } else if (indir & PV_WIN) {
- curwin->w_p_script_ctx[indir & PV_MASK] = last_set;
+ if (option_has_scope(opt_idx, kOptScopeBuf)) {
+ curbuf->b_p_script_ctx[option_scope_idx(opt_idx, kOptScopeBuf)] = last_set;
+ } else if ((option_has_scope(opt_idx, kOptScopeWin))) {
+ curwin->w_p_script_ctx[option_scope_idx(opt_idx, kOptScopeWin)] = last_set;
if (both) {
// also setting the "all buffers" value
- curwin->w_allbuf_opt.wo_script_ctx[indir & PV_MASK] = last_set;
+ curwin->w_allbuf_opt.wo_script_ctx[option_scope_idx(opt_idx, kOptScopeWin)] = last_set;
}
}
}
@@ -1959,7 +1883,7 @@ static const char *did_set_arabic(optset_T *args)
// set rightleft mode
if (!win->w_p_rl) {
win->w_p_rl = true;
- changed_window_setting(curwin);
+ changed_window_setting(win);
}
// Enable Arabic shaping (major part of what Arabic requires)
@@ -1974,8 +1898,8 @@ static const char *did_set_arabic(optset_T *args)
if (strcmp(p_enc, "utf-8") != 0) {
static char *w_arabic = N_("W17: Arabic requires UTF-8, do ':set encoding=utf-8'");
- msg_source(HL_ATTR(HLF_W));
- msg(_(w_arabic), HL_ATTR(HLF_W));
+ msg_source(HLF_W);
+ msg(_(w_arabic), HLF_W);
set_vim_var_string(VV_WARNINGMSG, _(w_arabic), -1);
}
@@ -1990,7 +1914,7 @@ static const char *did_set_arabic(optset_T *args)
// reset rightleft mode
if (win->w_p_rl) {
win->w_p_rl = false;
- changed_window_setting(curwin);
+ changed_window_setting(win);
}
// 'arabicshape' isn't reset, it is a global option and
@@ -2001,8 +1925,8 @@ static const char *did_set_arabic(optset_T *args)
// window may still want it "on".
// Revert to the default keymap
- curbuf->b_p_iminsert = B_IMODE_NONE;
- curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
+ win->w_buffer->b_p_iminsert = B_IMODE_NONE;
+ win->w_buffer->b_p_imsearch = B_IMODE_USE_INSERT;
}
return errmsg;
@@ -2124,9 +2048,7 @@ static const char *did_set_helpheight(optset_T *args)
{
// Change window height NOW
if (!ONE_WINDOW) {
- buf_T *buf = (buf_T *)args->os_buf;
- win_T *win = (win_T *)args->os_win;
- if (buf->b_help && win->w_height < p_hh) {
+ if (curbuf->b_help && curwin->w_height < p_hh) {
win_setheight((int)p_hh);
}
}
@@ -2278,7 +2200,7 @@ static const char *did_set_number_relativenumber(optset_T *args)
// When 'relativenumber'/'number' is changed and 'statuscolumn' is set, reset width.
win->w_nrwidth_line_count = 0;
}
- check_signcolumn(win);
+ check_signcolumn(NULL, win);
return NULL;
}
@@ -2455,14 +2377,16 @@ static const char *did_set_pumblend(optset_T *args FUNC_ATTR_UNUSED)
/// Process the updated 'readonly' option value.
static const char *did_set_readonly(optset_T *args)
{
+ buf_T *buf = (buf_T *)args->os_buf;
+
// when 'readonly' is reset globally, also reset readonlymode
- if (!curbuf->b_p_ro && (args->os_flags & OPT_LOCAL) == 0) {
+ if (!buf->b_p_ro && (args->os_flags & OPT_LOCAL) == 0) {
readonlymode = false;
}
// when 'readonly' is set may give W10 again
- if (curbuf->b_p_ro) {
- curbuf->b_did_warn = false;
+ if (buf->b_p_ro) {
+ buf->b_did_warn = false;
}
redraw_titles();
@@ -2578,8 +2502,7 @@ static const char *did_set_swapfile(optset_T *args)
if (buf->b_p_swf && p_uc) {
ml_open_file(buf); // create the swap file
} else {
- // no need to reset curbuf->b_may_swap, ml_open_file() will check
- // buf->b_p_swf
+ // no need to reset buf->b_may_swap, ml_open_file() will check buf->b_p_swf
mf_close_file(buf, true); // remove the swap file
}
return NULL;
@@ -2589,7 +2512,7 @@ static const char *did_set_swapfile(optset_T *args)
static const char *did_set_textwidth(optset_T *args FUNC_ATTR_UNUSED)
{
FOR_ALL_TAB_WINDOWS(tp, wp) {
- check_colorcolumn(wp);
+ check_colorcolumn(NULL, wp);
}
return NULL;
@@ -2619,8 +2542,10 @@ static const char *did_set_titlelen(optset_T *args)
/// Process the updated 'undofile' option value.
static const char *did_set_undofile(optset_T *args)
{
+ buf_T *buf = (buf_T *)args->os_buf;
+
// Only take action when the option was set.
- if (!curbuf->b_p_udf && !p_udf) {
+ if (!buf->b_p_udf && !p_udf) {
return NULL;
}
@@ -2633,7 +2558,7 @@ static const char *did_set_undofile(optset_T *args)
// only for the current buffer: Try to read in the undofile,
// if one exists, the buffer wasn't changed and the buffer was
// loaded
- if ((curbuf == bp
+ if ((buf == bp
|| (args->os_flags & OPT_GLOBAL) || args->os_flags == 0)
&& !bufIsChanged(bp) && bp->b_ml.ml_mfp != NULL) {
u_compute_hash(bp, hash);
@@ -2673,7 +2598,7 @@ static const char *did_set_undolevels(optset_T *args)
if (pp == &p_ul) { // global 'undolevels'
did_set_global_undolevels(args->os_newval.number, args->os_oldval.number);
- } else if (pp == &curbuf->b_p_ul) { // buffer local 'undolevels'
+ } else if (pp == &buf->b_p_ul) { // buffer local 'undolevels'
did_set_buflocal_undolevels(buf, args->os_newval.number, args->os_oldval.number);
}
@@ -2738,8 +2663,7 @@ static const char *did_set_winheight(optset_T *args)
{
// Change window height NOW
if (!ONE_WINDOW) {
- win_T *win = (win_T *)args->os_win;
- if (win->w_height < p_wh) {
+ if (curwin->w_height < p_wh) {
win_setheight((int)p_wh);
}
}
@@ -2750,9 +2674,7 @@ static const char *did_set_winheight(optset_T *args)
/// Process the new 'winwidth' option value.
static const char *did_set_winwidth(optset_T *args)
{
- win_T *win = (win_T *)args->os_win;
-
- if (!ONE_WINDOW && win->w_width < p_wiw) {
+ if (!ONE_WINDOW && curwin->w_width < p_wiw) {
win_setwidth((int)p_wiw);
}
return NULL;
@@ -2815,15 +2737,14 @@ static void do_spelllang_source(win_T *win)
/// Check the bounds of numeric options.
///
/// @param opt_idx Index in options[] table. Must not be kOptInvalid.
-/// @param[in] varp Pointer to option variable.
/// @param[in,out] newval Pointer to new option value. Will be set to bound checked value.
/// @param[out] errbuf Buffer for error message. Cannot be NULL.
/// @param errbuflen Length of error buffer.
///
/// @return Error message, if any.
-static const char *check_num_option_bounds(OptIndex opt_idx, void *varp, OptInt *newval,
- char *errbuf, size_t errbuflen)
- FUNC_ATTR_NONNULL_ARG(4)
+static const char *check_num_option_bounds(OptIndex opt_idx, OptInt *newval, char *errbuf,
+ size_t errbuflen)
+ FUNC_ATTR_NONNULL_ARG(3)
{
const char *errmsg = NULL;
@@ -2856,9 +2777,7 @@ static const char *check_num_option_bounds(OptIndex opt_idx, void *varp, OptInt
}
break;
case kOptScroll:
- if (varp == &(curwin->w_p_scr)
- && (*newval <= 0
- || (*newval > curwin->w_height_inner && curwin->w_height_inner > 0))
+ if ((*newval <= 0 || (*newval > curwin->w_height_inner && curwin->w_height_inner > 0))
&& full_screen) {
if (*newval != 0) {
errmsg = e_scroll;
@@ -2876,13 +2795,12 @@ static const char *check_num_option_bounds(OptIndex opt_idx, void *varp, OptInt
/// Validate and bound check option value.
///
/// @param opt_idx Index in options[] table. Must not be kOptInvalid.
-/// @param[in] varp Pointer to option variable.
/// @param[in,out] newval Pointer to new option value. Will be set to bound checked value.
/// @param[out] errbuf Buffer for error message. Cannot be NULL.
/// @param errbuflen Length of error buffer.
///
/// @return Error message, if any.
-static const char *validate_num_option(OptIndex opt_idx, void *varp, OptInt *newval, char *errbuf,
+static const char *validate_num_option(OptIndex opt_idx, OptInt *newval, char *errbuf,
size_t errbuflen)
{
OptInt value = *newval;
@@ -2892,167 +2810,168 @@ static const char *validate_num_option(OptIndex opt_idx, void *varp, OptInt *new
return e_invarg;
}
- if (varp == &p_wh) {
+ switch (opt_idx) {
+ case kOptHelpheight:
+ case kOptTitlelen:
+ case kOptUpdatecount:
+ case kOptReport:
+ case kOptUpdatetime:
+ case kOptSidescroll:
+ case kOptFoldlevel:
+ case kOptShiftwidth:
+ case kOptTextwidth:
+ case kOptWritedelay:
+ case kOptTimeoutlen:
+ if (value < 0) {
+ return e_positive;
+ }
+ break;
+ case kOptWinheight:
if (value < 1) {
return e_positive;
} else if (p_wmh > value) {
return e_winheight;
}
- } else if (varp == &p_hh) {
- if (value < 0) {
- return e_positive;
- }
- } else if (varp == &p_wmh) {
+ break;
+ case kOptWinminheight:
if (value < 0) {
return e_positive;
} else if (value > p_wh) {
return e_winheight;
}
- } else if (varp == &p_wiw) {
+ break;
+ case kOptWinwidth:
if (value < 1) {
return e_positive;
} else if (p_wmw > value) {
return e_winwidth;
}
- } else if (varp == &p_wmw) {
+ break;
+ case kOptWinminwidth:
if (value < 0) {
return e_positive;
} else if (value > p_wiw) {
return e_winwidth;
}
- } else if (varp == &p_titlelen) {
- if (value < 0) {
- return e_positive;
- }
- } else if (varp == &p_uc) {
- if (value < 0) {
- return e_positive;
- }
- } else if (varp == &p_ch) {
+ break;
+ case kOptMaxcombine:
+ *newval = MAX_MCO;
+ break;
+ case kOptCmdheight:
if (value < 0) {
return e_positive;
} else {
p_ch_was_zero = value == 0;
}
- } else if (varp == &p_tm) {
+ break;
+ case kOptHistory:
if (value < 0) {
return e_positive;
+ } else if (value > 10000) {
+ return e_invarg;
}
- } else if (varp == &p_hi) {
+ break;
+ case kOptMsghistory:
if (value < 0) {
return e_positive;
} else if (value > 10000) {
return e_invarg;
}
- } else if (varp == &p_pyx) {
+ break;
+ case kOptPyxversion:
if (value == 0) {
*newval = 3;
} else if (value != 3) {
return e_invarg;
}
- } else if (varp == &p_re) {
+ break;
+ case kOptRegexpengine:
if (value < 0 || value > 2) {
return e_invarg;
}
- } else if (varp == &p_report) {
- if (value < 0) {
- return e_positive;
- }
- } else if (varp == &p_so) {
+ break;
+ case kOptScrolloff:
if (value < 0 && full_screen) {
return e_positive;
}
- } else if (varp == &p_siso) {
+ break;
+ case kOptSidescrolloff:
if (value < 0 && full_screen) {
return e_positive;
}
- } else if (varp == &p_cwh) {
+ break;
+ case kOptCmdwinheight:
if (value < 1) {
return e_positive;
}
- } else if (varp == &p_ut) {
- if (value < 0) {
- return e_positive;
- }
- } else if (varp == &p_ss) {
- if (value < 0) {
- return e_positive;
- }
- } else if (varp == &curwin->w_p_fdl || varp == &curwin->w_allbuf_opt.wo_fdl) {
- if (value < 0) {
- return e_positive;
- }
- } else if (varp == &curwin->w_p_cole || varp == &curwin->w_allbuf_opt.wo_cole) {
+ break;
+ case kOptConceallevel:
if (value < 0) {
return e_positive;
} else if (value > 3) {
return e_invarg;
}
- } else if (varp == &curwin->w_p_nuw || varp == &curwin->w_allbuf_opt.wo_nuw) {
+ break;
+ case kOptNumberwidth:
if (value < 1) {
return e_positive;
} else if (value > MAX_NUMBERWIDTH) {
return e_invarg;
}
- } else if (varp == &curbuf->b_p_iminsert || varp == &p_iminsert) {
+ break;
+ case kOptIminsert:
if (value < 0 || value > B_IMODE_LAST) {
return e_invarg;
}
- } else if (varp == &curbuf->b_p_imsearch || varp == &p_imsearch) {
+ break;
+ case kOptImsearch:
if (value < -1 || value > B_IMODE_LAST) {
return e_invarg;
}
- } else if (varp == &curbuf->b_p_channel || varp == &p_channel) {
+ break;
+ case kOptChannel:
return e_invarg;
- } else if (varp == &curbuf->b_p_scbk || varp == &p_scbk) {
+ case kOptScrollback:
if (value < -1 || value > SB_MAX) {
return e_invarg;
}
- } else if (varp == &curbuf->b_p_sw || varp == &p_sw) {
- if (value < 0) {
- return e_positive;
- }
- } else if (varp == &curbuf->b_p_ts || varp == &p_ts) {
+ break;
+ case kOptTabstop:
if (value < 1) {
return e_positive;
} else if (value > TABSTOP_MAX) {
return e_invarg;
}
- } else if (varp == &curbuf->b_p_tw || varp == &p_tw) {
- if (value < 0) {
- return e_positive;
- }
- } else if (varp == &p_wd) {
- if (value < 0) {
- return e_positive;
- }
+ break;
+ default:
+ break;
}
- return check_num_option_bounds(opt_idx, varp, newval, errbuf, errbuflen);
+ return check_num_option_bounds(opt_idx, newval, errbuf, errbuflen);
}
/// Called after an option changed: check if something needs to be redrawn.
void check_redraw_for(buf_T *buf, win_T *win, uint32_t flags)
{
- // Careful: P_RALL is a combination of other P_ flags
- bool all = (flags & P_RALL) == P_RALL;
+ // Careful: kOptFlagRedrAll is a combination of other redraw flags
+ bool all = (flags & kOptFlagRedrAll) == kOptFlagRedrAll;
- if ((flags & P_RSTAT) || all) { // mark all status lines and window bars dirty
+ if ((flags & kOptFlagRedrStat) || all) { // mark all status lines and window bars dirty
status_redraw_all();
}
- if ((flags & P_RTABL) || all) { // mark tablines dirty
+ if ((flags & kOptFlagRedrTabl) || all) { // mark tablines dirty
redraw_tabline = true;
}
- if ((flags & P_RBUF) || (flags & P_RWIN) || all) {
- if (flags & P_HLONLY) {
+ if ((flags & kOptFlagRedrBuf) || (flags & kOptFlagRedrWin) || all) {
+ if (flags & kOptFlagHLOnly) {
redraw_later(win, UPD_NOT_VALID);
} else {
changed_window_setting(win);
}
}
- if (flags & P_RBUF) {
+ if (flags & kOptFlagRedrBuf) {
redraw_buf_later(buf, UPD_NOT_VALID);
}
if (all) {
@@ -3193,11 +3112,25 @@ bool optval_equal(OptVal o1, OptVal o2)
return o1.data.number == o2.data.number;
case kOptValTypeString:
return o1.data.string.size == o2.data.string.size
- && strnequal(o1.data.string.data, o2.data.string.data, o1.data.string.size);
+ && (o1.data.string.data == o2.data.string.data
+ || strnequal(o1.data.string.data, o2.data.string.data, o1.data.string.size));
}
UNREACHABLE;
}
+/// Get type of option. Does not support multitype options.
+static OptValType option_get_type(const OptIndex opt_idx)
+{
+ assert(!option_is_multitype(opt_idx));
+
+ // If the option only supports a single type, it means that the index of the option's type flag
+ // corresponds to the value of the type enum. So get the index of the type flag using xctz() and
+ // use that as the option's type.
+ OptValType type = xctz(options[opt_idx].type_flags);
+ assert(type > kOptValTypeNil && type < kOptValTypeSize);
+ return type;
+}
+
/// Create OptVal from var pointer.
///
/// @param opt_idx Option index in options[] table.
@@ -3205,6 +3138,7 @@ bool optval_equal(OptVal o1, OptVal o2)
///
/// @return Option value stored in varp.
OptVal optval_from_varp(OptIndex opt_idx, void *varp)
+ FUNC_ATTR_NONNULL_ARG(2)
{
// Special case: 'modified' is b_changed, but we also want to consider it set when 'ff' or 'fenc'
// changed.
@@ -3214,24 +3148,20 @@ OptVal optval_from_varp(OptIndex opt_idx, void *varp)
if (option_is_multitype(opt_idx)) {
// Multitype options are stored as OptVal.
- return varp == NULL ? NIL_OPTVAL : *(OptVal *)varp;
+ return *(OptVal *)varp;
}
- // If the option only supports a single type, it means that the index of the option's type flag
- // corresponds to the value of the type enum. So get the index of the type flag using xctz() and
- // use that as the option's type.
- OptValType type = xctz(options[opt_idx].type_flags);
- assert(type > kOptValTypeNil && type < kOptValTypeSize);
+ OptValType type = option_get_type(opt_idx);
switch (type) {
case kOptValTypeNil:
return NIL_OPTVAL;
case kOptValTypeBoolean:
- return BOOLEAN_OPTVAL(varp == NULL ? false : TRISTATE_FROM_INT(*(int *)varp));
+ return BOOLEAN_OPTVAL(TRISTATE_FROM_INT(*(int *)varp));
case kOptValTypeNumber:
- return NUMBER_OPTVAL(varp == NULL ? 0 : *(OptInt *)varp);
+ return NUMBER_OPTVAL(*(OptInt *)varp);
case kOptValTypeString:
- return STRING_OPTVAL(varp == NULL ? (String)STRING_INIT : cstr_as_string(*(char **)varp));
+ return STRING_OPTVAL(cstr_as_string(*(char **)varp));
}
UNREACHABLE;
}
@@ -3334,7 +3264,7 @@ OptVal object_as_optval(Object o, bool *error)
/// Get an allocated string containing a list of valid types for an option.
/// For options with a singular type, it returns the name of the type. For options with multiple
/// possible types, it returns a slash separated list of types. For example, if an option can be a
-/// number, boolean or string, the function returns "Number/Boolean/String"
+/// number, boolean or string, the function returns "number/boolean/string"
static char *option_get_valid_types(OptIndex opt_idx)
{
StringBuilder str = KV_INITIAL_VALUE;
@@ -3356,8 +3286,6 @@ static char *option_get_valid_types(OptIndex opt_idx)
// Ensure that the string is NUL-terminated.
kv_push(str, NUL);
return str.items;
-
-#undef OPTION_ADD_TYPE
}
/// Check if option is hidden.
@@ -3367,7 +3295,74 @@ static char *option_get_valid_types(OptIndex opt_idx)
/// @return True if option is hidden, false otherwise. Returns false if option name is invalid.
bool is_option_hidden(OptIndex opt_idx)
{
- return opt_idx == kOptInvalid ? false : get_varp(&options[opt_idx]) == NULL;
+ // Hidden options are always immutable and point to their default value
+ return opt_idx != kOptInvalid && options[opt_idx].immutable
+ && options[opt_idx].var == &options[opt_idx].def_val.data;
+}
+
+/// Check if option is multitype (supports multiple types).
+static bool option_is_multitype(OptIndex opt_idx)
+{
+ const OptTypeFlags type_flags = get_option(opt_idx)->type_flags;
+ assert(type_flags != 0);
+ return !is_power_of_two(type_flags);
+}
+
+/// Check if option supports a specific type.
+bool option_has_type(OptIndex opt_idx, OptValType type)
+{
+ // Ensure that type flags variable can hold all types.
+ STATIC_ASSERT(kOptValTypeSize <= sizeof(OptTypeFlags) * 8,
+ "Option type_flags cannot fit all option types");
+ // Ensure that the type is valid before accessing type_flags.
+ assert(type > kOptValTypeNil && type < kOptValTypeSize);
+ // Bitshift 1 by the value of type to get the type's corresponding flag, and check if it's set in
+ // the type_flags bit field.
+ return get_option(opt_idx)->type_flags & (1 << type);
+}
+
+/// Check if option supports a specific scope.
+bool option_has_scope(OptIndex opt_idx, OptScope scope)
+{
+ // Ensure that scope flags variable can hold all scopes.
+ STATIC_ASSERT(kOptScopeSize <= sizeof(OptScopeFlags) * 8,
+ "Option scope_flags cannot fit all option scopes");
+ // Ensure that the scope is valid before accessing scope_flags.
+ assert(scope >= kOptScopeGlobal && scope < kOptScopeSize);
+ // Bitshift 1 by the value of scope to get the scope's corresponding flag, and check if it's set
+ // in the scope_flags bit field.
+ return get_option(opt_idx)->scope_flags & (1 << scope);
+}
+
+/// Check if option is global-local.
+static inline bool option_is_global_local(OptIndex opt_idx)
+{
+ // Global-local options have at least two types, so their type flag cannot be a power of two.
+ return opt_idx != kOptInvalid && !is_power_of_two(options[opt_idx].scope_flags);
+}
+
+/// Check if option only supports global scope.
+static inline bool option_is_global_only(OptIndex opt_idx)
+{
+ // For an option to be global-only, it has to only have a single scope, which means the scope
+ // flags must be a power of two, and it must have the global scope.
+ return opt_idx != kOptInvalid && is_power_of_two(options[opt_idx].scope_flags)
+ && option_has_scope(opt_idx, kOptScopeGlobal);
+}
+
+/// Check if option only supports window scope.
+static inline bool option_is_window_local(OptIndex opt_idx)
+{
+ // For an option to be window-local it has to only have a single scope, which means the scope
+ // flags must be a power of two, and it must have the window scope.
+ return opt_idx != kOptInvalid && is_power_of_two(options[opt_idx].scope_flags)
+ && option_has_scope(opt_idx, kOptScopeWin);
+}
+
+/// Get option index for scope.
+ssize_t option_scope_idx(OptIndex opt_idx, OptScope scope)
+{
+ return options[opt_idx].scope_idx[scope];
}
/// Get option flags.
@@ -3418,7 +3413,7 @@ static OptVal get_option_unset_value(OptIndex opt_idx)
vimoption_T *opt = &options[opt_idx];
// For global-local options, use the unset value of the local value.
- if (opt->indir & PV_BOTH) {
+ if (option_is_global_local(opt_idx)) {
// String global-local options always use an empty string for the unset value.
if (option_has_type(opt_idx, kOptValTypeString)) {
return STATIC_CSTR_AS_OPTVAL("");
@@ -3450,7 +3445,7 @@ static bool is_option_local_value_unset(OptIndex opt_idx)
vimoption_T *opt = get_option(opt_idx);
// Local value of option that isn't global-local is always considered set.
- if (!((int)opt->indir & PV_BOTH)) {
+ if (!option_is_global_local(opt_idx)) {
return false;
}
@@ -3484,7 +3479,6 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value
vimoption_T *opt = &options[opt_idx];
const char *errmsg = NULL;
bool restore_chartab = false;
- bool free_oldval = (opt->flags & P_ALLOCED);
bool value_changed = false;
bool value_checked = false;
@@ -3503,15 +3497,15 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value
.os_win = curwin
};
- if (direct || opt->hidden) {
- // Don't do any extra processing if setting directly or if option is hidden.
+ if (direct) {
+ // Don't do any extra processing if setting directly.
}
// Disallow changing immutable options.
else if (opt->immutable && !optval_equal(old_value, new_value)) {
errmsg = e_unsupportedoption;
}
// Disallow changing some options from secure mode.
- else if ((secure || sandbox != 0) && (opt->flags & P_SECURE)) {
+ else if ((secure || sandbox != 0) && (opt->flags & kOptFlagSecure)) {
errmsg = e_secure;
}
// Check for a "normal" directory or file name in some string options.
@@ -3533,7 +3527,7 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value
// If option is hidden or if an error is detected, restore the previous value and don't do any
// further processing.
- if (opt->hidden || errmsg != NULL) {
+ if (errmsg != NULL) {
set_option_varp(opt_idx, varp, old_value, true);
// When resetting some values, need to act on it.
if (restore_chartab) {
@@ -3560,18 +3554,12 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value
set_option_sctx(opt_idx, opt_flags, script_ctx);
}
- // Free options that are in allocated memory.
- // Use "free_oldval", because recursiveness may change the flags (esp. init_highlight()).
- if (free_oldval) {
- optval_free(old_value);
- }
- opt->flags |= P_ALLOCED;
+ optval_free(old_value);
const bool scope_both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
- const bool opt_is_global_local = opt->indir & PV_BOTH;
if (scope_both) {
- if (opt_is_global_local) {
+ if (option_is_global_local(opt_idx)) {
// Global option with local value set to use global value.
// Free the local value and clear it.
void *varp_local = get_varp_scope(opt, OPT_LOCAL);
@@ -3618,7 +3606,8 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value
}
if (curwin->w_curswant != MAXCOL
- && (opt->flags & (P_CURSWANT | P_RALL)) != 0 && (opt->flags & P_HLONLY) == 0) {
+ && (opt->flags & (kOptFlagCurswant | kOptFlagRedrAll)) != 0
+ && (opt->flags & kOptFlagHLOnly) == 0) {
curwin->w_set_curswant = true;
}
@@ -3626,14 +3615,14 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value
if (errmsg == NULL) {
uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags);
- opt->flags |= P_WAS_SET;
+ opt->flags |= kOptFlagWasSet;
- // When an option is set in the sandbox, from a modeline or in secure mode set the P_INSECURE
+ // When an option is set in the sandbox, from a modeline or in secure mode set the kOptFlagInsecure
// flag. Otherwise, if a new value is stored reset the flag.
if (!value_checked && (secure || sandbox != 0 || (opt_flags & OPT_MODELINE))) {
- *p |= P_INSECURE;
+ *p |= kOptFlagInsecure;
} else if (value_replaced) {
- *p &= ~P_INSECURE;
+ *p &= ~(unsigned)kOptFlagInsecure;
}
}
@@ -3643,14 +3632,19 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value
/// Validate the new value for an option.
///
/// @param opt_idx Index in options[] table. Must not be kOptInvalid.
-/// @param varp Pointer to option variable.
/// @param newval[in,out] New option value. Might be modified.
-static const char *validate_option_value(const OptIndex opt_idx, void *varp, OptVal *newval,
- int opt_flags, char *errbuf, size_t errbuflen)
+static const char *validate_option_value(const OptIndex opt_idx, OptVal *newval, int opt_flags,
+ char *errbuf, size_t errbuflen)
{
const char *errmsg = NULL;
vimoption_T *opt = &options[opt_idx];
+ // Always allow unsetting local value of global-local option.
+ if (option_is_global_local(opt_idx) && (opt_flags & OPT_LOCAL)
+ && optval_equal(*newval, get_option_unset_value(opt_idx))) {
+ return NULL;
+ }
+
if (newval->type == kOptValTypeNil) {
// Don't try to unset local value if scope is global.
// TODO(famiu): Change this to forbid changing all non-local scopes when the API scope bug is
@@ -3658,7 +3652,6 @@ static const char *validate_option_value(const OptIndex opt_idx, void *varp, Opt
if (opt_flags == OPT_GLOBAL) {
errmsg = _("Cannot unset global option value");
} else {
- optval_free(*newval);
*newval = optval_copy(get_option_unset_value(opt_idx));
}
} else if (!option_has_type(opt_idx, newval->type)) {
@@ -3671,7 +3664,7 @@ static const char *validate_option_value(const OptIndex opt_idx, void *varp, Opt
errmsg = errbuf;
} else if (newval->type == kOptValTypeNumber) {
// Validate and bound check num option values.
- errmsg = validate_num_option(opt_idx, varp, &newval->data.number, errbuf, errbuflen);
+ errmsg = validate_num_option(opt_idx, &newval->data.number, errbuf, errbuflen);
}
return errmsg;
@@ -3680,7 +3673,6 @@ static const char *validate_option_value(const OptIndex opt_idx, void *varp, Opt
/// Set the value of an option using an OptVal.
///
/// @param opt_idx Index in options[] table. Must not be kOptInvalid.
-/// @param[in] varp Option variable pointer, cannot be NULL.
/// @param value New option value. Might get freed.
/// @param opt_flags Option flags.
/// @param set_sid Script ID. Special values:
@@ -3692,35 +3684,35 @@ static const char *validate_option_value(const OptIndex opt_idx, void *varp, Opt
/// @param errbuflen Length of error buffer.
///
/// @return NULL on success, an untranslated error message on error.
-static const char *set_option(const OptIndex opt_idx, void *varp, OptVal value, int opt_flags,
- scid_T set_sid, const bool direct, const bool value_replaced,
- char *errbuf, size_t errbuflen)
- FUNC_ATTR_NONNULL_ARG(2)
+static const char *set_option(const OptIndex opt_idx, OptVal value, int opt_flags, scid_T set_sid,
+ const bool direct, const bool value_replaced, char *errbuf,
+ size_t errbuflen)
{
assert(opt_idx != kOptInvalid);
- const char *errmsg = validate_option_value(opt_idx, varp, &value, opt_flags, errbuf, errbuflen);
+ const char *errmsg = NULL;
- if (errmsg != NULL) {
- optval_free(value);
- return errmsg;
+ if (!direct) {
+ errmsg = validate_option_value(opt_idx, &value, opt_flags, errbuf, errbuflen);
+
+ if (errmsg != NULL) {
+ optval_free(value);
+ return errmsg;
+ }
}
vimoption_T *opt = &options[opt_idx];
const bool scope_local = opt_flags & OPT_LOCAL;
const bool scope_global = opt_flags & OPT_GLOBAL;
const bool scope_both = !scope_local && !scope_global;
- const bool opt_is_global_local = opt->indir & PV_BOTH;
// Whether local value of global-local option is unset.
- // NOTE: When this is true, it also implies that opt_is_global_local is true.
+ // NOTE: When this is true, it also implies that the option is global-local.
const bool is_opt_local_unset = is_option_local_value_unset(opt_idx);
// When using ":set opt=val" for a global option with a local value the local value will be reset,
- // use the global value here.
- if (scope_both && opt_is_global_local) {
- varp = opt->var;
- }
-
+ // use the global value in that case.
+ void *varp
+ = scope_both && option_is_global_local(opt_idx) ? opt->var : get_varp_scope(opt, opt_flags);
void *varp_local = get_varp_scope(opt, OPT_LOCAL);
void *varp_global = get_varp_scope(opt, OPT_GLOBAL);
@@ -3749,9 +3741,9 @@ static const char *set_option(const OptIndex opt_idx, void *varp, OptVal value,
const int secure_saved = secure;
// When an option is set in the sandbox, from a modeline or in secure mode, then deal with side
- // effects in secure mode. Also when the value was set with the P_INSECURE flag and is not
+ // effects in secure mode. Also when the value was set with the kOptFlagInsecure flag and is not
// completely replaced.
- if ((opt_flags & OPT_MODELINE) || sandbox != 0 || (!value_replaced && (*p & P_INSECURE))) {
+ if ((opt_flags & OPT_MODELINE) || sandbox != 0 || (!value_replaced && (*p & kOptFlagInsecure))) {
secure = 1;
}
@@ -3768,7 +3760,7 @@ static const char *set_option(const OptIndex opt_idx, void *varp, OptVal value,
apply_optionset_autocmd(opt_idx, opt_flags, saved_used_value, saved_old_global_value,
saved_old_local_value, saved_new_value, errmsg);
}
- if (opt->flags & P_UI_OPTION) {
+ if (opt->flags & kOptFlagUIOption) {
ui_call_option_set(cstr_as_string(opt->fullname), optval_as_object(saved_new_value));
}
}
@@ -3794,17 +3786,14 @@ void set_option_direct(OptIndex opt_idx, OptVal value, int opt_flags, scid_T set
{
static char errbuf[IOSIZE];
- vimoption_T *opt = get_option(opt_idx);
-
- if (opt->var == NULL) {
+ if (is_option_hidden(opt_idx)) {
return;
}
- const bool scope_both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
- void *varp = get_varp_scope(opt, scope_both ? OPT_LOCAL : opt_flags);
-
- set_option(opt_idx, varp, optval_copy(value), opt_flags, set_sid, true, true, errbuf,
- sizeof(errbuf));
+ const char *errmsg = set_option(opt_idx, optval_copy(value), opt_flags, set_sid, true, true,
+ errbuf, sizeof(errbuf));
+ assert(errmsg == NULL);
+ (void)errmsg; // ignore unused warning
}
/// Set option value directly for buffer / window, without processing any side effects.
@@ -3815,10 +3804,10 @@ void set_option_direct(OptIndex opt_idx, OptVal value, int opt_flags, scid_T set
/// @param set_sid Script ID. Special values:
/// 0: Use current script ID.
/// SID_NONE: Don't set script ID.
-/// @param req_scope Requested option scope. See OptReqScope in option.h.
+/// @param req_scope Requested option scope. See OptScope in option.h.
/// @param[in] from Target buffer/window.
void set_option_direct_for(OptIndex opt_idx, OptVal value, int opt_flags, scid_T set_sid,
- OptReqScope req_scope, void *const from)
+ OptScope req_scope, void *const from)
{
buf_T *save_curbuf = curbuf;
win_T *save_curwin = curwin;
@@ -3827,15 +3816,15 @@ void set_option_direct_for(OptIndex opt_idx, OptVal value, int opt_flags, scid_T
// side-effects when setting an option directly. Just change the values of curbuf and curwin if
// needed, no need to properly switch the window / buffer.
switch (req_scope) {
- case kOptReqGlobal:
- break;
- case kOptReqBuf:
- curbuf = (buf_T *)from;
+ case kOptScopeGlobal:
break;
- case kOptReqWin:
+ case kOptScopeWin:
curwin = (win_T *)from;
curbuf = curwin->w_buffer;
break;
+ case kOptScopeBuf:
+ curbuf = (buf_T *)from;
+ break;
}
set_option_direct(opt_idx, value, opt_flags, set_sid);
@@ -3859,18 +3848,22 @@ const char *set_option_value(const OptIndex opt_idx, const OptVal value, int opt
uint32_t flags = options[opt_idx].flags;
// Disallow changing some options in the sandbox
- if (sandbox > 0 && (flags & P_SECURE)) {
+ if (sandbox > 0 && (flags & kOptFlagSecure)) {
return _(e_sandbox);
}
- void *varp = get_varp_scope(&(options[opt_idx]), opt_flags);
- if (varp == NULL) {
- // hidden option is not changed
- return NULL;
- }
+ return set_option(opt_idx, optval_copy(value), opt_flags, 0, false, true, errbuf, sizeof(errbuf));
+}
- return set_option(opt_idx, varp, optval_copy(value), opt_flags, 0, false, true, errbuf,
- sizeof(errbuf));
+/// Unset the local value of a global-local option.
+///
+/// @param opt_idx Index in options[] table. Must not be kOptInvalid.
+///
+/// @return NULL on success, an untranslated error message on error.
+static inline const char *unset_option_local_value(const OptIndex opt_idx)
+{
+ assert(option_is_global_local(opt_idx));
+ return set_option_value(opt_idx, get_option_unset_value(opt_idx), OPT_LOCAL);
}
/// Set the value of an option. Supports TTY options, unlike set_option_value().
@@ -3918,16 +3911,17 @@ void set_option_value_give_err(const OptIndex opt_idx, OptVal value, int opt_fla
/// Switch current context to get/set option value for window/buffer.
///
/// @param[out] ctx Current context. switchwin_T for window and aco_save_T for buffer.
-/// @param req_scope Requested option scope. See OptReqScope in option.h.
+/// @param req_scope Requested option scope. See OptScope in option.h.
/// @param[in] from Target buffer/window.
/// @param[out] err Error message, if any.
///
/// @return true if context was switched, false otherwise.
-static bool switch_option_context(void *const ctx, OptReqScope req_scope, void *const from,
- Error *err)
+static bool switch_option_context(void *const ctx, OptScope req_scope, void *const from, Error *err)
{
switch (req_scope) {
- case kOptReqWin: {
+ case kOptScopeGlobal:
+ return false;
+ case kOptScopeWin: {
win_T *const win = (win_T *)from;
switchwin_T *const switchwin = (switchwin_T *)ctx;
@@ -3947,7 +3941,7 @@ static bool switch_option_context(void *const ctx, OptReqScope req_scope, void *
}
return true;
}
- case kOptReqBuf: {
+ case kOptScopeBuf: {
buf_T *const buf = (buf_T *)from;
aco_save_T *const aco = (aco_save_T *)ctx;
@@ -3957,150 +3951,44 @@ static bool switch_option_context(void *const ctx, OptReqScope req_scope, void *
aucmd_prepbuf(aco, buf);
return true;
}
- case kOptReqGlobal:
- return false;
}
UNREACHABLE;
}
/// Restore context after getting/setting option for window/buffer. See switch_option_context() for
/// params.
-static void restore_option_context(void *const ctx, OptReqScope req_scope)
+static void restore_option_context(void *const ctx, OptScope req_scope)
{
switch (req_scope) {
- case kOptReqWin:
+ case kOptScopeGlobal:
+ break;
+ case kOptScopeWin:
restore_win_noblock((switchwin_T *)ctx, true);
break;
- case kOptReqBuf:
+ case kOptScopeBuf:
aucmd_restbuf((aco_save_T *)ctx);
break;
- case kOptReqGlobal:
- break;
}
}
-/// Get attributes for an option.
-///
-/// @param opt_idx Option index in options[] table.
-///
-/// @return Option attributes.
-/// 0 for hidden or unknown option.
-/// See SOPT_* in option_defs.h for other flags.
-int get_option_attrs(OptIndex opt_idx)
-{
- if (opt_idx == kOptInvalid) {
- return 0;
- }
-
- vimoption_T *opt = get_option(opt_idx);
-
- // Hidden option
- if (opt->var == NULL) {
- return 0;
- }
-
- int attrs = 0;
-
- if (opt->indir == PV_NONE || (opt->indir & PV_BOTH)) {
- attrs |= SOPT_GLOBAL;
- }
- if (opt->indir & PV_WIN) {
- attrs |= SOPT_WIN;
- } else if (opt->indir & PV_BUF) {
- attrs |= SOPT_BUF;
- }
-
- return attrs;
-}
-
-/// Check if option has a value in the requested scope.
-///
-/// @param opt_idx Option index in options[] table.
-/// @param req_scope Requested option scope. See OptReqScope in option.h.
-///
-/// @return true if option has a value in the requested scope, false otherwise.
-static bool option_has_scope(OptIndex opt_idx, OptReqScope req_scope)
-{
- if (opt_idx == kOptInvalid) {
- return false;
- }
-
- vimoption_T *opt = get_option(opt_idx);
-
- // Hidden option.
- if (opt->var == NULL) {
- return false;
- }
- // TTY option.
- if (is_tty_option(opt->fullname)) {
- return req_scope == kOptReqGlobal;
- }
-
- switch (req_scope) {
- case kOptReqGlobal:
- return opt->var != VAR_WIN;
- case kOptReqBuf:
- return opt->indir & PV_BUF;
- case kOptReqWin:
- return opt->indir & PV_WIN;
- }
- UNREACHABLE;
-}
-
-/// Get the option value in the requested scope.
-///
-/// @param opt_idx Option index in options[] table.
-/// @param req_scope Requested option scope. See OptReqScope in option.h.
-/// @param[in] from Pointer to buffer or window for local option value.
-/// @param[out] err Error message, if any.
-///
-/// @return Option value in the requested scope. Returns a Nil option value if option is not found,
-/// hidden or if it isn't present in the requested scope. (i.e. has no global, window-local or
-/// buffer-local value depending on opt_scope).
-OptVal get_option_value_strict(OptIndex opt_idx, OptReqScope req_scope, void *from, Error *err)
-{
- if (opt_idx == kOptInvalid || !option_has_scope(opt_idx, req_scope)) {
- return NIL_OPTVAL;
- }
-
- vimoption_T *opt = get_option(opt_idx);
- switchwin_T switchwin;
- aco_save_T aco;
- void *ctx = req_scope == kOptReqWin ? (void *)&switchwin
- : (req_scope == kOptReqBuf ? (void *)&aco : NULL);
- bool switched = switch_option_context(ctx, req_scope, from, err);
- if (ERROR_SET(err)) {
- return NIL_OPTVAL;
- }
-
- char *varp = get_varp_scope(opt, req_scope == kOptReqGlobal ? OPT_GLOBAL : OPT_LOCAL);
- OptVal retv = optval_from_varp(opt_idx, varp);
-
- if (switched) {
- restore_option_context(ctx, req_scope);
- }
-
- return retv;
-}
-
/// Get option value for buffer / window.
///
/// @param opt_idx Option index in options[] table.
-/// @param[out] flagsp Set to the option flags (P_xxxx) (if not NULL).
+/// @param[out] flagsp Set to the option flags (see OptFlags) (if not NULL).
/// @param[in] scope Option scope (can be OPT_LOCAL, OPT_GLOBAL or a combination).
/// @param[out] hidden Whether option is hidden.
-/// @param req_scope Requested option scope. See OptReqScope in option.h.
+/// @param req_scope Requested option scope. See OptScope in option.h.
/// @param[in] from Target buffer/window.
/// @param[out] err Error message, if any.
///
/// @return Option value. Must be freed by caller.
-OptVal get_option_value_for(OptIndex opt_idx, int scope, const OptReqScope req_scope,
- void *const from, Error *err)
+OptVal get_option_value_for(OptIndex opt_idx, int scope, const OptScope req_scope, void *const from,
+ Error *err)
{
switchwin_T switchwin;
aco_save_T aco;
- void *ctx = req_scope == kOptReqWin ? (void *)&switchwin
- : (req_scope == kOptReqBuf ? (void *)&aco : NULL);
+ void *ctx = req_scope == kOptScopeWin ? (void *)&switchwin
+ : (req_scope == kOptScopeBuf ? (void *)&aco : NULL);
bool switched = switch_option_context(ctx, req_scope, from, err);
if (ERROR_SET(err)) {
@@ -4122,17 +4010,17 @@ OptVal get_option_value_for(OptIndex opt_idx, int scope, const OptReqScope req_s
/// @param opt_idx Option index in options[] table.
/// @param[in] value Option value.
/// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both).
-/// @param req_scope Requested option scope. See OptReqScope in option.h.
+/// @param req_scope Requested option scope. See OptScope in option.h.
/// @param[in] from Target buffer/window.
/// @param[out] err Error message, if any.
void set_option_value_for(const char *name, OptIndex opt_idx, OptVal value, const int opt_flags,
- const OptReqScope req_scope, void *const from, Error *err)
+ const OptScope req_scope, void *const from, Error *err)
FUNC_ATTR_NONNULL_ARG(1)
{
switchwin_T switchwin;
aco_save_T aco;
- void *ctx = req_scope == kOptReqWin ? (void *)&switchwin
- : (req_scope == kOptReqBuf ? (void *)&aco : NULL);
+ void *ctx = req_scope == kOptScopeWin ? (void *)&switchwin
+ : (req_scope == kOptScopeBuf ? (void *)&aco : NULL);
bool switched = switch_option_context(ctx, req_scope, from, err);
if (ERROR_SET(err)) {
@@ -4177,7 +4065,7 @@ static void showoptions(bool all, int opt_flags)
// collect the items in items[]
int item_count = 0;
vimoption_T *opt;
- for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) {
opt = &options[opt_idx];
// apply :filter /pat/
if (message_filtered(opt->fullname)) {
@@ -4186,7 +4074,7 @@ static void showoptions(bool all, int opt_flags)
void *varp = NULL;
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) != 0) {
- if (opt->indir != PV_NONE) {
+ if (!option_is_global_only(opt_idx)) {
varp = get_varp_scope(opt, opt_flags);
}
} else {
@@ -4247,13 +4135,13 @@ static int optval_default(OptIndex opt_idx, void *varp)
{
vimoption_T *opt = &options[opt_idx];
- // Hidden or immutable options always use their default value.
- if (varp == NULL || opt->hidden || opt->immutable) {
+ // Hidden options always use their default value.
+ if (is_option_hidden(opt_idx)) {
return true;
}
OptVal current_val = optval_from_varp(opt_idx, varp);
- OptVal default_val = optval_from_varp(opt_idx, &opt->def_val);
+ OptVal default_val = opt->def_val;
return optval_equal(current_val, default_val);
}
@@ -4261,9 +4149,9 @@ static int optval_default(OptIndex opt_idx, void *varp)
/// Send update to UIs with values of UI relevant options
void ui_refresh_options(void)
{
- for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) {
uint32_t flags = options[opt_idx].flags;
- if (!(flags & P_UI_OPTION)) {
+ if (!(flags & kOptFlagUIOption)) {
continue;
}
String name = cstr_as_string(options[opt_idx].fullname);
@@ -4303,7 +4191,7 @@ static void showoneopt(vimoption_T *opt, int opt_flags)
msg_putchar('=');
// put value string in NameBuff
option_value2string(opt, opt_flags);
- msg_outtrans(NameBuff, 0);
+ msg_outtrans(NameBuff, 0, false);
}
silent_mode = save_silent;
@@ -4338,22 +4226,22 @@ int makeset(FILE *fd, int opt_flags, int local_only)
// - Hidden options.
//
// Do the loop over "options[]" twice: once for options with the
- // P_PRI_MKRC flag and once without.
+ // kOptFlagPriMkrc flag and once without.
for (int pri = 1; pri >= 0; pri--) {
vimoption_T *opt;
- for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) {
opt = &options[opt_idx];
- if (!(opt->flags & P_NO_MKRC)
- && ((pri == 1) == ((opt->flags & P_PRI_MKRC) != 0))) {
+ if (!(opt->flags & kOptFlagNoMkrc)
+ && ((pri == 1) == ((opt->flags & kOptFlagPriMkrc) != 0))) {
// skip global option when only doing locals
- if (opt->indir == PV_NONE && !(opt_flags & OPT_GLOBAL)) {
+ if (option_is_global_only(opt_idx) && !(opt_flags & OPT_GLOBAL)) {
continue;
}
// Do not store options like 'bufhidden' and 'syntax' in a vimrc
// file, they are always buffer-specific.
- if ((opt_flags & OPT_GLOBAL) && (opt->flags & P_NOGLOB)) {
+ if ((opt_flags & OPT_GLOBAL) && (opt->flags & kOptFlagNoGlob)) {
continue;
}
@@ -4374,21 +4262,19 @@ int makeset(FILE *fd, int opt_flags, int local_only)
int round = 2;
void *varp_local = NULL; // fresh value
- if (opt->indir != PV_NONE) {
- if (opt->var == VAR_WIN) {
- // skip window-local option when only doing globals
- if (!(opt_flags & OPT_LOCAL)) {
- continue;
- }
- // When fresh value of window-local option is not at the
- // default, need to write it too.
- if (!(opt_flags & OPT_GLOBAL) && !local_only) {
- void *varp_fresh = get_varp_scope(opt, OPT_GLOBAL); // local value
- if (!optval_default(opt_idx, varp_fresh)) {
- round = 1;
- varp_local = varp;
- varp = varp_fresh;
- }
+ if (option_is_window_local(opt_idx)) {
+ // skip window-local option when only doing globals
+ if (!(opt_flags & OPT_LOCAL)) {
+ continue;
+ }
+ // When fresh value of window-local option is not at the
+ // default, need to write it too.
+ if (!(opt_flags & OPT_GLOBAL) && !local_only) {
+ void *varp_fresh = get_varp_scope(opt, OPT_GLOBAL); // local value
+ if (!optval_default(opt_idx, varp_fresh)) {
+ round = 1;
+ varp_local = varp;
+ varp = varp_fresh;
}
}
}
@@ -4403,35 +4289,24 @@ int makeset(FILE *fd, int opt_flags, int local_only)
cmd = "setlocal";
}
- if (option_has_type(opt_idx, kOptValTypeBoolean)) {
- if (put_setbool(fd, cmd, opt->fullname, *(int *)varp) == FAIL) {
- return FAIL;
- }
- } else if (option_has_type(opt_idx, kOptValTypeNumber)) {
- if (put_setnum(fd, cmd, opt->fullname, (OptInt *)varp) == FAIL) {
+ bool do_endif = false;
+ // Don't set 'syntax' and 'filetype' again if the value is already right, avoids reloading
+ // the syntax file.
+ if (opt_idx == kOptSyntax || opt_idx == kOptFiletype) {
+ if (fprintf(fd, "if &%s != '%s'", opt->fullname,
+ *(char **)(varp)) < 0
+ || put_eol(fd) < 0) {
return FAIL;
}
- } else { // string
- bool do_endif = false;
-
- // Don't set 'syntax' and 'filetype' again if the value is
- // already right, avoids reloading the syntax file.
- if (opt->indir == PV_SYN || opt->indir == PV_FT) {
- if (fprintf(fd, "if &%s != '%s'", opt->fullname,
- *(char **)(varp)) < 0
- || put_eol(fd) < 0) {
- return FAIL;
- }
- do_endif = true;
- }
- if (put_setstring(fd, cmd, opt->fullname, (char **)varp, opt->flags) == FAIL) {
+ do_endif = true;
+ }
+ if (put_set(fd, cmd, opt_idx, varp) == FAIL) {
+ return FAIL;
+ }
+ if (do_endif) {
+ if (put_line(fd, "endif") == FAIL) {
return FAIL;
}
- if (do_endif) {
- if (put_line(fd, "endif") == FAIL) {
- return FAIL;
- }
- }
}
}
}
@@ -4444,110 +4319,133 @@ int makeset(FILE *fd, int opt_flags, int local_only)
/// 'sessionoptions' or 'viewoptions' contains "folds" but not "options".
int makefoldset(FILE *fd)
{
- if (put_setstring(fd, "setlocal", "fdm", &curwin->w_p_fdm, 0) == FAIL
- || put_setstring(fd, "setlocal", "fde", &curwin->w_p_fde, 0) == FAIL
- || put_setstring(fd, "setlocal", "fmr", &curwin->w_p_fmr, 0) == FAIL
- || put_setstring(fd, "setlocal", "fdi", &curwin->w_p_fdi, 0) == FAIL
- || put_setnum(fd, "setlocal", "fdl", &curwin->w_p_fdl) == FAIL
- || put_setnum(fd, "setlocal", "fml", &curwin->w_p_fml) == FAIL
- || put_setnum(fd, "setlocal", "fdn", &curwin->w_p_fdn) == FAIL
- || put_setbool(fd, "setlocal", "fen", curwin->w_p_fen) == FAIL) {
+ if (put_set(fd, "setlocal", kOptFoldmethod, &curwin->w_p_fdm) == FAIL
+ || put_set(fd, "setlocal", kOptFoldexpr, &curwin->w_p_fde) == FAIL
+ || put_set(fd, "setlocal", kOptFoldmarker, &curwin->w_p_fmr) == FAIL
+ || put_set(fd, "setlocal", kOptFoldignore, &curwin->w_p_fdi) == FAIL
+ || put_set(fd, "setlocal", kOptFoldlevel, &curwin->w_p_fdl) == FAIL
+ || put_set(fd, "setlocal", kOptFoldminlines, &curwin->w_p_fml) == FAIL
+ || put_set(fd, "setlocal", kOptFoldnestmax, &curwin->w_p_fdn) == FAIL
+ || put_set(fd, "setlocal", kOptFoldenable, &curwin->w_p_fen) == FAIL) {
return FAIL;
}
return OK;
}
-static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_t flags)
+/// Print the ":set" command to set a single option to file.
+///
+/// @param fd File descriptor.
+/// @param cmd Command name.
+/// @param opt_idx Option index in options[] table.
+/// @param varp Pointer to option variable.
+///
+/// @return FAIL on error, OK otherwise.
+static int put_set(FILE *fd, char *cmd, OptIndex opt_idx, void *varp)
{
- if (fprintf(fd, "%s %s=", cmd, name) < 0) {
- return FAIL;
+ OptVal value = optval_from_varp(opt_idx, varp);
+ vimoption_T *opt = &options[opt_idx];
+ char *name = opt->fullname;
+ uint64_t flags = opt->flags;
+
+ if (option_is_global_local(opt_idx) && varp != opt->var
+ && optval_equal(value, get_option_unset_value(opt_idx))) {
+ // Processing unset local value of global-local option. Do nothing.
+ return OK;
+ }
+
+ switch (value.type) {
+ case kOptValTypeNil:
+ abort();
+ case kOptValTypeBoolean: {
+ assert(value.data.boolean != kNone);
+ bool value_bool = TRISTATE_TO_BOOL(value.data.boolean, false);
+
+ if (fprintf(fd, "%s %s%s", cmd, value_bool ? "" : "no", name) < 0) {
+ return FAIL;
+ }
+ break;
+ }
+ case kOptValTypeNumber: {
+ if (fprintf(fd, "%s %s=", cmd, name) < 0) {
+ return FAIL;
+ }
+
+ OptInt value_num = value.data.number;
+
+ OptInt wc;
+ if (wc_use_keyname(varp, &wc)) {
+ // print 'wildchar' and 'wildcharm' as a key name
+ if (fputs(get_special_key_name((int)wc, 0), fd) < 0) {
+ return FAIL;
+ }
+ } else if (fprintf(fd, "%" PRId64, value_num) < 0) {
+ return FAIL;
+ }
+ break;
}
+ case kOptValTypeString: {
+ if (fprintf(fd, "%s %s=", cmd, name) < 0) {
+ return FAIL;
+ }
- char *buf = NULL;
- char *part = NULL;
+ char *value_str = value.data.string.data;
+ char *buf = NULL;
+ char *part = NULL;
- if (*valuep != NULL) {
- if ((flags & P_EXPAND) != 0) {
- size_t size = (size_t)strlen(*valuep) + 1;
+ if (value_str != NULL) {
+ if ((flags & kOptFlagExpand) != 0) {
+ size_t size = (size_t)strlen(value_str) + 1;
- // replace home directory in the whole option value into "buf"
- buf = xmalloc(size);
- home_replace(NULL, *valuep, buf, size, false);
+ // replace home directory in the whole option value into "buf"
+ buf = xmalloc(size);
+ home_replace(NULL, value_str, buf, size, false);
- // If the option value is longer than MAXPATHL, we need to append
- // each comma separated part of the option separately, so that it
- // can be expanded when read back.
- if (size >= MAXPATHL && (flags & P_COMMA) != 0
- && vim_strchr(*valuep, ',') != NULL) {
- part = xmalloc(size);
+ // If the option value is longer than MAXPATHL, we need to append
+ // each comma separated part of the option separately, so that it
+ // can be expanded when read back.
+ if (size >= MAXPATHL && (flags & kOptFlagComma) != 0
+ && vim_strchr(value_str, ',') != NULL) {
+ part = xmalloc(size);
- // write line break to clear the option, e.g. ':set rtp='
- if (put_eol(fd) == FAIL) {
- goto fail;
- }
- char *p = buf;
- while (*p != NUL) {
- // for each comma separated option part, append value to
- // the option, :set rtp+=value
- if (fprintf(fd, "%s %s+=", cmd, name) < 0) {
+ // write line break to clear the option, e.g. ':set rtp='
+ if (put_eol(fd) == FAIL) {
goto fail;
}
- copy_option_part(&p, part, size, ",");
- if (put_escstr(fd, part, 2) == FAIL || put_eol(fd) == FAIL) {
- goto fail;
+ char *p = buf;
+ while (*p != NUL) {
+ // for each comma separated option part, append value to
+ // the option, :set rtp+=value
+ if (fprintf(fd, "%s %s+=", cmd, name) < 0) {
+ goto fail;
+ }
+ copy_option_part(&p, part, size, ",");
+ if (put_escstr(fd, part, 2) == FAIL || put_eol(fd) == FAIL) {
+ goto fail;
+ }
}
+ xfree(buf);
+ xfree(part);
+ return OK;
+ }
+ if (put_escstr(fd, buf, 2) == FAIL) {
+ xfree(buf);
+ return FAIL;
}
xfree(buf);
- xfree(part);
- return OK;
- }
- if (put_escstr(fd, buf, 2) == FAIL) {
- xfree(buf);
+ } else if (put_escstr(fd, value_str, 2) == FAIL) {
return FAIL;
}
- xfree(buf);
- } else if (put_escstr(fd, *valuep, 2) == FAIL) {
- return FAIL;
}
- }
- if (put_eol(fd) < 0) {
- return FAIL;
- }
- return OK;
-fail:
- xfree(buf);
- xfree(part);
- return FAIL;
-}
-
-static int put_setnum(FILE *fd, char *cmd, char *name, OptInt *valuep)
-{
- if (fprintf(fd, "%s %s=", cmd, name) < 0) {
- return FAIL;
- }
- OptInt wc;
- if (wc_use_keyname(valuep, &wc)) {
- // print 'wildchar' and 'wildcharm' as a key name
- if (fputs(get_special_key_name((int)wc, 0), fd) < 0) {
- return FAIL;
- }
- } else if (fprintf(fd, "%" PRId64, (int64_t)(*valuep)) < 0) {
+ break;
+ fail:
+ xfree(buf);
+ xfree(part);
return FAIL;
}
- if (put_eol(fd) < 0) {
- return FAIL;
}
- return OK;
-}
-static int put_setbool(FILE *fd, char *cmd, char *name, int value)
-{
- if (value < 0) { // global/local option using global value
- return OK;
- }
- if (fprintf(fd, "%s %s%s", cmd, value ? "" : "no", name) < 0
- || put_eol(fd) < 0) {
+ if (put_eol(fd) < 0) {
return FAIL;
}
return OK;
@@ -4555,74 +4453,80 @@ static int put_setbool(FILE *fd, char *cmd, char *name, int value)
void *get_varp_scope_from(vimoption_T *p, int scope, buf_T *buf, win_T *win)
{
- if ((scope & OPT_GLOBAL) && p->indir != PV_NONE) {
- if (p->var == VAR_WIN) {
+ OptIndex opt_idx = get_opt_idx(p);
+
+ if ((scope & OPT_GLOBAL) && !option_is_global_only(opt_idx)) {
+ if (option_is_window_local(opt_idx)) {
return GLOBAL_WO(get_varp_from(p, buf, win));
}
return p->var;
}
- if ((scope & OPT_LOCAL) && ((int)p->indir & PV_BOTH)) {
- switch ((int)p->indir) {
- case PV_FP:
+
+ if ((scope & OPT_LOCAL) && option_is_global_local(opt_idx)) {
+ switch (opt_idx) {
+ case kOptFormatprg:
return &(buf->b_p_fp);
- case PV_EFM:
+ case kOptFindfunc:
+ return &(buf->b_p_ffu);
+ case kOptErrorformat:
return &(buf->b_p_efm);
- case PV_GP:
+ case kOptGrepprg:
return &(buf->b_p_gp);
- case PV_MP:
+ case kOptMakeprg:
return &(buf->b_p_mp);
- case PV_EP:
+ case kOptEqualprg:
return &(buf->b_p_ep);
- case PV_KP:
+ case kOptKeywordprg:
return &(buf->b_p_kp);
- case PV_PATH:
+ case kOptPath:
return &(buf->b_p_path);
- case PV_AR:
+ case kOptAutoread:
return &(buf->b_p_ar);
- case PV_TAGS:
+ case kOptTags:
return &(buf->b_p_tags);
- case PV_TC:
+ case kOptTagcase:
return &(buf->b_p_tc);
- case PV_SISO:
+ case kOptSidescrolloff:
return &(win->w_p_siso);
- case PV_SO:
+ case kOptScrolloff:
return &(win->w_p_so);
- case PV_DEF:
+ case kOptDefine:
return &(buf->b_p_def);
- case PV_INC:
+ case kOptInclude:
return &(buf->b_p_inc);
- case PV_COT:
+ case kOptCompleteopt:
return &(buf->b_p_cot);
- case PV_DICT:
+ case kOptDictionary:
return &(buf->b_p_dict);
- case PV_TSR:
+ case kOptThesaurus:
return &(buf->b_p_tsr);
- case PV_TSRFU:
+ case kOptThesaurusfunc:
return &(buf->b_p_tsrfu);
- case PV_TFU:
+ case kOptTagfunc:
return &(buf->b_p_tfu);
- case PV_SBR:
+ case kOptShowbreak:
return &(win->w_p_sbr);
- case PV_STL:
+ case kOptStatusline:
return &(win->w_p_stl);
- case PV_WBR:
+ case kOptWinbar:
return &(win->w_p_wbr);
- case PV_UL:
+ case kOptUndolevels:
return &(buf->b_p_ul);
- case PV_LW:
+ case kOptLispwords:
return &(buf->b_p_lw);
- case PV_BKC:
+ case kOptBackupcopy:
return &(buf->b_p_bkc);
- case PV_MENC:
+ case kOptMakeencoding:
return &(buf->b_p_menc);
- case PV_FCS:
+ case kOptFillchars:
return &(win->w_p_fcs);
- case PV_LCS:
+ case kOptListchars:
return &(win->w_p_lcs);
- case PV_VE:
+ case kOptVirtualedit:
return &(win->w_p_ve);
+ default:
+ abort();
}
- return NULL; // "cannot happen"
}
return get_varp_from(p, buf, win);
}
@@ -4644,291 +4548,292 @@ void *get_option_varp_scope_from(OptIndex opt_idx, int scope, buf_T *buf, win_T
void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
{
- // hidden option, always return NULL
- if (p->var == NULL) {
- return NULL;
- }
+ OptIndex opt_idx = get_opt_idx(p);
- switch ((int)p->indir) {
- case PV_NONE:
+ // Hidden options and global-only options always use the same var pointer
+ if (is_option_hidden(opt_idx) || option_is_global_only(opt_idx)) {
return p->var;
+ }
+ switch (opt_idx) {
// global option with local value: use local value if it's been set
- case PV_EP:
+ case kOptEqualprg:
return *buf->b_p_ep != NUL ? &buf->b_p_ep : p->var;
- case PV_KP:
+ case kOptKeywordprg:
return *buf->b_p_kp != NUL ? &buf->b_p_kp : p->var;
- case PV_PATH:
+ case kOptPath:
return *buf->b_p_path != NUL ? &(buf->b_p_path) : p->var;
- case PV_AR:
+ case kOptAutoread:
return buf->b_p_ar >= 0 ? &(buf->b_p_ar) : p->var;
- case PV_TAGS:
+ case kOptTags:
return *buf->b_p_tags != NUL ? &(buf->b_p_tags) : p->var;
- case PV_TC:
+ case kOptTagcase:
return *buf->b_p_tc != NUL ? &(buf->b_p_tc) : p->var;
- case PV_SISO:
+ case kOptSidescrolloff:
return win->w_p_siso >= 0 ? &(win->w_p_siso) : p->var;
- case PV_SO:
+ case kOptScrolloff:
return win->w_p_so >= 0 ? &(win->w_p_so) : p->var;
- case PV_BKC:
+ case kOptBackupcopy:
return *buf->b_p_bkc != NUL ? &(buf->b_p_bkc) : p->var;
- case PV_DEF:
+ case kOptDefine:
return *buf->b_p_def != NUL ? &(buf->b_p_def) : p->var;
- case PV_INC:
+ case kOptInclude:
return *buf->b_p_inc != NUL ? &(buf->b_p_inc) : p->var;
- case PV_COT:
+ case kOptCompleteopt:
return *buf->b_p_cot != NUL ? &(buf->b_p_cot) : p->var;
- case PV_DICT:
+ case kOptDictionary:
return *buf->b_p_dict != NUL ? &(buf->b_p_dict) : p->var;
- case PV_TSR:
+ case kOptThesaurus:
return *buf->b_p_tsr != NUL ? &(buf->b_p_tsr) : p->var;
- case PV_TSRFU:
+ case kOptThesaurusfunc:
return *buf->b_p_tsrfu != NUL ? &(buf->b_p_tsrfu) : p->var;
- case PV_FP:
+ case kOptFormatprg:
return *buf->b_p_fp != NUL ? &(buf->b_p_fp) : p->var;
- case PV_EFM:
+ case kOptFindfunc:
+ return *buf->b_p_ffu != NUL ? &(buf->b_p_ffu) : p->var;
+ case kOptErrorformat:
return *buf->b_p_efm != NUL ? &(buf->b_p_efm) : p->var;
- case PV_GP:
+ case kOptGrepprg:
return *buf->b_p_gp != NUL ? &(buf->b_p_gp) : p->var;
- case PV_MP:
+ case kOptMakeprg:
return *buf->b_p_mp != NUL ? &(buf->b_p_mp) : p->var;
- case PV_SBR:
+ case kOptShowbreak:
return *win->w_p_sbr != NUL ? &(win->w_p_sbr) : p->var;
- case PV_STL:
+ case kOptStatusline:
return *win->w_p_stl != NUL ? &(win->w_p_stl) : p->var;
- case PV_WBR:
+ case kOptWinbar:
return *win->w_p_wbr != NUL ? &(win->w_p_wbr) : p->var;
- case PV_UL:
+ case kOptUndolevels:
return buf->b_p_ul != NO_LOCAL_UNDOLEVEL ? &(buf->b_p_ul) : p->var;
- case PV_LW:
+ case kOptLispwords:
return *buf->b_p_lw != NUL ? &(buf->b_p_lw) : p->var;
- case PV_MENC:
+ case kOptMakeencoding:
return *buf->b_p_menc != NUL ? &(buf->b_p_menc) : p->var;
- case PV_FCS:
+ case kOptFillchars:
return *win->w_p_fcs != NUL ? &(win->w_p_fcs) : p->var;
- case PV_LCS:
+ case kOptListchars:
return *win->w_p_lcs != NUL ? &(win->w_p_lcs) : p->var;
- case PV_VE:
+ case kOptVirtualedit:
return *win->w_p_ve != NUL ? &win->w_p_ve : p->var;
- case PV_ARAB:
+ case kOptArabic:
return &(win->w_p_arab);
- case PV_LIST:
+ case kOptList:
return &(win->w_p_list);
- case PV_SPELL:
+ case kOptSpell:
return &(win->w_p_spell);
- case PV_CUC:
+ case kOptCursorcolumn:
return &(win->w_p_cuc);
- case PV_CUL:
+ case kOptCursorline:
return &(win->w_p_cul);
- case PV_CULOPT:
+ case kOptCursorlineopt:
return &(win->w_p_culopt);
- case PV_CC:
+ case kOptColorcolumn:
return &(win->w_p_cc);
- case PV_DIFF:
+ case kOptDiff:
return &(win->w_p_diff);
- case PV_FDC:
+ case kOptFoldcolumn:
return &(win->w_p_fdc);
- case PV_FEN:
+ case kOptFoldenable:
return &(win->w_p_fen);
- case PV_FDI:
+ case kOptFoldignore:
return &(win->w_p_fdi);
- case PV_FDL:
+ case kOptFoldlevel:
return &(win->w_p_fdl);
- case PV_FDM:
+ case kOptFoldmethod:
return &(win->w_p_fdm);
- case PV_FML:
+ case kOptFoldminlines:
return &(win->w_p_fml);
- case PV_FDN:
+ case kOptFoldnestmax:
return &(win->w_p_fdn);
- case PV_FDE:
+ case kOptFoldexpr:
return &(win->w_p_fde);
- case PV_FDT:
+ case kOptFoldtext:
return &(win->w_p_fdt);
- case PV_FMR:
+ case kOptFoldmarker:
return &(win->w_p_fmr);
- case PV_NU:
+ case kOptNumber:
return &(win->w_p_nu);
- case PV_RNU:
+ case kOptRelativenumber:
return &(win->w_p_rnu);
- case PV_NUW:
+ case kOptNumberwidth:
return &(win->w_p_nuw);
- case PV_WFB:
+ case kOptWinfixbuf:
return &(win->w_p_wfb);
- case PV_WFH:
+ case kOptWinfixheight:
return &(win->w_p_wfh);
- case PV_WFW:
+ case kOptWinfixwidth:
return &(win->w_p_wfw);
- case PV_PVW:
+ case kOptPreviewwindow:
return &(win->w_p_pvw);
- case PV_RL:
+ case kOptRightleft:
return &(win->w_p_rl);
- case PV_RLC:
+ case kOptRightleftcmd:
return &(win->w_p_rlc);
- case PV_SCROLL:
+ case kOptScroll:
return &(win->w_p_scr);
- case PV_SMS:
+ case kOptSmoothscroll:
return &(win->w_p_sms);
- case PV_WRAP:
+ case kOptWrap:
return &(win->w_p_wrap);
- case PV_LBR:
+ case kOptLinebreak:
return &(win->w_p_lbr);
- case PV_BRI:
+ case kOptBreakindent:
return &(win->w_p_bri);
- case PV_BRIOPT:
+ case kOptBreakindentopt:
return &(win->w_p_briopt);
- case PV_SCBIND:
+ case kOptScrollbind:
return &(win->w_p_scb);
- case PV_CRBIND:
+ case kOptCursorbind:
return &(win->w_p_crb);
- case PV_COCU:
+ case kOptConcealcursor:
return &(win->w_p_cocu);
- case PV_COLE:
+ case kOptConceallevel:
return &(win->w_p_cole);
- case PV_AI:
+ case kOptAutoindent:
return &(buf->b_p_ai);
- case PV_BIN:
+ case kOptBinary:
return &(buf->b_p_bin);
- case PV_BOMB:
+ case kOptBomb:
return &(buf->b_p_bomb);
- case PV_BH:
+ case kOptBufhidden:
return &(buf->b_p_bh);
- case PV_BT:
+ case kOptBuftype:
return &(buf->b_p_bt);
- case PV_BL:
+ case kOptBuflisted:
return &(buf->b_p_bl);
- case PV_CHANNEL:
+ case kOptChannel:
return &(buf->b_p_channel);
- case PV_CI:
+ case kOptCopyindent:
return &(buf->b_p_ci);
- case PV_CIN:
+ case kOptCindent:
return &(buf->b_p_cin);
- case PV_CINK:
+ case kOptCinkeys:
return &(buf->b_p_cink);
- case PV_CINO:
+ case kOptCinoptions:
return &(buf->b_p_cino);
- case PV_CINSD:
+ case kOptCinscopedecls:
return &(buf->b_p_cinsd);
- case PV_CINW:
+ case kOptCinwords:
return &(buf->b_p_cinw);
- case PV_COM:
+ case kOptComments:
return &(buf->b_p_com);
- case PV_CMS:
+ case kOptCommentstring:
return &(buf->b_p_cms);
- case PV_CPT:
+ case kOptComplete:
return &(buf->b_p_cpt);
#ifdef BACKSLASH_IN_FILENAME
- case PV_CSL:
+ case kOptCompleteslash:
return &(buf->b_p_csl);
#endif
- case PV_CFU:
+ case kOptCompletefunc:
return &(buf->b_p_cfu);
- case PV_OFU:
+ case kOptOmnifunc:
return &(buf->b_p_ofu);
- case PV_URF:
+ case kOptUserregfunc:
return &(buf->b_p_urf);
- case PV_EOF:
+ case kOptEndoffile:
return &(buf->b_p_eof);
- case PV_EOL:
+ case kOptEndofline:
return &(buf->b_p_eol);
- case PV_FIXEOL:
+ case kOptFixendofline:
return &(buf->b_p_fixeol);
- case PV_ET:
+ case kOptExpandtab:
return &(buf->b_p_et);
- case PV_FENC:
+ case kOptFileencoding:
return &(buf->b_p_fenc);
- case PV_FF:
+ case kOptFileformat:
return &(buf->b_p_ff);
- case PV_FT:
+ case kOptFiletype:
return &(buf->b_p_ft);
- case PV_FO:
+ case kOptFormatoptions:
return &(buf->b_p_fo);
- case PV_FLP:
+ case kOptFormatlistpat:
return &(buf->b_p_flp);
- case PV_IMI:
+ case kOptIminsert:
return &(buf->b_p_iminsert);
- case PV_IMS:
+ case kOptImsearch:
return &(buf->b_p_imsearch);
- case PV_INF:
+ case kOptInfercase:
return &(buf->b_p_inf);
- case PV_ISK:
+ case kOptIskeyword:
return &(buf->b_p_isk);
- case PV_INEX:
+ case kOptIncludeexpr:
return &(buf->b_p_inex);
- case PV_INDE:
+ case kOptIndentexpr:
return &(buf->b_p_inde);
- case PV_INDK:
+ case kOptIndentkeys:
return &(buf->b_p_indk);
- case PV_FEX:
+ case kOptFormatexpr:
return &(buf->b_p_fex);
- case PV_LISP:
+ case kOptLisp:
return &(buf->b_p_lisp);
- case PV_LOP:
+ case kOptLispoptions:
return &(buf->b_p_lop);
- case PV_ML:
+ case kOptModeline:
return &(buf->b_p_ml);
- case PV_MPS:
+ case kOptMatchpairs:
return &(buf->b_p_mps);
- case PV_MA:
+ case kOptModifiable:
return &(buf->b_p_ma);
- case PV_MOD:
+ case kOptModified:
return &(buf->b_changed);
- case PV_NF:
+ case kOptNrformats:
return &(buf->b_p_nf);
- case PV_PI:
+ case kOptPreserveindent:
return &(buf->b_p_pi);
- case PV_QE:
+ case kOptQuoteescape:
return &(buf->b_p_qe);
- case PV_RO:
+ case kOptReadonly:
return &(buf->b_p_ro);
- case PV_SCBK:
+ case kOptScrollback:
return &(buf->b_p_scbk);
- case PV_SI:
+ case kOptSmartindent:
return &(buf->b_p_si);
- case PV_STS:
+ case kOptSofttabstop:
return &(buf->b_p_sts);
- case PV_SUA:
+ case kOptSuffixesadd:
return &(buf->b_p_sua);
- case PV_SWF:
+ case kOptSwapfile:
return &(buf->b_p_swf);
- case PV_SMC:
+ case kOptSynmaxcol:
return &(buf->b_p_smc);
- case PV_SYN:
+ case kOptSyntax:
return &(buf->b_p_syn);
- case PV_SPC:
+ case kOptSpellcapcheck:
return &(win->w_s->b_p_spc);
- case PV_SPF:
+ case kOptSpellfile:
return &(win->w_s->b_p_spf);
- case PV_SPL:
+ case kOptSpelllang:
return &(win->w_s->b_p_spl);
- case PV_SPO:
+ case kOptSpelloptions:
return &(win->w_s->b_p_spo);
- case PV_SW:
+ case kOptShiftwidth:
return &(buf->b_p_sw);
- case PV_TFU:
+ case kOptTagfunc:
return &(buf->b_p_tfu);
- case PV_TS:
+ case kOptTabstop:
return &(buf->b_p_ts);
- case PV_TW:
+ case kOptTextwidth:
return &(buf->b_p_tw);
- case PV_UDF:
+ case kOptUndofile:
return &(buf->b_p_udf);
- case PV_WM:
+ case kOptWrapmargin:
return &(buf->b_p_wm);
- case PV_VSTS:
+ case kOptVarsofttabstop:
return &(buf->b_p_vsts);
- case PV_VTS:
+ case kOptVartabstop:
return &(buf->b_p_vts);
- case PV_KMAP:
+ case kOptKeymap:
return &(buf->b_p_keymap);
- case PV_SCL:
+ case kOptSigncolumn:
return &(win->w_p_scl);
- case PV_WINHL:
+ case kOptWinhighlight:
return &(win->w_p_winhl);
- case PV_WINBL:
+ case kOptWinblend:
return &(win->w_p_winbl);
- case PV_STC:
+ case kOptStatuscolumn:
return &(win->w_p_stc);
default:
iemsg(_("E356: get_varp ERROR"));
@@ -4959,6 +4864,15 @@ char *get_equalprg(void)
return curbuf->b_p_ep;
}
+/// Get the value of 'findfunc', either the buffer-local one or the global one.
+char *get_findfunc(void)
+{
+ if (*curbuf->b_p_ffu == NUL) {
+ return p_ffu;
+ }
+ return curbuf->b_p_ffu;
+}
+
/// Copy options from one window to another.
/// Used when splitting a window.
void win_copy_options(win_T *wp_from, win_T *wp_to)
@@ -5110,38 +5024,20 @@ void didset_window_options(win_T *wp, bool valid_cursor)
} else {
wp->w_skipcol = 0;
}
- check_colorcolumn(wp);
- briopt_check(wp);
+ check_colorcolumn(NULL, wp);
+ briopt_check(NULL, wp);
fill_culopt_flags(NULL, wp);
set_chars_option(wp, wp->w_p_fcs, kFillchars, true, NULL, 0);
set_chars_option(wp, wp->w_p_lcs, kListchars, true, NULL, 0);
- parse_winhl_opt(wp); // sets w_hl_needs_update also for w_p_winbl
+ parse_winhl_opt(NULL, wp); // sets w_hl_needs_update also for w_p_winbl
check_blending(wp);
set_winbar_win(wp, false, valid_cursor);
- check_signcolumn(wp);
+ check_signcolumn(NULL, wp);
wp->w_grid_alloc.blending = wp->w_p_winbl > 0;
}
-/// Index into the options table for a buffer-local option enum.
-static OptIndex buf_opt_idx[BV_COUNT];
#define COPY_OPT_SCTX(buf, bv) buf->b_p_script_ctx[bv] = options[buf_opt_idx[bv]].last_set
-/// Initialize buf_opt_idx[] if not done already.
-static void init_buf_opt_idx(void)
-{
- static bool did_init_buf_opt_idx = false;
-
- if (did_init_buf_opt_idx) {
- return;
- }
- did_init_buf_opt_idx = true;
- for (OptIndex i = 0; i < kOptIndexCount; i++) {
- if (options[i].indir & PV_BUF) {
- buf_opt_idx[options[i].indir & PV_MASK] = i;
- }
- }
-}
-
/// Copy global option values to local options for one buffer.
/// Used when creating a new buffer and sometimes when entering a buffer.
/// flags:
@@ -5179,7 +5075,6 @@ void buf_copy_options(buf_T *buf, int flags)
if (should_copy || (flags & BCO_ALWAYS)) {
CLEAR_FIELD(buf->b_p_script_ctx);
- init_buf_opt_idx();
// Don't copy the options specific to a help buffer when
// BCO_NOHELP is given or the options were initialized already
// (jumping back to a help file with CTRL-T or CTRL-O)
@@ -5196,13 +5091,13 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_p_fenc = xstrdup(p_fenc);
switch (*p_ffs) {
case 'm':
- buf->b_p_ff = xstrdup(FF_MAC);
+ buf->b_p_ff = xstrdup("mac");
break;
case 'd':
- buf->b_p_ff = xstrdup(FF_DOS);
+ buf->b_p_ff = xstrdup("dos");
break;
case 'u':
- buf->b_p_ff = xstrdup(FF_UNIX);
+ buf->b_p_ff = xstrdup("unix");
break;
default:
buf->b_p_ff = xstrdup(p_ff);
@@ -5215,63 +5110,63 @@ void buf_copy_options(buf_T *buf, int flags)
}
buf->b_p_ai = p_ai;
- COPY_OPT_SCTX(buf, BV_AI);
+ COPY_OPT_SCTX(buf, kBufOptAutoindent);
buf->b_p_ai_nopaste = p_ai_nopaste;
buf->b_p_sw = p_sw;
- COPY_OPT_SCTX(buf, BV_SW);
+ COPY_OPT_SCTX(buf, kBufOptShiftwidth);
buf->b_p_scbk = p_scbk;
- COPY_OPT_SCTX(buf, BV_SCBK);
+ COPY_OPT_SCTX(buf, kBufOptScrollback);
buf->b_p_tw = p_tw;
- COPY_OPT_SCTX(buf, BV_TW);
+ COPY_OPT_SCTX(buf, kBufOptTextwidth);
buf->b_p_tw_nopaste = p_tw_nopaste;
buf->b_p_tw_nobin = p_tw_nobin;
buf->b_p_wm = p_wm;
- COPY_OPT_SCTX(buf, BV_WM);
+ COPY_OPT_SCTX(buf, kBufOptWrapmargin);
buf->b_p_wm_nopaste = p_wm_nopaste;
buf->b_p_wm_nobin = p_wm_nobin;
buf->b_p_bin = p_bin;
- COPY_OPT_SCTX(buf, BV_BIN);
+ COPY_OPT_SCTX(buf, kBufOptBinary);
buf->b_p_bomb = p_bomb;
- COPY_OPT_SCTX(buf, BV_BOMB);
+ COPY_OPT_SCTX(buf, kBufOptBomb);
buf->b_p_et = p_et;
- COPY_OPT_SCTX(buf, BV_ET);
+ COPY_OPT_SCTX(buf, kBufOptExpandtab);
buf->b_p_fixeol = p_fixeol;
- COPY_OPT_SCTX(buf, BV_FIXEOL);
+ COPY_OPT_SCTX(buf, kBufOptFixendofline);
buf->b_p_et_nobin = p_et_nobin;
buf->b_p_et_nopaste = p_et_nopaste;
buf->b_p_ml = p_ml;
- COPY_OPT_SCTX(buf, BV_ML);
+ COPY_OPT_SCTX(buf, kBufOptModeline);
buf->b_p_ml_nobin = p_ml_nobin;
buf->b_p_inf = p_inf;
- COPY_OPT_SCTX(buf, BV_INF);
+ COPY_OPT_SCTX(buf, kBufOptInfercase);
if (cmdmod.cmod_flags & CMOD_NOSWAPFILE) {
buf->b_p_swf = false;
} else {
buf->b_p_swf = p_swf;
- COPY_OPT_SCTX(buf, BV_SWF);
+ COPY_OPT_SCTX(buf, kBufOptSwapfile);
}
buf->b_p_cpt = xstrdup(p_cpt);
- COPY_OPT_SCTX(buf, BV_CPT);
+ COPY_OPT_SCTX(buf, kBufOptComplete);
#ifdef BACKSLASH_IN_FILENAME
buf->b_p_csl = xstrdup(p_csl);
- COPY_OPT_SCTX(buf, BV_CSL);
+ COPY_OPT_SCTX(buf, kBufOptCompleteslash);
#endif
buf->b_p_cfu = xstrdup(p_cfu);
- COPY_OPT_SCTX(buf, BV_CFU);
+ COPY_OPT_SCTX(buf, kBufOptCompletefunc);
set_buflocal_cfu_callback(buf);
buf->b_p_ofu = xstrdup(p_ofu);
- COPY_OPT_SCTX(buf, BV_OFU);
+ COPY_OPT_SCTX(buf, kBufOptOmnifunc);
buf->b_p_urf = xstrdup(p_urf);
- COPY_OPT_SCTX(buf, BV_URF);
set_buflocal_ofu_callback(buf);
+ COPY_OPT_SCTX(buf, kBufOptUserregfunc);
buf->b_p_tfu = xstrdup(p_tfu);
- COPY_OPT_SCTX(buf, BV_TFU);
+ COPY_OPT_SCTX(buf, kBufOptTagfunc);
set_buflocal_tfu_callback(buf);
buf->b_p_sts = p_sts;
- COPY_OPT_SCTX(buf, BV_STS);
+ COPY_OPT_SCTX(buf, kBufOptSofttabstop);
buf->b_p_sts_nopaste = p_sts_nopaste;
buf->b_p_vsts = xstrdup(p_vsts);
- COPY_OPT_SCTX(buf, BV_VSTS);
+ COPY_OPT_SCTX(buf, kBufOptVarsofttabstop);
if (p_vsts && p_vsts != empty_string_option) {
tabstop_set(p_vsts, &buf->b_p_vsts_array);
} else {
@@ -5279,74 +5174,75 @@ void buf_copy_options(buf_T *buf, int flags)
}
buf->b_p_vsts_nopaste = p_vsts_nopaste ? xstrdup(p_vsts_nopaste) : NULL;
buf->b_p_com = xstrdup(p_com);
- COPY_OPT_SCTX(buf, BV_COM);
+ COPY_OPT_SCTX(buf, kBufOptComments);
buf->b_p_cms = xstrdup(p_cms);
- COPY_OPT_SCTX(buf, BV_CMS);
+ COPY_OPT_SCTX(buf, kBufOptCommentstring);
buf->b_p_fo = xstrdup(p_fo);
- COPY_OPT_SCTX(buf, BV_FO);
+ COPY_OPT_SCTX(buf, kBufOptFormatoptions);
buf->b_p_flp = xstrdup(p_flp);
- COPY_OPT_SCTX(buf, BV_FLP);
+ COPY_OPT_SCTX(buf, kBufOptFormatlistpat);
buf->b_p_nf = xstrdup(p_nf);
- COPY_OPT_SCTX(buf, BV_NF);
+ COPY_OPT_SCTX(buf, kBufOptNrformats);
buf->b_p_mps = xstrdup(p_mps);
- COPY_OPT_SCTX(buf, BV_MPS);
+ COPY_OPT_SCTX(buf, kBufOptMatchpairs);
buf->b_p_si = p_si;
- COPY_OPT_SCTX(buf, BV_SI);
+ COPY_OPT_SCTX(buf, kBufOptSmartindent);
buf->b_p_channel = 0;
buf->b_p_ci = p_ci;
- COPY_OPT_SCTX(buf, BV_CI);
+ COPY_OPT_SCTX(buf, kBufOptCopyindent);
buf->b_p_cin = p_cin;
- COPY_OPT_SCTX(buf, BV_CIN);
+ COPY_OPT_SCTX(buf, kBufOptCindent);
buf->b_p_cink = xstrdup(p_cink);
- COPY_OPT_SCTX(buf, BV_CINK);
+ COPY_OPT_SCTX(buf, kBufOptCinkeys);
buf->b_p_cino = xstrdup(p_cino);
- COPY_OPT_SCTX(buf, BV_CINO);
+ COPY_OPT_SCTX(buf, kBufOptCinoptions);
buf->b_p_cinsd = xstrdup(p_cinsd);
- COPY_OPT_SCTX(buf, BV_CINSD);
+ COPY_OPT_SCTX(buf, kBufOptCinscopedecls);
buf->b_p_lop = xstrdup(p_lop);
- COPY_OPT_SCTX(buf, BV_LOP);
+ COPY_OPT_SCTX(buf, kBufOptLispoptions);
// Don't copy 'filetype', it must be detected
buf->b_p_ft = empty_string_option;
buf->b_p_pi = p_pi;
- COPY_OPT_SCTX(buf, BV_PI);
+ COPY_OPT_SCTX(buf, kBufOptPreserveindent);
buf->b_p_cinw = xstrdup(p_cinw);
- COPY_OPT_SCTX(buf, BV_CINW);
+ COPY_OPT_SCTX(buf, kBufOptCinwords);
buf->b_p_lisp = p_lisp;
- COPY_OPT_SCTX(buf, BV_LISP);
+ COPY_OPT_SCTX(buf, kBufOptLisp);
// Don't copy 'syntax', it must be set
buf->b_p_syn = empty_string_option;
buf->b_p_smc = p_smc;
- COPY_OPT_SCTX(buf, BV_SMC);
+ COPY_OPT_SCTX(buf, kBufOptSynmaxcol);
buf->b_s.b_syn_isk = empty_string_option;
buf->b_s.b_p_spc = xstrdup(p_spc);
- COPY_OPT_SCTX(buf, BV_SPC);
+ COPY_OPT_SCTX(buf, kBufOptSpellcapcheck);
compile_cap_prog(&buf->b_s);
buf->b_s.b_p_spf = xstrdup(p_spf);
- COPY_OPT_SCTX(buf, BV_SPF);
+ COPY_OPT_SCTX(buf, kBufOptSpellfile);
buf->b_s.b_p_spl = xstrdup(p_spl);
- COPY_OPT_SCTX(buf, BV_SPL);
+ COPY_OPT_SCTX(buf, kBufOptSpelllang);
buf->b_s.b_p_spo = xstrdup(p_spo);
- COPY_OPT_SCTX(buf, BV_SPO);
+ COPY_OPT_SCTX(buf, kBufOptSpelloptions);
+ buf->b_s.b_p_spo_flags = spo_flags;
buf->b_p_inde = xstrdup(p_inde);
- COPY_OPT_SCTX(buf, BV_INDE);
+ COPY_OPT_SCTX(buf, kBufOptIndentexpr);
buf->b_p_indk = xstrdup(p_indk);
- COPY_OPT_SCTX(buf, BV_INDK);
+ COPY_OPT_SCTX(buf, kBufOptIndentkeys);
buf->b_p_fp = empty_string_option;
buf->b_p_fex = xstrdup(p_fex);
- COPY_OPT_SCTX(buf, BV_FEX);
+ COPY_OPT_SCTX(buf, kBufOptFormatexpr);
buf->b_p_sua = xstrdup(p_sua);
- COPY_OPT_SCTX(buf, BV_SUA);
+ COPY_OPT_SCTX(buf, kBufOptSuffixesadd);
buf->b_p_keymap = xstrdup(p_keymap);
- COPY_OPT_SCTX(buf, BV_KMAP);
+ COPY_OPT_SCTX(buf, kBufOptKeymap);
buf->b_kmap_state |= KEYMAP_INIT;
// This isn't really an option, but copying the langmap and IME
// state from the current buffer is better than resetting it.
buf->b_p_iminsert = p_iminsert;
- COPY_OPT_SCTX(buf, BV_IMI);
+ COPY_OPT_SCTX(buf, kBufOptIminsert);
buf->b_p_imsearch = p_imsearch;
- COPY_OPT_SCTX(buf, BV_IMS);
+ COPY_OPT_SCTX(buf, kBufOptImsearch);
// options that are normally global but also have a local value
// are not copied, start using the global value
@@ -5358,6 +5254,7 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_p_mp = empty_string_option;
buf->b_p_efm = empty_string_option;
buf->b_p_ep = empty_string_option;
+ buf->b_p_ffu = empty_string_option;
buf->b_p_kp = empty_string_option;
buf->b_p_path = empty_string_option;
buf->b_p_tags = empty_string_option;
@@ -5366,16 +5263,16 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_p_def = empty_string_option;
buf->b_p_inc = empty_string_option;
buf->b_p_inex = xstrdup(p_inex);
- COPY_OPT_SCTX(buf, BV_INEX);
+ COPY_OPT_SCTX(buf, kBufOptIncludeexpr);
buf->b_p_cot = empty_string_option;
buf->b_cot_flags = 0;
buf->b_p_dict = empty_string_option;
buf->b_p_tsr = empty_string_option;
buf->b_p_tsrfu = empty_string_option;
buf->b_p_qe = xstrdup(p_qe);
- COPY_OPT_SCTX(buf, BV_QE);
+ COPY_OPT_SCTX(buf, kBufOptQuoteescape);
buf->b_p_udf = p_udf;
- COPY_OPT_SCTX(buf, BV_UDF);
+ COPY_OPT_SCTX(buf, kBufOptUndofile);
buf->b_p_lw = empty_string_option;
buf->b_p_menc = empty_string_option;
@@ -5392,12 +5289,12 @@ void buf_copy_options(buf_T *buf, int flags)
}
} else {
buf->b_p_isk = xstrdup(p_isk);
- COPY_OPT_SCTX(buf, BV_ISK);
+ COPY_OPT_SCTX(buf, kBufOptIskeyword);
did_isk = true;
buf->b_p_ts = p_ts;
- COPY_OPT_SCTX(buf, BV_TS);
+ COPY_OPT_SCTX(buf, kBufOptTabstop);
buf->b_p_vts = xstrdup(p_vts);
- COPY_OPT_SCTX(buf, BV_VTS);
+ COPY_OPT_SCTX(buf, kBufOptVartabstop);
if (p_vts && p_vts != empty_string_option && !buf->b_p_vts_array) {
tabstop_set(p_vts, &buf->b_p_vts_array);
} else {
@@ -5408,7 +5305,7 @@ void buf_copy_options(buf_T *buf, int flags)
clear_string_option(&buf->b_p_bt);
}
buf->b_p_ma = p_ma;
- COPY_OPT_SCTX(buf, BV_MA);
+ COPY_OPT_SCTX(buf, kBufOptModifiable);
}
}
@@ -5430,7 +5327,7 @@ void reset_modifiable(void)
{
curbuf->b_p_ma = false;
p_ma = false;
- options[kOptModifiable].def_val.boolean = false;
+ change_option_default(kOptModifiable, BOOLEAN_OPTVAL(false));
}
/// Set the global value for 'iminsert' to the local value.
@@ -5537,7 +5434,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
}
nextchar = *p;
opt_idx = find_option_len(arg, (size_t)(p - arg));
- if (opt_idx == kOptInvalid || options[opt_idx].var == NULL) {
+ if (opt_idx == kOptInvalid || is_option_hidden(opt_idx)) {
xp->xp_context = EXPAND_NOTHING;
return;
}
@@ -5613,8 +5510,8 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
// Only string options below
- // Options that have P_EXPAND are considered to all use file/dir expansion.
- if (flags & P_EXPAND) {
+ // Options that have kOptFlagExpand are considered to all use file/dir expansion.
+ if (flags & kOptFlagExpand) {
p = options[opt_idx].var;
if (p == (char *)&p_bdir
|| p == (char *)&p_dir
@@ -5638,7 +5535,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
xp->xp_backslash = XP_BS_ONE;
}
}
- if (flags & P_COMMA) {
+ if (flags & kOptFlagComma) {
xp->xp_backslash |= XP_BS_COMMA;
}
}
@@ -5648,21 +5545,21 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
// pattern, while accounting for backslash-escaped space/commas/colons.
// Triple-backslashed escaped file names (e.g. 'path') can also be
// delimited by space.
- if ((flags & P_EXPAND) || (flags & P_COMMA) || (flags & P_COLON)) {
+ if ((flags & kOptFlagExpand) || (flags & kOptFlagComma) || (flags & kOptFlagColon)) {
for (p = argend - 1; p > xp->xp_pattern; p--) {
// count number of backslashes before ' ' or ','
- if (*p == ' ' || *p == ',' || (*p == ':' && (flags & P_COLON))) {
+ if (*p == ' ' || *p == ',' || (*p == ':' && (flags & kOptFlagColon))) {
char *s = p;
while (s > xp->xp_pattern && *(s - 1) == '\\') {
s--;
}
if ((*p == ' ' && ((xp->xp_backslash & XP_BS_THREE) && (p - s) < 3))
#if defined(BACKSLASH_IN_FILENAME)
- || (*p == ',' && (flags & P_COMMA) && (p - s) < 1)
+ || (*p == ',' && (flags & kOptFlagComma) && (p - s) < 1)
#else
- || (*p == ',' && (flags & P_COMMA) && (p - s) < 2)
+ || (*p == ',' && (flags & kOptFlagComma) && (p - s) < 2)
#endif
- || (*p == ':' && (flags & P_COLON))) {
+ || (*p == ':' && (flags & kOptFlagColon))) {
xp->xp_pattern = p + 1;
break;
}
@@ -5672,7 +5569,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
// An option that is a list of single-character flags should always start
// at the end as we don't complete words.
- if (flags & P_FLAGLIST) {
+ if (flags & kOptFlagFlagList) {
xp->xp_pattern = argend;
}
@@ -5759,9 +5656,9 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, char *fuzzystr, int *numM
}
}
char *str;
- for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) {
str = options[opt_idx].fullname;
- if (options[opt_idx].var == NULL) {
+ if (is_option_hidden(opt_idx)) {
continue;
}
if (xp->xp_context == EXPAND_BOOL_SETTINGS
@@ -5825,7 +5722,7 @@ static char *escape_option_str_cmdline(char *var)
for (var = buf; *var != NUL; MB_PTR_ADV(var)) {
if (var[0] == '\\' && var[1] == '\\'
&& expand_option_idx != kOptInvalid
- && (options[expand_option_idx].flags & P_EXPAND)
+ && (options[expand_option_idx].flags & kOptFlagExpand)
&& vim_isfilec((uint8_t)var[2])
&& (var[2] != '\\' || (var == buf && var[4] != '\\'))) {
STRMOVE(var, var + 1);
@@ -5911,11 +5808,11 @@ int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, c
if (option_has_type(expand_option_idx, kOptValTypeNumber)) {
return ExpandOldSetting(numMatches, matches);
- } else if (option_flags & P_COMMA) {
+ } else if (option_flags & kOptFlagComma) {
// Split the option by comma, then present each option to the user if
// it matches the pattern.
// This condition needs to go first, because 'whichwrap' has both
- // P_COMMA and P_FLAGLIST.
+ // kOptFlagComma and kOptFlagFlagList.
if (*option_val == NUL) {
return FAIL;
@@ -5962,7 +5859,7 @@ int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, c
*matches = ga.ga_data;
*numMatches = ga.ga_len;
return OK;
- } else if (option_flags & P_FLAGLIST) {
+ } else if (option_flags & kOptFlagFlagList) {
// Only present the flags that are set on the option as the other flags
// are not meaningful to do set-= on.
@@ -6009,6 +5906,7 @@ int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, c
static void option_value2string(vimoption_T *opt, int scope)
{
void *varp = get_varp_scope(opt, scope);
+ assert(varp != NULL);
if (option_has_type(get_opt_idx(opt), kOptValTypeNumber)) {
OptInt wc = 0;
@@ -6025,9 +5923,8 @@ static void option_value2string(vimoption_T *opt, int scope)
}
} else { // string
varp = *(char **)(varp);
- if (varp == NULL) { // Just in case.
- NameBuff[0] = NUL;
- } else if (opt->flags & P_EXPAND) {
+
+ if (opt->flags & kOptFlagExpand) {
home_replace(NULL, varp, NameBuff, MAXPATHL, false);
} else {
xstrlcpy(NameBuff, varp, MAXPATHL);
@@ -6088,7 +5985,7 @@ void vimrc_found(char *fname, char *envname)
bool option_was_set(OptIndex opt_idx)
{
assert(opt_idx != kOptInvalid);
- return options[opt_idx].flags & P_WAS_SET;
+ return options[opt_idx].flags & kOptFlagWasSet;
}
/// Reset the flag indicating option "name" was set.
@@ -6097,7 +5994,7 @@ bool option_was_set(OptIndex opt_idx)
void reset_option_was_set(OptIndex opt_idx)
{
assert(opt_idx != kOptInvalid);
- options[opt_idx].flags &= ~P_WAS_SET;
+ options[opt_idx].flags &= ~(unsigned)kOptFlagWasSet;
}
/// fill_culopt_flags() -- called when 'culopt' changes value
@@ -6331,13 +6228,13 @@ void set_fileformat(int eol_style, int opt_flags)
switch (eol_style) {
case EOL_UNIX:
- p = FF_UNIX;
+ p = "unix";
break;
case EOL_MAC:
- p = FF_MAC;
+ p = "mac";
break;
case EOL_DOS:
- p = FF_DOS;
+ p = "dos";
break;
}
@@ -6420,11 +6317,11 @@ dict_T *get_winbuf_options(const int bufopt)
{
dict_T *const d = tv_dict_alloc();
- for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) {
vimoption_T *opt = &options[opt_idx];
- if ((bufopt && (opt->indir & PV_BUF))
- || (!bufopt && (opt->indir & PV_WIN))) {
+ if ((bufopt && (option_has_scope(opt_idx, kOptScopeBuf)))
+ || (!bufopt && (option_has_scope(opt_idx, kOptScopeWin)))) {
void *varp = get_varp(opt);
if (varp != NULL) {
@@ -6467,8 +6364,8 @@ Dict get_vimoption(String name, int scope, buf_T *buf, win_T *win, Arena *arena,
Dict get_all_vimoptions(Arena *arena)
{
- Dict retval = arena_dict(arena, kOptIndexCount);
- for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ Dict retval = arena_dict(arena, kOptCount);
+ for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) {
Dict opt_dict = vimoption2dict(&options[opt_idx], OPT_GLOBAL, curbuf, curwin, arena);
PUT_C(retval, options[opt_idx].fullname, DICT_OBJ(opt_dict));
}
@@ -6477,15 +6374,16 @@ Dict get_all_vimoptions(Arena *arena)
static Dict vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, win_T *win, Arena *arena)
{
+ OptIndex opt_idx = get_opt_idx(opt);
Dict dict = arena_dict(arena, 13);
PUT_C(dict, "name", CSTR_AS_OBJ(opt->fullname));
PUT_C(dict, "shortname", CSTR_AS_OBJ(opt->shortname));
const char *scope;
- if (opt->indir & PV_BUF) {
+ if (option_has_scope(opt_idx, kOptScopeBuf)) {
scope = "buf";
- } else if (opt->indir & PV_WIN) {
+ } else if (option_has_scope(opt_idx, kOptScopeWin)) {
scope = "win";
} else {
scope = "global";
@@ -6494,22 +6392,22 @@ static Dict vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, win_T *w
PUT_C(dict, "scope", CSTR_AS_OBJ(scope));
// welcome to the jungle
- PUT_C(dict, "global_local", BOOLEAN_OBJ(opt->indir & PV_BOTH));
- PUT_C(dict, "commalist", BOOLEAN_OBJ(opt->flags & P_COMMA));
- PUT_C(dict, "flaglist", BOOLEAN_OBJ(opt->flags & P_FLAGLIST));
+ PUT_C(dict, "global_local", BOOLEAN_OBJ(option_is_global_local(opt_idx)));
+ PUT_C(dict, "commalist", BOOLEAN_OBJ(opt->flags & kOptFlagComma));
+ PUT_C(dict, "flaglist", BOOLEAN_OBJ(opt->flags & kOptFlagFlagList));
- PUT_C(dict, "was_set", BOOLEAN_OBJ(opt->flags & P_WAS_SET));
+ PUT_C(dict, "was_set", BOOLEAN_OBJ(opt->flags & kOptFlagWasSet));
LastSet last_set = { .channel_id = 0 };
if (req_scope == OPT_GLOBAL) {
last_set = opt->last_set;
} else {
// Scope is either OPT_LOCAL or a fallback mode was requested.
- if (opt->indir & PV_BUF) {
- last_set = buf->b_p_script_ctx[opt->indir & PV_MASK];
+ if (option_has_scope(opt_idx, kOptScopeBuf)) {
+ last_set = buf->b_p_script_ctx[opt->scope_idx[kOptScopeBuf]];
}
- if (opt->indir & PV_WIN) {
- last_set = win->w_p_script_ctx[opt->indir & PV_MASK];
+ if (option_has_scope(opt_idx, kOptScopeWin)) {
+ last_set = win->w_p_script_ctx[opt->scope_idx[kOptScopeWin]];
}
if (req_scope != OPT_LOCAL && last_set.script_ctx.sc_sid == 0) {
last_set = opt->last_set;
@@ -6520,33 +6418,9 @@ static Dict vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, win_T *w
PUT_C(dict, "last_set_linenr", INTEGER_OBJ(last_set.script_ctx.sc_lnum));
PUT_C(dict, "last_set_chan", INTEGER_OBJ((int64_t)last_set.channel_id));
- // TODO(bfredl): do you even nocp?
- OptVal def = optval_from_varp(get_opt_idx(opt), &opt->def_val);
-
- PUT_C(dict, "type", CSTR_AS_OBJ(optval_type_get_name(def.type)));
- PUT_C(dict, "default", optval_as_object(def));
- PUT_C(dict, "allows_duplicates", BOOLEAN_OBJ(!(opt->flags & P_NODUP)));
+ PUT_C(dict, "type", CSTR_AS_OBJ(optval_type_get_name(option_get_type(get_opt_idx(opt)))));
+ PUT_C(dict, "default", optval_as_object(opt->def_val));
+ PUT_C(dict, "allows_duplicates", BOOLEAN_OBJ(!(opt->flags & kOptFlagNoDup)));
return dict;
}
-
-/// Check if option is multitype (supports multiple types).
-static bool option_is_multitype(OptIndex opt_idx)
-{
- const OptTypeFlags type_flags = get_option(opt_idx)->type_flags;
- assert(type_flags != 0);
- return !is_power_of_two(type_flags);
-}
-
-/// Check if option supports a specific type.
-bool option_has_type(OptIndex opt_idx, OptValType type)
-{
- // Ensure that type flags variable can hold all types.
- STATIC_ASSERT(kOptValTypeSize <= sizeof(OptTypeFlags) * 8,
- "Option type_flags cannot fit all option types");
- // Ensure that the type is valid before accessing type_flags.
- assert(type > kOptValTypeNil && type < kOptValTypeSize);
- // Bitshift 1 by the value of type to get the type's corresponding flag, and check if it's set in
- // the type_flags bit field.
- return get_option(opt_idx)->type_flags & (1 << type);
-}