From f25ebc229042d605cde1ba365883657fd0c0e693 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 15 Oct 2024 09:40:54 +0800 Subject: vim-patch:9.1.0783: 'spell' option setting has problems (#30818) Problem: 'spell' option setting has problems Solution: correctly check for comma for 'spellfile' option, remove unnecessary checks, refactor slightly (Milly) closes: vim/vim#15873 https://github.com/vim/vim/commit/322ad0c953b7a3023cd2a65db61d05e180a5d682 Co-authored-by: Milly --- src/nvim/option.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index f54da54a4b..0aa9cf4d93 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1705,7 +1705,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'. -- cgit From 1b9dafa67ba98e360444832e1fddce1e96acc1d6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 22 Oct 2024 11:34:09 +0800 Subject: fix(options): fix :setglobal not working for 'spelloptions' (#30894) --- src/nvim/option.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 0aa9cf4d93..2e6d317778 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -5325,6 +5325,7 @@ void buf_copy_options(buf_T *buf, int flags) COPY_OPT_SCTX(buf, BV_SPL); buf->b_s.b_p_spo = xstrdup(p_spo); COPY_OPT_SCTX(buf, BV_SPO); + buf->b_s.b_p_spo_flags = spo_flags; buf->b_p_inde = xstrdup(p_inde); COPY_OPT_SCTX(buf, BV_INDE); buf->b_p_indk = xstrdup(p_indk); -- cgit From 8c532a9ea8a0bb2ee93d772c9589d1a84afeb541 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 22 Oct 2024 16:10:15 +0800 Subject: fix(options): fix 'winhl' still accepting invalid value (#30896) --- src/nvim/option.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 2e6d317778..89753f7cf8 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1853,6 +1853,9 @@ bool parse_winhl_opt(win_T *wp) 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; -- cgit From 5436d9b3c6c537b243ea6af4f1acc143bf94de1c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 24 Oct 2024 06:23:00 +0800 Subject: vim-patch:9.1.0804: tests: no error check when setting global 'cc' Problem: tests: no error check when setting global 'cc' Solution: also parse and check global 'cc' value (Milly) closes: vim/vim#15914 https://github.com/vim/vim/commit/a441a3eaabbfc14b4772e07ecbecaaff3bd06a58 Co-authored-by: Milly --- src/nvim/option.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 89753f7cf8..8e6e068e96 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2592,7 +2592,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; @@ -5111,7 +5111,7 @@ void didset_window_options(win_T *wp, bool valid_cursor) } else { wp->w_skipcol = 0; } - check_colorcolumn(wp); + check_colorcolumn(NULL, wp); briopt_check(wp); fill_culopt_flags(NULL, wp); set_chars_option(wp, wp->w_p_fcs, kFillchars, true, NULL, 0); -- cgit From 6b63fe798b7481edd8e3b0ed75a33bf297ca2856 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 24 Oct 2024 06:31:09 +0800 Subject: vim-patch:9.1.0806: tests: no error check when setting global 'briopt' Problem: tests: no error check when setting global 'briopt' Solution: also parse and check global 'briopt' value (Milly) closes: vim/vim#15911 https://github.com/vim/vim/commit/b38700ac81d90a652e5c8495056dd78df5babdde Co-authored-by: Milly --- src/nvim/option.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 8e6e068e96..933ee4ba75 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -5112,7 +5112,7 @@ void didset_window_options(win_T *wp, bool valid_cursor) wp->w_skipcol = 0; } check_colorcolumn(NULL, wp); - briopt_check(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); -- cgit From 50e63c8171d47157cfad5c1b8f1958a4a7e9d9c7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 24 Oct 2024 10:03:38 +0800 Subject: fix(options): missing error check for global 'scl' and 'winhl' (#30919) --- src/nvim/option.c | 59 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 21 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 933ee4ba75..5f0115b46c 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1816,12 +1816,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,24 +1839,27 @@ 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) { @@ -1857,14 +1870,18 @@ bool parse_winhl_opt(win_T *wp) 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; } @@ -2281,7 +2298,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; } @@ -5116,10 +5133,10 @@ void didset_window_options(win_T *wp, bool valid_cursor) 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; } -- cgit From b922b7d6d7889cce863540df7b0da7d512f8a2a1 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Fri, 25 Oct 2024 20:10:40 +0600 Subject: refactor(options)!: use OptVal for option defaults #26691 Problem: We use `void *` for option default values, which is confusing and can cause problems with type-correctness. It also doesn't accomodate for multitype options. On top of that, it also leads to default boolean option values not behaving correctly on big endian systems. Solution: Use `OptVal` for option default values. BREAKING CHANGE: - `:set {option}<` removes the local value for all global-local options instead of just string global-local options. - `:setlocal {option}<` copies the global value to the local value for number and boolean global-local options instead of removing the local value. --- src/nvim/option.c | 424 ++++++++++++++++++++++++------------------------------ 1 file changed, 186 insertions(+), 238 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 5f0115b46c..a237689eb0 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,9 @@ static void set_init_default_cdpath(void) } } buf[j] = NUL; - options[kOptCdpath].def_val.string = buf; + options[kOptCdpath].def_val = CSTR_AS_OPTVAL(buf); options[kOptCdpath].flags |= P_DEF_ALLOCED; + xfree(cdpath); } @@ -317,12 +318,13 @@ static void set_init_expand_env(void) p = option_expand(opt_idx, NULL); } if (p != NULL) { - p = xstrdup(p); - *(char **)opt->var = p; + set_option_varp(opt_idx, opt->var, CSTR_TO_OPTVAL(p), opt->flags & P_ALLOCED); + opt->flags |= P_ALLOCED; + if (opt->flags & P_DEF_ALLOCED) { - xfree(opt->def_val.string); + optval_free(opt->def_val); } - opt->def_val.string = p; + opt->def_val = CSTR_TO_OPTVAL(p); opt->flags |= P_DEF_ALLOCED; } } @@ -430,71 +432,54 @@ 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 = opt->indir & PV_BOTH; + #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 & P_NO_DEF_EXP)) { + // 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 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); } - set_option_sctx(opt_idx, opt_flags, current_sctx); + // The default value is not insecure. + uint32_t *flagsp = insecure_flag(curwin, opt_idx, opt_flags); + *flagsp = *flagsp & ~P_INSECURE; } /// Set all options (except terminal options) to their default value. @@ -522,6 +507,8 @@ 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 { @@ -531,10 +518,10 @@ static void set_string_default(OptIndex opt_idx, char *val, bool allocated) vimoption_T *opt = &options[opt_idx]; if (opt->flags & P_DEF_ALLOCED) { - xfree(opt->def_val.string); + optval_free(opt->def_val); } - opt->def_val.string = allocated ? val : xstrdup(val); + opt->def_val = CSTR_AS_OPTVAL(allocated ? val : xstrdup(val)); opt->flags |= P_DEF_ALLOCED; } @@ -569,15 +556,6 @@ 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) @@ -589,7 +567,7 @@ void free_all_options(void) 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)); + optval_free(options[opt_idx].def_val); } } else if (options[opt_idx].var != VAR_WIN) { // buffer-local option: free global value @@ -622,7 +600,7 @@ void set_init_2(bool headless) if (!option_was_set(kOptWindow)) { p_window = Rows - 1; } - set_number_default(kOptWindow, Rows - 1); + options[kOptWindow].def_val = NUMBER_OPTVAL(Rows - 1); } /// Initialize the options, part three: After reading the .vimrc @@ -640,43 +618,29 @@ void set_init_3(void) 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); + options[kOptShellpipe].def_val = 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); + options[kOptShellredir].def_val = srr; } - xfree(p); } + xfree(p); if (buf_is_empty(curbuf)) { int idx_ffs = find_option("ffs"); @@ -734,12 +698,12 @@ void set_title_defaults(void) // 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; + options[kOptTitle].def_val = BOOLEAN_OPTVAL(false); + p_title = 0; } if (!(options[kOptIcon].flags & P_WAS_SET)) { - options[kOptIcon].def_val.boolean = false; - p_icon = false; + options[kOptIcon].def_val = BOOLEAN_OPTVAL(false); + p_icon = 0; } } @@ -758,27 +722,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, @@ -922,10 +865,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 +876,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 & P_COMMA)) { + 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 & P_NODUP)) { + 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 & P_FLAGLIST) { + // Remove flags that appear twice. + stropt_remove_dupflags(newval, flags); } if (save_arg != NULL) { @@ -1152,6 +1087,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) @@ -1166,6 +1102,20 @@ static OptVal get_option_newval(OptIndex opt_idx, int opt_flags, set_prefix_T pr 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 +1123,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 +1135,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 +1153,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 // 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; @@ -3218,6 +3141,19 @@ bool optval_equal(OptVal o1, OptVal o2) 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. @@ -3237,11 +3173,7 @@ OptVal optval_from_varp(OptIndex opt_idx, void *varp) return varp == NULL ? NIL_OPTVAL : *(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: @@ -3390,6 +3322,11 @@ bool is_option_hidden(OptIndex opt_idx) return opt_idx == kOptInvalid ? false : get_varp(&options[opt_idx]) == NULL; } +static inline bool option_is_global_local(OptIndex opt_idx) +{ + return opt_idx == kOptInvalid ? false : (options[opt_idx].indir & PV_BOTH); +} + /// Get option flags. /// /// @param opt_idx Option index in options[] table. @@ -3588,10 +3525,9 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value opt->flags |= P_ALLOCED; 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); @@ -3678,7 +3614,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)) { @@ -3719,25 +3654,28 @@ static const char *set_option(const OptIndex opt_idx, void *varp, OptVal value, { 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, varp, &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) { + if (scope_both && option_is_global_local(opt_idx)) { varp = opt->var; } @@ -3823,8 +3761,10 @@ void set_option_direct(OptIndex opt_idx, OptVal value, int opt_flags, scid_T set 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, varp, 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. @@ -3893,6 +3833,17 @@ const char *set_option_value(const OptIndex opt_idx, const OptVal value, int opt 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(). /// /// @param name Option name. Used for error messages and for setting TTY options. @@ -4273,7 +4224,7 @@ static int optval_default(OptIndex opt_idx, void *varp) } 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); } @@ -5447,7 +5398,7 @@ void reset_modifiable(void) { curbuf->b_p_ma = false; p_ma = false; - options[kOptModifiable].def_val.boolean = false; + options[kOptModifiable].def_val = BOOLEAN_OPTVAL(false); } /// Set the global value for 'iminsert' to the local value. @@ -6537,11 +6488,8 @@ 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, "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 & P_NODUP))); return dict; -- cgit From b136a9ee4c5689c655713ab006be84ae9e7a313a Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sun, 27 Oct 2024 19:09:24 +0600 Subject: refactor(options): always allocate option values (#30917) Instead of keeping `P_ALLOCED` and `P_DEF_ALLOCED` flags to check if an option value is allocated, always allocate option values to simplify the logic. Ref: #25672 --- src/nvim/option.c | 81 +++++++++++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 44 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index a237689eb0..72f8a5d2f3 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -291,8 +291,7 @@ static void set_init_default_cdpath(void) } } buf[j] = NUL; - options[kOptCdpath].def_val = CSTR_AS_OPTVAL(buf); - options[kOptCdpath].flags |= P_DEF_ALLOCED; + change_option_default(kOptCdpath, CSTR_AS_OPTVAL(buf)); xfree(cdpath); } @@ -302,8 +301,6 @@ 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++) { @@ -318,14 +315,8 @@ static void set_init_expand_env(void) p = option_expand(opt_idx, NULL); } if (p != NULL) { - set_option_varp(opt_idx, opt->var, CSTR_TO_OPTVAL(p), opt->flags & P_ALLOCED); - opt->flags |= P_ALLOCED; - - if (opt->flags & P_DEF_ALLOCED) { - optval_free(opt->def_val); - } - opt->def_val = CSTR_TO_OPTVAL(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)); } } } @@ -356,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(); @@ -463,6 +457,25 @@ static OptVal get_option_default(const OptIndex opt_idx, int opt_flags) } } +/// 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 < kOptIndexCount; 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! /// @@ -512,17 +525,8 @@ static void set_options_default(int opt_flags) 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) { - optval_free(opt->def_val); - } - - opt->def_val = CSTR_AS_OPTVAL(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 @@ -563,16 +567,14 @@ void free_all_options(void) for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) { if (options[opt_idx].indir == PV_NONE) { // global option: free value and default value. - if ((options[opt_idx].flags & P_ALLOCED) && options[opt_idx].var != NULL) { + if (options[opt_idx].var != NULL) { optval_free(optval_from_varp(opt_idx, options[opt_idx].var)); } - if (options[opt_idx].flags & P_DEF_ALLOCED) { - optval_free(options[opt_idx].def_val); - } } else if (options[opt_idx].var != VAR_WIN) { // 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(); @@ -600,7 +602,7 @@ void set_init_2(bool headless) if (!option_was_set(kOptWindow)) { p_window = Rows - 1; } - options[kOptWindow].def_val = NUMBER_OPTVAL(Rows - 1); + change_option_default(kOptWindow, NUMBER_OPTVAL(Rows - 1)); } /// Initialize the options, part three: After reading the .vimrc @@ -632,12 +634,12 @@ void set_init_3(void) 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); - options[kOptShellpipe].def_val = sp; + 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); - options[kOptShellredir].def_val = srr; + change_option_default(kOptShellredir, optval_copy(srr)); } } xfree(p); @@ -670,9 +672,7 @@ void set_helplang_default(const char *lang) 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) { @@ -684,7 +684,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 @@ -698,11 +697,11 @@ void set_title_defaults(void) // 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_OPTVAL(false); + change_option_default(kOptTitle, BOOLEAN_OPTVAL(false)); p_title = 0; } if (!(options[kOptIcon].flags & P_WAS_SET)) { - options[kOptIcon].def_val = BOOLEAN_OPTVAL(false); + change_option_default(kOptIcon, BOOLEAN_OPTVAL(false)); p_icon = 0; } } @@ -3441,7 +3440,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; @@ -3517,12 +3515,7 @@ 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; @@ -5398,7 +5391,7 @@ void reset_modifiable(void) { curbuf->b_p_ma = false; p_ma = false; - options[kOptModifiable].def_val = BOOLEAN_OPTVAL(false); + change_option_default(kOptModifiable, BOOLEAN_OPTVAL(false)); } /// Set the global value for 'iminsert' to the local value. -- cgit From 34c44c355646311aa67fe53e1e5ce040789430c6 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Mon, 28 Oct 2024 19:49:16 +0600 Subject: refactor(options): option flags enum #30961 Problem: Currently we use macros with hardcoded flag values for option flags, which is messy and requires a lot of mental math for adding / removing option flags. Using macros for option flags also means that they cannot be used inside debuggers. Solution: Create a new `OptFlags` enum that stores all the option flags in an organized way that is easier to understand. --- src/nvim/option.c | 151 +++++++++++++++++++++++++++--------------------------- 1 file changed, 76 insertions(+), 75 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 72f8a5d2f3..7c32c99d0e 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -305,11 +305,11 @@ static void set_init_expand_env(void) { for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; 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); @@ -447,7 +447,7 @@ static OptVal get_option_default(const OptIndex opt_idx, int opt_flags) 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 & P_NO_DEF_EXP)) { + } 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); @@ -492,7 +492,7 @@ static void set_option_default(const OptIndex opt_idx, int opt_flags) // The default value is not insecure. uint32_t *flagsp = insecure_flag(curwin, opt_idx, opt_flags); - *flagsp = *flagsp & ~P_INSECURE; + *flagsp = *flagsp & ~(unsigned)kOptFlagInsecure; } /// Set all options (except terminal options) to their default value. @@ -501,7 +501,7 @@ static void set_option_default(const OptIndex opt_idx, int opt_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)) { + if (!(options[opt_idx].flags & kOptFlagNoDefault)) { set_option_default(opt_idx, opt_flags); } } @@ -542,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 @@ -592,7 +592,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(); @@ -613,8 +613,8 @@ 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); @@ -648,7 +648,7 @@ void set_init_3(void) 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 (idx_ffs >= 0 && (options[idx_ffs].flags & kOptFlagWasSet)) { set_fileformat(default_fileformat(), OPT_LOCAL); } } @@ -668,7 +668,7 @@ 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; } @@ -696,11 +696,11 @@ 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)) { + if (!(options[kOptTitle].flags & kOptFlagWasSet)) { change_option_default(kOptTitle, BOOLEAN_OPTVAL(false)); p_title = 0; } - if (!(options[kOptIcon].flags & P_WAS_SET)) { + if (!(options[kOptIcon].flags & kOptFlagWasSet)) { change_option_default(kOptIcon, BOOLEAN_OPTVAL(false)); p_icon = 0; } @@ -744,7 +744,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] != '\\' @@ -793,12 +793,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--; @@ -823,7 +823,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] == ',') { @@ -845,8 +845,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. @@ -854,7 +854,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; @@ -890,14 +890,14 @@ static char *stropt_get_newval(int nextchar, OptIndex opt_idx, char **argp, void // Expand environment variables and ~. // Don't do it when adding without inserting a comma. - if (op == OP_NONE || (flags & P_COMMA)) { + if (op == OP_NONE || (flags & kOptFlagComma)) { newval = stropt_expand_envvar(opt_idx, origval, newval, op); } // locate newval[] in origval[] when removing it // and when adding to avoid duplicates int len = 0; - if (op == OP_REMOVING || (flags & P_NODUP)) { + if (op == OP_REMOVING || (flags & kOptFlagNoDup)) { len = (int)strlen(newval); s = find_dup_item(origval, newval, (size_t)len, flags); @@ -922,7 +922,7 @@ static char *stropt_get_newval(int nextchar, OptIndex opt_idx, char **argp, void stropt_remove_val(origval, newval, flags, s, len); } - if (flags & P_FLAGLIST) { + if (flags & kOptFlagFlagList) { // Remove flags that appear twice. stropt_remove_dupflags(newval, flags); } @@ -986,11 +986,11 @@ static int validate_opt_idx(win_T *win, OptIndex opt_idx, int opt_flags, uint32_ // 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; } @@ -1006,7 +1006,7 @@ static int validate_opt_idx(win_T *win, OptIndex opt_idx, int opt_flags, uint32_ } // Disallow changing some options in the sandbox - if (sandbox != 0 && (flags & P_SECURE)) { + if (sandbox != 0 && (flags & kOptFlagSecure)) { *errmsg = e_sandbox; return FAIL; } @@ -1586,7 +1586,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) || options[opt_idx].var == NULL) { return NULL; } @@ -1677,10 +1677,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. @@ -2976,25 +2976,25 @@ static const char *validate_num_option(OptIndex opt_idx, void *varp, OptInt *new /// 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) { @@ -3466,7 +3466,7 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_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. @@ -3567,7 +3567,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; } @@ -3575,14 +3576,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; } } @@ -3700,9 +3701,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; } @@ -3719,7 +3720,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)); } } @@ -3812,7 +3813,7 @@ 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); } @@ -4050,7 +4051,7 @@ OptVal get_option_value_strict(OptIndex opt_idx, OptReqScope req_scope, void *fr /// 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. @@ -4227,7 +4228,7 @@ void ui_refresh_options(void) { for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; 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); @@ -4302,14 +4303,14 @@ 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++) { 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)) { continue; @@ -4317,7 +4318,7 @@ int makeset(FILE *fd, int opt_flags, int local_only) // 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; } @@ -4432,7 +4433,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_ char *part = NULL; if (*valuep != NULL) { - if ((flags & P_EXPAND) != 0) { + if ((flags & kOptFlagExpand) != 0) { size_t size = (size_t)strlen(*valuep) + 1; // replace home directory in the whole option value into "buf" @@ -4442,7 +4443,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_ // 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 + if (size >= MAXPATHL && (flags & kOptFlagComma) != 0 && vim_strchr(*valuep, ',') != NULL) { part = xmalloc(size); @@ -5574,8 +5575,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 @@ -5599,7 +5600,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; } } @@ -5609,21 +5610,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; } @@ -5633,7 +5634,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; } @@ -5786,7 +5787,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); @@ -5872,11 +5873,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; @@ -5923,7 +5924,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. @@ -5988,7 +5989,7 @@ static void option_value2string(vimoption_T *opt, int scope) varp = *(char **)(varp); if (varp == NULL) { // Just in case. NameBuff[0] = NUL; - } else if (opt->flags & P_EXPAND) { + } else if (opt->flags & kOptFlagExpand) { home_replace(NULL, varp, NameBuff, MAXPATHL, false); } else { xstrlcpy(NameBuff, varp, MAXPATHL); @@ -6049,7 +6050,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. @@ -6058,7 +6059,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 @@ -6456,10 +6457,10 @@ static Dict vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, win_T *w // 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, "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) { @@ -6483,7 +6484,7 @@ static Dict vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, win_T *w 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 & P_NODUP))); + PUT_C(dict, "allows_duplicates", BOOLEAN_OBJ(!(opt->flags & kOptFlagNoDup))); return dict; } -- cgit From 378d9135e7ac0f91a4944be816dc9f693d5078af Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 28 Oct 2024 15:14:15 +0800 Subject: vim-patch:9.1.0810: cannot easily adjust the |:find| command Problem: cannot easily adjust the |:find| command Solution: Add support for the 'findexpr' option (Yegappan Lakshmanan) closes: vim/vim#15901 closes: vim/vim#15905 https://github.com/vim/vim/commit/aeb1c97db5b9de4f4903e7f288f2aa5ad6c49440 Co-authored-by: Yegappan Lakshmanan --- src/nvim/option.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 7c32c99d0e..65f03ca77f 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -4530,6 +4530,8 @@ void *get_varp_scope_from(vimoption_T *p, int scope, buf_T *buf, win_T *win) switch ((int)p->indir) { case PV_FP: return &(buf->b_p_fp); + case PV_FEXPR: + return &(buf->b_p_fexpr); case PV_EFM: return &(buf->b_p_efm); case PV_GP: @@ -4651,6 +4653,8 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win) return *buf->b_p_tsrfu != NUL ? &(buf->b_p_tsrfu) : p->var; case PV_FP: return *buf->b_p_fp != NUL ? &(buf->b_p_fp) : p->var; + case PV_FEXPR: + return *buf->b_p_fexpr != NUL ? &(buf->b_p_fexpr) : p->var; case PV_EFM: return *buf->b_p_efm != NUL ? &(buf->b_p_efm) : p->var; case PV_GP: @@ -4922,6 +4926,15 @@ char *get_equalprg(void) return curbuf->b_p_ep; } +/// Get the value of 'findexpr', either the buffer-local one or the global one. +char *get_findexpr(void) +{ + if (*curbuf->b_p_fexpr == NUL) { + return p_fexpr; + } + return curbuf->b_p_fexpr; +} + /// Copy options from one window to another. /// Used when splitting a window. void win_copy_options(win_T *wp_from, win_T *wp_to) @@ -5320,6 +5333,8 @@ 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_fexpr = xstrdup(p_fexpr); + COPY_OPT_SCTX(buf, BV_FEXPR); buf->b_p_kp = empty_string_option; buf->b_p_path = empty_string_option; buf->b_p_tags = empty_string_option; -- cgit From ec0c53b3da5484f1068e476a477d3f96a0a1a811 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sat, 2 Nov 2024 04:44:56 +0600 Subject: refactor(options): unify `put_set(num|bool|string)` (#30993) Problem: There are three separate functions for printing the `:set` command for an setting an option to a file descriptor. These functions are used when creating the session file for an option. Having a function for each type increase code duplication and also makes it harder to add logic for new option types. Solution: Replace `put_set(num|bool|string)` with a single `put_set` function which works for all option types, this reduces code duplication and also makes it trivial to add support for more option types in the future. --- src/nvim/option.c | 220 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 116 insertions(+), 104 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 65f03ca77f..a8ec5b2919 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -4368,35 +4368,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) { + 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; } - } else if (option_has_type(opt_idx, kOptValTypeNumber)) { - if (put_setnum(fd, cmd, opt->fullname, (OptInt *)varp) == FAIL) { - 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; - } - } } } } @@ -4409,110 +4398,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 ((opt->indir & PV_BOTH) && 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 & kOptFlagExpand) != 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 & kOptFlagComma) != 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; -- cgit From 86e54734bf9e05605d8b7146e7b0e79025138ba2 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Tue, 29 Oct 2024 03:21:33 +0600 Subject: refactor(options): remove `get_option_value_strict` Problem: `get_option_value_for` can perfectly replace `get_option_value_strict`, making the latter redundant. Solution: Remove `get_option_value_strict` --- src/nvim/option.c | 70 ------------------------------------------------------- 1 file changed, 70 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index a8ec5b2919..a7e56d6d39 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3978,76 +3978,6 @@ int get_option_attrs(OptIndex opt_idx) 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. -- cgit From 3075c69ff02faf396e5efbdcb4a255b0b0309649 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 3 Nov 2024 10:06:41 +0800 Subject: vim-patch:9.1.0831: 'findexpr' can't be used as lambad or Funcref (#31058) Problem: 'findexpr' can't be used for lambads (Justin Keyes) Solution: Replace the findexpr option with the findfunc option (Yegappan Lakshmanan) related: vim/vim#15905 closes: vim/vim#15976 https://github.com/vim/vim/commit/a13f3a4f5de9c150f70298850e34747838904995 Co-authored-by: Yegappan Lakshmanan --- src/nvim/option.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index a7e56d6d39..5d2e1ce4c6 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -578,6 +578,7 @@ void free_all_options(void) } free_operatorfunc_option(); free_tagfunc_option(); + free_findfunc_option(); XFREE_CLEAR(fenc_default); XFREE_CLEAR(p_term); XFREE_CLEAR(p_ttytype); @@ -4472,8 +4473,8 @@ void *get_varp_scope_from(vimoption_T *p, int scope, buf_T *buf, win_T *win) switch ((int)p->indir) { case PV_FP: return &(buf->b_p_fp); - case PV_FEXPR: - return &(buf->b_p_fexpr); + case PV_FFU: + return &(buf->b_p_ffu); case PV_EFM: return &(buf->b_p_efm); case PV_GP: @@ -4595,8 +4596,8 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win) return *buf->b_p_tsrfu != NUL ? &(buf->b_p_tsrfu) : p->var; case PV_FP: return *buf->b_p_fp != NUL ? &(buf->b_p_fp) : p->var; - case PV_FEXPR: - return *buf->b_p_fexpr != NUL ? &(buf->b_p_fexpr) : p->var; + case PV_FFU: + return *buf->b_p_ffu != NUL ? &(buf->b_p_ffu) : p->var; case PV_EFM: return *buf->b_p_efm != NUL ? &(buf->b_p_efm) : p->var; case PV_GP: @@ -4868,13 +4869,13 @@ char *get_equalprg(void) return curbuf->b_p_ep; } -/// Get the value of 'findexpr', either the buffer-local one or the global one. -char *get_findexpr(void) +/// Get the value of 'findfunc', either the buffer-local one or the global one. +char *get_findfunc(void) { - if (*curbuf->b_p_fexpr == NUL) { - return p_fexpr; + if (*curbuf->b_p_ffu == NUL) { + return p_ffu; } - return curbuf->b_p_fexpr; + return curbuf->b_p_ffu; } /// Copy options from one window to another. @@ -5275,8 +5276,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_fexpr = xstrdup(p_fexpr); - COPY_OPT_SCTX(buf, BV_FEXPR); + 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; -- cgit From a27419f3fc540f66567f4559a796cd6758f1bb1f Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Mon, 4 Nov 2024 19:00:12 +0600 Subject: feat(options)!: disallow setting hidden options #28400 Problem: There are three different ways of marking an option as hidden, `enable_if = false`, `hidden = true` and `immutable = true`. These also have different behaviors. Options hidden with `enable_if = false` can't have their value fetched using Vim script or the API, but options hidden with `hidden = true` or `immutable = true` can. On the other hand, options with `hidden = true` do not error when trying to set their value, but options with `immutable = true` do. Solution: Remove `enable_if = false`, remove the `hidden` property for options, and use `immutable = true` to mark an option as hidden instead. Also make hidden option variable pointers always point to the default value, which allows fetching the value of every hidden option using Vim script and the API. This does also mean that trying to set a hidden option will now give an error instead of just being ignored. --- src/nvim/option.c | 76 ++++++++++++++++++++++++------------------------------- 1 file changed, 33 insertions(+), 43 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 5d2e1ce4c6..783ec0abf4 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -565,13 +565,16 @@ static char *find_dup_item(char *origval, const char *newval, const size_t newva void free_all_options(void) { for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) { - if (options[opt_idx].indir == PV_NONE) { + bool hidden = is_option_hidden(opt_idx); + + if (options[opt_idx].indir == PV_NONE || hidden) { // global option: free value and default value. - if (options[opt_idx].var != NULL) { + // hidden option: free default value only. + if (!hidden) { optval_free(optval_from_varp(opt_idx, options[opt_idx].var)); } } else if (options[opt_idx].var != VAR_WIN) { - // buffer-local option: free global value + // buffer-local option: free global value. optval_free(optval_from_varp(opt_idx, options[opt_idx].var)); } optval_free(options[opt_idx].def_val); @@ -1244,16 +1247,6 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char * 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); @@ -1325,11 +1318,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); @@ -1587,7 +1575,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 & kOptFlagExpand) || options[opt_idx].var == NULL) { + if (!(options[opt_idx].flags & kOptFlagExpand) || is_option_hidden(opt_idx)) { return NULL; } @@ -2863,6 +2851,8 @@ static const char *validate_num_option(OptIndex opt_idx, void *varp, OptInt *new } else if (value > p_wiw) { return e_winwidth; } + } else if (varp == &p_mco) { + *newval = MAX_MCO; } else if (varp == &p_titlelen) { if (value < 0) { return e_positive; @@ -3161,6 +3151,7 @@ static OptValType option_get_type(const OptIndex opt_idx) /// /// @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. @@ -3170,7 +3161,7 @@ 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; } OptValType type = option_get_type(opt_idx); @@ -3179,11 +3170,11 @@ OptVal optval_from_varp(OptIndex opt_idx, void *varp) 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; } @@ -3319,7 +3310,10 @@ 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 + ? false + : (options[opt_idx].immutable && options[opt_idx].var == &options[opt_idx].def_val.data); } static inline bool option_is_global_local(OptIndex opt_idx) @@ -3459,8 +3453,8 @@ 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)) { @@ -3489,7 +3483,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) { @@ -3749,7 +3743,7 @@ void set_option_direct(OptIndex opt_idx, OptVal value, int opt_flags, scid_T set vimoption_T *opt = get_option(opt_idx); - if (opt->var == NULL) { + if (is_option_hidden(opt_idx)) { return; } @@ -3960,11 +3954,6 @@ int get_option_attrs(OptIndex opt_idx) 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)) { @@ -3976,6 +3965,7 @@ int get_option_attrs(OptIndex opt_idx) attrs |= SOPT_BUF; } + assert(attrs != 0); return attrs; } @@ -4143,8 +4133,8 @@ 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; } @@ -4554,9 +4544,9 @@ 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; + // hidden options always use the same var pointer + if (is_option_hidden(get_opt_idx(p))) { + return p->var; } switch ((int)p->indir) { @@ -5456,7 +5446,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; } @@ -5680,7 +5670,7 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, char *fuzzystr, int *numM char *str; for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; 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 @@ -5928,6 +5918,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; @@ -5944,9 +5935,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 & kOptFlagExpand) { + + if (opt->flags & kOptFlagExpand) { home_replace(NULL, varp, NameBuff, MAXPATHL, false); } else { xstrlcpy(NameBuff, varp, MAXPATHL); -- cgit From cbc9a03f58394bbb85bbe70c48856cc1efca4ab7 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sun, 3 Nov 2024 16:36:26 +0600 Subject: refactor(options): remove fileformat macros --- src/nvim/option.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 783ec0abf4..14553f9989 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -5105,13 +5105,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); @@ -6240,13 +6240,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; } -- cgit From 04274a417358a4eb9b3b3d1f7e1ea4a4b4419c5c Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Wed, 6 Nov 2024 04:07:29 +0600 Subject: refactor(options): remove unnecessary call to `find_option()` (#31088) --- src/nvim/option.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 783ec0abf4..cff8707edb 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -649,10 +649,8 @@ void set_init_3(void) 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 & kOptFlagWasSet)) { + if (options[kOptFileformats].flags & kOptFlagWasSet) { set_fileformat(default_fileformat(), OPT_LOCAL); } } -- cgit From 8af1702647e865009db66a68aeb821ef185986a9 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Fri, 8 Nov 2024 11:28:18 +0600 Subject: refactor(options): remove `varp` argument for `set_option` (#31111) Problem: The `varp` argument for `set_option` is extraneous as the option's variable pointer can be retrieved using the option's index and flags. Solution: Remove the `varp` argument for `set_option` --- src/nvim/option.c | 196 ++++++++++++++++++++++++------------------------------ 1 file changed, 86 insertions(+), 110 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 635d26f123..7172584e52 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1242,11 +1242,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 - - 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; @@ -1323,8 +1322,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. @@ -2744,15 +2742,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; @@ -2785,9 +2782,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; @@ -2805,13 +2800,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; @@ -2821,145 +2815,137 @@ 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_mco) { + break; + case kOptMaxcombine: *newval = MAX_MCO; - } 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 kOptCmdheight: if (value < 0) { return e_positive; } else { p_ch_was_zero = value == 0; } - } else if (varp == &p_tm) { - if (value < 0) { - return e_positive; - } - } else if (varp == &p_hi) { + break; + case kOptHistory: 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. @@ -3124,7 +3110,8 @@ 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; } @@ -3586,14 +3573,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 @@ -3613,7 +3605,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; @@ -3622,7 +3614,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: @@ -3634,17 +3625,16 @@ 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 = NULL; if (!direct) { - errmsg = validate_option_value(opt_idx, varp, &value, opt_flags, errbuf, errbuflen); + errmsg = validate_option_value(opt_idx, &value, opt_flags, errbuf, errbuflen); if (errmsg != NULL) { optval_free(value); @@ -3661,11 +3651,9 @@ static const char *set_option(const OptIndex opt_idx, void *varp, OptVal value, 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 && option_is_global_local(opt_idx)) { - 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); @@ -3739,16 +3727,11 @@ 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 (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); - - const char *errmsg = set_option(opt_idx, varp, optval_copy(value), opt_flags, set_sid, true, true, + 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 @@ -3810,14 +3793,7 @@ const char *set_option_value(const OptIndex opt_idx, const OptVal value, int opt 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, varp, optval_copy(value), opt_flags, 0, false, true, errbuf, - sizeof(errbuf)); + return set_option(opt_idx, optval_copy(value), opt_flags, 0, false, true, errbuf, sizeof(errbuf)); } /// Unset the local value of a global-local option. -- cgit From f83a31b49d5d976cd39f7faa6356565cb0a4a97a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 8 Nov 2024 14:54:28 +0800 Subject: refactor(options): use os_win/os_buf for local options (#31060) Conversely, don't use them for global options. --- src/nvim/option.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 7172584e52..0396f7740e 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1886,7 +1886,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) @@ -1917,7 +1917,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 @@ -1928,8 +1928,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; @@ -2051,9 +2051,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); } } @@ -2382,14 +2380,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(); @@ -2505,8 +2505,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; @@ -2546,8 +2545,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; } @@ -2560,7 +2561,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); @@ -2600,7 +2601,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); } @@ -2665,8 +2666,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); } } @@ -2677,9 +2677,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; -- cgit From 5cfa7a72f8c40cdcc0fa93693689915e913806f1 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Tue, 20 Feb 2024 17:25:57 +0100 Subject: refactor(message): propagate highlight id instead of attrs Problem: Highlight group id is not propagated to the end of the message call stack, where ext_messages are emitted. Solution: Refactor message functions to pass along highlight group id instead of attr id. --- src/nvim/option.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 635d26f123..0944a3041e 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1903,8 +1903,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 + 1); + msg(_(w_arabic), HLF_W + 1); set_vim_var_string(VV_WARNINGMSG, _(w_arabic), -1); } @@ -4187,7 +4187,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; -- cgit From 5a27d02584656f35d757c01f10a1d3c88910c519 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 9 Nov 2024 01:10:56 +0100 Subject: docs: misc (#30914) Co-authored-by: Ernie Rael Co-authored-by: Famiu Haque Co-authored-by: Jade Co-authored-by: glepnir Co-authored-by: zeertzjq --- src/nvim/option.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 0396f7740e..c7aaf7975d 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3282,8 +3282,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. -- cgit From ff7518b83cb270f8fcaded19bf640cf4bdfb0ff0 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 11 Nov 2024 13:06:37 +0100 Subject: refactor(highlight): make enum of builtin highlights start with 1 This makes it possible to use HLF_ values directly as highlight id:s and avoids +1 adjustments especially around messages. --- src/nvim/option.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 25e9fa471d..03b7c8cb14 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1901,8 +1901,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(HLF_W + 1); - msg(_(w_arabic), HLF_W + 1); + msg_source(HLF_W); + msg(_(w_arabic), HLF_W); set_vim_var_string(VV_WARNINGMSG, _(w_arabic), -1); } -- cgit From fa0dcde3d9f17f85baa9dd41aa751c123281ced3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 15 Nov 2024 08:04:49 +0800 Subject: vim-patch:9.1.0864: message history is fixed to 200 (#31215) Problem: message history is fixed to 200 Solution: Add the 'msghistory' option, increase the default value to 500 (Shougo Matsushita) closes: vim/vim#16048 https://github.com/vim/vim/commit/4bd9b2b2467e696061104a029000e9824c6c609e Co-authored-by: Shougo Matsushita Co-authored-by: Milly --- src/nvim/option.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index 03b7c8cb14..efd52f9233 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2874,6 +2874,13 @@ static const char *validate_num_option(OptIndex opt_idx, OptInt *newval, char *e return e_invarg; } break; + case kOptMsghistory: + if (value < 0) { + return e_positive; + } else if (value > 10000) { + return e_invarg; + } + break; case kOptPyxversion: if (value == 0) { *newval = 3; -- cgit From 29ded889579a9d590e8ea885a9a402ff4bae87be Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sun, 17 Nov 2024 02:56:16 +0600 Subject: refactor(options): remove `.indir`, redesign option scopes #31066 Problem: The way option scopes currently work is inflexible and does not allow for nested option scopes or easily finding the value of an option at any arbitrary scope without having to do long handwritten switch-case statements like in `get_varp()`. `.indir` is also confusing and redundant since option indices for each scope can be autogenerated. Solution: Expand option scopes in such a way that an option can support any amount of scopes using a set of scope flags, similarly to how it's already done for option types. Also make options contain information about its index at each scope it supports. This allows for massively simplifying `get_varp()` and `get_varp_scope()` in the future by just using a struct for options at each scope. This would be done by creating a table that stores the offset of an option's variable at a scope by using the option's index at that scope as a key. This PR also autogenerates enums for option indices at each scope to remove the need for `.indir` entirely, and also to allow easily iterating over options all options that support any scope. Ref: #29314 --- src/nvim/option.c | 803 +++++++++++++++++++++++++++--------------------------- 1 file changed, 395 insertions(+), 408 deletions(-) (limited to 'src/nvim/option.c') diff --git a/src/nvim/option.c b/src/nvim/option.c index efd52f9233..8e94c342f7 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -303,7 +303,7 @@ static void set_init_default_cdpath(void) /// them. 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 & kOptFlagNoDefExp) { continue; @@ -435,7 +435,7 @@ void set_init_1(bool clean_arg) static OptVal get_option_default(const OptIndex opt_idx, int opt_flags) { vimoption_T *opt = &options[opt_idx]; - bool is_global_local_option = opt->indir & PV_BOTH; + bool is_global_local_option = option_is_global_local(opt_idx); #ifdef UNIX if (opt_idx == kOptModeline && getuid() == ROOT_UID) { @@ -461,7 +461,7 @@ static OptVal get_option_default(const OptIndex opt_idx, int opt_flags) /// 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 < kOptIndexCount; opt_idx++) { + for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) { options[opt_idx].def_val = optval_copy(options[opt_idx].def_val); } } @@ -500,7 +500,7 @@ 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++) { + for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) { if (!(options[opt_idx].flags & kOptFlagNoDefault)) { set_option_default(opt_idx, opt_flags); } @@ -564,16 +564,16 @@ static char *find_dup_item(char *origval, const char *newval, const size_t newva /// Free all options. void free_all_options(void) { - for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) { + for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) { bool hidden = is_option_hidden(opt_idx); - if (options[opt_idx].indir == PV_NONE || hidden) { + if (option_is_global_only(opt_idx) || hidden) { // global option: free value and default value. // hidden option: free default value only. if (!hidden) { optval_free(optval_from_varp(opt_idx, options[opt_idx].var)); } - } else if (options[opt_idx].var != VAR_WIN) { + } 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)); } @@ -977,12 +977,12 @@ 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; } @@ -999,10 +999,7 @@ static int validate_opt_idx(win_T *win, OptIndex opt_idx, int opt_flags, uint32_ // 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; } } @@ -1099,7 +1096,7 @@ 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; @@ -1285,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)]); } } @@ -1643,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]))); } @@ -1673,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; } @@ -1804,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, @@ -1818,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; } } } @@ -3267,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; @@ -3299,14 +3296,73 @@ static char *option_get_valid_types(OptIndex opt_idx) bool is_option_hidden(OptIndex opt_idx) { // Hidden options are always immutable and point to their default value - return opt_idx == kOptInvalid - ? false - : (options[opt_idx].immutable && options[opt_idx].var == &options[opt_idx].def_val.data); + 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) { - return opt_idx == kOptInvalid ? false : (options[opt_idx].indir & PV_BOTH); + // 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. @@ -3357,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(""); @@ -3389,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; } @@ -3748,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; @@ -3760,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: + case kOptScopeGlobal: break; - case kOptReqBuf: - curbuf = (buf_T *)from; - 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); @@ -3855,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; @@ -3884,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; @@ -3894,76 +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); - - 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; - } - - assert(attrs != 0); - return attrs; -} - /// Get option value for buffer / window. /// /// @param opt_idx Option index in options[] table. /// @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)) { @@ -3985,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)) { @@ -4040,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)) { @@ -4049,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 { @@ -4124,7 +4149,7 @@ 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 & kOptFlagUIOption)) { continue; @@ -4204,13 +4229,13 @@ int makeset(FILE *fd, int opt_flags, int local_only) // 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 & 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; } @@ -4237,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; } } } @@ -4267,9 +4290,9 @@ int makeset(FILE *fd, int opt_flags, int local_only) } 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) { + // 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) { @@ -4325,7 +4348,7 @@ static int put_set(FILE *fd, char *cmd, OptIndex opt_idx, void *varp) char *name = opt->fullname; uint64_t flags = opt->flags; - if ((opt->indir & PV_BOTH) && varp != opt->var + 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; @@ -4430,76 +4453,80 @@ static int put_set(FILE *fd, char *cmd, OptIndex opt_idx, void *varp) 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_FFU: + case kOptFindfunc: return &(buf->b_p_ffu); - case PV_EFM: + 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); } @@ -4521,291 +4548,290 @@ 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 options always use the same var pointer - if (is_option_hidden(get_opt_idx(p))) { - return p->var; - } + 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_FFU: + case kOptFindfunc: return *buf->b_p_ffu != NUL ? &(buf->b_p_ffu) : p->var; - case PV_EFM: + 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_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")); @@ -5008,26 +5034,8 @@ void didset_window_options(win_T *wp, bool valid_cursor) 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: @@ -5065,7 +5073,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) @@ -5101,61 +5108,61 @@ 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); set_buflocal_ofu_callback(buf); 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 { @@ -5163,75 +5170,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 @@ -5252,16 +5259,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; @@ -5278,12 +5285,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 { @@ -5294,7 +5301,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); } } @@ -5645,7 +5652,7 @@ 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 (is_option_hidden(opt_idx)) { continue; @@ -6306,11 +6313,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) { @@ -6353,8 +6360,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)); } @@ -6363,15 +6370,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"; @@ -6380,7 +6388,7 @@ 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, "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)); @@ -6391,11 +6399,11 @@ static Dict vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, win_T *w 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; @@ -6412,24 +6420,3 @@ static Dict vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, win_T *w 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); -} -- cgit