aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/option.c
diff options
context:
space:
mode:
authorFamiu Haque <famiuhaque@proton.me>2024-11-02 04:44:56 +0600
committerGitHub <noreply@github.com>2024-11-02 06:44:56 +0800
commitec0c53b3da5484f1068e476a477d3f96a0a1a811 (patch)
tree97125a7596ea46b9e2f55d6b694c2fc7cbce886c /src/nvim/option.c
parent7bf3a616e18205d353d9c4a44e8c2f885d700129 (diff)
downloadrneovim-ec0c53b3da5484f1068e476a477d3f96a0a1a811.tar.gz
rneovim-ec0c53b3da5484f1068e476a477d3f96a0a1a811.tar.bz2
rneovim-ec0c53b3da5484f1068e476a477d3f96a0a1a811.zip
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.
Diffstat (limited to 'src/nvim/option.c')
-rw-r--r--src/nvim/option.c220
1 files changed, 116 insertions, 104 deletions
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;