aboutsummaryrefslogtreecommitdiff
path: root/src/nvim
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2025-01-10 10:20:43 +0000
committerLewis Russell <me@lewisr.dev>2025-01-13 16:58:25 +0000
commit34e2185022ab698827b72751d77e218a1b6b6afe (patch)
tree9b8c0fe0a24b77a60e1e6511cfb3e2135b7789af /src/nvim
parentcb7b4e296238b46025de05203c886d67da401728 (diff)
downloadrneovim-34e2185022ab698827b72751d77e218a1b6b6afe.tar.gz
rneovim-34e2185022ab698827b72751d77e218a1b6b6afe.tar.bz2
rneovim-34e2185022ab698827b72751d77e218a1b6b6afe.zip
fix(options): better handling of empty values
Problem: Whether an option is allowed to be empty isn't well defined and isn't properly checked. Solution: - For non-list string options, explicitly check the option value if it is empty. - Annotate non-list string options that can accept an empty value. - Adjust command completion to ignore the empty value. - Render values in Lua meta files
Diffstat (limited to 'src/nvim')
-rw-r--r--src/nvim/options.lua17
-rw-r--r--src/nvim/optionstr.c16
2 files changed, 22 insertions, 11 deletions
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 15a4e8ddc2..2425dcb93e 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -7,7 +7,7 @@
--- @field alias? string|string[]
--- @field short_desc? string|fun(): string
--- @field varname? string
---- @field type vim.option_type|vim.option_type[]
+--- @field type vim.option_type
--- @field immutable? boolean
--- @field list? 'comma'|'onecomma'|'commacolon'|'onecommacolon'|'flags'|'flagscomma'
--- @field scope vim.option_scope[]
@@ -834,7 +834,7 @@ return {
abbreviation = 'bh',
cb = 'did_set_bufhidden',
defaults = { if_true = '' },
- values = { 'hide', 'unload', 'delete', 'wipe' },
+ values = { '', 'hide', 'unload', 'delete', 'wipe' },
desc = [=[
This option specifies what happens when a buffer is no longer
displayed in a window:
@@ -888,11 +888,12 @@ return {
cb = 'did_set_buftype',
defaults = { if_true = '' },
values = {
+ '',
+ 'acwrite',
+ 'help',
'nofile',
'nowrite',
'quickfix',
- 'help',
- 'acwrite',
'terminal',
'prompt',
},
@@ -1554,7 +1555,7 @@ return {
abbreviation = 'csl',
cb = 'did_set_completeslash',
defaults = { if_true = '' },
- values = { 'slash', 'backslash' },
+ values = { '', 'slash', 'backslash' },
desc = [=[
only modifiable in MS-Windows
When this option is set it overrules 'shellslash' for completion:
@@ -2017,8 +2018,10 @@ return {
"msg" and "throw" are useful for debugging 'foldexpr', 'formatexpr' or
'indentexpr'.
]=],
+ -- TODO(lewis6991): bug, values currently cannot be combined
expand_cb = 'expand_set_debug',
full_name = 'debug',
+ list = 'comma',
scope = { 'global' },
short_desc = N_('to "msg" to see all error messages'),
type = 'string',
@@ -4299,7 +4302,7 @@ return {
abbreviation = 'icm',
cb = 'did_set_inccommand',
defaults = { if_true = 'nosplit' },
- values = { 'nosplit', 'split' },
+ values = { 'nosplit', 'split', '' },
desc = [=[
When nonempty, shows the effects of |:substitute|, |:smagic|,
|:snomagic| and user commands with the |:command-preview| flag as you
@@ -5735,7 +5738,7 @@ return {
abbreviation = 'mousem',
cb = 'did_set_mousemodel',
defaults = { if_true = 'popup_setpos' },
- values = { 'extend', 'popup', 'popup_setpos', 'mac' },
+ values = { 'extend', 'popup', 'popup_setpos' },
desc = [=[
Sets the model to use for the mouse. The name mostly specifies what
the right mouse button is used for:
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index 9b7b50ae04..eac9ea02e0 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -395,7 +395,9 @@ static int expand_set_opt_string(optexpand_T *args, const char **values, size_t
}
for (const char **val = values; *val != NULL; val++) {
- if (include_orig_val && *option_val != NUL) {
+ if (**val == NUL) {
+ continue; // Ignore empty
+ } else if (include_orig_val && *option_val != NUL) {
if (strcmp(*val, option_val) == 0) {
continue;
}
@@ -1091,7 +1093,7 @@ int expand_set_cursorlineopt(optexpand_T *args, int *numMatches, char ***matches
/// The 'debug' option is changed.
const char *did_set_debug(optset_T *args FUNC_ATTR_UNUSED)
{
- return did_set_opt_strings(p_debug, opt_debug_values, false);
+ return did_set_opt_strings(p_debug, opt_debug_values, true);
}
int expand_set_debug(optexpand_T *args, int *numMatches, char ***matches)
@@ -2545,7 +2547,7 @@ int expand_set_winhighlight(optexpand_T *args, int *numMatches, char ***matches)
/// @param list when true: accept a list of values
///
/// @return OK for correct value, FAIL otherwise. Empty is always OK.
-static int check_opt_strings(char *val, const char **values, int list)
+static int check_opt_strings(char *val, const char **values, bool list)
{
return opt_strings_flags(val, values, NULL, list);
}
@@ -2562,7 +2564,10 @@ static int opt_strings_flags(const char *val, const char **values, unsigned *fla
{
unsigned new_flags = 0;
- while (*val) {
+ // If not list and val is empty, then force one iteration of the while loop
+ bool iter_one = (*val == NUL) && !list;
+
+ while (*val || iter_one) {
for (unsigned i = 0;; i++) {
if (values[i] == NULL) { // val not found in values[]
return FAIL;
@@ -2577,6 +2582,9 @@ static int opt_strings_flags(const char *val, const char **values, unsigned *fla
break; // check next item in val list
}
}
+ if (iter_one) {
+ break;
+ }
}
if (flagp != NULL) {
*flagp = new_flags;