diff options
author | Gregory Anders <8965202+gpanders@users.noreply.github.com> | 2021-12-21 14:20:34 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-21 14:20:34 -0700 |
commit | 33cd1ba00ad4483aa2d7cb386e7204737f8936fe (patch) | |
tree | 0e8d112f80521aaca152d95d982a684b3e4a6979 | |
parent | 1b04da52b3ce611e06b7d1c87af4a71c37ad127a (diff) | |
download | rneovim-33cd1ba00ad4483aa2d7cb386e7204737f8936fe.tar.gz rneovim-33cd1ba00ad4483aa2d7cb386e7204737f8936fe.tar.bz2 rneovim-33cd1ba00ad4483aa2d7cb386e7204737f8936fe.zip |
fix(api): make nil value in nvim_set_option_value clear local value (#16710)
For special options such as 'undolevels' and 'scrolloff', this sets the
local value to the special "unset" value (e.g. -12345 for 'undolevels').
-rw-r--r-- | src/nvim/api/vim.c | 14 | ||||
-rw-r--r-- | src/nvim/option.c | 22 | ||||
-rw-r--r-- | src/nvim/option.h | 1 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 34 |
4 files changed, 66 insertions, 5 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 4f7c320129..f81cdf9deb 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -696,7 +696,17 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) rv = INTEGER_OBJ(numval); break; case 2: - rv = BOOLEAN_OBJ(!!numval); + switch (numval) { + case 0: + case 1: + rv = BOOLEAN_OBJ(numval); + break; + default: + // Boolean options that return something other than 0 or 1 should return nil. Currently this + // only applies to 'autoread' which uses -1 as a local value to indicate "unset" + rv = NIL; + break; + } break; default: api_set_error(err, kErrorTypeValidation, "unknown option '%s'", name.data); @@ -749,7 +759,7 @@ void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error stringval = value.data.string.data; break; case kObjectTypeNil: - // Do nothing + scope |= OPT_CLEAR; break; default: api_set_error(err, kErrorTypeValidation, "invalid value for option"); diff --git a/src/nvim/option.c b/src/nvim/option.c index 2ceb1bd992..04bd968ac8 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -5059,6 +5059,9 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o /// @param[in] number New value for the number or boolean option. /// @param[in] string New value for string option. /// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both). +/// If OPT_CLEAR is set, the value of the option +/// is cleared (the exact semantics of this depend +/// on the option). /// /// @return NULL on success, error message on error. char *set_option_value(const char *const name, const long number, const char *const string, @@ -5084,7 +5087,7 @@ char *set_option_value(const char *const name, const long number, const char *co } if (flags & P_STRING) { const char *s = string; - if (s == NULL) { + if (s == NULL || opt_flags & OPT_CLEAR) { s = ""; } return set_string_option(opt_idx, s, opt_flags); @@ -5106,10 +5109,23 @@ char *set_option_value(const char *const name, const long number, const char *co return NULL; // do nothing as we hit an error } } + long numval = number; + if (opt_flags & OPT_CLEAR) { + if ((int *)varp == &curbuf->b_p_ar) { + numval = -1; + } else if ((long *)varp == &curbuf->b_p_ul) { + numval = NO_LOCAL_UNDOLEVEL; + } else if ((long *)varp == &curwin->w_p_so || (long *)varp == &curwin->w_p_siso) { + numval = -1; + } else { + char *s = NULL; + (void)get_option_value(name, &numval, (char_u **)&s, OPT_GLOBAL); + } + } if (flags & P_NUM) { - return set_num_option(opt_idx, varp, number, NULL, 0, opt_flags); + return set_num_option(opt_idx, varp, numval, NULL, 0, opt_flags); } else { - return set_bool_option(opt_idx, varp, (int)number, opt_flags); + return set_bool_option(opt_idx, varp, (int)numval, opt_flags); } } } diff --git a/src/nvim/option.h b/src/nvim/option.h index 452494172f..fbd8f38110 100644 --- a/src/nvim/option.h +++ b/src/nvim/option.h @@ -22,6 +22,7 @@ typedef enum { OPT_ONECOLUMN = 64, ///< list options one per line OPT_NO_REDRAW = 128, ///< ignore redraw flags on option OPT_SKIPRTP = 256, ///< "skiprtp" in 'sessionoptions' + OPT_CLEAR = 512, ///< Clear local value of an option. } OptionFlags; #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index d53208a915..112adfaf2d 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -974,6 +974,40 @@ describe('API', function() eq('hello', nvim('get_option_value', 'makeprg', {})) eq('', nvim('get_option_value', 'makeprg', {scope = 'local'})) end) + + it('clears the local value of an option with nil', function() + -- Set global value + nvim('set_option_value', 'shiftwidth', 42, {}) + eq(42, nvim('get_option_value', 'shiftwidth', {})) + + -- Set local value + nvim('set_option_value', 'shiftwidth', 8, {scope = 'local'}) + eq(8, nvim('get_option_value', 'shiftwidth', {})) + eq(8, nvim('get_option_value', 'shiftwidth', {scope = 'local'})) + eq(42, nvim('get_option_value', 'shiftwidth', {scope = 'global'})) + + -- Clear value without scope + nvim('set_option_value', 'shiftwidth', NIL, {}) + eq(42, nvim('get_option_value', 'shiftwidth', {})) + eq(42, nvim('get_option_value', 'shiftwidth', {scope = 'local'})) + + -- Clear value with explicit scope + nvim('set_option_value', 'shiftwidth', 8, {scope = 'local'}) + nvim('set_option_value', 'shiftwidth', NIL, {scope = 'local'}) + eq(42, nvim('get_option_value', 'shiftwidth', {})) + eq(42, nvim('get_option_value', 'shiftwidth', {scope = 'local'})) + + -- Now try with options with a special "local is unset" value (e.g. 'undolevels') + nvim('set_option_value', 'undolevels', 1000, {}) + eq(1000, nvim('get_option_value', 'undolevels', {scope = 'local'})) + nvim('set_option_value', 'undolevels', NIL, {scope = 'local'}) + eq(-123456, nvim('get_option_value', 'undolevels', {scope = 'local'})) + + nvim('set_option_value', 'autoread', true, {}) + eq(true, nvim('get_option_value', 'autoread', {scope = 'local'})) + nvim('set_option_value', 'autoread', NIL, {scope = 'local'}) + eq(NIL, nvim('get_option_value', 'autoread', {scope = 'local'})) + end) end) describe('nvim_{get,set}_current_buf, nvim_list_bufs', function() |