mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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').
This commit is contained in:
parent
1b04da52b3
commit
33cd1ba00a
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user