diff options
author | Famiu Haque <famiuhaque@proton.me> | 2024-11-02 04:44:56 +0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-02 06:44:56 +0800 |
commit | ec0c53b3da5484f1068e476a477d3f96a0a1a811 (patch) | |
tree | 97125a7596ea46b9e2f55d6b694c2fc7cbce886c /src/nvim/option.c | |
parent | 7bf3a616e18205d353d9c4a44e8c2f885d700129 (diff) | |
download | rneovim-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.c | 220 |
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; |