diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
commit | 9be89f131f87608f224f0ee06d199fcd09d32176 (patch) | |
tree | 11022dcfa9e08cb4ac5581b16734196128688d48 /src/nvim/option.c | |
parent | ff7ed8f586589d620a806c3758fac4a47a8e7e15 (diff) | |
parent | 88085c2e80a7e3ac29aabb6b5420377eed99b8b6 (diff) | |
download | rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.gz rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.bz2 rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.zip |
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'src/nvim/option.c')
-rw-r--r-- | src/nvim/option.c | 140 |
1 files changed, 87 insertions, 53 deletions
diff --git a/src/nvim/option.c b/src/nvim/option.c index 22897d4f7e..ff0c0e2acf 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -44,6 +44,7 @@ #include "nvim/decoration_provider.h" #include "nvim/diff.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/vars.h" @@ -87,6 +88,7 @@ #include "nvim/os/os.h" #include "nvim/os/os_defs.h" #include "nvim/path.h" +#include "nvim/plines.h" #include "nvim/popupmenu.h" #include "nvim/pos_defs.h" #include "nvim/regexp.h" @@ -208,39 +210,53 @@ static void set_init_default_backupskip(void) OptIndex opt_idx = kOptBackupskip; ga_init(&ga, 1, 100); - for (size_t n = 0; n < ARRAY_SIZE(names); n++) { + for (size_t i = 0; i < ARRAY_SIZE(names); i++) { bool mustfree = true; char *p; + size_t plen; #ifdef UNIX - if (*names[n] == NUL) { + if (*names[i] == NUL) { # ifdef __APPLE__ p = "/private/tmp"; + plen = STRLEN_LITERAL("/private/tmp"); # else p = "/tmp"; + plen = STRLEN_LITERAL("/tmp"); # endif mustfree = false; } else #endif { - p = vim_getenv(names[n]); + p = vim_getenv(names[i]); + plen = 0; // will be calcuated below } if (p != NULL && *p != NUL) { - // First time count the NUL, otherwise count the ','. - const size_t len = strlen(p) + 3; - char *item = xmalloc(len); - xstrlcpy(item, p, len); - add_pathsep(item); - xstrlcat(item, "*", len); - if (find_dup_item(ga.ga_data, item, options[opt_idx].flags) - == NULL) { - ga_grow(&ga, (int)len); - if (!GA_EMPTY(&ga)) { - STRCAT(ga.ga_data, ","); + bool has_trailing_path_sep = false; + + if (plen == 0) { + // the value was retrieved from the environment + plen = strlen(p); + // does the value include a trailing path separator? + if (after_pathsep(p, p + plen)) { + has_trailing_path_sep = true; } - STRCAT(ga.ga_data, p); - add_pathsep(ga.ga_data); - STRCAT(ga.ga_data, "*"); - ga.ga_len += (int)len; + } + + // item size needs to be large enough to include "/*" and a trailing NUL + // note: the value (and therefore plen) may already include a path separator + size_t itemsize = plen + (has_trailing_path_sep ? 0 : 1) + 2; + char *item = xmalloc(itemsize); + // add a preceding comma as a separator after the first item + size_t itemseplen = (ga.ga_len == 0) ? 0 : 1; + + size_t itemlen = (size_t)vim_snprintf(item, itemsize, "%s%s*", p, + has_trailing_path_sep ? "" : PATHSEPSTR); + + if (find_dup_item(ga.ga_data, item, itemlen, options[opt_idx].flags) == NULL) { + ga_grow(&ga, (int)(itemseplen + itemlen + 1)); + ga.ga_len += vim_snprintf((char *)ga.ga_data + ga.ga_len, + itemseplen + itemlen + 1, + "%s%s", (itemseplen > 0) ? "," : "", item); } xfree(item); } @@ -524,7 +540,8 @@ static void set_string_default(OptIndex opt_idx, char *val, bool allocated) /// For an option value that contains comma separated items, find "newval" in /// "origval". Return NULL if not found. -static char *find_dup_item(char *origval, const char *newval, uint32_t flags) +static char *find_dup_item(char *origval, const char *newval, const size_t newvallen, + uint32_t flags) FUNC_ATTR_NONNULL_ARG(2) { if (origval == NULL) { @@ -533,11 +550,10 @@ static char *find_dup_item(char *origval, const char *newval, uint32_t flags) int bs = 0; - const size_t newlen = strlen(newval); for (char *s = origval; *s != NUL; s++) { if ((!(flags & P_COMMA) || s == origval || (s[-1] == ',' && !(bs & 1))) - && strncmp(s, newval, newlen) == 0 - && (!(flags & P_COMMA) || s[newlen] == ',' || s[newlen] == NUL)) { + && strncmp(s, newval, newvallen) == 0 + && (!(flags & P_COMMA) || s[newvallen] == ',' || s[newvallen] == NUL)) { return s; } // Count backslashes. Only a comma with an even number of backslashes @@ -695,10 +711,10 @@ void set_helplang_default(const char *lang) } p_hlg = xmemdupz(lang, lang_len); // zh_CN becomes "cn", zh_TW becomes "tw". - if (STRNICMP(p_hlg, "zh_", 3) == 0 && strlen(p_hlg) >= 5) { + if (STRNICMP(p_hlg, "zh_", 3) == 0 && lang_len >= 5) { p_hlg[0] = (char)TOLOWER_ASC(p_hlg[3]); p_hlg[1] = (char)TOLOWER_ASC(p_hlg[4]); - } else if (strlen(p_hlg) >= 1 && *p_hlg == 'C') { + } else if (lang_len && *p_hlg == 'C') { // any C like setting, such as C.UTF-8, becomes "en" p_hlg[0] = 'e'; p_hlg[1] = 'n'; @@ -948,7 +964,7 @@ static char *stropt_get_newval(int nextchar, OptIndex opt_idx, char **argp, void int len = 0; if (op == OP_REMOVING || (flags & P_NODUP)) { len = (int)strlen(newval); - s = find_dup_item(origval, newval, flags); + s = find_dup_item(origval, newval, (size_t)len, flags); // do not add if already there if ((op == OP_ADDING || op == OP_PREPENDING) && s != NULL) { @@ -1200,8 +1216,9 @@ static OptVal get_option_newval(OptIndex opt_idx, int opt_flags, set_prefix_T pr // Different ways to set a number option: // & set to default value // < set to global value - // <xx> accept special key codes for 'wildchar' - // c accept any non-digit for 'wildchar' + // <xx> accept special key codes for 'wildchar' or 'wildcharm' + // ^x accept ctrl key codes for 'wildchar' or 'wildcharm' + // c accept any non-digit for 'wildchar' or 'wildcharm' // [-]0-9 set number // other error arg++; @@ -1223,7 +1240,7 @@ static OptVal get_option_newval(OptIndex opt_idx, int opt_flags, set_prefix_T pr || (*arg != NUL && (!arg[1] || ascii_iswhite(arg[1])) && !ascii_isdigit(*arg)))) { newval_num = string_to_key(arg); - if (newval_num == 0 && (OptInt *)varp != &p_wcm) { + if (newval_num == 0) { *errmsg = e_invarg; return newval; } @@ -1462,11 +1479,10 @@ int do_set(char *arg, int opt_flags) } if (errmsg != NULL) { - xstrlcpy(IObuff, _(errmsg), IOSIZE); - int i = (int)strlen(IObuff) + 2; + int i = vim_snprintf((char *)IObuff, IOSIZE, "%s", _(errmsg)) + 2; if (i + (arg - startarg) < IOSIZE) { // append the argument with the error - xstrlcat(IObuff, ": ", IOSIZE); + xstrlcpy(IObuff + i - 2, ": ", (size_t)(IOSIZE - i + 2)); assert(arg >= startarg); memmove(IObuff + i, startarg, (size_t)(arg - startarg)); IObuff[i + (arg - startarg)] = NUL; @@ -1509,7 +1525,9 @@ static int find_key_len(const char *arg_arg, size_t len, bool has_lt) // Don't use get_special_key_code() for t_xx, we don't want it to call // add_termcap_entry(). if (len >= 4 && arg[0] == 't' && arg[1] == '_') { - key = TERMCAP2KEY((uint8_t)arg[2], (uint8_t)arg[3]); + if (!has_lt || arg[4] == '>') { + key = TERMCAP2KEY((uint8_t)arg[2], (uint8_t)arg[3]); + } } else if (has_lt) { arg--; // put arg at the '<' int modifiers = 0; @@ -1523,14 +1541,18 @@ static int find_key_len(const char *arg_arg, size_t len, bool has_lt) } /// Convert a key name or string into a key value. -/// Used for 'wildchar' and 'cedit' options. +/// Used for 'cedit', 'wildchar' and 'wildcharm' options. int string_to_key(char *arg) { - if (*arg == '<') { + if (*arg == '<' && arg[1]) { return find_key_len(arg + 1, strlen(arg), true); } - if (*arg == '^') { - return CTRL_CHR((uint8_t)arg[1]); + if (*arg == '^' && arg[1]) { + int key = CTRL_CHR((uint8_t)arg[1]); + if (key == 0) { // ^@ is <Nul> + key = K_ZERO; + } + return key; } return (uint8_t)(*arg); } @@ -2473,7 +2495,7 @@ static const char *did_set_scrollbind(optset_T *args) return NULL; } do_check_scrollbind(false); - win->w_scbind_pos = win->w_topline; + win->w_scbind_pos = get_vtopline(win); return NULL; } @@ -4569,6 +4591,8 @@ void *get_varp_scope_from(vimoption_T *p, int scope, buf_T *buf, win_T *win) return &(buf->b_p_def); case PV_INC: return &(buf->b_p_inc); + case PV_COT: + return &(buf->b_p_cot); case PV_DICT: return &(buf->b_p_dict); case PV_TSR: @@ -4652,6 +4676,8 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win) return *buf->b_p_def != NUL ? &(buf->b_p_def) : p->var; case PV_INC: return *buf->b_p_inc != NUL ? &(buf->b_p_inc) : p->var; + case PV_COT: + return *buf->b_p_cot != NUL ? &(buf->b_p_cot) : p->var; case PV_DICT: return *buf->b_p_dict != NUL ? &(buf->b_p_dict) : p->var; case PV_TSR: @@ -5078,6 +5104,12 @@ void clear_winopt(winopt_T *wop) void didset_window_options(win_T *wp, bool valid_cursor) { + // Set w_leftcol or w_skipcol to zero. + if (wp->w_p_wrap) { + wp->w_leftcol = 0; + } else { + wp->w_skipcol = 0; + } check_colorcolumn(wp); briopt_check(wp); fill_culopt_flags(NULL, wp); @@ -5335,6 +5367,8 @@ void buf_copy_options(buf_T *buf, int flags) buf->b_p_inc = empty_string_option; buf->b_p_inex = xstrdup(p_inex); COPY_OPT_SCTX(buf, BV_INEX); + buf->b_p_cot = empty_string_option; + buf->b_cot_flags = 0; buf->b_p_dict = empty_string_option; buf->b_p_tsr = empty_string_option; buf->b_p_tsrfu = empty_string_option; @@ -5427,7 +5461,8 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) xp->xp_pattern = arg; return; } - char *p = arg + strlen(arg) - 1; + char *const argend = arg + strlen(arg); + char *p = argend - 1; if (*p == ' ' && *(p - 1) != '\\') { xp->xp_pattern = p + 1; return; @@ -5614,7 +5649,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) // Triple-backslashed escaped file names (e.g. 'path') can also be // delimited by space. if ((flags & P_EXPAND) || (flags & P_COMMA) || (flags & P_COLON)) { - for (p = arg + strlen(arg) - 1; p > xp->xp_pattern; p--) { + for (p = argend - 1; p > xp->xp_pattern; p--) { // count number of backslashes before ' ' or ',' if (*p == ' ' || *p == ',' || (*p == ':' && (flags & P_COLON))) { char *s = p; @@ -5638,7 +5673,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) // An option that is a list of single-character flags should always start // at the end as we don't complete words. if (flags & P_FLAGLIST) { - xp->xp_pattern = arg + strlen(arg); + xp->xp_pattern = argend; } // Some options can either be using file/dir expansions, or custom value @@ -5948,7 +5983,7 @@ int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, c int count = 0; - (*matches)[count++] = xstrdup(option_val); + (*matches)[count++] = xmemdupz(option_val, num_flags); if (num_flags > 1) { // If more than one flags, split the flags up and expose each @@ -6189,10 +6224,10 @@ bool can_bs(int what) return vim_strchr(p_bs, what) != NULL; } -/// Get the local or global value of 'backupcopy'. +/// Get the local or global value of 'backupcopy' flags. /// /// @param buf The buffer. -unsigned get_bkc_value(buf_T *buf) +unsigned get_bkc_flags(buf_T *buf) { return buf->b_bkc_flags ? buf->b_bkc_flags : bkc_flags; } @@ -6208,7 +6243,7 @@ char *get_flp_value(buf_T *buf) return buf->b_p_flp; } -/// Get the local or global value of the 'virtualedit' flags. +/// Get the local or global value of 'virtualedit' flags. unsigned get_ve_flags(win_T *wp) { return (wp->w_ve_flags ? wp->w_ve_flags : ve_flags) & ~(VE_NONE | VE_NONEU); @@ -6420,30 +6455,29 @@ int get_sidescrolloff_value(win_T *wp) return (int)(wp->w_p_siso < 0 ? p_siso : wp->w_p_siso); } -Dictionary get_vimoption(String name, int scope, buf_T *buf, win_T *win, Arena *arena, Error *err) +Dict get_vimoption(String name, int scope, buf_T *buf, win_T *win, Arena *arena, Error *err) { OptIndex opt_idx = find_option_len(name.data, name.size); VALIDATE_S(opt_idx != kOptInvalid, "option (not found)", name.data, { - return (Dictionary)ARRAY_DICT_INIT; + return (Dict)ARRAY_DICT_INIT; }); return vimoption2dict(&options[opt_idx], scope, buf, win, arena); } -Dictionary get_all_vimoptions(Arena *arena) +Dict get_all_vimoptions(Arena *arena) { - Dictionary retval = arena_dict(arena, kOptIndexCount); + Dict retval = arena_dict(arena, kOptIndexCount); for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) { - Dictionary opt_dict = vimoption2dict(&options[opt_idx], OPT_GLOBAL, curbuf, curwin, arena); - PUT_C(retval, options[opt_idx].fullname, DICTIONARY_OBJ(opt_dict)); + Dict opt_dict = vimoption2dict(&options[opt_idx], OPT_GLOBAL, curbuf, curwin, arena); + PUT_C(retval, options[opt_idx].fullname, DICT_OBJ(opt_dict)); } return retval; } -static Dictionary vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, win_T *win, - Arena *arena) +static Dict vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, win_T *win, Arena *arena) { - Dictionary dict = arena_dict(arena, 13); + Dict dict = arena_dict(arena, 13); PUT_C(dict, "name", CSTR_AS_OBJ(opt->fullname)); PUT_C(dict, "shortname", CSTR_AS_OBJ(opt->shortname)); |