diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/keysets.lua | 3 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 113 | ||||
-rw-r--r-- | src/nvim/eval.c | 2 | ||||
-rw-r--r-- | src/nvim/option.c | 25 |
4 files changed, 129 insertions, 14 deletions
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua index 144c252687..e956a54dbc 100644 --- a/src/nvim/api/keysets.lua +++ b/src/nvim/api/keysets.lua @@ -58,5 +58,8 @@ return { "highlights"; "use_tabline"; }; + option = { + "scope"; + }; } diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 3103905819..36179b1fab 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -642,7 +642,7 @@ void nvim_set_vvar(String name, Object value, Error *err) dict_set_var(&vimvardict, name, value, false, false, err); } -/// Gets an option value string. +/// Gets the global value of an option. /// /// @param name Option name /// @param[out] err Error details, if any @@ -653,6 +653,115 @@ Object nvim_get_option(String name, Error *err) return get_option_from(NULL, SREQ_GLOBAL, name, err); } +/// Gets the value of an option. The behavior of this function matches that of +/// |:set|: the local value of an option is returned if it exists; otherwise, +/// the global value is returned. Local values always correspond to the current +/// buffer or window. To get a buffer-local or window-local option for a +/// specific buffer or window, use |nvim_buf_get_option()| or +/// |nvim_win_get_option()|. +/// +/// @param name Option name +/// @param opts Optional parameters +/// - scope: One of 'global' or 'local'. Analagous to +/// |:setglobal| and |:setlocal|, respectively. +/// @param[out] err Error details, if any +/// @return Option value +Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) + FUNC_API_SINCE(9) +{ + Object rv = OBJECT_INIT; + + int scope = 0; + if (opts->scope.type == kObjectTypeString) { + if (!strcmp(opts->scope.data.string.data, "local")) { + scope = OPT_LOCAL; + } else if (!strcmp(opts->scope.data.string.data, "global")) { + scope = OPT_GLOBAL; + } else { + api_set_error(err, kErrorTypeValidation, "invalid scope: must be 'local' or 'global'"); + goto end; + } + } else if (HAS_KEY(opts->scope)) { + api_set_error(err, kErrorTypeValidation, "invalid value for key: scope"); + goto end; + } + + long numval = 0; + char *stringval = NULL; + switch (get_option_value(name.data, &numval, (char_u **)&stringval, scope)) { + case 0: + rv = STRING_OBJ(cstr_as_string(stringval)); + break; + case 1: + rv = INTEGER_OBJ(numval); + break; + case 2: + rv = BOOLEAN_OBJ(!!numval); + break; + default: + api_set_error(err, kErrorTypeValidation, "unknown option '%s'", name.data); + goto end; + } + +end: + return rv; +} + +/// Sets the value of an option. The behavior of this function matches that of +/// |:set|: for global-local options, both the global and local value are set +/// unless otherwise specified with {scope}. +/// +/// @param name Option name +/// @param value New option value +/// @param opts Optional parameters +/// - scope: One of 'global' or 'local'. Analagous to +/// |:setglobal| and |:setlocal|, respectively. +/// @param[out] err Error details, if any +void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error *err) + FUNC_API_SINCE(9) +{ + int scope = 0; + if (opts->scope.type == kObjectTypeString) { + if (!strcmp(opts->scope.data.string.data, "local")) { + scope = OPT_LOCAL; + } else if (!strcmp(opts->scope.data.string.data, "global")) { + scope = OPT_GLOBAL; + } else { + api_set_error(err, kErrorTypeValidation, "invalid scope: must be 'local' or 'global'"); + return; + } + } else if (HAS_KEY(opts->scope)) { + api_set_error(err, kErrorTypeValidation, "invalid value for key: scope"); + return; + } + + long numval = 0; + char *stringval = NULL; + + switch (value.type) { + case kObjectTypeInteger: + numval = value.data.integer; + break; + case kObjectTypeBoolean: + numval = value.data.boolean ? 1 : 0; + break; + case kObjectTypeString: + stringval = value.data.string.data; + break; + case kObjectTypeNil: + // Do nothing + break; + default: + api_set_error(err, kErrorTypeValidation, "invalid value for option"); + return; + } + + char *e = set_option_value(name.data, numval, stringval, scope); + if (e) { + api_set_error(err, kErrorTypeException, "%s", e); + } +} + /// Gets the option information for all options. /// /// The dictionary has the full option names as keys and option metadata @@ -694,7 +803,7 @@ Dictionary nvim_get_option_info(String name, Error *err) return get_vimoption(name, err); } -/// Sets an option value. +/// Sets the global value of an option. /// /// @param channel_id /// @param name Option name diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 29740283c6..2faae08fc8 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -4828,7 +4828,7 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval } else if (opt_type == -1) { // hidden number option rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; - } else if (opt_type == 1) { // number option + } else if (opt_type == 1 || opt_type == 2) { // number or boolean option rettv->v_type = VAR_NUMBER; rettv->vval.v_number = numval; } else { // string option diff --git a/src/nvim/option.c b/src/nvim/option.c index 45e2032b35..ee5f62d826 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -4771,7 +4771,8 @@ static int findoption(const char *const arg) /// @param stringval NULL when only checking existence /// /// @returns: -/// Number or Toggle option: 1, *numval gets value. +/// Toggle option: 2, *numval gets value. +/// Number option: 1, *numval gets value. /// String option: 0, *stringval gets allocated string. /// Hidden Number or Toggle option: -1. /// hidden String option: -2. @@ -4804,16 +4805,18 @@ int get_option_value(const char *name, long *numval, char_u **stringval, int opt } if (options[opt_idx].flags & P_NUM) { *numval = *(long *)varp; + return 1; + } + + // Special case: 'modified' is b_changed, but we also want to consider + // it set when 'ff' or 'fenc' changed. + if ((int *)varp == &curbuf->b_changed) { + *numval = curbufIsChanged(); } else { - // Special case: 'modified' is b_changed, but we also want to consider - // it set when 'ff' or 'fenc' changed. - if ((int *)varp == &curbuf->b_changed) { - *numval = curbufIsChanged(); - } else { - *numval = (long)*(int *)varp; // NOLINT(whitespace/cast) - } + *numval = (long)*(int *)varp; // NOLINT(whitespace/cast) } - return 1; + + return 2; } // Returns the option attributes and its value. Unlike the above function it @@ -4909,7 +4912,7 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o // only getting a pointer, no need to use aucmd_prepbuf() curbuf = (buf_T *)from; curwin->w_buffer = curbuf; - varp = get_varp(p); + varp = get_varp_scope(p, OPT_LOCAL); curbuf = save_curbuf; curwin->w_buffer = curbuf; } @@ -4917,7 +4920,7 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o win_T *save_curwin = curwin; curwin = (win_T *)from; curbuf = curwin->w_buffer; - varp = get_varp(p); + varp = get_varp_scope(p, OPT_LOCAL); curwin = save_curwin; curbuf = curwin->w_buffer; } |