From f15947866ce59589346a4074a1fdc10f941a16b5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 07:46:51 +0800 Subject: vim-patch:9.0.1243: :setglobal cannot use script-local function for "expr" option (#21997) Problem: :setglobal cannot use script-local function for "expr" option. Solution: Use the pointer to the option value properly. (closes vim/vim#11883) https://github.com/vim/vim/commit/01d4efe2e87632aa085897d3d64e27585908f977 --- src/nvim/optionstr.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index a5a708600f..162d8b691a 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1497,12 +1497,12 @@ static void did_set_vartabstop(buf_T *buf, win_T *win, char **varp, char **errms } } -static void did_set_optexpr(win_T *win, char **p_opt, char **varp, char **gvarp) +static void did_set_optexpr(char **varp) { - char *name = get_scriptlocal_funcname(*p_opt); + char *name = get_scriptlocal_funcname(*varp); if (name != NULL) { - free_string_option(*p_opt); - *p_opt = name; + free_string_option(*varp); + *varp = name; } } @@ -1808,23 +1808,18 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char did_set_varsoftabstop(buf, varp, &errmsg); } else if (varp == &buf->b_p_vts) { // 'vartabstop' did_set_vartabstop(buf, win, varp, &errmsg); - } else if (varp == &p_dex) { // 'diffexpr' - did_set_optexpr(win, &p_dex, varp, gvarp); - } else if (varp == &win->w_p_fde) { // 'foldexpr' - did_set_optexpr(win, &win->w_p_fde, varp, gvarp); - if (foldmethodIsExpr(win)) { + } else if (varp == &p_dex // 'diffexpr' + || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr' + || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext' + || gvarp == &p_fex // 'formatexpr' + || gvarp == &p_inex // 'includeexpr' + || gvarp == &p_inde // 'indentexpr' + || varp == &p_pex // 'patchexpr' + || varp == &p_ccv) { // 'charconvert' + did_set_optexpr(varp); + if (varp == &win->w_p_fde && foldmethodIsExpr(win)) { foldUpdateAll(win); } - } else if (varp == &win->w_p_fdt) { // 'foldtext' - did_set_optexpr(win, &win->w_p_fdt, varp, gvarp); - } else if (varp == &p_pex) { // 'patchexpr' - did_set_optexpr(win, &p_pex, varp, gvarp); - } else if (gvarp == &p_fex) { // 'formatexpr' - did_set_optexpr(win, &buf->b_p_fex, varp, gvarp); - } else if (gvarp == &p_inex) { // 'includeexpr' - did_set_optexpr(win, &buf->b_p_inex, varp, gvarp); - } else if (gvarp == &p_inde) { // 'indentexpr' - did_set_optexpr(win, &buf->b_p_inde, varp, gvarp); } else if (gvarp == &p_cfu) { // 'completefunc' set_completefunc_option(&errmsg); } else if (gvarp == &p_ofu) { // 'omnifunc' -- cgit From 116766f243b4ac647f040181334c8001e01aab75 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 09:12:33 +0800 Subject: refactor(options): don't pass negative number to illegal_char() (#21999) This only changes the error messages for an unexpected Unicode char in an option to show its first byte instead of some special keycode. The second argument of vim_strchr() usually doesn't matter, but it may be better to consistently cast to uint8_t. --- src/nvim/optionstr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 162d8b691a..5ebff9ed77 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -615,7 +615,7 @@ char *check_stl_option(char *s) continue; } if (vim_strchr(STL_ALL, (uint8_t)(*s)) == NULL) { - return illegal_char(errbuf, sizeof(errbuf), *s); + return illegal_char(errbuf, sizeof(errbuf), (uint8_t)(*s)); } if (*s == '{') { bool reevaluate = (*++s == '%'); @@ -957,7 +957,7 @@ static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, char * while (*s && *s != ':') { if (vim_strchr(COM_ALL, (uint8_t)(*s)) == NULL && !ascii_isdigit(*s) && *s != '-') { - *errmsg = illegal_char(errbuf, errbuflen, *s); + *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); break; } s++; @@ -1029,7 +1029,7 @@ static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, ch for (char *s = p_shada; *s;) { // Check it's a valid character if (vim_strchr("!\"%'/:<@cfhnrs", (uint8_t)(*s)) == NULL) { - *errmsg = illegal_char(errbuf, errbuflen, *s); + *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); break; } if (*s == 'n') { // name is always last one @@ -1236,7 +1236,7 @@ static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, char * break; } if (vim_strchr(".wbuksid]tU", (uint8_t)(*s)) == NULL) { - *errmsg = illegal_char(errbuf, errbuflen, *s); + *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); break; } if (*++s != NUL && *s != ',' && *s != ' ') { @@ -1511,8 +1511,8 @@ static void did_set_option_listflag(char **varp, char *flags, char *errbuf, size char **errmsg) { for (char *s = *varp; *s; s++) { - if (vim_strchr(flags, *s) == NULL) { - *errmsg = illegal_char(errbuf, errbuflen, *s); + if (vim_strchr(flags, (uint8_t)(*s)) == NULL) { + *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); break; } } -- cgit From 4c90a84c61d19e5131579b2c38960de3ec8e4a5e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 29 Jan 2023 07:42:22 +0800 Subject: vim-patch:9.0.1255: changing 'virtualedit' does not have immediate effect (#22039) Problem: Changing 'virtualedit' does not have immediate effect. Solution: Correct how is checked for a changed value. (closes vim/vim#11878) https://github.com/vim/vim/commit/8fe5b9c8c1223861cec0484ccc031858ae08d107 Co-authored-by: Bram Moolenaar --- src/nvim/optionstr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 5ebff9ed77..30afb0db37 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1404,10 +1404,11 @@ static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, char ** } else { if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) { *errmsg = e_invarg; - } else if (strcmp(p_ve, oldval) != 0) { + } else if (strcmp(ve, oldval) != 0) { // Recompute cursor position in case the new 've' setting // changes something. validate_virtcol_win(win); + // XXX: this only works when win == curwin coladvance(win->w_virtcol); } } -- cgit From 249b9de4056d0e0a57c59bc533a0cf2b96c42436 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 1 Feb 2023 08:17:18 +0800 Subject: refactor(optionstr.c): align comments (#22070) Align comments in did_set_string_option_for() at column 57. --- src/nvim/optionstr.c | 276 ++++++++++++++++++++++++++------------------------- 1 file changed, 143 insertions(+), 133 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 30afb0db37..ca50c3ab00 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -638,13 +638,11 @@ char *check_stl_option(char *s) return NULL; } -static int shada_idx = -1; - +/// Check for a "normal" directory or file name in some options. Disallow a +/// path separator (slash and/or backslash), wildcards and characters that are +/// often illegal in a file name. Be more permissive if "secure" is off. static bool check_illegal_path_names(char *val, uint32_t flags) { - // Disallow a path separator (slash and/or backslash), wildcards and - // characters that are often illegal in a file name. Be more permissive - // if "secure" is off. return (((flags & P_NFNAME) && strpbrk(val, (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL) || ((flags & P_NDNAME) @@ -701,8 +699,8 @@ static void did_set_breakindentopt(win_T *win, char **errmsg) static void did_set_isopt(buf_T *buf, bool *did_chartab, char **errmsg) { // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[] - // If the new option is invalid, use old value. 'lisp' option: refill - // g_chartab[] for '-' char + // If the new option is invalid, use old value. + // 'lisp' option: refill g_chartab[] for '-' char if (buf_init_chartab(buf, true) == FAIL) { *did_chartab = true; // need to restore it below *errmsg = e_invarg; // error in value @@ -1013,6 +1011,8 @@ static void did_set_verbosefile(char **errmsg) } } +static int shada_idx = -1; + static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, size_t errbuflen, char **errmsg) { @@ -1272,6 +1272,16 @@ static void did_set_completeopt(char **errmsg) } } +#ifdef BACKSLASH_IN_FILENAME +static void did_set_completeslash(buf_T *buf, char **errmsg) +{ + if (check_opt_strings(p_csl, p_csl_values, false) != OK + || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) { + *errmsg = e_invarg; + } +} +#endif + static void did_set_signcolumn(win_T *win, char **varp, const char *oldval, char **errmsg) { if (check_signcolumn(*varp) != OK) { @@ -1561,7 +1571,7 @@ static void do_filetype_autocmd(buf_T *buf, char **varp, int opt_flags, bool val } } -static void did_set_spelllang_source(win_T *win) +static void do_spelllang_source(win_T *win) { char fname[200]; char *q = win->w_s->b_p_spl; @@ -1614,238 +1624,238 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char char **gvarp = (char **)get_varp_scope(opt, OPT_GLOBAL); // Disallow changing some options from secure mode - if ((secure || sandbox != 0) - && (opt->flags & P_SECURE)) { + if ((secure || sandbox != 0) && (opt->flags & P_SECURE)) { errmsg = e_secure; - } else if (check_illegal_path_names(*varp, opt->flags)) { // Check for a "normal" directory or file name in some options. + } else if (check_illegal_path_names(*varp, opt->flags)) { errmsg = e_invarg; - } else if (gvarp == &p_bkc) { // 'backupcopy' + } else if (gvarp == &p_bkc) { // 'backupcopy' did_set_backupcopy(buf, oldval, opt_flags, &errmsg); - } else if (varp == &p_bex || varp == &p_pm) { // 'backupext' and 'patchmode' + } else if (varp == &p_bex // 'backupext' + || varp == &p_pm) { // 'patchmode' did_set_backupext_or_patchmode(&errmsg); - } else if (varp == &win->w_p_briopt) { // 'breakindentopt' + } else if (varp == &win->w_p_briopt) { // 'breakindentopt' did_set_breakindentopt(win, &errmsg); - } else if (varp == &p_isi - || varp == &buf->b_p_isk - || varp == &p_isp - || varp == &p_isf) { - // 'isident', 'iskeyword', 'isprint or 'isfname' option + } else if (varp == &p_isi // 'isident' + || varp == &buf->b_p_isk // 'iskeyword' + || varp == &p_isp // 'isprint' + || varp == &p_isf) { // 'isfname' did_set_isopt(buf, &did_chartab, &errmsg); - } else if (varp == &p_hf) { // 'helpfile' + } else if (varp == &p_hf) { // 'helpfile' did_set_helpfile(); - } else if (varp == &p_rtp || varp == &p_pp) { // 'runtimepath' 'packpath' + } else if (varp == &p_rtp // 'runtimepath' + || varp == &p_pp) { // 'packpath' runtime_search_path_invalidate(); - } else if (varp == &win->w_p_culopt - || gvarp == &win->w_allbuf_opt.wo_culopt) { // 'cursorlineopt' + } else if (gvarp == &win->w_allbuf_opt.wo_culopt) { // 'cursorlineopt' did_set_cursorlineopt(win, varp, &errmsg); - } else if (varp == &win->w_p_cc) { // 'colorcolumn' + } else if (varp == &win->w_p_cc) { // 'colorcolumn' errmsg = check_colorcolumn(win); - } else if (varp == &p_hlg) { // 'helplang' + } else if (varp == &p_hlg) { // 'helplang' did_set_helplang(&errmsg); - } else if (varp == &p_hl) { // 'highlight' + } else if (varp == &p_hl) { // 'highlight' did_set_highlight(varp, &errmsg); - } else if (varp == &p_jop) { // 'jumpoptions' + } else if (varp == &p_jop) { // 'jumpoptions' did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true, &errmsg); - } else if (gvarp == &p_nf) { // 'nrformats' + } else if (gvarp == &p_nf) { // 'nrformats' did_set_opt_strings(*varp, p_nf_values, true, &errmsg); - } else if (varp == &p_ssop) { // 'sessionoptions' + } else if (varp == &p_ssop) { // 'sessionoptions' did_set_sessionoptions(oldval, &errmsg); - } else if (varp == &p_vop) { // 'viewoptions' + } else if (varp == &p_vop) { // 'viewoptions' did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, true, &errmsg); - } else if (varp == &p_rdb) { // 'redrawdebug' + } else if (varp == &p_rdb) { // 'redrawdebug' did_set_opt_flags(p_rdb, p_rdb_values, &rdb_flags, true, &errmsg); - } else if (varp == &p_sbo) { // 'scrollopt' + } else if (varp == &p_sbo) { // 'scrollopt' did_set_opt_strings(p_sbo, p_scbopt_values, true, &errmsg); - } else if (varp == &p_ambw || (int *)varp == &p_emoji) { // 'ambiwidth' + } else if (varp == &p_ambw // 'ambiwidth' + || (int *)varp == &p_emoji) { // 'emoji' did_set_ambiwidth(&errmsg); - } else if (varp == &p_bg) { // 'background' + } else if (varp == &p_bg) { // 'background' did_set_background(&errmsg); - } else if (varp == &p_wim) { // 'wildmode' + } else if (varp == &p_wim) { // 'wildmode' did_set_wildmode(&errmsg); - } else if (varp == &p_wop) { // 'wildoptions' + } else if (varp == &p_wop) { // 'wildoptions' did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true, &errmsg); - } else if (varp == &p_wak) { // 'winaltkeys' + } else if (varp == &p_wak) { // 'winaltkeys' did_set_winaltkeys(&errmsg); - } else if (varp == &p_ei) { // 'eventignore' + } else if (varp == &p_ei) { // 'eventignore' did_set_eventignore(&errmsg); - } else if (varp == &p_enc || gvarp == &p_fenc || gvarp == &p_menc) { - // 'encoding', 'fileencoding' and 'makeencoding' + } else if (varp == &p_enc // 'encoding' + || gvarp == &p_fenc // 'fileencoding' + || gvarp == &p_menc) { // 'makeencoding' did_set_encoding(buf, varp, gvarp, opt_flags, &errmsg); - } else if (varp == &buf->b_p_keymap) { + } else if (varp == &buf->b_p_keymap) { // 'keymap' did_set_keymap(buf, varp, opt_flags, value_checked, &errmsg); - } else if (gvarp == &p_ff) { // 'fileformat' + } else if (gvarp == &p_ff) { // 'fileformat' did_set_fileformat(buf, varp, oldval, opt_flags, &errmsg); - } else if (varp == &p_ffs) { // 'fileformats' + } else if (varp == &p_ffs) { // 'fileformats' did_set_opt_strings(p_ffs, p_ff_values, true, &errmsg); - } else if (gvarp == &p_mps) { // 'matchpairs' + } else if (gvarp == &p_mps) { // 'matchpairs' did_set_matchpairs(varp, &errmsg); - } else if (gvarp == &p_com) { // 'comments' + } else if (gvarp == &p_com) { // 'comments' did_set_comments(varp, errbuf, errbuflen, &errmsg); - } else if (varp == &p_lcs || varp == &p_fcs) { // global 'listchars' or 'fillchars' + } else if (varp == &p_lcs // global 'listchars' + || varp == &p_fcs) { // global 'fillchars' did_set_global_listfillchars(win, varp, opt_flags, &errmsg); - } else if (varp == &win->w_p_lcs) { // local 'listchars' + } else if (varp == &win->w_p_lcs) { // local 'listchars' errmsg = set_chars_option(win, varp, true); - } else if (varp == &win->w_p_fcs) { // local 'fillchars' + } else if (varp == &win->w_p_fcs) { // local 'fillchars' errmsg = set_chars_option(win, varp, true); - } else if (varp == &p_cedit) { // 'cedit' + } else if (varp == &p_cedit) { // 'cedit' errmsg = check_cedit(); - } else if (varp == &p_vfile) { // 'verbosefile' + } else if (varp == &p_vfile) { // 'verbosefile' did_set_verbosefile(&errmsg); - } else if (varp == &p_shada) { // 'shada' + } else if (varp == &p_shada) { // 'shada' did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen, &errmsg); - } else if (gvarp == &p_sbr) { // 'showbreak' + } else if (gvarp == &p_sbr) { // 'showbreak' did_set_showbreak(varp, &errmsg); - } else if (varp == &p_guicursor) { // 'guicursor' + } else if (varp == &p_guicursor) { // 'guicursor' errmsg = parse_shape_opt(SHAPE_CURSOR); - } else if (varp == &p_langmap) { // 'langmap' + } else if (varp == &p_langmap) { // 'langmap' langmap_set(); - } else if (varp == &p_breakat) { // 'breakat' + } else if (varp == &p_breakat) { // 'breakat' fill_breakat_flags(); - } else if (varp == &p_titlestring || varp == &p_iconstring) { - // 'titlestring' and 'iconstring' + } else if (varp == &p_titlestring // 'titlestring' + || varp == &p_iconstring) { // 'iconstring' did_set_titleiconstring(varp); - } else if (varp == &p_sel) { // 'selection' + } else if (varp == &p_sel) { // 'selection' did_set_selection(&errmsg); - } else if (varp == &p_slm) { // 'selectmode' + } else if (varp == &p_slm) { // 'selectmode' did_set_opt_strings(p_slm, p_slm_values, true, &errmsg); - } else if (varp == &p_km) { // 'keymodel' + } else if (varp == &p_km) { // 'keymodel' did_set_keymodel(&errmsg); - } else if (varp == &p_mousem) { // 'mousemodel' + } else if (varp == &p_mousem) { // 'mousemodel' did_set_opt_strings(p_mousem, p_mousem_values, false, &errmsg); - } else if (varp == &p_mousescroll) { // 'mousescroll' + } else if (varp == &p_mousescroll) { // 'mousescroll' errmsg = check_mousescroll(p_mousescroll); - } else if (varp == &p_swb) { // 'switchbuf' + } else if (varp == &p_swb) { // 'switchbuf' did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true, &errmsg); - } else if (varp == &p_spk) { // 'splitkeep' + } else if (varp == &p_spk) { // 'splitkeep' did_set_opt_strings(p_spk, p_spk_values, false, &errmsg); - } else if (varp == &p_debug) { // 'debug' + } else if (varp == &p_debug) { // 'debug' did_set_opt_strings(p_debug, p_debug_values, true, &errmsg); - } else if (varp == &p_dy) { // 'display' + } else if (varp == &p_dy) { // 'display' did_set_display(&errmsg); - } else if (varp == &p_ead) { // 'eadirection' + } else if (varp == &p_ead) { // 'eadirection' did_set_opt_strings(p_ead, p_ead_values, false, &errmsg); - } else if (varp == &p_cb) { // 'clipboard' + } else if (varp == &p_cb) { // 'clipboard' did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true, &errmsg); - } else if (varp == &win->w_s->b_p_spf) { + } else if (varp == &win->w_s->b_p_spf) { // 'spellfile' did_set_spellfile(varp, &errmsg); - } else if (varp == &win->w_s->b_p_spl) { // 'spell' + } else if (varp == &win->w_s->b_p_spl) { // 'spell' did_set_spell(varp, &errmsg); - } else if (varp == &win->w_s->b_p_spc) { + } else if (varp == &win->w_s->b_p_spc) { // 'spellcapcheck' did_set_spellcapcheck(win, &errmsg); - } else if (varp == &win->w_s->b_p_spo) { // 'spelloptions' + } else if (varp == &win->w_s->b_p_spo) { // 'spelloptions' did_set_spelloptions(win, &errmsg); - } else if (varp == &p_sps) { // 'spellsuggest' + } else if (varp == &p_sps) { // 'spellsuggest' did_set_spellsuggest(&errmsg); - } else if (varp == &p_msm) { // 'mkspellmem' + } else if (varp == &p_msm) { // 'mkspellmem' did_set_mkspellmem(&errmsg); - } else if (gvarp == &p_bh) { + } else if (gvarp == &p_bh) { // 'bufhidden' did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false, &errmsg); - } else if (gvarp == &p_bt) { // 'buftype' + } else if (gvarp == &p_bt) { // 'buftype' did_set_buftype(buf, win, &errmsg); - } else if (gvarp == &p_stl || gvarp == &p_wbr || varp == &p_tal - || varp == &p_ruf || varp == &win->w_p_stc) { - // 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn' + } else if (gvarp == &p_stl // 'statusline' + || gvarp == &p_wbr // 'winbar' + || varp == &p_tal // 'tabline' + || varp == &p_ruf // 'rulerformat' + || varp == &win->w_p_stc) { // 'statuscolumn' did_set_statusline(win, varp, gvarp, &errmsg); - } else if (gvarp == &p_cpt) { // 'complete' + } else if (gvarp == &p_cpt) { // 'complete' did_set_complete(varp, errbuf, errbuflen, &errmsg); - } else if (varp == &p_cot) { // 'completeopt' + } else if (varp == &p_cot) { // 'completeopt' did_set_completeopt(&errmsg); #ifdef BACKSLASH_IN_FILENAME - } else if (gvarp == &p_csl) { // 'completeslash' - if (check_opt_strings(p_csl, p_csl_values, false) != OK - || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) { - errmsg = e_invarg; - } + } else if (gvarp == &p_csl) { // 'completeslash' + did_set_completeslash(buf, &errmsg); #endif - } else if (varp == &win->w_p_scl) { // 'signcolumn' + } else if (varp == &win->w_p_scl) { // 'signcolumn' did_set_signcolumn(win, varp, oldval, &errmsg); - } else if (varp == &p_sloc) { // 'showcmdloc' + } else if (varp == &p_sloc) { // 'showcmdloc' did_set_opt_strings(*varp, p_sloc_values, false, &errmsg); - } else if (varp == &win->w_p_fdc - || varp == &win->w_allbuf_opt.wo_fdc) { - // 'foldcolumn' + } else if (gvarp == &win->w_allbuf_opt.wo_fdc) { // 'foldcolumn' did_set_foldcolumn(varp, &errmsg); - } else if (varp == &p_pt) { // 'pastetoggle' + } else if (varp == &p_pt) { // 'pastetoggle' did_set_pastetoggle(); - } else if (varp == &p_bs) { // 'backspace' + } else if (varp == &p_bs) { // 'backspace' did_set_backspace(&errmsg); } else if (varp == &p_bo) { did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true, &errmsg); - } else if (gvarp == &p_tc) { // 'tagcase' + } else if (gvarp == &p_tc) { // 'tagcase' did_set_tagcase(buf, opt_flags, &errmsg); - } else if (varp == &p_cmp) { // 'casemap' + } else if (varp == &p_cmp) { // 'casemap' did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true, &errmsg); - } else if (varp == &p_dip) { // 'diffopt' + } else if (varp == &p_dip) { // 'diffopt' did_set_diffopt(&errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fdm) { // 'foldmethod' + } else if (gvarp == &win->w_allbuf_opt.wo_fdm) { // 'foldmethod' did_set_foldmethod(win, varp, &errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fmr) { // 'foldmarker' + } else if (gvarp == &win->w_allbuf_opt.wo_fmr) { // 'foldmarker' did_set_foldmarker(win, varp, &errmsg); - } else if (gvarp == &p_cms) { // 'commentstring' + } else if (gvarp == &p_cms) { // 'commentstring' did_set_commentstring(varp, &errmsg); - } else if (varp == &p_fdo) { // 'foldopen' + } else if (varp == &p_fdo) { // 'foldopen' did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true, &errmsg); - } else if (varp == &p_fcl) { // 'foldclose' + } else if (varp == &p_fcl) { // 'foldclose' did_set_opt_strings(*varp, p_fcl_values, true, &errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fdi) { // 'foldignore' + } else if (gvarp == &win->w_allbuf_opt.wo_fdi) { // 'foldignore' did_set_foldignore(win); - } else if (gvarp == &p_ve) { // 'virtualedit' + } else if (gvarp == &p_ve) { // 'virtualedit' did_set_virtualedit(win, opt_flags, oldval, &errmsg); - } else if (gvarp == &p_cino) { // 'cinoptions' + } else if (gvarp == &p_cino) { // 'cinoptions' // TODO(vim): recognize errors parse_cino(buf); - } else if (gvarp == &p_lop) { // 'lispoptions' + } else if (gvarp == &p_lop) { // 'lispoptions' did_set_lispoptions(varp, &errmsg); - } else if (varp == &p_icm) { // 'inccommand' + } else if (varp == &p_icm) { // 'inccommand' did_set_opt_strings(*varp, p_icm_values, false, &errmsg); - } else if (gvarp == &p_ft || gvarp == &p_syn) { + } else if (gvarp == &p_ft // 'filetype' + || gvarp == &p_syn) { // 'syntax' did_set_filetype_or_syntax(varp, oldval, value_checked, &value_changed, &errmsg); - } else if (varp == &win->w_p_winhl) { + } else if (varp == &win->w_p_winhl) { // 'winhighlight' did_set_winhl(win, &errmsg); } else if (varp == &p_tpf) { did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true, &errmsg); - } else if (varp == &buf->b_p_vsts) { // 'varsofttabstop' + } else if (varp == &buf->b_p_vsts) { // 'varsofttabstop' did_set_varsoftabstop(buf, varp, &errmsg); - } else if (varp == &buf->b_p_vts) { // 'vartabstop' + } else if (varp == &buf->b_p_vts) { // 'vartabstop' did_set_vartabstop(buf, win, varp, &errmsg); - } else if (varp == &p_dex // 'diffexpr' - || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr' - || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext' - || gvarp == &p_fex // 'formatexpr' - || gvarp == &p_inex // 'includeexpr' - || gvarp == &p_inde // 'indentexpr' - || varp == &p_pex // 'patchexpr' - || varp == &p_ccv) { // 'charconvert' + } else if (varp == &p_dex // 'diffexpr' + || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr' + || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext' + || gvarp == &p_fex // 'formatexpr' + || gvarp == &p_inex // 'includeexpr' + || gvarp == &p_inde // 'indentexpr' + || varp == &p_pex // 'patchexpr' + || varp == &p_ccv) { // 'charconvert' did_set_optexpr(varp); if (varp == &win->w_p_fde && foldmethodIsExpr(win)) { foldUpdateAll(win); } - } else if (gvarp == &p_cfu) { // 'completefunc' + } else if (gvarp == &p_cfu) { // 'completefunc' set_completefunc_option(&errmsg); - } else if (gvarp == &p_ofu) { // 'omnifunc' + } else if (gvarp == &p_ofu) { // 'omnifunc' set_omnifunc_option(buf, &errmsg); - } else if (gvarp == &p_tsrfu) { // 'thesaurusfunc' + } else if (gvarp == &p_tsrfu) { // 'thesaurusfunc' set_thesaurusfunc_option(&errmsg); - } else if (varp == &p_opfunc) { // 'operatorfunc' + } else if (varp == &p_opfunc) { // 'operatorfunc' set_operatorfunc_option(&errmsg); - } else if (varp == &p_qftf) { // 'quickfixtextfunc' + } else if (varp == &p_qftf) { // 'quickfixtextfunc' qf_process_qftf_option(&errmsg); - } else if (gvarp == &p_tfu) { // 'tagfunc' + } else if (gvarp == &p_tfu) { // 'tagfunc' set_tagfunc_option(&errmsg); - } else if (varp == &p_ww) { // 'whichwrap' + } else if (varp == &p_ww) { // 'whichwrap' did_set_option_listflag(varp, WW_ALL, errbuf, errbuflen, &errmsg); - } else if (varp == &p_shm) { // 'shortmess' + } else if (varp == &p_shm) { // 'shortmess' did_set_option_listflag(varp, SHM_ALL, errbuf, errbuflen, &errmsg); - } else if (varp == &p_cpo) { // 'cpoptions' + } else if (varp == &p_cpo) { // 'cpoptions' did_set_option_listflag(varp, CPO_VI, errbuf, errbuflen, &errmsg); - } else if (varp == &buf->b_p_fo) { // 'formatoptions' + } else if (varp == &buf->b_p_fo) { // 'formatoptions' did_set_option_listflag(varp, FO_ALL, errbuf, errbuflen, &errmsg); - } else if (varp == &win->w_p_cocu) { // 'concealcursor' + } else if (varp == &win->w_p_cocu) { // 'concealcursor' did_set_option_listflag(varp, COCU_ALL, errbuf, errbuflen, &errmsg); - } else if (varp == &p_mouse) { // 'mouse' + } else if (varp == &p_mouse) { // 'mouse' did_set_option_listflag(varp, MOUSE_ALL, errbuf, errbuflen, &errmsg); - } else if (gvarp == &p_flp) { + } else if (gvarp == &p_flp) { // 'formatlistpat' if (win->w_briopt_list) { // Changing Formatlistpattern when briopt includes the list setting: // redraw @@ -1853,7 +1863,7 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char } } - // If error detected, restore the previous value. + // If an error is detected, restore the previous value. if (errmsg != NULL) { free_string_option(*varp); *varp = oldval; @@ -1890,7 +1900,7 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char } else if (varp == &buf->b_p_ft) { do_filetype_autocmd(buf, varp, opt_flags, value_changed); } else if (varp == &win->w_s->b_p_spl) { - did_set_spelllang_source(win); + do_spelllang_source(win); } } -- cgit From e1f03c481a1cf87cead2c5af66b36dbdfbb9a983 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Mon, 6 Feb 2023 10:01:38 +0100 Subject: feat(spell): also source `spell/LANG.lua` when setting `spelllang` (#22111) Problem: only Vimscript files are sourced when setting spelling language Solution: also source Lua files after sourcing Vimscript files Closes #22110 --- src/nvim/optionstr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index ca50c3ab00..901477d869 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1581,7 +1581,7 @@ static void do_spelllang_source(win_T *win) q += 4; } - // Source the spell/LANG.vim in 'runtimepath'. + // Source the spell/LANG.{vim,lua} in 'runtimepath'. // They could set 'spellcapcheck' depending on the language. // Use the first name in 'spelllang' up to '_region' or // '.encoding'. @@ -1592,7 +1592,7 @@ static void do_spelllang_source(win_T *win) } } if (p > q) { - vim_snprintf(fname, sizeof(fname), "spell/%.*s.vim", (int)(p - q), q); + vim_snprintf(fname, sizeof(fname), "spell/%.*s.\\(vim\\|lua\\)", (int)(p - q), q); source_runtime(fname, DIP_ALL); } } -- cgit From 625e990976540a0e2d2bccb98deb57d0919d1e89 Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 8 Feb 2023 16:16:16 +0100 Subject: refactor(ui): cleanup 'redrawdebug', introduce "flush" mode --- src/nvim/optionstr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 901477d869..7efbeadb2f 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -125,7 +125,8 @@ static char *(p_spo_values[]) = { "camel", "noplainbuffer", NULL }; static char *(p_icm_values[]) = { "nosplit", "split", NULL }; static char *(p_jop_values[]) = { "stack", "view", NULL }; static char *(p_tpf_values[]) = { "BS", "HT", "FF", "ESC", "DEL", "C0", "C1", NULL }; -static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelta", NULL }; +static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelta", "line", + "flush", NULL }; static char *(p_sloc_values[]) = { "last", "statusline", "tabline", NULL }; /// All possible flags for 'shm'. -- cgit From 27177e581902967dcf4f2f426464da1b636ca420 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 11 Feb 2023 14:14:24 +0100 Subject: refactor: reduce scope of locals as per the style guide (#22211) --- src/nvim/optionstr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 7efbeadb2f..5f8514b1a6 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -330,7 +330,6 @@ void set_string_option_direct(const char *name, int opt_idx, const char *val, in int set_sid) { char *s; - char **varp; int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; int idx = opt_idx; @@ -353,7 +352,7 @@ void set_string_option_direct(const char *name, int opt_idx, const char *val, in s = xstrdup(val); { - varp = (char **)get_varp_scope(opt, both ? OPT_LOCAL : opt_flags); + char **varp = (char **)get_varp_scope(opt, both ? OPT_LOCAL : opt_flags); if ((opt_flags & OPT_FREE) && (opt->flags & P_ALLOCED)) { free_string_option(*varp); } -- cgit From 20c9f4b3521fa7ab5c5997c0ec1a3df2b5bd0dbe Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 14 Feb 2023 08:29:05 +0800 Subject: vim-patch:9.0.1307: setting 'formatoptions' with :let doesn't check for errors (#22252) Problem: Setting 'formatoptions' with :let doesn't check for errors. Solution: Pass "errbuf" to set_string_option(). (Yegappan Lakshmanan, closes vim/vim#11974, closes vim/vim#11972) https://github.com/vim/vim/commit/32ff96ef018eb1a5bea0953648b4892a6ee71658 Co-authored-by: Yegappan Lakshmanan --- src/nvim/optionstr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 5f8514b1a6..f903ad3d09 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -410,7 +410,8 @@ void set_string_option_direct_in_win(win_T *wp, const char *name, int opt_idx, c /// #OPT_GLOBAL. /// /// @return NULL on success, an untranslated error message on error. -char *set_string_option(const int opt_idx, const char *const value, const int opt_flags) +char *set_string_option(const int opt_idx, const char *const value, const int opt_flags, + char *const errbuf, const size_t errbuflen) FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_WARN_UNUSED_RESULT { vimoption_T *opt = get_option(opt_idx); @@ -442,7 +443,7 @@ char *set_string_option(const int opt_idx, const char *const value, const int op int value_checked = false; char *const errmsg = did_set_string_option(opt_idx, varp, oldval, - NULL, 0, + errbuf, errbuflen, opt_flags, &value_checked); if (errmsg == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); -- cgit From bf4eada2c83f5402fc56370fd22af11029a4a3aa Mon Sep 17 00:00:00 2001 From: luukvbaal <31730729+luukvbaal@users.noreply.github.com> Date: Tue, 7 Mar 2023 01:45:08 +0100 Subject: fix(column): issues with 'statuscolumn' width (#22542) Problem: 'statuscolumn' width can be incorrect when toggling 'number' or setting 'statuscolumn'. Solution: Make sure the width is reset and re-estimated when 'statuscolumn' and 'number' are set. (When 'relativenumber' is set this already happens because it always changes "nrwidth_line_count".) --- src/nvim/optionstr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index f903ad3d09..b335e255a4 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1199,6 +1199,7 @@ static void did_set_statusline(win_T *win, char **varp, char **gvarp, char **err ru_wid = 0; } else if (varp == &win->w_p_stc) { win->w_nrwidth_line_count = 0; + win->w_statuscol_line_count = 0; } char *s = *varp; if (varp == &p_ruf && *s == '%') { -- cgit From fe11079721084b3638ae3d8e5266f95d52028fb7 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Wed, 8 Mar 2023 12:36:03 +0100 Subject: perf(statusline): UI elements are always redrawn on K_EVENT Problem: 'statusline'-format UI elements are redrawn on each K_EVENT. Solution: Only redraw UI elements when something relevant has changed. --- src/nvim/optionstr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index b335e255a4..0774baf2d8 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -49,6 +49,7 @@ #include "nvim/spell.h" #include "nvim/spellfile.h" #include "nvim/spellsuggest.h" +#include "nvim/statusline.h" #include "nvim/strings.h" #include "nvim/tag.h" #include "nvim/ui.h" @@ -1220,6 +1221,7 @@ static void did_set_statusline(win_T *win, char **varp, char **gvarp, char **err } if (varp == &p_ruf && *errmsg == NULL) { comp_col(); + win_redr_ruler(curwin); } // add / remove window bars for 'winbar' if (gvarp == &p_wbr) { -- cgit From 846a056744bf458d4376cd7638c94f7c82862046 Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 9 Mar 2023 11:45:20 +0100 Subject: refactor(redraw): make cursor position redraw use the "redraw later" pattern --- src/nvim/optionstr.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 0774baf2d8..5127bb2097 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1221,7 +1221,6 @@ static void did_set_statusline(win_T *win, char **varp, char **gvarp, char **err } if (varp == &p_ruf && *errmsg == NULL) { comp_col(); - win_redr_ruler(curwin); } // add / remove window bars for 'winbar' if (gvarp == &p_wbr) { -- cgit From 2daf0b37dbfe54a4510c1033531dbaefd168c387 Mon Sep 17 00:00:00 2001 From: ii14 <59243201+ii14@users.noreply.github.com> Date: Mon, 13 Mar 2023 03:29:11 +0100 Subject: feat(options)!: deprecate paste, remove pastetoggle (#22647) we cannot remove 'paste'. It is very common in plugins and configs. 'pastetoggle' can and should be removed though, it's a total waste of everyone's time because it generates bug reports and doesn't work well, and is useless because bracketed-paste works better. --- src/nvim/optionstr.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 5127bb2097..cba95377a2 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1306,22 +1306,6 @@ static void did_set_foldcolumn(char **varp, char **errmsg) } } -static void did_set_pastetoggle(void) -{ - // 'pastetoggle': translate key codes like in a mapping - if (*p_pt) { - char *p = NULL; - (void)replace_termcodes(p_pt, - strlen(p_pt), - &p, REPTERM_FROM_PART | REPTERM_DO_LT, NULL, - CPO_TO_CPO_FLAGS); - if (p != NULL) { - free_string_option(p_pt); - p_pt = p; - } - } -} - static void did_set_backspace(char **errmsg) { if (ascii_isdigit(*p_bs)) { @@ -1778,8 +1762,6 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char did_set_opt_strings(*varp, p_sloc_values, false, &errmsg); } else if (gvarp == &win->w_allbuf_opt.wo_fdc) { // 'foldcolumn' did_set_foldcolumn(varp, &errmsg); - } else if (varp == &p_pt) { // 'pastetoggle' - did_set_pastetoggle(); } else if (varp == &p_bs) { // 'backspace' did_set_backspace(&errmsg); } else if (varp == &p_bo) { -- cgit From d6ecead36406233cc56353dd05f3380f0497630f Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 14 Mar 2023 11:49:46 +0100 Subject: refactor(screen): screen.c delenda est drawscreen.c vs screen.c makes absolutely no sense. The screen exists only to draw upon it, therefore helper functions are distributed randomly between screen.c and the file that does the redrawing. In addition screen.c does a lot of drawing on the screen. It made more sense for vim/vim as our grid.c is their screen.c Not sure if we want to dump all the code for option chars into optionstr.c, so keep these in a optionchar.c for now. --- src/nvim/optionstr.c | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 282 insertions(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index cba95377a2..40cddebc2e 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -45,7 +45,6 @@ #include "nvim/pos.h" #include "nvim/quickfix.h" #include "nvim/runtime.h" -#include "nvim/screen.h" #include "nvim/spell.h" #include "nvim/spellfile.h" #include "nvim/spellsuggest.h" @@ -1960,3 +1959,285 @@ int check_ff_value(char *p) { return check_opt_strings(p, p_ff_values, false); } + +static char e_conflicts_with_value_of_listchars[] = N_("E834: Conflicts with value of 'listchars'"); +static char e_conflicts_with_value_of_fillchars[] = N_("E835: Conflicts with value of 'fillchars'"); + +/// Calls mb_cptr2char_adv(p) and returns the character. +/// If "p" starts with "\x", "\u" or "\U" the hex or unicode value is used. +/// Returns 0 for invalid hex or invalid UTF-8 byte. +static int get_encoded_char_adv(const char **p) +{ + const char *s = *p; + + if (s[0] == '\\' && (s[1] == 'x' || s[1] == 'u' || s[1] == 'U')) { + int64_t num = 0; + for (int bytes = s[1] == 'x' ? 1 : s[1] == 'u' ? 2 : 4; bytes > 0; bytes--) { + *p += 2; + int n = hexhex2nr(*p); + if (n < 0) { + return 0; + } + num = num * 256 + n; + } + *p += 2; + return (int)num; + } + + // TODO(bfredl): use schar_T representation and utfc_ptr2len + int clen = utf_ptr2len(s); + int c = mb_cptr2char_adv(p); + if (clen == 1 && c > 127) { // Invalid UTF-8 byte + return 0; + } + return c; +} + +/// Handle setting 'listchars' or 'fillchars'. +/// Assume monocell characters +/// +/// @param varp either the global or the window-local value. +/// @param apply if false, do not store the flags, only check for errors. +/// @return error message, NULL if it's OK. +char *set_chars_option(win_T *wp, char **varp, bool apply) +{ + const char *last_multispace = NULL; // Last occurrence of "multispace:" + const char *last_lmultispace = NULL; // Last occurrence of "leadmultispace:" + int multispace_len = 0; // Length of lcs-multispace string + int lead_multispace_len = 0; // Length of lcs-leadmultispace string + const bool is_listchars = (varp == &p_lcs || varp == &wp->w_p_lcs); + + struct chars_tab { + int *cp; ///< char value + char *name; ///< char id + int def; ///< default value + }; + + // XXX: Characters taking 2 columns is forbidden (TUI limitation?). Set old defaults in this case. + struct chars_tab fcs_tab[] = { + { &wp->w_p_fcs_chars.stl, "stl", ' ' }, + { &wp->w_p_fcs_chars.stlnc, "stlnc", ' ' }, + { &wp->w_p_fcs_chars.wbr, "wbr", ' ' }, + { &wp->w_p_fcs_chars.horiz, "horiz", char2cells(0x2500) == 1 ? 0x2500 : '-' }, // ─ + { &wp->w_p_fcs_chars.horizup, "horizup", char2cells(0x2534) == 1 ? 0x2534 : '-' }, // ┴ + { &wp->w_p_fcs_chars.horizdown, "horizdown", char2cells(0x252c) == 1 ? 0x252c : '-' }, // ┬ + { &wp->w_p_fcs_chars.vert, "vert", char2cells(0x2502) == 1 ? 0x2502 : '|' }, // │ + { &wp->w_p_fcs_chars.vertleft, "vertleft", char2cells(0x2524) == 1 ? 0x2524 : '|' }, // ┤ + { &wp->w_p_fcs_chars.vertright, "vertright", char2cells(0x251c) == 1 ? 0x251c : '|' }, // ├ + { &wp->w_p_fcs_chars.verthoriz, "verthoriz", char2cells(0x253c) == 1 ? 0x253c : '+' }, // ┼ + { &wp->w_p_fcs_chars.fold, "fold", char2cells(0x00b7) == 1 ? 0x00b7 : '-' }, // · + { &wp->w_p_fcs_chars.foldopen, "foldopen", '-' }, + { &wp->w_p_fcs_chars.foldclosed, "foldclose", '+' }, + { &wp->w_p_fcs_chars.foldsep, "foldsep", char2cells(0x2502) == 1 ? 0x2502 : '|' }, // │ + { &wp->w_p_fcs_chars.diff, "diff", '-' }, + { &wp->w_p_fcs_chars.msgsep, "msgsep", ' ' }, + { &wp->w_p_fcs_chars.eob, "eob", '~' }, + { &wp->w_p_fcs_chars.lastline, "lastline", '@' }, + }; + + struct chars_tab lcs_tab[] = { + { &wp->w_p_lcs_chars.eol, "eol", NUL }, + { &wp->w_p_lcs_chars.ext, "extends", NUL }, + { &wp->w_p_lcs_chars.nbsp, "nbsp", NUL }, + { &wp->w_p_lcs_chars.prec, "precedes", NUL }, + { &wp->w_p_lcs_chars.space, "space", NUL }, + { &wp->w_p_lcs_chars.tab2, "tab", NUL }, + { &wp->w_p_lcs_chars.lead, "lead", NUL }, + { &wp->w_p_lcs_chars.trail, "trail", NUL }, + { &wp->w_p_lcs_chars.conceal, "conceal", NUL }, + }; + + struct chars_tab *tab; + int entries; + const char *value = *varp; + if (is_listchars) { + tab = lcs_tab; + entries = ARRAY_SIZE(lcs_tab); + if (varp == &wp->w_p_lcs && wp->w_p_lcs[0] == NUL) { + value = p_lcs; // local value is empty, use the global value + } + } else { + tab = fcs_tab; + entries = ARRAY_SIZE(fcs_tab); + if (varp == &wp->w_p_fcs && wp->w_p_fcs[0] == NUL) { + value = p_fcs; // local value is empty, use the global value + } + } + + // first round: check for valid value, second round: assign values + for (int round = 0; round <= (apply ? 1 : 0); round++) { + if (round > 0) { + // After checking that the value is valid: set defaults + for (int i = 0; i < entries; i++) { + if (tab[i].cp != NULL) { + *(tab[i].cp) = tab[i].def; + } + } + if (is_listchars) { + wp->w_p_lcs_chars.tab1 = NUL; + wp->w_p_lcs_chars.tab3 = NUL; + + xfree(wp->w_p_lcs_chars.multispace); + if (multispace_len > 0) { + wp->w_p_lcs_chars.multispace = xmalloc(((size_t)multispace_len + 1) * sizeof(int)); + wp->w_p_lcs_chars.multispace[multispace_len] = NUL; + } else { + wp->w_p_lcs_chars.multispace = NULL; + } + + xfree(wp->w_p_lcs_chars.leadmultispace); + if (lead_multispace_len > 0) { + wp->w_p_lcs_chars.leadmultispace + = xmalloc(((size_t)lead_multispace_len + 1) * sizeof(int)); + wp->w_p_lcs_chars.leadmultispace[lead_multispace_len] = NUL; + } else { + wp->w_p_lcs_chars.leadmultispace = NULL; + } + } + } + const char *p = value; + while (*p) { + int i; + for (i = 0; i < entries; i++) { + const size_t len = strlen(tab[i].name); + if (strncmp(p, tab[i].name, len) == 0 + && p[len] == ':' + && p[len + 1] != NUL) { + const char *s = p + len + 1; + int c1 = get_encoded_char_adv(&s); + if (c1 == 0 || char2cells(c1) > 1) { + return e_invarg; + } + int c2 = 0, c3 = 0; + if (tab[i].cp == &wp->w_p_lcs_chars.tab2) { + if (*s == NUL) { + return e_invarg; + } + c2 = get_encoded_char_adv(&s); + if (c2 == 0 || char2cells(c2) > 1) { + return e_invarg; + } + if (!(*s == ',' || *s == NUL)) { + c3 = get_encoded_char_adv(&s); + if (c3 == 0 || char2cells(c3) > 1) { + return e_invarg; + } + } + } + if (*s == ',' || *s == NUL) { + if (round > 0) { + if (tab[i].cp == &wp->w_p_lcs_chars.tab2) { + wp->w_p_lcs_chars.tab1 = c1; + wp->w_p_lcs_chars.tab2 = c2; + wp->w_p_lcs_chars.tab3 = c3; + } else if (tab[i].cp != NULL) { + *(tab[i].cp) = c1; + } + } + p = s; + break; + } + } + } + + if (i == entries) { + const size_t len = strlen("multispace"); + const size_t len2 = strlen("leadmultispace"); + if (is_listchars + && strncmp(p, "multispace", len) == 0 + && p[len] == ':' + && p[len + 1] != NUL) { + const char *s = p + len + 1; + if (round == 0) { + // Get length of lcs-multispace string in the first round + last_multispace = p; + multispace_len = 0; + while (*s != NUL && *s != ',') { + int c1 = get_encoded_char_adv(&s); + if (c1 == 0 || char2cells(c1) > 1) { + return e_invarg; + } + multispace_len++; + } + if (multispace_len == 0) { + // lcs-multispace cannot be an empty string + return e_invarg; + } + p = s; + } else { + int multispace_pos = 0; + while (*s != NUL && *s != ',') { + int c1 = get_encoded_char_adv(&s); + if (p == last_multispace) { + wp->w_p_lcs_chars.multispace[multispace_pos++] = c1; + } + } + p = s; + } + } else if (is_listchars + && strncmp(p, "leadmultispace", len2) == 0 + && p[len2] == ':' + && p[len2 + 1] != NUL) { + const char *s = p + len2 + 1; + if (round == 0) { + // get length of lcs-leadmultispace string in first round + last_lmultispace = p; + lead_multispace_len = 0; + while (*s != NUL && *s != ',') { + int c1 = get_encoded_char_adv(&s); + if (c1 == 0 || char2cells(c1) > 1) { + return e_invarg; + } + lead_multispace_len++; + } + if (lead_multispace_len == 0) { + // lcs-leadmultispace cannot be an empty string + return e_invarg; + } + p = s; + } else { + int multispace_pos = 0; + while (*s != NUL && *s != ',') { + int c1 = get_encoded_char_adv(&s); + if (p == last_lmultispace) { + wp->w_p_lcs_chars.leadmultispace[multispace_pos++] = c1; + } + } + p = s; + } + } else { + return e_invarg; + } + } + + if (*p == ',') { + p++; + } + } + } + + return NULL; // no error +} + +/// Check all global and local values of 'listchars' and 'fillchars'. +/// May set different defaults in case character widths change. +/// +/// @return an untranslated error message if any of them is invalid, NULL otherwise. +char *check_chars_options(void) +{ + if (set_chars_option(curwin, &p_lcs, false) != NULL) { + return e_conflicts_with_value_of_listchars; + } + if (set_chars_option(curwin, &p_fcs, false) != NULL) { + return e_conflicts_with_value_of_fillchars; + } + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (set_chars_option(wp, &wp->w_p_lcs, true) != NULL) { + return e_conflicts_with_value_of_listchars; + } + if (set_chars_option(wp, &wp->w_p_fcs, true) != NULL) { + return e_conflicts_with_value_of_fillchars; + } + } + return NULL; +} -- cgit From c6f8af36e134a67b489d59e078425cada5eafd7b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 18 Mar 2023 09:55:08 +0800 Subject: fix(spell): properly source spell/LANG.{vim,lua} (#22716) Using regexp doesn't work here because there are no wildcards. --- src/nvim/optionstr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 40cddebc2e..218b34472a 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1578,7 +1578,9 @@ static void do_spelllang_source(win_T *win) } } if (p > q) { - vim_snprintf(fname, sizeof(fname), "spell/%.*s.\\(vim\\|lua\\)", (int)(p - q), q); + vim_snprintf(fname, sizeof(fname), "spell/%.*s.vim", (int)(p - q), q); + source_runtime(fname, DIP_ALL); + vim_snprintf(fname, sizeof(fname), "spell/%.*s.lua", (int)(p - q), q); source_runtime(fname, DIP_ALL); } } -- cgit From eeac80de0cf45951dd696f82e5a823c6de20728c Mon Sep 17 00:00:00 2001 From: luukvbaal <31730729+luukvbaal@users.noreply.github.com> Date: Sun, 19 Mar 2023 10:21:49 +0100 Subject: fix(column): invalidate statuscolumn width when UPD_NOT_VALID (#22723) --- src/nvim/optionstr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 218b34472a..170800b4e6 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1198,8 +1198,8 @@ static void did_set_statusline(win_T *win, char **varp, char **gvarp, char **err if (varp == &p_ruf) { // reset ru_wid first ru_wid = 0; } else if (varp == &win->w_p_stc) { - win->w_nrwidth_line_count = 0; - win->w_statuscol_line_count = 0; + win->w_nrwidth_line_count = 0; // make sure width is reset + win->w_statuscol_line_count = 0; // make sure width is re-estimated } char *s = *varp; if (varp == &p_ruf && *s == '%') { -- cgit From 8b7fb668e440f7793564b764bc9a691e3f45382a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 29 Mar 2023 19:54:12 +0100 Subject: fix(filetype): avoid recursive FileType autocmds (#22813) --- src/nvim/optionstr.c | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 170800b4e6..bf4ebbb3e2 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1529,34 +1529,6 @@ static void do_syntax_autocmd(buf_T *buf, bool value_changed) syn_recursive--; } -static void do_filetype_autocmd(buf_T *buf, char **varp, int opt_flags, bool value_changed) -{ - // 'filetype' is set, trigger the FileType autocommand - // Skip this when called from a modeline and the filetype was - // already set to this value. - if (!(opt_flags & OPT_MODELINE) || value_changed) { - static int ft_recursive = 0; - int secure_save = secure; - - // Reset the secure flag, since the value of 'filetype' has - // been checked to be safe. - secure = 0; - - ft_recursive++; - did_filetype = true; - // Only pass true for "force" when the value changed or not - // used recursively, to avoid endless recurrence. - apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, buf->b_fname, - value_changed || ft_recursive == 1, buf); - ft_recursive--; - // Just in case the old "buf" is now invalid - if (varp != &(buf->b_p_ft)) { - varp = NULL; - } - secure = secure_save; - } -} - static void do_spelllang_source(win_T *win) { char fname[200]; @@ -1884,7 +1856,12 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char if (varp == &buf->b_p_syn) { do_syntax_autocmd(buf, value_changed); } else if (varp == &buf->b_p_ft) { - do_filetype_autocmd(buf, varp, opt_flags, value_changed); + // 'filetype' is set, trigger the FileType autocommand + // Skip this when called from a modeline + // Force autocmd when the filetype was changed + if (!(opt_flags & OPT_MODELINE) || value_changed) { + do_filetype_autocmd(buf, value_changed); + } } else if (varp == &win->w_s->b_p_spl) { do_spelllang_source(win); } -- cgit From 371823d407d7d7519735131bcad4670c62a731a7 Mon Sep 17 00:00:00 2001 From: ii14 <59243201+ii14@users.noreply.github.com> Date: Wed, 5 Apr 2023 21:13:53 +0200 Subject: refactor: make error message definitions const message.c functions now take const char * as a format. Error message definitions can be made const. --- src/nvim/optionstr.c | 152 ++++++++++++++++++++++++++------------------------- 1 file changed, 78 insertions(+), 74 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index bf4ebbb3e2..3372c7b6c6 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -59,13 +59,13 @@ # include "optionstr.c.generated.h" #endif -static char e_unclosed_expression_sequence[] +static const char e_unclosed_expression_sequence[] = N_("E540: Unclosed expression sequence"); -static char e_unbalanced_groups[] +static const char e_unbalanced_groups[] = N_("E542: unbalanced groups"); -static char e_backupext_and_patchmode_are_equal[] +static const char e_backupext_and_patchmode_are_equal[] = N_("E589: 'backupext' and 'patchmode' are equal"); -static char e_showbreak_contains_unprintable_or_wide_character[] +static const char e_showbreak_contains_unprintable_or_wide_character[] = N_("E595: 'showbreak' contains unprintable or wide character"); static char *(p_ambw_values[]) = { "single", "double", NULL }; @@ -410,8 +410,8 @@ void set_string_option_direct_in_win(win_T *wp, const char *name, int opt_idx, c /// #OPT_GLOBAL. /// /// @return NULL on success, an untranslated error message on error. -char *set_string_option(const int opt_idx, const char *const value, const int opt_flags, - char *const errbuf, const size_t errbuflen) +const char *set_string_option(const int opt_idx, const char *const value, const int opt_flags, + char *const errbuf, const size_t errbuflen) FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_WARN_UNUSED_RESULT { vimoption_T *opt = get_option(opt_idx); @@ -442,9 +442,8 @@ char *set_string_option(const int opt_idx, const char *const value, const int op char *const saved_newval = xstrdup(s); int value_checked = false; - char *const errmsg = did_set_string_option(opt_idx, varp, oldval, - errbuf, errbuflen, - opt_flags, &value_checked); + const char *const errmsg = did_set_string_option(opt_idx, varp, oldval, errbuf, errbuflen, + opt_flags, &value_checked); if (errmsg == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); } @@ -478,7 +477,7 @@ static bool valid_filetype(const char *val) /// Handle setting 'mousescroll'. /// @return error message, NULL if it's OK. -static char *check_mousescroll(char *string) +static const char *check_mousescroll(char *string) { long vertical = -1; long horizontal = -1; @@ -571,7 +570,7 @@ static int check_signcolumn(char *val) /// Check validity of options with the 'statusline' format. /// Return an untranslated error message or NULL. -char *check_stl_option(char *s) +const char *check_stl_option(char *s) { int groupdepth = 0; static char errbuf[80]; @@ -650,7 +649,7 @@ static bool check_illegal_path_names(char *val, uint32_t flags) && strpbrk(val, "*?[|;&<>\r\n") != NULL)); } -static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, char **errmsg) +static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, const char **errmsg) { char *bkc = p_bkc; unsigned int *flags = &bkc_flags; @@ -678,7 +677,7 @@ static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, char **e } } -static void did_set_backupext_or_patchmode(char **errmsg) +static void did_set_backupext_or_patchmode(const char **errmsg) { if (strcmp(*p_bex == '.' ? p_bex + 1 : p_bex, *p_pm == '.' ? p_pm + 1 : p_pm) == 0) { @@ -686,7 +685,7 @@ static void did_set_backupext_or_patchmode(char **errmsg) } } -static void did_set_breakindentopt(win_T *win, char **errmsg) +static void did_set_breakindentopt(win_T *win, const char **errmsg) { if (briopt_check(win) == FAIL) { *errmsg = e_invarg; @@ -697,7 +696,7 @@ static void did_set_breakindentopt(win_T *win, char **errmsg) } } -static void did_set_isopt(buf_T *buf, bool *did_chartab, char **errmsg) +static void did_set_isopt(buf_T *buf, bool *did_chartab, const char **errmsg) { // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[] // If the new option is invalid, use old value. @@ -719,14 +718,14 @@ static void did_set_helpfile(void) } } -static void did_set_cursorlineopt(win_T *win, char **varp, char **errmsg) +static void did_set_cursorlineopt(win_T *win, char **varp, const char **errmsg) { if (**varp == NUL || fill_culopt_flags(*varp, win) != OK) { *errmsg = e_invarg; } } -static void did_set_helplang(char **errmsg) +static void did_set_helplang(const char **errmsg) { // Check for "", "ab", "ab,cd", etc. for (char *s = p_hlg; *s != NUL; s += 3) { @@ -740,26 +739,27 @@ static void did_set_helplang(char **errmsg) } } -static void did_set_highlight(char **varp, char **errmsg) +static void did_set_highlight(char **varp, const char **errmsg) { if (strcmp(*varp, HIGHLIGHT_INIT) != 0) { *errmsg = e_unsupportedoption; } } -static void did_set_opt_flags(char *val, char **values, unsigned *flagp, bool list, char **errmsg) +static void did_set_opt_flags(char *val, char **values, unsigned *flagp, bool list, + const char **errmsg) { if (opt_strings_flags(val, values, flagp, list) != OK) { *errmsg = e_invarg; } } -static void did_set_opt_strings(char *val, char **values, bool list, char **errmsg) +static void did_set_opt_strings(char *val, char **values, bool list, const char **errmsg) { did_set_opt_flags(val, values, NULL, list, errmsg); } -static void did_set_sessionoptions(char *oldval, char **errmsg) +static void did_set_sessionoptions(char *oldval, const char **errmsg) { if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true) != OK) { *errmsg = e_invarg; @@ -771,7 +771,7 @@ static void did_set_sessionoptions(char *oldval, char **errmsg) } } -static void did_set_ambiwidth(char **errmsg) +static void did_set_ambiwidth(const char **errmsg) { if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) { *errmsg = e_invarg; @@ -780,7 +780,7 @@ static void did_set_ambiwidth(char **errmsg) } } -static void did_set_background(char **errmsg) +static void did_set_background(const char **errmsg) { if (check_opt_strings(p_bg, p_bg_values, false) != OK) { *errmsg = e_invarg; @@ -803,21 +803,21 @@ static void did_set_background(char **errmsg) } } -static void did_set_wildmode(char **errmsg) +static void did_set_wildmode(const char **errmsg) { if (check_opt_wim() == FAIL) { *errmsg = e_invarg; } } -static void did_set_winaltkeys(char **errmsg) +static void did_set_winaltkeys(const char **errmsg) { if (*p_wak == NUL || check_opt_strings(p_wak, p_wak_values, false) != OK) { *errmsg = e_invarg; } } -static void did_set_eventignore(char **errmsg) +static void did_set_eventignore(const char **errmsg) { if (check_ei() == FAIL) { *errmsg = e_invarg; @@ -825,7 +825,8 @@ static void did_set_eventignore(char **errmsg) } // 'encoding', 'fileencoding' and 'makeencoding' -static void did_set_encoding(buf_T *buf, char **varp, char **gvarp, int opt_flags, char **errmsg) +static void did_set_encoding(buf_T *buf, char **varp, char **gvarp, int opt_flags, + const char **errmsg) { if (gvarp == &p_fenc) { if (!MODIFIABLE(buf) && opt_flags != OPT_GLOBAL) { @@ -861,7 +862,7 @@ static void did_set_encoding(buf_T *buf, char **varp, char **gvarp, int opt_flag } static void did_set_keymap(buf_T *buf, char **varp, int opt_flags, int *value_checked, - char **errmsg) + const char **errmsg) { if (!valid_filetype(*varp)) { *errmsg = e_invarg; @@ -908,7 +909,7 @@ static void did_set_keymap(buf_T *buf, char **varp, int opt_flags, int *value_ch } static void did_set_fileformat(buf_T *buf, char **varp, const char *oldval, int opt_flags, - char **errmsg) + const char **errmsg) { if (!MODIFIABLE(buf) && !(opt_flags & OPT_GLOBAL)) { *errmsg = e_modifiable; @@ -926,7 +927,7 @@ static void did_set_fileformat(buf_T *buf, char **varp, const char *oldval, int } } -static void did_set_matchpairs(char **varp, char **errmsg) +static void did_set_matchpairs(char **varp, const char **errmsg) { for (char *p = *varp; *p != NUL; p++) { int x2 = -1; @@ -950,7 +951,7 @@ static void did_set_matchpairs(char **varp, char **errmsg) } } -static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, char **errmsg) +static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, const char **errmsg) { for (char *s = *varp; *s;) { while (*s && *s != ':') { @@ -979,7 +980,8 @@ static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, char * } } -static void did_set_global_listfillchars(win_T *win, char **varp, int opt_flags, char **errmsg) +static void did_set_global_listfillchars(win_T *win, char **varp, int opt_flags, + const char **errmsg) { char **local_ptr = varp == &p_lcs ? &win->w_p_lcs : &win->w_p_fcs; // only apply the global value to "win" when it does not have a local value @@ -1004,7 +1006,7 @@ static void did_set_global_listfillchars(win_T *win, char **varp, int opt_flags, } } -static void did_set_verbosefile(char **errmsg) +static void did_set_verbosefile(const char **errmsg) { verbose_stop(); if (*p_vfile != NUL && verbose_open() == FAIL) { @@ -1015,7 +1017,7 @@ static void did_set_verbosefile(char **errmsg) static int shada_idx = -1; static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, - size_t errbuflen, char **errmsg) + size_t errbuflen, const char **errmsg) { // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo // option. @@ -1073,7 +1075,7 @@ static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, ch } } -static void did_set_showbreak(char **varp, char **errmsg) +static void did_set_showbreak(char **varp, const char **errmsg) { for (char *s = *varp; *s;) { if (ptr2cells(s) != 1) { @@ -1097,14 +1099,14 @@ static void did_set_titleiconstring(char **varp) did_set_title(); } -static void did_set_selection(char **errmsg) +static void did_set_selection(const char **errmsg) { if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, false) != OK) { *errmsg = e_invarg; } } -static void did_set_keymodel(char **errmsg) +static void did_set_keymodel(const char **errmsg) { if (check_opt_strings(p_km, p_km_values, true) != OK) { *errmsg = e_invarg; @@ -1114,7 +1116,7 @@ static void did_set_keymodel(char **errmsg) km_startsel = (vim_strchr(p_km, 'a') != NULL); } -static void did_set_display(char **errmsg) +static void did_set_display(const char **errmsg) { if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) { *errmsg = e_invarg; @@ -1124,7 +1126,7 @@ static void did_set_display(char **errmsg) msg_grid_validate(); } -static void did_set_spellfile(char **varp, char **errmsg) +static void did_set_spellfile(char **varp, const char **errmsg) { // When there is a window for this buffer in which 'spell' // is set load the wordlists. @@ -1136,7 +1138,7 @@ static void did_set_spellfile(char **varp, char **errmsg) } } -static void did_set_spell(char **varp, char **errmsg) +static void did_set_spell(char **varp, const char **errmsg) { // When there is a window for this buffer in which 'spell' // is set load the wordlists. @@ -1147,13 +1149,13 @@ static void did_set_spell(char **varp, char **errmsg) } } -static void did_set_spellcapcheck(win_T *win, char **errmsg) +static void did_set_spellcapcheck(win_T *win, const char **errmsg) { // When 'spellcapcheck' is set compile the regexp program. *errmsg = compile_cap_prog(win->w_s); } -static void did_set_spelloptions(win_T *win, char **errmsg) +static void did_set_spelloptions(win_T *win, const char **errmsg) { if (opt_strings_flags(win->w_s->b_p_spo, p_spo_values, &(win->w_s->b_p_spo_flags), true) != OK) { @@ -1161,21 +1163,21 @@ static void did_set_spelloptions(win_T *win, char **errmsg) } } -static void did_set_spellsuggest(char **errmsg) +static void did_set_spellsuggest(const char **errmsg) { if (spell_check_sps() != OK) { *errmsg = e_invarg; } } -static void did_set_mkspellmem(char **errmsg) +static void did_set_mkspellmem(const char **errmsg) { if (spell_check_msm() != OK) { *errmsg = e_invarg; } } -static void did_set_buftype(buf_T *buf, win_T *win, char **errmsg) +static void did_set_buftype(buf_T *buf, win_T *win, const char **errmsg) { // When 'buftype' is set, check for valid value. if ((buf->terminal && buf->b_p_bt[0] != 't') @@ -1193,7 +1195,7 @@ static void did_set_buftype(buf_T *buf, win_T *win, char **errmsg) } // 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn' -static void did_set_statusline(win_T *win, char **varp, char **gvarp, char **errmsg) +static void did_set_statusline(win_T *win, char **varp, char **gvarp, const char **errmsg) { if (varp == &p_ruf) { // reset ru_wid first ru_wid = 0; @@ -1227,7 +1229,7 @@ static void did_set_statusline(win_T *win, char **varp, char **gvarp, char **err } } -static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, char **errmsg) +static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, const char **errmsg) { // check if it is a valid value for 'complete' -- Acevedo for (char *s = *varp; *s;) { @@ -1265,7 +1267,7 @@ static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, char * } } -static void did_set_completeopt(char **errmsg) +static void did_set_completeopt(const char **errmsg) { if (check_opt_strings(p_cot, p_cot_values, true) != OK) { *errmsg = e_invarg; @@ -1275,7 +1277,7 @@ static void did_set_completeopt(char **errmsg) } #ifdef BACKSLASH_IN_FILENAME -static void did_set_completeslash(buf_T *buf, char **errmsg) +static void did_set_completeslash(buf_T *buf, const char **errmsg) { if (check_opt_strings(p_csl, p_csl_values, false) != OK || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) { @@ -1284,7 +1286,7 @@ static void did_set_completeslash(buf_T *buf, char **errmsg) } #endif -static void did_set_signcolumn(win_T *win, char **varp, const char *oldval, char **errmsg) +static void did_set_signcolumn(win_T *win, char **varp, const char *oldval, const char **errmsg) { if (check_signcolumn(*varp) != OK) { *errmsg = e_invarg; @@ -1298,14 +1300,14 @@ static void did_set_signcolumn(win_T *win, char **varp, const char *oldval, char } } -static void did_set_foldcolumn(char **varp, char **errmsg) +static void did_set_foldcolumn(char **varp, const char **errmsg) { if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) { *errmsg = e_invarg; } } -static void did_set_backspace(char **errmsg) +static void did_set_backspace(const char **errmsg) { if (ascii_isdigit(*p_bs)) { if (*p_bs > '3' || p_bs[1] != NUL) { @@ -1316,7 +1318,7 @@ static void did_set_backspace(char **errmsg) } } -static void did_set_tagcase(buf_T *buf, int opt_flags, char **errmsg) +static void did_set_tagcase(buf_T *buf, int opt_flags, const char **errmsg) { unsigned int *flags; char *p; @@ -1338,14 +1340,14 @@ static void did_set_tagcase(buf_T *buf, int opt_flags, char **errmsg) } } -static void did_set_diffopt(char **errmsg) +static void did_set_diffopt(const char **errmsg) { if (diffopt_changed() == FAIL) { *errmsg = e_invarg; } } -static void did_set_foldmethod(win_T *win, char **varp, char **errmsg) +static void did_set_foldmethod(win_T *win, char **varp, const char **errmsg) { if (check_opt_strings(*varp, p_fdm_values, false) != OK || *win->w_p_fdm == NUL) { @@ -1358,7 +1360,7 @@ static void did_set_foldmethod(win_T *win, char **varp, char **errmsg) } } -static void did_set_foldmarker(win_T *win, char **varp, char **errmsg) +static void did_set_foldmarker(win_T *win, char **varp, const char **errmsg) { char *p = vim_strchr(*varp, ','); if (p == NULL) { @@ -1370,7 +1372,7 @@ static void did_set_foldmarker(win_T *win, char **varp, char **errmsg) } } -static void did_set_commentstring(char **varp, char **errmsg) +static void did_set_commentstring(char **varp, const char **errmsg) { if (**varp != NUL && strstr(*varp, "%s") == NULL) { *errmsg = N_("E537: 'commentstring' must be empty or contain %s"); @@ -1384,7 +1386,7 @@ static void did_set_foldignore(win_T *win) } } -static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, char **errmsg) +static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, const char **errmsg) { char *ve = p_ve; unsigned int *flags = &ve_flags; @@ -1410,7 +1412,7 @@ static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, char ** } } -static void did_set_lispoptions(char **varp, char **errmsg) +static void did_set_lispoptions(char **varp, const char **errmsg) { if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) { *errmsg = e_invarg; @@ -1418,7 +1420,7 @@ static void did_set_lispoptions(char **varp, char **errmsg) } static void did_set_filetype_or_syntax(char **varp, char *oldval, int *value_checked, - bool *value_changed, char **errmsg) + bool *value_changed, const char **errmsg) { if (!valid_filetype(*varp)) { *errmsg = e_invarg; @@ -1432,14 +1434,14 @@ static void did_set_filetype_or_syntax(char **varp, char *oldval, int *value_che *value_checked = true; } -static void did_set_winhl(win_T *win, char **errmsg) +static void did_set_winhl(win_T *win, const char **errmsg) { if (!parse_winhl_opt(win)) { *errmsg = e_invarg; } } -static void did_set_varsoftabstop(buf_T *buf, char **varp, char **errmsg) +static void did_set_varsoftabstop(buf_T *buf, char **varp, const char **errmsg) { if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) { XFREE_CLEAR(buf->b_p_vsts_array); @@ -1465,7 +1467,7 @@ static void did_set_varsoftabstop(buf_T *buf, char **varp, char **errmsg) } } -static void did_set_vartabstop(buf_T *buf, win_T *win, char **varp, char **errmsg) +static void did_set_vartabstop(buf_T *buf, win_T *win, char **varp, const char **errmsg) { if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) { XFREE_CLEAR(buf->b_p_vts_array); @@ -1505,7 +1507,7 @@ static void did_set_optexpr(char **varp) // handle option that is a list of flags. static void did_set_option_listflag(char **varp, char *flags, char *errbuf, size_t errbuflen, - char **errmsg) + const char **errmsg) { for (char *s = *varp; *s; s++) { if (vim_strchr(flags, (uint8_t)(*s)) == NULL) { @@ -1569,11 +1571,11 @@ static void do_spelllang_source(win_T *win) /// @param value_checked value was checked to be safe, no need to set P_INSECURE /// /// @return NULL for success, or an untranslated error message for an error -static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char **varp, - char *oldval, char *errbuf, size_t errbuflen, int opt_flags, - int *value_checked) +static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char **varp, + char *oldval, char *errbuf, size_t errbuflen, + int opt_flags, int *value_checked) { - char *errmsg = NULL; + const char *errmsg = NULL; bool did_chartab = false; vimoption_T *opt = get_option(opt_idx); bool free_oldval = (opt->flags & P_ALLOCED); @@ -1881,8 +1883,8 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char return errmsg; } -char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf, size_t errbuflen, - int opt_flags, int *value_checked) +const char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf, + size_t errbuflen, int opt_flags, int *value_checked) { return did_set_string_option_for(curbuf, curwin, opt_idx, varp, oldval, errbuf, errbuflen, opt_flags, value_checked); @@ -1939,8 +1941,10 @@ int check_ff_value(char *p) return check_opt_strings(p, p_ff_values, false); } -static char e_conflicts_with_value_of_listchars[] = N_("E834: Conflicts with value of 'listchars'"); -static char e_conflicts_with_value_of_fillchars[] = N_("E835: Conflicts with value of 'fillchars'"); +static const char e_conflicts_with_value_of_listchars[] + = N_("E834: Conflicts with value of 'listchars'"); +static const char e_conflicts_with_value_of_fillchars[] + = N_("E835: Conflicts with value of 'fillchars'"); /// Calls mb_cptr2char_adv(p) and returns the character. /// If "p" starts with "\x", "\u" or "\U" the hex or unicode value is used. @@ -1978,7 +1982,7 @@ static int get_encoded_char_adv(const char **p) /// @param varp either the global or the window-local value. /// @param apply if false, do not store the flags, only check for errors. /// @return error message, NULL if it's OK. -char *set_chars_option(win_T *wp, char **varp, bool apply) +const char *set_chars_option(win_T *wp, char **varp, bool apply) { const char *last_multispace = NULL; // Last occurrence of "multispace:" const char *last_lmultispace = NULL; // Last occurrence of "leadmultispace:" @@ -2202,7 +2206,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply) /// May set different defaults in case character widths change. /// /// @return an untranslated error message if any of them is invalid, NULL otherwise. -char *check_chars_options(void) +const char *check_chars_options(void) { if (set_chars_option(curwin, &p_lcs, false) != NULL) { return e_conflicts_with_value_of_listchars; -- cgit From e24a84f18e59b356925a435d5ee3085842415299 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 16 Apr 2023 00:16:36 +0800 Subject: vim-patch:9.0.1064: code for making 'shortmess' temporarily empty is repeated Problem: Code for making 'shortmess' temporarily empty is repeated. Solution: Add functions for making 'shortmess' empty and restoring it. (Christian Brabandt, closes vim/vim#11709) https://github.com/vim/vim/commit/9aee8ec400fe617f6d82441c46a22d0cef6fa3e6 Co-authored-by: Christian Brabandt --- src/nvim/optionstr.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 3372c7b6c6..6c6190cb08 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -67,6 +67,8 @@ static const char e_backupext_and_patchmode_are_equal[] = N_("E589: 'backupext' and 'patchmode' are equal"); static const char e_showbreak_contains_unprintable_or_wide_character[] = N_("E595: 'showbreak' contains unprintable or wide character"); +static const char e_internal_error_shortmess_too_long[] + = N_("E1336: Internal error: shortmess too long"); static char *(p_ambw_values[]) = { "single", "double", NULL }; static char *(p_bg_values[]) = { "light", "dark", NULL }; @@ -1941,6 +1943,37 @@ int check_ff_value(char *p) return check_opt_strings(p, p_ff_values, false); } +static char shm_buf[SHM_LEN]; +static int set_shm_recursive = 0; + +/// Save the acutal shortmess Flags and clear them +/// temporarily to avoid that file messages +/// overwrites any output from the following commands. +/// +/// Caller must make sure to first call save_clear_shm_value() and then +/// restore_shm_value() exactly the same number of times. +void save_clear_shm_value(void) +{ + if (strlen(p_shm) >= SHM_LEN) { + iemsg(e_internal_error_shortmess_too_long); + return; + } + + if (++set_shm_recursive == 1) { + STRCPY(shm_buf, p_shm); + set_option_value_give_err("shm", 0L, "", 0); + } +} + +/// Restore the shortmess Flags set from the save_clear_shm_value() function. +void restore_shm_value(void) +{ + if (--set_shm_recursive == 0) { + set_option_value_give_err("shm", 0L, shm_buf, 0); + memset(shm_buf, 0, SHM_LEN); + } +} + static const char e_conflicts_with_value_of_listchars[] = N_("E834: Conflicts with value of 'listchars'"); static const char e_conflicts_with_value_of_fillchars[] -- cgit From 44d4f0357341d661a8fa7bd88c244e0ab196a838 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Wed, 19 Apr 2023 00:19:26 +0200 Subject: fix(column): rebuild status column when sign column is invalid --- src/nvim/optionstr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 6c6190cb08..1f3fb942ff 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1202,8 +1202,8 @@ static void did_set_statusline(win_T *win, char **varp, char **gvarp, const char if (varp == &p_ruf) { // reset ru_wid first ru_wid = 0; } else if (varp == &win->w_p_stc) { - win->w_nrwidth_line_count = 0; // make sure width is reset - win->w_statuscol_line_count = 0; // make sure width is re-estimated + // reset 'statuscolumn' width + win->w_nrwidth_line_count = 0; } char *s = *varp; if (varp == &p_ruf && *s == '%') { -- cgit From 3b0df1780e2c8526bda5dead18ee7cc45925caba Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 26 Apr 2023 23:23:44 +0200 Subject: refactor: uncrustify Notable changes: replace all infinite loops to `while(true)` and remove `int` from `unsigned int`. --- src/nvim/optionstr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 1f3fb942ff..ece7a90b4a 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -484,7 +484,7 @@ static const char *check_mousescroll(char *string) long vertical = -1; long horizontal = -1; - for (;;) { + while (true) { char *end = vim_strchr(string, ','); size_t length = end ? (size_t)(end - string) : strlen(string); @@ -654,7 +654,7 @@ static bool check_illegal_path_names(char *val, uint32_t flags) static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, const char **errmsg) { char *bkc = p_bkc; - unsigned int *flags = &bkc_flags; + unsigned *flags = &bkc_flags; if (opt_flags & OPT_LOCAL) { bkc = buf->b_p_bkc; @@ -1322,7 +1322,7 @@ static void did_set_backspace(const char **errmsg) static void did_set_tagcase(buf_T *buf, int opt_flags, const char **errmsg) { - unsigned int *flags; + unsigned *flags; char *p; if (opt_flags & OPT_LOCAL) { @@ -1391,7 +1391,7 @@ static void did_set_foldignore(win_T *win) static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, const char **errmsg) { char *ve = p_ve; - unsigned int *flags = &ve_flags; + unsigned *flags = &ve_flags; if (opt_flags & OPT_LOCAL) { ve = win->w_p_ve; @@ -1912,10 +1912,10 @@ static int check_opt_strings(char *val, char **values, int list) /// @return OK for correct value, FAIL otherwise. Empty is always OK. static int opt_strings_flags(char *val, char **values, unsigned *flagp, bool list) { - unsigned int new_flags = 0; + unsigned new_flags = 0; while (*val) { - for (unsigned int i = 0;; i++) { + for (unsigned i = 0;; i++) { if (values[i] == NULL) { // val not found in values[] return FAIL; } -- cgit From ff34c91194f9ab9d02808f2880029c38a4655eb5 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 17 Apr 2023 17:23:47 +0100 Subject: vim-patch:9.0.1330: handling new value of an option has a long "else if" chain Problem: Handling new value of an option has a long "else if" chain. Solution: Use a function pointer. (Yegappan Lakshmanan, closes vim/vim#12015) https://github.com/vim/vim/commit/af93691b53f38784efce0b93fe7644c44a7e382e --- src/nvim/optionstr.c | 716 +++++++++++++++++++++++++++------------------------ 1 file changed, 386 insertions(+), 330 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index ece7a90b4a..d7cf948730 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -444,7 +444,7 @@ const char *set_string_option(const int opt_idx, const char *const value, const char *const saved_newval = xstrdup(s); int value_checked = false; - const char *const errmsg = did_set_string_option(opt_idx, varp, oldval, errbuf, errbuflen, + const char *const errmsg = did_set_string_option(opt_idx, varp, oldval, s, errbuf, errbuflen, opt_flags, &value_checked); if (errmsg == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); @@ -479,11 +479,13 @@ static bool valid_filetype(const char *val) /// Handle setting 'mousescroll'. /// @return error message, NULL if it's OK. -static const char *check_mousescroll(char *string) +const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) { long vertical = -1; long horizontal = -1; + char *string = p_mousescroll; + while (true) { char *end = vim_strchr(string, ','); size_t length = end ? (size_t)(end - string) : strlen(string); @@ -651,8 +653,12 @@ static bool check_illegal_path_names(char *val, uint32_t flags) && strpbrk(val, "*?[|;&<>\r\n") != NULL)); } -static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, const char **errmsg) +/// The 'backupcopy' option is changed. +const char *did_set_backupcopy(optset_T *args) { + buf_T *buf = (buf_T *)args->os_buf; + const char *oldval = args->os_oldval.string; + int opt_flags = args->os_flags; char *bkc = p_bkc; unsigned *flags = &bkc_flags; @@ -666,7 +672,7 @@ static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, const ch *flags = 0; } else { if (opt_strings_flags(bkc, p_bkc_values, flags, true) != OK) { - *errmsg = e_invarg; + return e_invarg; } if (((*flags & BKC_AUTO) != 0) @@ -674,30 +680,41 @@ static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, const ch + ((*flags & BKC_NO) != 0) != 1) { // Must have exactly one of "auto", "yes" and "no". (void)opt_strings_flags(oldval, p_bkc_values, flags, true); - *errmsg = e_invarg; + return e_invarg; } } + + return NULL; } -static void did_set_backupext_or_patchmode(const char **errmsg) +/// The 'backupext' or the 'patchmode' option is changed. +const char *did_set_backupext_or_patchmode(optset_T *args FUNC_ATTR_UNUSED) { if (strcmp(*p_bex == '.' ? p_bex + 1 : p_bex, *p_pm == '.' ? p_pm + 1 : p_pm) == 0) { - *errmsg = e_backupext_and_patchmode_are_equal; + return e_backupext_and_patchmode_are_equal; } + + return NULL; } -static void did_set_breakindentopt(win_T *win, const char **errmsg) +/// The 'breakindentopt' option is changed. +const char *did_set_breakindentopt(optset_T *args) { + win_T *win = (win_T *)args->os_win; if (briopt_check(win) == FAIL) { - *errmsg = e_invarg; + return e_invarg; } // list setting requires a redraw if (win == curwin && win->w_briopt_list) { redraw_all_later(UPD_NOT_VALID); } + + return NULL; } +/// The 'isident' or the 'iskeyword' or the 'isprint' or the 'isfname' option is +/// changed. static void did_set_isopt(buf_T *buf, bool *did_chartab, const char **errmsg) { // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[] @@ -709,7 +726,8 @@ static void did_set_isopt(buf_T *buf, bool *did_chartab, const char **errmsg) } } -static void did_set_helpfile(void) +/// The 'helpfile' option is changed. +const char *did_set_helpfile(optset_T *args FUNC_ATTR_UNUSED) { // May compute new values for $VIM and $VIMRUNTIME if (didset_vim) { @@ -718,8 +736,10 @@ static void did_set_helpfile(void) if (didset_vimruntime) { vim_unsetenv_ext("VIMRUNTIME"); } + return NULL; } +/// The 'cursorlineopt' option is changed. static void did_set_cursorlineopt(win_T *win, char **varp, const char **errmsg) { if (**varp == NUL || fill_culopt_flags(*varp, win) != OK) { @@ -727,25 +747,28 @@ static void did_set_cursorlineopt(win_T *win, char **varp, const char **errmsg) } } -static void did_set_helplang(const char **errmsg) +/// The 'helplang' option is changed. +const char *did_set_helplang(optset_T *args FUNC_ATTR_UNUSED) { // Check for "", "ab", "ab,cd", etc. for (char *s = p_hlg; *s != NUL; s += 3) { if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL)) { - *errmsg = e_invarg; - break; + return e_invarg; } if (s[2] == NUL) { break; } } + return NULL; } -static void did_set_highlight(char **varp, const char **errmsg) +/// The 'highlight' option is changed. +const char *did_set_highlight(optset_T *args) { - if (strcmp(*varp, HIGHLIGHT_INIT) != 0) { - *errmsg = e_unsupportedoption; + if (strcmp(args->os_varp, HIGHLIGHT_INIT) != 0) { + return e_unsupportedoption; } + return NULL; } static void did_set_opt_flags(char *val, char **values, unsigned *flagp, bool list, @@ -761,32 +784,35 @@ static void did_set_opt_strings(char *val, char **values, bool list, const char did_set_opt_flags(val, values, NULL, list, errmsg); } -static void did_set_sessionoptions(char *oldval, const char **errmsg) +/// The 'sessionoptions' option is changed. +const char *did_set_sessionoptions(optset_T *args) { if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true) != OK) { - *errmsg = e_invarg; + return e_invarg; } if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) { // Don't allow both "sesdir" and "curdir". + const char *oldval = args->os_oldval.string; (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true); - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_ambiwidth(const char **errmsg) +/// The 'ambiwidth' option is changed. +const char *did_set_ambiwidth(optset_T *args FUNC_ATTR_UNUSED) { if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) { - *errmsg = e_invarg; - } else { - *errmsg = check_chars_options(); + return e_invarg; } + return check_chars_options(); } -static void did_set_background(const char **errmsg) +/// The 'background' option is changed. +const char *did_set_background(optset_T *args FUNC_ATTR_UNUSED) { if (check_opt_strings(p_bg, p_bg_values, false) != OK) { - *errmsg = e_invarg; - return; + return e_invarg; } int dark = (*p_bg == 'd'); @@ -803,27 +829,34 @@ static void did_set_background(const char **errmsg) check_string_option(&p_bg); init_highlight(false, false); } + return NULL; } -static void did_set_wildmode(const char **errmsg) +/// The 'wildmode' option is changed. +const char *did_set_wildmode(optset_T *args FUNC_ATTR_UNUSED) { if (check_opt_wim() == FAIL) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_winaltkeys(const char **errmsg) +/// The 'winaltkeys' option is changed. +const char *did_set_winaltkeys(optset_T *args FUNC_ATTR_UNUSED) { if (*p_wak == NUL || check_opt_strings(p_wak, p_wak_values, false) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_eventignore(const char **errmsg) +/// The 'eventignore' option is changed. +const char *did_set_eventignore(optset_T *args FUNC_ATTR_UNUSED) { if (check_ei() == FAIL) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } // 'encoding', 'fileencoding' and 'makeencoding' @@ -886,7 +919,7 @@ static void did_set_keymap(buf_T *buf, char **varp, int opt_flags, int *value_ch // even when the value comes from a modeline. *value_checked = true; - if (*errmsg == NULL) { + if (errmsg == NULL) { if (*buf->b_p_keymap != NUL) { // Installed a new keymap, switch on using it. buf->b_p_iminsert = B_IMODE_LMAP; @@ -910,28 +943,32 @@ static void did_set_keymap(buf_T *buf, char **varp, int opt_flags, int *value_ch } } -static void did_set_fileformat(buf_T *buf, char **varp, const char *oldval, int opt_flags, - const char **errmsg) +/// The 'fileformat' option is changed. +const char *did_set_fileformat(optset_T *args) { + buf_T *buf = (buf_T *)args->os_buf; + const char *oldval = args->os_oldval.string; + int opt_flags = args->os_flags; if (!MODIFIABLE(buf) && !(opt_flags & OPT_GLOBAL)) { - *errmsg = e_modifiable; - } else if (check_opt_strings(*varp, p_ff_values, false) != OK) { - *errmsg = e_invarg; - } else { - redraw_titles(); - // update flag in swap file - ml_setflags(buf); - // Redraw needed when switching to/from "mac": a CR in the text - // will be displayed differently. - if (get_fileformat(buf) == EOL_MAC || *oldval == 'm') { - redraw_buf_later(buf, UPD_NOT_VALID); - } + return e_modifiable; + } else if (check_opt_strings(args->os_varp, p_ff_values, false) != OK) { + return e_invarg; + } + redraw_titles(); + // update flag in swap file + ml_setflags(buf); + // Redraw needed when switching to/from "mac": a CR in the text + // will be displayed differently. + if (get_fileformat(buf) == EOL_MAC || *oldval == 'm') { + redraw_buf_later(buf, UPD_NOT_VALID); } + return NULL; } -static void did_set_matchpairs(char **varp, const char **errmsg) +/// The 'matchpairs' option is changed. +const char *did_set_matchpairs(optset_T *args) { - for (char *p = *varp; *p != NUL; p++) { + for (char *p = args->os_varp; *p != NUL; p++) { int x2 = -1; int x3 = -1; @@ -944,13 +981,22 @@ static void did_set_matchpairs(char **varp, const char **errmsg) p += utfc_ptr2len(p); } if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ',')) { - *errmsg = e_invarg; - break; + return e_invarg; } if (*p == NUL) { break; } } + return NULL; +} + +/// The 'cinoptions' option is changed. +const char *did_set_cinoptions(optset_T *args FUNC_ATTR_UNUSED) +{ + // TODO(vim): recognize errors + parse_cino(curbuf); + + return NULL; } static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, const char **errmsg) @@ -1008,18 +1054,20 @@ static void did_set_global_listfillchars(win_T *win, char **varp, int opt_flags, } } -static void did_set_verbosefile(const char **errmsg) +/// The 'verbosefile' option is changed. +const char *did_set_verbosefile(optset_T *args) { verbose_stop(); if (*p_vfile != NUL && verbose_open() == FAIL) { - *errmsg = e_invarg; + return (char *)e_invarg; } + return NULL; } static int shada_idx = -1; -static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, - size_t errbuflen, const char **errmsg) +static const char *did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, + size_t errbuflen) { // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo // option. @@ -1034,8 +1082,7 @@ static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, ch for (char *s = p_shada; *s;) { // Check it's a valid character if (vim_strchr("!\"%'/:<@cfhnrs", (uint8_t)(*s)) == NULL) { - *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); - break; + return illegal_char(errbuf, errbuflen, (uint8_t)(*s)); } if (*s == 'n') { // name is always last one break; @@ -1054,181 +1101,241 @@ static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, ch vim_snprintf(errbuf, errbuflen, _("E526: Missing number after <%s>"), transchar_byte((uint8_t)(*(s - 1)))); - *errmsg = errbuf; + return errbuf; } else { - *errmsg = ""; + return ""; } - break; } } if (*s == ',') { s++; } else if (*s) { if (errbuf != NULL) { - *errmsg = N_("E527: Missing comma"); + return N_("E527: Missing comma"); } else { - *errmsg = ""; + return ""; } - break; } } - if (*p_shada && *errmsg == NULL && get_shada_parameter('\'') < 0) { - *errmsg = N_("E528: Must specify a ' value"); + if (*p_shada && get_shada_parameter('\'') < 0) { + return N_("E528: Must specify a ' value"); } + return NULL; } -static void did_set_showbreak(char **varp, const char **errmsg) +/// The 'showbreak' option is changed. +const char *did_set_showbreak(optset_T *args) { - for (char *s = *varp; *s;) { + for (char *s = args->os_varp; *s;) { if (ptr2cells(s) != 1) { - *errmsg = e_showbreak_contains_unprintable_or_wide_character; + return e_showbreak_contains_unprintable_or_wide_character; } MB_PTR_ADV(s); } + return NULL; } -static void did_set_titleiconstring(char **varp) +/// The 'titlestring' or the 'iconstring' option is changed. +static const char *did_set_titleiconstring(optset_T *args, int flagval) { - // 'titlestring' and 'iconstring' - int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON; - // NULL => statusline syntax - if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) { + if (vim_strchr(args->os_varp, '%') && check_stl_option(args->os_varp) == NULL) { stl_syntax |= flagval; } else { stl_syntax &= ~flagval; } did_set_title(); + + return NULL; +} + +/// The 'titlestring' option is changed. +const char *did_set_titlestring(optset_T *args) +{ + return did_set_titleiconstring(args, STL_IN_TITLE); +} + +/// The 'iconstring' option is changed. +const char *did_set_iconstring(optset_T *args) +{ + return did_set_titleiconstring(args, STL_IN_ICON); } -static void did_set_selection(const char **errmsg) +/// The 'selection' option is changed. +const char *did_set_selection(optset_T *args FUNC_ATTR_UNUSED) { if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, false) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_keymodel(const char **errmsg) +/// The 'keymodel' option is changed. +const char *did_set_keymodel(optset_T *args FUNC_ATTR_UNUSED) { if (check_opt_strings(p_km, p_km_values, true) != OK) { - *errmsg = e_invarg; - return; + return e_invarg; } km_stopsel = (vim_strchr(p_km, 'o') != NULL); km_startsel = (vim_strchr(p_km, 'a') != NULL); + return NULL; } -static void did_set_display(const char **errmsg) +/// The 'display' option is changed. +const char *did_set_display(optset_T *args FUNC_ATTR_UNUSED) { if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) { - *errmsg = e_invarg; - return; + return e_invarg; } (void)init_chartab(); msg_grid_validate(); + return NULL; } -static void did_set_spellfile(char **varp, const char **errmsg) +/// The 'spellfile' option is changed. +const char *did_set_spellfile(optset_T *args) { // When there is a window for this buffer in which 'spell' // is set load the wordlists. - - if ((!valid_spellfile(*varp))) { - *errmsg = e_invarg; - } else { - *errmsg = did_set_spell_option(true); + if ((!valid_spellfile(args->os_varp))) { + return e_invarg; } + return did_set_spell_option(true); } -static void did_set_spell(char **varp, const char **errmsg) +const char *did_set_spelllang(optset_T *args) { // When there is a window for this buffer in which 'spell' // is set load the wordlists. - if (!valid_spelllang(*varp)) { - *errmsg = e_invarg; - } else { - *errmsg = did_set_spell_option(false); + if (!valid_spelllang(args->os_varp)) { + return e_invarg; } + return did_set_spell_option(false); } -static void did_set_spellcapcheck(win_T *win, const char **errmsg) +/// The 'spellcapcheck' option is changed. +const char *did_set_spellcapcheck(optset_T *args) { + win_T *win = (win_T *)args->os_win; // When 'spellcapcheck' is set compile the regexp program. - *errmsg = compile_cap_prog(win->w_s); + return compile_cap_prog(win->w_s); } -static void did_set_spelloptions(win_T *win, const char **errmsg) +/// The 'spelloptions' option is changed. +const char *did_set_spelloptions(optset_T *args) { + win_T *win = (win_T *)args->os_win; if (opt_strings_flags(win->w_s->b_p_spo, p_spo_values, &(win->w_s->b_p_spo_flags), true) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_spellsuggest(const char **errmsg) +/// The 'spellsuggest' option is changed. +const char *did_set_spellsuggest(optset_T *args FUNC_ATTR_UNUSED) { if (spell_check_sps() != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_mkspellmem(const char **errmsg) + /// The 'mkspellmem' option is changed. +const char *did_set_mkspellmem(optset_T *args FUNC_ATTR_UNUSED) { if (spell_check_msm() != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_buftype(buf_T *buf, win_T *win, const char **errmsg) +/// The 'buftype' option is changed. +const char *did_set_buftype(optset_T *args) { + buf_T *buf = (buf_T *)args->os_buf; + win_T *win = (win_T *)args->os_win; // When 'buftype' is set, check for valid value. if ((buf->terminal && buf->b_p_bt[0] != 't') || (!buf->terminal && buf->b_p_bt[0] == 't') || check_opt_strings(buf->b_p_bt, p_buftype_values, false) != OK) { - *errmsg = e_invarg; - } else { - if (win->w_status_height || global_stl_height()) { - win->w_redr_status = true; - redraw_later(win, UPD_VALID); - } - buf->b_help = (buf->b_p_bt[0] == 'h'); - redraw_titles(); + return e_invarg; } + if (win->w_status_height || global_stl_height()) { + win->w_redr_status = true; + redraw_later(win, UPD_VALID); + } + buf->b_help = (buf->b_p_bt[0] == 'h'); + redraw_titles(); + return NULL; } -// 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn' -static void did_set_statusline(win_T *win, char **varp, char **gvarp, const char **errmsg) +/// The 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn' option is changed. +/// +/// @param rulerformat true if the 'rulerformat' option is changed +/// @param statuscolumn true if the 'statuscolumn' option is changed +static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerformat, + bool statuscolumn) { - if (varp == &p_ruf) { // reset ru_wid first + win_T *win = (win_T *)args->os_win; + if (rulerformat) { // reset ru_wid first ru_wid = 0; - } else if (varp == &win->w_p_stc) { + } else if (statuscolumn) { // reset 'statuscolumn' width win->w_nrwidth_line_count = 0; } - char *s = *varp; - if (varp == &p_ruf && *s == '%') { + const char *errmsg = NULL; + char *s = args->os_varp; + if (rulerformat && *s == '%') { // set ru_wid if 'ruf' starts with "%99(" if (*++s == '-') { // ignore a '-' s++; } int wid = getdigits_int(&s, true, 0); - if (wid && *s == '(' && (*errmsg = check_stl_option(p_ruf)) == NULL) { + if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL) { ru_wid = wid; } else { - *errmsg = check_stl_option(p_ruf); + errmsg = check_stl_option(p_ruf); } - } else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') { + } else if (rulerformat || s[0] != '%' || s[1] != '!') { // check 'statusline', 'winbar', 'tabline' or 'statuscolumn' // only if it doesn't start with "%!" - *errmsg = check_stl_option(s); + errmsg = check_stl_option(s); } - if (varp == &p_ruf && *errmsg == NULL) { + if (rulerformat && errmsg == NULL) { comp_col(); } - // add / remove window bars for 'winbar' - if (gvarp == &p_wbr) { - set_winbar(true); - } + return errmsg; +} + +/// The 'statusline' option is changed. +const char *did_set_statusline(optset_T *args) +{ + return did_set_statustabline_rulerformat(args, false, false); +} + +/// The 'tabline' option is changed. +const char *did_set_tabline(optset_T *args) +{ + return did_set_statustabline_rulerformat(args, false, false); +} + +/// The 'rulerformat' option is changed. +const char *did_set_rulerformat(optset_T *args) +{ + return did_set_statustabline_rulerformat(args, true, false); +} + +/// The 'winbar' option is changed. +const char *did_set_winbar(optset_T *args) +{ + return did_set_statustabline_rulerformat(args, false, false); +} + +/// The 'statuscolumn' option is changed. +const char *did_set_statuscolumn(optset_T *args) +{ + return did_set_statustabline_rulerformat(args, false, true); } static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, const char **errmsg) @@ -1269,29 +1376,36 @@ static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, const } } -static void did_set_completeopt(const char **errmsg) +/// The 'completeopt' option is changed. +const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED) { if (check_opt_strings(p_cot, p_cot_values, true) != OK) { - *errmsg = e_invarg; - } else { - completeopt_was_set(); + return e_invarg; } + completeopt_was_set(); + return NULL; } #ifdef BACKSLASH_IN_FILENAME -static void did_set_completeslash(buf_T *buf, const char **errmsg) +/// The 'completeslash' option is changed. +const char *did_set_completeslash(optset_T *args) { + buf_T *buf = (buf_T *)args->os_buf; if (check_opt_strings(p_csl, p_csl_values, false) != OK || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } #endif -static void did_set_signcolumn(win_T *win, char **varp, const char *oldval, const char **errmsg) +/// The 'signcolumn' option is changed. +const char *did_set_signcolumn(optset_T *args) { - if (check_signcolumn(*varp) != OK) { - *errmsg = e_invarg; + win_T *win = (win_T *)args->os_win; + const char *oldval = args->os_oldval.string; + if (check_signcolumn(args->os_varp) != OK) { + return e_invarg; } // When changing the 'signcolumn' to or from 'number', recompute the // width of the number column if 'number' or 'relativenumber' is set. @@ -1300,28 +1414,37 @@ static void did_set_signcolumn(win_T *win, char **varp, const char *oldval, cons && (win->w_p_nu || win->w_p_rnu)) { win->w_nrwidth_line_count = 0; } + return NULL; } -static void did_set_foldcolumn(char **varp, const char **errmsg) +/// The 'foldcolumn' option is changed. +const char *did_set_foldcolumn(optset_T *args) { - if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) { - *errmsg = e_invarg; + if (*args->os_varp == NUL || check_opt_strings(args->os_varp, p_fdc_values, false) != OK) { + return e_invarg; } + return NULL; } -static void did_set_backspace(const char **errmsg) +/// The 'backspace' option is changed. +const char *did_set_backspace(optset_T *args FUNC_ATTR_UNUSED) { if (ascii_isdigit(*p_bs)) { if (*p_bs > '3' || p_bs[1] != NUL) { - *errmsg = e_invarg; + return e_invarg; } } else if (check_opt_strings(p_bs, p_bs_values, true) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_tagcase(buf_T *buf, int opt_flags, const char **errmsg) +/// The 'tagcase' option is changed. +const char *did_set_tagcase(optset_T *args) { + buf_T *buf = (buf_T *)args->os_buf; + int opt_flags = args->os_flags; + unsigned *flags; char *p; @@ -1338,73 +1461,95 @@ static void did_set_tagcase(buf_T *buf, int opt_flags, const char **errmsg) *flags = 0; } else if (*p == NUL || opt_strings_flags(p, p_tc_values, flags, false) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_diffopt(const char **errmsg) +/// The 'diffopt' option is changed. +const char *did_set_diffopt(optset_T *args FUNC_ATTR_UNUSED) { if (diffopt_changed() == FAIL) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_foldmethod(win_T *win, char **varp, const char **errmsg) +/// The 'foldmethod' option is changed. +const char *did_set_foldmethod(optset_T *args) { - if (check_opt_strings(*varp, p_fdm_values, false) != OK + win_T *win = (win_T *)args->os_win; + if (check_opt_strings(args->os_varp, p_fdm_values, false) != OK || *win->w_p_fdm == NUL) { - *errmsg = e_invarg; - } else { - foldUpdateAll(win); - if (foldmethodIsDiff(win)) { - newFoldLevel(); - } + return e_invarg; } + foldUpdateAll(win); + if (foldmethodIsDiff(win)) { + newFoldLevel(); + } + return NULL; } -static void did_set_foldmarker(win_T *win, char **varp, const char **errmsg) +/// The 'foldmarker' option is changed. +const char *did_set_foldmarker(optset_T *args) { - char *p = vim_strchr(*varp, ','); + win_T *win = (win_T *)args->os_win; + char *p = vim_strchr(args->os_varp, ','); + if (p == NULL) { - *errmsg = N_("E536: comma required"); - } else if (p == *varp || p[1] == NUL) { - *errmsg = e_invarg; - } else if (foldmethodIsMarker(win)) { + return N_("E536: comma required"); + } + + if (p == args->os_varp || p[1] == NUL) { + return e_invarg; + } + + if (foldmethodIsMarker(win)) { foldUpdateAll(win); } + + return NULL; } -static void did_set_commentstring(char **varp, const char **errmsg) +/// The 'commentstring' option is changed. +const char *did_set_commentstring(optset_T *args) { - if (**varp != NUL && strstr(*varp, "%s") == NULL) { - *errmsg = N_("E537: 'commentstring' must be empty or contain %s"); + if (*args->os_varp != NUL && strstr(args->os_varp, "%s") == NULL) { + return N_("E537: 'commentstring' must be empty or contain %s"); } + return NULL; } -static void did_set_foldignore(win_T *win) +/// The 'foldignore' option is changed. +const char *did_set_foldignore(optset_T *args) { + win_T *win = (win_T *)args->os_win; if (foldmethodIsIndent(win)) { foldUpdateAll(win); } + return NULL; } -static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, const char **errmsg) +/// The 'virtualedit' option is changed. +const char *did_set_virtualedit(optset_T *args) { + win_T *win = (win_T *)args->os_win; + char *ve = p_ve; unsigned *flags = &ve_flags; - if (opt_flags & OPT_LOCAL) { + if (args->os_flags & OPT_LOCAL) { ve = win->w_p_ve; flags = &win->w_ve_flags; } - if ((opt_flags & OPT_LOCAL) && *ve == NUL) { + if ((args->os_flags & OPT_LOCAL) && *ve == NUL) { // make the local value empty: use the global value *flags = 0; } else { if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) { - *errmsg = e_invarg; - } else if (strcmp(ve, oldval) != 0) { + return e_invarg; + } else if (strcmp(ve, args->os_oldval.string) != 0) { // Recompute cursor position in case the new 've' setting // changes something. validate_virtcol_win(win); @@ -1412,15 +1557,20 @@ static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, const c coladvance(win->w_virtcol); } } + return NULL; } -static void did_set_lispoptions(char **varp, const char **errmsg) +/// The 'lispoptions' option is changed. +const char *did_set_lispoptions(optset_T *args) { - if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) { - *errmsg = e_invarg; + if (*args->os_varp != NUL + && strcmp(args->os_varp, "expr:0") != 0 && strcmp(args->os_varp, "expr:1") != 0) { + return e_invarg; } + return NULL; } +/// The 'filetype' or the 'syntax' option is changed. static void did_set_filetype_or_syntax(char **varp, char *oldval, int *value_checked, bool *value_changed, const char **errmsg) { @@ -1436,66 +1586,75 @@ static void did_set_filetype_or_syntax(char **varp, char *oldval, int *value_che *value_checked = true; } -static void did_set_winhl(win_T *win, const char **errmsg) +const char *did_set_winhl(optset_T *args) { + win_T *win = (win_T *)args->os_win; if (!parse_winhl_opt(win)) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_varsoftabstop(buf_T *buf, char **varp, const char **errmsg) +/// The 'varsofttabstop' option is changed. +const char *did_set_varsofttabstop(optset_T *args) { - if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) { + buf_T *buf = (buf_T *)args->os_buf; + + if (!(args->os_varp[0]) || ((args->os_varp[0]) == '0' && !(args->os_varp[1]))) { XFREE_CLEAR(buf->b_p_vsts_array); - return; + return NULL; } - for (char *cp = *varp; *cp; cp++) { + for (char *cp = args->os_varp; *cp; cp++) { if (ascii_isdigit(*cp)) { continue; } - if (*cp == ',' && cp > *varp && *(cp - 1) != ',') { + if (*cp == ',' && cp > args->os_varp && *(cp - 1) != ',') { continue; } - *errmsg = e_invarg; - return; + return e_invarg; } long *oldarray = buf->b_p_vsts_array; - if (tabstop_set(*varp, &(buf->b_p_vsts_array))) { + if (tabstop_set(args->os_varp, &(buf->b_p_vsts_array))) { xfree(oldarray); } else { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_vartabstop(buf_T *buf, win_T *win, char **varp, const char **errmsg) +/// The 'varstabstop' option is changed. +const char *did_set_vartabstop(optset_T *args) { - if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) { + buf_T *buf = (buf_T *)args->os_buf; + win_T *win = (win_T *)args->os_win; + + if (!(args->os_varp[0]) || ((args->os_varp[0]) == '0' && !(args->os_varp[1]))) { XFREE_CLEAR(buf->b_p_vts_array); - return; + return NULL; } - for (char *cp = *varp; *cp; cp++) { + for (char *cp = args->os_varp; *cp; cp++) { if (ascii_isdigit(*cp)) { continue; } - if (*cp == ',' && cp > *varp && *(cp - 1) != ',') { + if (*cp == ',' && cp > args->os_varp && *(cp - 1) != ',') { continue; } - *errmsg = e_invarg; - return; + return e_invarg; } long *oldarray = buf->b_p_vts_array; - if (tabstop_set(*varp, &(buf->b_p_vts_array))) { + if (tabstop_set(args->os_varp, &(buf->b_p_vts_array))) { xfree(oldarray); if (foldmethodIsIndent(win)) { foldUpdateAll(win); } } else { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } static void did_set_optexpr(char **varp) @@ -1519,6 +1678,11 @@ static void did_set_option_listflag(char **varp, char *flags, char *errbuf, size } } +const char *did_set_guicursor(optset_T *args FUNC_ATTR_UNUSED) +{ + return parse_shape_opt(SHAPE_CURSOR); +} + // When 'syntax' is set, load the syntax of that name static void do_syntax_autocmd(buf_T *buf, bool value_changed) { @@ -1574,87 +1738,68 @@ static void do_spelllang_source(win_T *win) /// /// @return NULL for success, or an untranslated error message for an error static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char **varp, - char *oldval, char *errbuf, size_t errbuflen, - int opt_flags, int *value_checked) + char *oldval, const char *value, char *errbuf, + size_t errbuflen, int opt_flags, int *value_checked) { const char *errmsg = NULL; bool did_chartab = false; vimoption_T *opt = get_option(opt_idx); bool free_oldval = (opt->flags & P_ALLOCED); + opt_did_set_cb_T did_set_cb = get_option_did_set_cb(opt_idx); bool value_changed = false; // Get the global option to compare with, otherwise we would have to check // two values for all local options. char **gvarp = (char **)get_varp_scope(opt, OPT_GLOBAL); + optset_T args = { + .os_varp = *varp, + .os_flags = opt_flags, + .os_oldval.string = oldval, + .os_newval.string = value, + .os_win = curwin, + .os_buf = curbuf, + }; + // Disallow changing some options from secure mode if ((secure || sandbox != 0) && (opt->flags & P_SECURE)) { errmsg = e_secure; // Check for a "normal" directory or file name in some options. } else if (check_illegal_path_names(*varp, opt->flags)) { errmsg = e_invarg; - } else if (gvarp == &p_bkc) { // 'backupcopy' - did_set_backupcopy(buf, oldval, opt_flags, &errmsg); - } else if (varp == &p_bex // 'backupext' - || varp == &p_pm) { // 'patchmode' - did_set_backupext_or_patchmode(&errmsg); - } else if (varp == &win->w_p_briopt) { // 'breakindentopt' - did_set_breakindentopt(win, &errmsg); + } else if (did_set_cb != NULL) { + // Invoke the option specific callback function to validate and apply + // the new option value. + errmsg = did_set_cb(&args); } else if (varp == &p_isi // 'isident' || varp == &buf->b_p_isk // 'iskeyword' || varp == &p_isp // 'isprint' || varp == &p_isf) { // 'isfname' did_set_isopt(buf, &did_chartab, &errmsg); - } else if (varp == &p_hf) { // 'helpfile' - did_set_helpfile(); - } else if (varp == &p_rtp // 'runtimepath' - || varp == &p_pp) { // 'packpath' - runtime_search_path_invalidate(); } else if (gvarp == &win->w_allbuf_opt.wo_culopt) { // 'cursorlineopt' did_set_cursorlineopt(win, varp, &errmsg); } else if (varp == &win->w_p_cc) { // 'colorcolumn' errmsg = check_colorcolumn(win); - } else if (varp == &p_hlg) { // 'helplang' - did_set_helplang(&errmsg); - } else if (varp == &p_hl) { // 'highlight' - did_set_highlight(varp, &errmsg); } else if (varp == &p_jop) { // 'jumpoptions' did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true, &errmsg); } else if (gvarp == &p_nf) { // 'nrformats' did_set_opt_strings(*varp, p_nf_values, true, &errmsg); - } else if (varp == &p_ssop) { // 'sessionoptions' - did_set_sessionoptions(oldval, &errmsg); } else if (varp == &p_vop) { // 'viewoptions' did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, true, &errmsg); } else if (varp == &p_rdb) { // 'redrawdebug' did_set_opt_flags(p_rdb, p_rdb_values, &rdb_flags, true, &errmsg); } else if (varp == &p_sbo) { // 'scrollopt' did_set_opt_strings(p_sbo, p_scbopt_values, true, &errmsg); - } else if (varp == &p_ambw // 'ambiwidth' - || (int *)varp == &p_emoji) { // 'emoji' - did_set_ambiwidth(&errmsg); - } else if (varp == &p_bg) { // 'background' - did_set_background(&errmsg); - } else if (varp == &p_wim) { // 'wildmode' - did_set_wildmode(&errmsg); } else if (varp == &p_wop) { // 'wildoptions' did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true, &errmsg); - } else if (varp == &p_wak) { // 'winaltkeys' - did_set_winaltkeys(&errmsg); - } else if (varp == &p_ei) { // 'eventignore' - did_set_eventignore(&errmsg); } else if (varp == &p_enc // 'encoding' || gvarp == &p_fenc // 'fileencoding' || gvarp == &p_menc) { // 'makeencoding' did_set_encoding(buf, varp, gvarp, opt_flags, &errmsg); } else if (varp == &buf->b_p_keymap) { // 'keymap' did_set_keymap(buf, varp, opt_flags, value_checked, &errmsg); - } else if (gvarp == &p_ff) { // 'fileformat' - did_set_fileformat(buf, varp, oldval, opt_flags, &errmsg); } else if (varp == &p_ffs) { // 'fileformats' did_set_opt_strings(p_ffs, p_ff_values, true, &errmsg); - } else if (gvarp == &p_mps) { // 'matchpairs' - did_set_matchpairs(varp, &errmsg); } else if (gvarp == &p_com) { // 'comments' did_set_comments(varp, errbuf, errbuflen, &errmsg); } else if (varp == &p_lcs // global 'listchars' @@ -1664,123 +1809,43 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx errmsg = set_chars_option(win, varp, true); } else if (varp == &win->w_p_fcs) { // local 'fillchars' errmsg = set_chars_option(win, varp, true); - } else if (varp == &p_cedit) { // 'cedit' - errmsg = check_cedit(); - } else if (varp == &p_vfile) { // 'verbosefile' - did_set_verbosefile(&errmsg); } else if (varp == &p_shada) { // 'shada' - did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen, &errmsg); - } else if (gvarp == &p_sbr) { // 'showbreak' - did_set_showbreak(varp, &errmsg); - } else if (varp == &p_guicursor) { // 'guicursor' - errmsg = parse_shape_opt(SHAPE_CURSOR); - } else if (varp == &p_langmap) { // 'langmap' - langmap_set(); - } else if (varp == &p_breakat) { // 'breakat' - fill_breakat_flags(); - } else if (varp == &p_titlestring // 'titlestring' - || varp == &p_iconstring) { // 'iconstring' - did_set_titleiconstring(varp); - } else if (varp == &p_sel) { // 'selection' - did_set_selection(&errmsg); + errmsg = did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen); } else if (varp == &p_slm) { // 'selectmode' did_set_opt_strings(p_slm, p_slm_values, true, &errmsg); - } else if (varp == &p_km) { // 'keymodel' - did_set_keymodel(&errmsg); } else if (varp == &p_mousem) { // 'mousemodel' did_set_opt_strings(p_mousem, p_mousem_values, false, &errmsg); - } else if (varp == &p_mousescroll) { // 'mousescroll' - errmsg = check_mousescroll(p_mousescroll); } else if (varp == &p_swb) { // 'switchbuf' did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true, &errmsg); } else if (varp == &p_spk) { // 'splitkeep' did_set_opt_strings(p_spk, p_spk_values, false, &errmsg); } else if (varp == &p_debug) { // 'debug' did_set_opt_strings(p_debug, p_debug_values, true, &errmsg); - } else if (varp == &p_dy) { // 'display' - did_set_display(&errmsg); } else if (varp == &p_ead) { // 'eadirection' did_set_opt_strings(p_ead, p_ead_values, false, &errmsg); } else if (varp == &p_cb) { // 'clipboard' did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true, &errmsg); - } else if (varp == &win->w_s->b_p_spf) { // 'spellfile' - did_set_spellfile(varp, &errmsg); - } else if (varp == &win->w_s->b_p_spl) { // 'spell' - did_set_spell(varp, &errmsg); - } else if (varp == &win->w_s->b_p_spc) { // 'spellcapcheck' - did_set_spellcapcheck(win, &errmsg); - } else if (varp == &win->w_s->b_p_spo) { // 'spelloptions' - did_set_spelloptions(win, &errmsg); - } else if (varp == &p_sps) { // 'spellsuggest' - did_set_spellsuggest(&errmsg); - } else if (varp == &p_msm) { // 'mkspellmem' - did_set_mkspellmem(&errmsg); } else if (gvarp == &p_bh) { // 'bufhidden' did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false, &errmsg); - } else if (gvarp == &p_bt) { // 'buftype' - did_set_buftype(buf, win, &errmsg); - } else if (gvarp == &p_stl // 'statusline' - || gvarp == &p_wbr // 'winbar' - || varp == &p_tal // 'tabline' - || varp == &p_ruf // 'rulerformat' - || varp == &win->w_p_stc) { // 'statuscolumn' - did_set_statusline(win, varp, gvarp, &errmsg); } else if (gvarp == &p_cpt) { // 'complete' did_set_complete(varp, errbuf, errbuflen, &errmsg); - } else if (varp == &p_cot) { // 'completeopt' - did_set_completeopt(&errmsg); -#ifdef BACKSLASH_IN_FILENAME - } else if (gvarp == &p_csl) { // 'completeslash' - did_set_completeslash(buf, &errmsg); -#endif - } else if (varp == &win->w_p_scl) { // 'signcolumn' - did_set_signcolumn(win, varp, oldval, &errmsg); } else if (varp == &p_sloc) { // 'showcmdloc' did_set_opt_strings(*varp, p_sloc_values, false, &errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fdc) { // 'foldcolumn' - did_set_foldcolumn(varp, &errmsg); - } else if (varp == &p_bs) { // 'backspace' - did_set_backspace(&errmsg); } else if (varp == &p_bo) { did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true, &errmsg); - } else if (gvarp == &p_tc) { // 'tagcase' - did_set_tagcase(buf, opt_flags, &errmsg); } else if (varp == &p_cmp) { // 'casemap' did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true, &errmsg); - } else if (varp == &p_dip) { // 'diffopt' - did_set_diffopt(&errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fdm) { // 'foldmethod' - did_set_foldmethod(win, varp, &errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fmr) { // 'foldmarker' - did_set_foldmarker(win, varp, &errmsg); - } else if (gvarp == &p_cms) { // 'commentstring' - did_set_commentstring(varp, &errmsg); } else if (varp == &p_fdo) { // 'foldopen' did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true, &errmsg); } else if (varp == &p_fcl) { // 'foldclose' did_set_opt_strings(*varp, p_fcl_values, true, &errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fdi) { // 'foldignore' - did_set_foldignore(win); - } else if (gvarp == &p_ve) { // 'virtualedit' - did_set_virtualedit(win, opt_flags, oldval, &errmsg); - } else if (gvarp == &p_cino) { // 'cinoptions' - // TODO(vim): recognize errors - parse_cino(buf); - } else if (gvarp == &p_lop) { // 'lispoptions' - did_set_lispoptions(varp, &errmsg); } else if (varp == &p_icm) { // 'inccommand' did_set_opt_strings(*varp, p_icm_values, false, &errmsg); } else if (gvarp == &p_ft // 'filetype' || gvarp == &p_syn) { // 'syntax' did_set_filetype_or_syntax(varp, oldval, value_checked, &value_changed, &errmsg); - } else if (varp == &win->w_p_winhl) { // 'winhighlight' - did_set_winhl(win, &errmsg); } else if (varp == &p_tpf) { did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true, &errmsg); - } else if (varp == &buf->b_p_vsts) { // 'varsofttabstop' - did_set_varsoftabstop(buf, varp, &errmsg); - } else if (varp == &buf->b_p_vts) { // 'vartabstop' - did_set_vartabstop(buf, win, varp, &errmsg); } else if (varp == &p_dex // 'diffexpr' || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr' || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext' @@ -1793,18 +1858,6 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx if (varp == &win->w_p_fde && foldmethodIsExpr(win)) { foldUpdateAll(win); } - } else if (gvarp == &p_cfu) { // 'completefunc' - set_completefunc_option(&errmsg); - } else if (gvarp == &p_ofu) { // 'omnifunc' - set_omnifunc_option(buf, &errmsg); - } else if (gvarp == &p_tsrfu) { // 'thesaurusfunc' - set_thesaurusfunc_option(&errmsg); - } else if (varp == &p_opfunc) { // 'operatorfunc' - set_operatorfunc_option(&errmsg); - } else if (varp == &p_qftf) { // 'quickfixtextfunc' - qf_process_qftf_option(&errmsg); - } else if (gvarp == &p_tfu) { // 'tagfunc' - set_tagfunc_option(&errmsg); } else if (varp == &p_ww) { // 'whichwrap' did_set_option_listflag(varp, WW_ALL, errbuf, errbuflen, &errmsg); } else if (varp == &p_shm) { // 'shortmess' @@ -1817,12 +1870,6 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx did_set_option_listflag(varp, COCU_ALL, errbuf, errbuflen, &errmsg); } else if (varp == &p_mouse) { // 'mouse' did_set_option_listflag(varp, MOUSE_ALL, errbuf, errbuflen, &errmsg); - } else if (gvarp == &p_flp) { // 'formatlistpat' - if (win->w_briopt_list) { - // Changing Formatlistpattern when briopt includes the list setting: - // redraw - redraw_all_later(UPD_NOT_VALID); - } } // If an error is detected, restore the previous value. @@ -1875,6 +1922,16 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx setmouse(); // in case 'mouse' changed } + if ((varp == &p_flp || varp == &(buf->b_p_flp)) + && win->w_briopt_list) { + // Changing Formatlistpattern when briopt includes the list setting: + // redraw + redraw_all_later(UPD_NOT_VALID); + } else if (varp == &p_wbr || varp == &(win->w_p_wbr)) { + // add / remove window bars for 'winbar' + set_winbar(true); + } + if (win->w_curswant != MAXCOL && (opt->flags & (P_CURSWANT | P_RALL)) != 0) { win->w_set_curswant = true; @@ -1885,11 +1942,11 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx return errmsg; } -const char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf, +const char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *value, char *errbuf, size_t errbuflen, int opt_flags, int *value_checked) { - return did_set_string_option_for(curbuf, curwin, opt_idx, varp, oldval, errbuf, errbuflen, - opt_flags, value_checked); + return did_set_string_option_for(curbuf, curwin, opt_idx, varp, oldval, value, errbuf, + errbuflen, opt_flags, value_checked); } /// Check an option that can be a range of string values. @@ -1910,7 +1967,7 @@ static int check_opt_strings(char *val, char **values, int list) /// @param list when true: accept a list of values /// /// @return OK for correct value, FAIL otherwise. Empty is always OK. -static int opt_strings_flags(char *val, char **values, unsigned *flagp, bool list) +static int opt_strings_flags(const char *val, char **values, unsigned *flagp, bool list) { unsigned new_flags = 0; @@ -1946,9 +2003,8 @@ int check_ff_value(char *p) static char shm_buf[SHM_LEN]; static int set_shm_recursive = 0; -/// Save the acutal shortmess Flags and clear them -/// temporarily to avoid that file messages -/// overwrites any output from the following commands. +/// Save the actual shortmess Flags and clear them temporarily to avoid that +/// file messages overwrites any output from the following commands. /// /// Caller must make sure to first call save_clear_shm_value() and then /// restore_shm_value() exactly the same number of times. -- cgit From 46022a6b38adf335fe2454a5b498dcd3d317d154 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 26 Apr 2023 16:14:48 +0100 Subject: vim-patch:9.0.1345: too many "else if" statements for handling options Problem: Too many "else if" statements for handling options. Solution: Add more functions to handle options. (Yegappan Lakshmanan, closes vim/vim#12051) https://github.com/vim/vim/commit/8ad862a1f9d6f4128de856ccfabbeb7546d33b98 --- src/nvim/optionstr.c | 210 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 153 insertions(+), 57 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index d7cf948730..9c173f5c2c 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -698,6 +698,18 @@ const char *did_set_backupext_or_patchmode(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +/// The 'belloff' option is changed. +const char *did_set_belloff(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true); +} + +/// The 'termpastefilter' option is changed. +const char *did_set_termpastefilter(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true); +} + /// The 'breakindentopt' option is changed. const char *did_set_breakindentopt(optset_T *args) { @@ -740,11 +752,15 @@ const char *did_set_helpfile(optset_T *args FUNC_ATTR_UNUSED) } /// The 'cursorlineopt' option is changed. -static void did_set_cursorlineopt(win_T *win, char **varp, const char **errmsg) +const char *did_set_cursorlineopt(optset_T *args) { - if (**varp == NUL || fill_culopt_flags(*varp, win) != OK) { - *errmsg = e_invarg; + win_T *win = (win_T *)args->os_win; + + if (*args->os_varp == NUL || fill_culopt_flags(args->os_varp, win) != OK) { + return e_invarg; } + + return NULL; } /// The 'helplang' option is changed. @@ -771,17 +787,29 @@ const char *did_set_highlight(optset_T *args) return NULL; } -static void did_set_opt_flags(char *val, char **values, unsigned *flagp, bool list, - const char **errmsg) +static const char *did_set_opt_flags(char *val, char **values, unsigned *flagp, bool list) { if (opt_strings_flags(val, values, flagp, list) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; +} + +static const char *did_set_opt_strings(char *val, char **values, bool list) +{ + return did_set_opt_flags(val, values, NULL, list); +} + +/// The 'selectmode' option is changed. +const char *did_set_selectmode(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_strings(p_slm, p_slm_values, true); } -static void did_set_opt_strings(char *val, char **values, bool list, const char **errmsg) +/// The 'inccommand' option is changed. +const char *did_set_inccommand(optset_T *args FUNC_ATTR_UNUSED) { - did_set_opt_flags(val, values, NULL, list, errmsg); + return did_set_opt_strings(p_icm, p_icm_values, false); } /// The 'sessionoptions' option is changed. @@ -832,6 +860,18 @@ const char *did_set_background(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +/// The 'clipboard' option is changed. +const char *did_set_clipboard(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true); +} + +/// The 'foldopen' option is changed. +const char *did_set_foldopen(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true); +} + /// The 'wildmode' option is changed. const char *did_set_wildmode(optset_T *args FUNC_ATTR_UNUSED) { @@ -859,6 +899,12 @@ const char *did_set_eventignore(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +/// The 'eadirection' option is changed. +const char *did_set_eadirection(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_strings(p_ead, p_ead_values, false); +} + // 'encoding', 'fileencoding' and 'makeencoding' static void did_set_encoding(buf_T *buf, char **varp, char **gvarp, int opt_flags, const char **errmsg) @@ -965,6 +1011,12 @@ const char *did_set_fileformat(optset_T *args) return NULL; } +/// The 'fileformats' option is changed. +const char *did_set_fileformats(optset_T *args) +{ + return did_set_opt_strings(p_ffs, p_ff_values, true); +} + /// The 'matchpairs' option is changed. const char *did_set_matchpairs(optset_T *args) { @@ -999,6 +1051,13 @@ const char *did_set_cinoptions(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +/// The 'colorcolumn' option is changed. +const char *did_set_colorcolumn(optset_T *args) +{ + win_T *win = (win_T *)args->os_win; + return check_colorcolumn(win); +} + static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, const char **errmsg) { for (char *s = *varp; *s;) { @@ -1064,6 +1123,12 @@ const char *did_set_verbosefile(optset_T *args) return NULL; } +/// The 'viewoptions' option is changed. +const char *did_set_viewoptions(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, true); +} + static int shada_idx = -1; static const char *did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, @@ -1241,7 +1306,13 @@ const char *did_set_spellsuggest(optset_T *args FUNC_ATTR_UNUSED) return NULL; } - /// The 'mkspellmem' option is changed. +/// The 'splitkeep' option is changed. +const char *did_set_splitkeep(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_strings(p_spk, p_spk_values, false); +} + +/// The 'mkspellmem' option is changed. const char *did_set_mkspellmem(optset_T *args FUNC_ATTR_UNUSED) { if (spell_check_msm() != OK) { @@ -1250,6 +1321,19 @@ const char *did_set_mkspellmem(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +/// The 'mousemodel' option is changed. +const char *did_set_mousemodel(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_strings(p_mousem, p_mousem_values, false); +} + +/// The 'bufhidden' option is changed. +const char *did_set_bufhidden(optset_T *args) +{ + buf_T *buf = (buf_T *)args->os_buf; + return did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false); +} + /// The 'buftype' option is changed. const char *did_set_buftype(optset_T *args) { @@ -1270,6 +1354,12 @@ const char *did_set_buftype(optset_T *args) return NULL; } +/// The 'casemap' option is changed. +const char *did_set_casemap(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true); +} + /// The 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn' option is changed. /// /// @param rulerformat true if the 'rulerformat' option is changed @@ -1338,6 +1428,12 @@ const char *did_set_statuscolumn(optset_T *args) return did_set_statustabline_rulerformat(args, false, true); } +/// The 'scrollopt' option is changed. +const char *did_set_scrollopt(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_strings(p_sbo, p_scbopt_values, true); +} + static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, const char **errmsg) { // check if it is a valid value for 'complete' -- Acevedo @@ -1399,6 +1495,12 @@ const char *did_set_completeslash(optset_T *args) } #endif +/// The 'showcmdloc' option is changed. +const char *did_set_showcmdloc(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_strings(p_sloc, p_sloc_values, true); +} + /// The 'signcolumn' option is changed. const char *did_set_signcolumn(optset_T *args) { @@ -1439,6 +1541,12 @@ const char *did_set_backspace(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +/// The 'switchbuf' option is changed. +const char *did_set_switchbuf(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true); +} + /// The 'tagcase' option is changed. const char *did_set_tagcase(optset_T *args) { @@ -1466,6 +1574,12 @@ const char *did_set_tagcase(optset_T *args) return NULL; } +/// The 'debug' option is changed. +const char *did_set_debug(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_strings(p_debug, p_debug_values, false); +} + /// The 'diffopt' option is changed. const char *did_set_diffopt(optset_T *args FUNC_ATTR_UNUSED) { @@ -1560,6 +1674,24 @@ const char *did_set_virtualedit(optset_T *args) return NULL; } +/// The 'jumpoptions' option is changed. +const char *did_set_jumpoptions(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true); +} + +/// The 'redrawdebug' option is changed. +const char *did_set_redrawdebug(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_rdb, p_rdb_values, &rdb_flags, true); +} + +/// The 'wildoptions' option is changed. +const char *did_set_wildoptions(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true); +} + /// The 'lispoptions' option is changed. const char *did_set_lispoptions(optset_T *args) { @@ -1657,6 +1789,12 @@ const char *did_set_vartabstop(optset_T *args) return NULL; } +/// The 'nrformats' option is changed. +const char *did_set_nrformats(optset_T *args) +{ + return did_set_opt_strings(args->os_varp, p_nf_values, true); +} + static void did_set_optexpr(char **varp) { char *name = get_scriptlocal_funcname(*varp); @@ -1666,6 +1804,12 @@ static void did_set_optexpr(char **varp) } } +/// The 'foldclose' option is changed. +const char *did_set_foldclose(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_strings(p_fcl, p_fcl_values, true); +} + // handle option that is a list of flags. static void did_set_option_listflag(char **varp, char *flags, char *errbuf, size_t errbuflen, const char **errmsg) @@ -1776,30 +1920,12 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx || varp == &p_isp // 'isprint' || varp == &p_isf) { // 'isfname' did_set_isopt(buf, &did_chartab, &errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_culopt) { // 'cursorlineopt' - did_set_cursorlineopt(win, varp, &errmsg); - } else if (varp == &win->w_p_cc) { // 'colorcolumn' - errmsg = check_colorcolumn(win); - } else if (varp == &p_jop) { // 'jumpoptions' - did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true, &errmsg); - } else if (gvarp == &p_nf) { // 'nrformats' - did_set_opt_strings(*varp, p_nf_values, true, &errmsg); - } else if (varp == &p_vop) { // 'viewoptions' - did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, true, &errmsg); - } else if (varp == &p_rdb) { // 'redrawdebug' - did_set_opt_flags(p_rdb, p_rdb_values, &rdb_flags, true, &errmsg); - } else if (varp == &p_sbo) { // 'scrollopt' - did_set_opt_strings(p_sbo, p_scbopt_values, true, &errmsg); - } else if (varp == &p_wop) { // 'wildoptions' - did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true, &errmsg); } else if (varp == &p_enc // 'encoding' || gvarp == &p_fenc // 'fileencoding' || gvarp == &p_menc) { // 'makeencoding' did_set_encoding(buf, varp, gvarp, opt_flags, &errmsg); } else if (varp == &buf->b_p_keymap) { // 'keymap' did_set_keymap(buf, varp, opt_flags, value_checked, &errmsg); - } else if (varp == &p_ffs) { // 'fileformats' - did_set_opt_strings(p_ffs, p_ff_values, true, &errmsg); } else if (gvarp == &p_com) { // 'comments' did_set_comments(varp, errbuf, errbuflen, &errmsg); } else if (varp == &p_lcs // global 'listchars' @@ -1811,41 +1937,11 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx errmsg = set_chars_option(win, varp, true); } else if (varp == &p_shada) { // 'shada' errmsg = did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen); - } else if (varp == &p_slm) { // 'selectmode' - did_set_opt_strings(p_slm, p_slm_values, true, &errmsg); - } else if (varp == &p_mousem) { // 'mousemodel' - did_set_opt_strings(p_mousem, p_mousem_values, false, &errmsg); - } else if (varp == &p_swb) { // 'switchbuf' - did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true, &errmsg); - } else if (varp == &p_spk) { // 'splitkeep' - did_set_opt_strings(p_spk, p_spk_values, false, &errmsg); - } else if (varp == &p_debug) { // 'debug' - did_set_opt_strings(p_debug, p_debug_values, true, &errmsg); - } else if (varp == &p_ead) { // 'eadirection' - did_set_opt_strings(p_ead, p_ead_values, false, &errmsg); - } else if (varp == &p_cb) { // 'clipboard' - did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true, &errmsg); - } else if (gvarp == &p_bh) { // 'bufhidden' - did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false, &errmsg); } else if (gvarp == &p_cpt) { // 'complete' did_set_complete(varp, errbuf, errbuflen, &errmsg); - } else if (varp == &p_sloc) { // 'showcmdloc' - did_set_opt_strings(*varp, p_sloc_values, false, &errmsg); - } else if (varp == &p_bo) { - did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true, &errmsg); - } else if (varp == &p_cmp) { // 'casemap' - did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true, &errmsg); - } else if (varp == &p_fdo) { // 'foldopen' - did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true, &errmsg); - } else if (varp == &p_fcl) { // 'foldclose' - did_set_opt_strings(*varp, p_fcl_values, true, &errmsg); - } else if (varp == &p_icm) { // 'inccommand' - did_set_opt_strings(*varp, p_icm_values, false, &errmsg); } else if (gvarp == &p_ft // 'filetype' || gvarp == &p_syn) { // 'syntax' did_set_filetype_or_syntax(varp, oldval, value_checked, &value_changed, &errmsg); - } else if (varp == &p_tpf) { - did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true, &errmsg); } else if (varp == &p_dex // 'diffexpr' || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr' || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext' -- cgit From bb7371ad82a1b65217565d578158f269dc735139 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 26 Apr 2023 17:12:01 +0100 Subject: vim-patch:9.0.1353: too many "else if" statements to handle option values Problem: Too many "else if" statements to handle option values. Solution: Add more functions to handle option value changes. (Yegappan Lakshmanan, closes vim/vim#12058) https://github.com/vim/vim/commit/6d611de58c8e324491415da8e79c6bd3faa3e848 --- src/nvim/optionstr.c | 156 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 102 insertions(+), 54 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 9c173f5c2c..8b77af591c 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -860,6 +860,24 @@ const char *did_set_background(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +/// The 'whichwrap' option is changed. +const char *did_set_whichwrap(optset_T *args) +{ + return did_set_option_listflag(args->os_varp, WW_ALL, args->os_errbuf, args->os_errbuflen); +} + +/// The 'shortmess' option is changed. +const char *did_set_shortmess(optset_T *args) +{ + return did_set_option_listflag(args->os_varp, SHM_ALL, args->os_errbuf, args->os_errbuflen); +} + +/// The 'cpoptions' option is changed. +const char *did_set_cpoptions(optset_T *args) +{ + return did_set_option_listflag(args->os_varp, CPO_VI, args->os_errbuf, args->os_errbuflen); +} + /// The 'clipboard' option is changed. const char *did_set_clipboard(optset_T *args FUNC_ATTR_UNUSED) { @@ -872,6 +890,24 @@ const char *did_set_foldopen(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true); } +/// The 'formatoptions' option is changed. +const char *did_set_formatoptions(optset_T *args) +{ + return did_set_option_listflag(args->os_varp, FO_ALL, args->os_errbuf, args->os_errbuflen); +} + +/// The 'concealcursor' option is changed. +const char *did_set_concealcursor(optset_T *args) +{ + return did_set_option_listflag(args->os_varp, COCU_ALL, args->os_errbuf, args->os_errbuflen); +} + +/// The 'mouse' option is changed. +const char *did_set_mouse(optset_T *args) +{ + return did_set_option_listflag(args->os_varp, MOUSE_ALL, args->os_errbuf, args->os_errbuflen); +} + /// The 'wildmode' option is changed. const char *did_set_wildmode(optset_T *args FUNC_ATTR_UNUSED) { @@ -1058,23 +1094,24 @@ const char *did_set_colorcolumn(optset_T *args) return check_colorcolumn(win); } -static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, const char **errmsg) +const char *did_set_comments(optset_T *args) { - for (char *s = *varp; *s;) { + char *errmsg = NULL; + for (char *s = args->os_varp; *s;) { while (*s && *s != ':') { if (vim_strchr(COM_ALL, (uint8_t)(*s)) == NULL && !ascii_isdigit(*s) && *s != '-') { - *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); + errmsg = illegal_char(args->os_errbuf, args->os_errbuflen, (uint8_t)(*s)); break; } s++; } if (*s++ == NUL) { - *errmsg = N_("E524: Missing colon"); + errmsg = N_("E524: Missing colon"); } else if (*s == ',' || *s == NUL) { - *errmsg = N_("E525: Zero length string"); + errmsg = N_("E525: Zero length string"); } - if (*errmsg != NULL) { + if (errmsg != NULL) { break; } while (*s && *s != ',') { @@ -1085,6 +1122,7 @@ static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, const } s = skip_to_option_part(s); } + return errmsg; } static void did_set_global_listfillchars(win_T *win, char **varp, int opt_flags, @@ -1434,10 +1472,11 @@ const char *did_set_scrollopt(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_strings(p_sbo, p_scbopt_values, true); } -static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, const char **errmsg) +/// The 'complete' option is changed. +const char *did_set_complete(optset_T *args) { // check if it is a valid value for 'complete' -- Acevedo - for (char *s = *varp; *s;) { + for (char *s = args->os_varp; *s;) { while (*s == ',' || *s == ' ') { s++; } @@ -1445,8 +1484,7 @@ static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, const break; } if (vim_strchr(".wbuksid]tU", (uint8_t)(*s)) == NULL) { - *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); - break; + return illegal_char(args->os_errbuf, args->os_errbuflen, (uint8_t)(*s)); } if (*++s != NUL && *s != ',' && *s != ' ') { if (s[-1] == 'k' || s[-1] == 's') { @@ -1458,18 +1496,17 @@ static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, const s++; } } else { - if (errbuf != NULL) { - vim_snprintf(errbuf, errbuflen, + if (args->os_errbuf != NULL) { + vim_snprintf(args->os_errbuf, args->os_errbuflen, _("E535: Illegal character after <%c>"), *--s); - *errmsg = errbuf; - } else { - *errmsg = ""; + return args->os_errbuf; } - break; + return ""; } } } + return NULL; } /// The 'completeopt' option is changed. @@ -1795,13 +1832,45 @@ const char *did_set_nrformats(optset_T *args) return did_set_opt_strings(args->os_varp, p_nf_values, true); } -static void did_set_optexpr(char **varp) +/// Returns TRUE if the option pointed by "varp" or "gvarp" is one of the +/// '*expr' options: 'balloonexpr', 'diffexpr', 'foldexpr', 'foldtext', +/// 'formatexpr', 'includeexpr', 'indentexpr', 'patchexpr', 'printexpr' or +/// 'charconvert'. +static int is_expr_option(win_T *win, char **varp, char **gvarp) +{ + return (varp == &p_dex // 'diffexpr' + || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr' + || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext' + || gvarp == &p_fex // 'formatexpr' + || gvarp == &p_inex // 'includeexpr' + || gvarp == &p_inde // 'indentexpr' + || varp == &p_pex // 'patchexpr' + || varp == &p_ccv); // 'charconvert' +} + +/// One of the '*expr' options is changed:, 'diffexpr', 'foldexpr', 'foldtext', +/// 'formatexpr', 'includeexpr', 'indentexpr', 'patchexpr' and 'charconvert'. +const char *did_set_optexpr(optset_T *args) { - char *name = get_scriptlocal_funcname(*varp); + // If the option value starts with or s:, then replace that with + // the script identifier. + char *name = get_scriptlocal_funcname(args->os_varp); if (name != NULL) { - free_string_option(*varp); - *varp = name; + free_string_option(args->os_varp); + args->os_varp = name; } + return NULL; +} + +/// The 'foldexpr' option is changed. +const char *did_set_foldexpr(optset_T *args) +{ + win_T *win = (win_T *)args->os_win; + (void)did_set_optexpr(args); + if (foldmethodIsExpr(win)) { + foldUpdateAll(win); + } + return NULL; } /// The 'foldclose' option is changed. @@ -1810,16 +1879,16 @@ const char *did_set_foldclose(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_strings(p_fcl, p_fcl_values, true); } -// handle option that is a list of flags. -static void did_set_option_listflag(char **varp, char *flags, char *errbuf, size_t errbuflen, - const char **errmsg) +/// An option which is a list of flags is set. Valid values are in 'flags'. +static const char *did_set_option_listflag(char *varp, char *flags, char *errbuf, size_t errbuflen) { - for (char *s = *varp; *s; s++) { + for (char *s = varp; *s; s++) { if (vim_strchr(flags, (uint8_t)(*s)) == NULL) { - *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); - break; + return illegal_char(errbuf, errbuflen, (uint8_t)(*s)); } } + + return NULL; } const char *did_set_guicursor(optset_T *args FUNC_ATTR_UNUSED) @@ -1901,6 +1970,8 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx .os_flags = opt_flags, .os_oldval.string = oldval, .os_newval.string = value, + .os_errbuf = errbuf, + .os_errbuflen = errbuflen, .os_win = curwin, .os_buf = curbuf, }; @@ -1915,6 +1986,11 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx // Invoke the option specific callback function to validate and apply // the new option value. errmsg = did_set_cb(&args); + // When processing the '*expr' options (e.g. diffexpr, foldexpr, etc.), + // the did_set_cb() function may modify '*varp'. + if (errmsg == NULL && is_expr_option(curwin, varp, gvarp)) { + *varp = args.os_varp; + } } else if (varp == &p_isi // 'isident' || varp == &buf->b_p_isk // 'iskeyword' || varp == &p_isp // 'isprint' @@ -1926,8 +2002,6 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx did_set_encoding(buf, varp, gvarp, opt_flags, &errmsg); } else if (varp == &buf->b_p_keymap) { // 'keymap' did_set_keymap(buf, varp, opt_flags, value_checked, &errmsg); - } else if (gvarp == &p_com) { // 'comments' - did_set_comments(varp, errbuf, errbuflen, &errmsg); } else if (varp == &p_lcs // global 'listchars' || varp == &p_fcs) { // global 'fillchars' did_set_global_listfillchars(win, varp, opt_flags, &errmsg); @@ -1937,35 +2011,9 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx errmsg = set_chars_option(win, varp, true); } else if (varp == &p_shada) { // 'shada' errmsg = did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen); - } else if (gvarp == &p_cpt) { // 'complete' - did_set_complete(varp, errbuf, errbuflen, &errmsg); } else if (gvarp == &p_ft // 'filetype' || gvarp == &p_syn) { // 'syntax' did_set_filetype_or_syntax(varp, oldval, value_checked, &value_changed, &errmsg); - } else if (varp == &p_dex // 'diffexpr' - || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr' - || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext' - || gvarp == &p_fex // 'formatexpr' - || gvarp == &p_inex // 'includeexpr' - || gvarp == &p_inde // 'indentexpr' - || varp == &p_pex // 'patchexpr' - || varp == &p_ccv) { // 'charconvert' - did_set_optexpr(varp); - if (varp == &win->w_p_fde && foldmethodIsExpr(win)) { - foldUpdateAll(win); - } - } else if (varp == &p_ww) { // 'whichwrap' - did_set_option_listflag(varp, WW_ALL, errbuf, errbuflen, &errmsg); - } else if (varp == &p_shm) { // 'shortmess' - did_set_option_listflag(varp, SHM_ALL, errbuf, errbuflen, &errmsg); - } else if (varp == &p_cpo) { // 'cpoptions' - did_set_option_listflag(varp, CPO_VI, errbuf, errbuflen, &errmsg); - } else if (varp == &buf->b_p_fo) { // 'formatoptions' - did_set_option_listflag(varp, FO_ALL, errbuf, errbuflen, &errmsg); - } else if (varp == &win->w_p_cocu) { // 'concealcursor' - did_set_option_listflag(varp, COCU_ALL, errbuf, errbuflen, &errmsg); - } else if (varp == &p_mouse) { // 'mouse' - did_set_option_listflag(varp, MOUSE_ALL, errbuf, errbuflen, &errmsg); } // If an error is detected, restore the previous value. -- cgit From 5cda9c267ab951c9d3ba05cddd0e8f63b3a7680a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 26 Apr 2023 15:32:48 +0100 Subject: vim-patch:9.0.1359: too many "else if" statements in handling options Problem: Too many "else if" statements in handling options. Solution: Add more functions for handling option changes. (Yegappan Lakshmanan, closes vim/vim#12060) https://github.com/vim/vim/commit/5da901bb68717b2baff6e971c1517219b6ee3a67 --- src/nvim/optionstr.c | 81 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 31 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 8b77af591c..694738d8f1 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -727,15 +727,17 @@ const char *did_set_breakindentopt(optset_T *args) /// The 'isident' or the 'iskeyword' or the 'isprint' or the 'isfname' option is /// changed. -static void did_set_isopt(buf_T *buf, bool *did_chartab, const char **errmsg) +const char *did_set_isopt(optset_T *args) { + buf_T *buf = (buf_T *)args->os_buf; // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[] // If the new option is invalid, use old value. // 'lisp' option: refill g_chartab[] for '-' char if (buf_init_chartab(buf, true) == FAIL) { - *did_chartab = true; // need to restore it below - *errmsg = e_invarg; // error in value + args->os_restore_chartab = true; // need to restore it below + return e_invarg; // error in value } + return NULL; } /// The 'helpfile' option is changed. @@ -978,12 +980,14 @@ static void did_set_encoding(buf_T *buf, char **varp, char **gvarp, int opt_flag } } -static void did_set_keymap(buf_T *buf, char **varp, int opt_flags, int *value_checked, - const char **errmsg) +/// The 'keymap' option has changed. +const char *did_set_keymap(optset_T *args) { - if (!valid_filetype(*varp)) { - *errmsg = e_invarg; - return; + buf_T *buf = (buf_T *)args->os_buf; + int opt_flags = args->os_flags; + + if (!valid_filetype(args->os_varp)) { + return e_invarg; } int secure_save = secure; @@ -993,13 +997,13 @@ static void did_set_keymap(buf_T *buf, char **varp, int opt_flags, int *value_ch secure = 0; // load or unload key mapping tables - *errmsg = keymap_init(); + const char *errmsg = keymap_init(); secure = secure_save; // Since we check the value, there is no need to set P_INSECURE, // even when the value comes from a modeline. - *value_checked = true; + args->os_value_checked = true; if (errmsg == NULL) { if (*buf->b_p_keymap != NUL) { @@ -1023,6 +1027,8 @@ static void did_set_keymap(buf_T *buf, char **varp, int opt_flags, int *value_ch } status_redraw_buf(buf); } + + return errmsg; } /// The 'fileformat' option is changed. @@ -1739,20 +1745,31 @@ const char *did_set_lispoptions(optset_T *args) return NULL; } +/// The 'rightleftcmd' option is changed. +const char *did_set_rightleftcmd(optset_T *args) +{ + // Currently only "search" is a supported value. + if (*args->os_varp != NUL && strcmp(args->os_varp, "search") != 0) { + return e_invarg; + } + + return NULL; +} + /// The 'filetype' or the 'syntax' option is changed. -static void did_set_filetype_or_syntax(char **varp, char *oldval, int *value_checked, - bool *value_changed, const char **errmsg) +const char *did_set_filetype_or_syntax(optset_T *args) { - if (!valid_filetype(*varp)) { - *errmsg = e_invarg; - return; + if (!valid_filetype(args->os_varp)) { + return e_invarg; } - *value_changed = strcmp(oldval, *varp) != 0; + args->os_value_changed = strcmp(args->os_oldval.string, args->os_varp) != 0; // Since we check the value, there is no need to set P_INSECURE, // even when the value comes from a modeline. - *value_checked = true; + args->os_value_checked = true; + + return NULL; } const char *did_set_winhl(optset_T *args) @@ -1955,7 +1972,7 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx size_t errbuflen, int opt_flags, int *value_checked) { const char *errmsg = NULL; - bool did_chartab = false; + int restore_chartab = false; vimoption_T *opt = get_option(opt_idx); bool free_oldval = (opt->flags & P_ALLOCED); opt_did_set_cb_T did_set_cb = get_option_did_set_cb(opt_idx); @@ -1970,6 +1987,9 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx .os_flags = opt_flags, .os_oldval.string = oldval, .os_newval.string = value, + .os_value_checked = false, + .os_value_changed = false, + .os_restore_chartab = false, .os_errbuf = errbuf, .os_errbuflen = errbuflen, .os_win = curwin, @@ -1991,17 +2011,21 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx if (errmsg == NULL && is_expr_option(curwin, varp, gvarp)) { *varp = args.os_varp; } - } else if (varp == &p_isi // 'isident' - || varp == &buf->b_p_isk // 'iskeyword' - || varp == &p_isp // 'isprint' - || varp == &p_isf) { // 'isfname' - did_set_isopt(buf, &did_chartab, &errmsg); + // The 'filetype' and 'syntax' option callback functions may change + // the os_value_changed field. + value_changed = args.os_value_changed; + // The 'keymap', 'filetype' and 'syntax' option callback functions + // may change the os_value_checked field. + *value_checked = args.os_value_checked; + // The 'isident', 'iskeyword', 'isprint' and 'isfname' options may + // change the character table. On failure, this needs to be restored. + restore_chartab = args.os_restore_chartab; + } else if (varp == &p_shada) { // 'shada' + errmsg = did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen); } else if (varp == &p_enc // 'encoding' || gvarp == &p_fenc // 'fileencoding' || gvarp == &p_menc) { // 'makeencoding' did_set_encoding(buf, varp, gvarp, opt_flags, &errmsg); - } else if (varp == &buf->b_p_keymap) { // 'keymap' - did_set_keymap(buf, varp, opt_flags, value_checked, &errmsg); } else if (varp == &p_lcs // global 'listchars' || varp == &p_fcs) { // global 'fillchars' did_set_global_listfillchars(win, varp, opt_flags, &errmsg); @@ -2009,11 +2033,6 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx errmsg = set_chars_option(win, varp, true); } else if (varp == &win->w_p_fcs) { // local 'fillchars' errmsg = set_chars_option(win, varp, true); - } else if (varp == &p_shada) { // 'shada' - errmsg = did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen); - } else if (gvarp == &p_ft // 'filetype' - || gvarp == &p_syn) { // 'syntax' - did_set_filetype_or_syntax(varp, oldval, value_checked, &value_changed, &errmsg); } // If an error is detected, restore the previous value. @@ -2021,7 +2040,7 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx free_string_option(*varp); *varp = oldval; // When resetting some values, need to act on it. - if (did_chartab) { + if (restore_chartab) { (void)buf_init_chartab(buf, true); } } else { -- cgit From d04770a5436f2cc054473b983109f7a94dec6878 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 26 Apr 2023 12:00:12 +0100 Subject: vim-patch:9.0.1369: still some "else if" constructs for setting options Problem: Still some "else if" constructs for setting options. Solution: Add a few more functions for handling options. (Yegappan Lakshmanan, closes vim/vim#12090) https://github.com/vim/vim/commit/c6ff21e876af0e3ad59664dd0f69359c4b6e9f1d --- src/nvim/optionstr.c | 119 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 81 insertions(+), 38 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 694738d8f1..2c38835625 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1131,30 +1131,79 @@ const char *did_set_comments(optset_T *args) return errmsg; } -static void did_set_global_listfillchars(win_T *win, char **varp, int opt_flags, - const char **errmsg) -{ - char **local_ptr = varp == &p_lcs ? &win->w_p_lcs : &win->w_p_fcs; - // only apply the global value to "win" when it does not have a local value - *errmsg = set_chars_option(win, varp, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL)); - if (*errmsg == NULL) { - // If the current window is set to use the global - // 'listchars'/'fillchars' value, clear the window-local value. - if (!(opt_flags & OPT_GLOBAL)) { - clear_string_option(local_ptr); - } - FOR_ALL_TAB_WINDOWS(tp, wp) { - // If the current window has a local value need to apply it - // again, it was changed when setting the global value. - // If no error was returned above, we don't expect an error - // here, so ignore the return value. - local_ptr = varp == &p_lcs ? &wp->w_p_lcs : &wp->w_p_fcs; - if (**local_ptr == NUL) { - (void)set_chars_option(wp, local_ptr, true); +/// The global 'listchars' or 'fillchars' option is changed. +static const char *did_set_global_listfillchars(win_T *win, char *val, bool opt_lcs, int opt_flags) +{ + const char *errmsg = NULL; + char **local_ptr = opt_lcs ? &win->w_p_lcs : &win->w_p_fcs; + + // only apply the global value to "win" when it does not have a + // local value + if (opt_lcs) { + errmsg = set_listchars_option(win, val, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL)); + } else { + errmsg = set_fillchars_option(win, val, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL)); + } + if (errmsg != NULL) { + return errmsg; + } + + // If the current window is set to use the global + // 'listchars'/'fillchars' value, clear the window-local value. + if (!(opt_flags & OPT_GLOBAL)) { + clear_string_option(local_ptr); + } + + FOR_ALL_TAB_WINDOWS(tp, wp) { + // If the current window has a local value need to apply it + // again, it was changed when setting the global value. + // If no error was returned above, we don't expect an error + // here, so ignore the return value. + if (opt_lcs) { + if (*wp->w_p_lcs == NUL) { + (void)set_listchars_option(wp, wp->w_p_lcs, true); + } + } else { + if (*wp->w_p_fcs == NUL) { + (void)set_fillchars_option(wp, wp->w_p_fcs, true); } } - redraw_all_later(UPD_NOT_VALID); } + + redraw_all_later(UPD_NOT_VALID); + + return NULL; +} + +/// Handle the new value of 'fillchars'. +const char *set_fillchars_option(win_T *wp, char *val, int apply) +{ + return set_chars_option(wp, val, false, apply); +} + +/// Handle the new value of 'listchars'. +const char *set_listchars_option(win_T *wp, char *val, int apply) +{ + return set_chars_option(wp, val, true, apply); +} + +/// The 'fillchars' option or the 'listchars' option is changed. +const char *did_set_chars_option(optset_T *args) +{ + win_T *win = (win_T *)args->os_win; + const char *errmsg = NULL; + + if (args->os_varp == p_lcs // global 'listchars' + || args->os_varp == p_fcs) { // global 'fillchars' + errmsg = did_set_global_listfillchars(win, args->os_varp, + args->os_varp == p_lcs, args->os_flags); + } else if (args->os_varp == win->w_p_lcs) { // local 'listchars' + errmsg = set_listchars_option(win, args->os_varp, true); + } else if (args->os_varp == win->w_p_fcs) { // local 'fillchars' + errmsg = set_fillchars_option(win, args->os_varp, true); + } + + return errmsg; } /// The 'verbosefile' option is changed. @@ -2026,13 +2075,6 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx || gvarp == &p_fenc // 'fileencoding' || gvarp == &p_menc) { // 'makeencoding' did_set_encoding(buf, varp, gvarp, opt_flags, &errmsg); - } else if (varp == &p_lcs // global 'listchars' - || varp == &p_fcs) { // global 'fillchars' - did_set_global_listfillchars(win, varp, opt_flags, &errmsg); - } else if (varp == &win->w_p_lcs) { // local 'listchars' - errmsg = set_chars_option(win, varp, true); - } else if (varp == &win->w_p_fcs) { // local 'fillchars' - errmsg = set_chars_option(win, varp, true); } // If an error is detected, restore the previous value. @@ -2231,16 +2273,17 @@ static int get_encoded_char_adv(const char **p) /// Handle setting 'listchars' or 'fillchars'. /// Assume monocell characters /// -/// @param varp either the global or the window-local value. +/// @param val points to either the global or the window-local value. +/// @param opt_lcs is tue for "listchars" and FALSE for "fillchars". /// @param apply if false, do not store the flags, only check for errors. /// @return error message, NULL if it's OK. -const char *set_chars_option(win_T *wp, char **varp, bool apply) +static const char *set_chars_option(win_T *wp, const char *val, bool opt_lcs, bool apply) { const char *last_multispace = NULL; // Last occurrence of "multispace:" const char *last_lmultispace = NULL; // Last occurrence of "leadmultispace:" int multispace_len = 0; // Length of lcs-multispace string int lead_multispace_len = 0; // Length of lcs-leadmultispace string - const bool is_listchars = (varp == &p_lcs || varp == &wp->w_p_lcs); + const bool is_listchars = opt_lcs; struct chars_tab { int *cp; ///< char value @@ -2284,17 +2327,17 @@ const char *set_chars_option(win_T *wp, char **varp, bool apply) struct chars_tab *tab; int entries; - const char *value = *varp; + const char *value = val; if (is_listchars) { tab = lcs_tab; entries = ARRAY_SIZE(lcs_tab); - if (varp == &wp->w_p_lcs && wp->w_p_lcs[0] == NUL) { + if (opt_lcs && wp->w_p_lcs[0] == NUL) { value = p_lcs; // local value is empty, use the global value } } else { tab = fcs_tab; entries = ARRAY_SIZE(fcs_tab); - if (varp == &wp->w_p_fcs && wp->w_p_fcs[0] == NUL) { + if (!opt_lcs && wp->w_p_fcs[0] == NUL) { value = p_fcs; // local value is empty, use the global value } } @@ -2460,17 +2503,17 @@ const char *set_chars_option(win_T *wp, char **varp, bool apply) /// @return an untranslated error message if any of them is invalid, NULL otherwise. const char *check_chars_options(void) { - if (set_chars_option(curwin, &p_lcs, false) != NULL) { + if (set_listchars_option(curwin, p_lcs, false) != NULL) { return e_conflicts_with_value_of_listchars; } - if (set_chars_option(curwin, &p_fcs, false) != NULL) { + if (set_fillchars_option(curwin, p_fcs, false) != NULL) { return e_conflicts_with_value_of_fillchars; } FOR_ALL_TAB_WINDOWS(tp, wp) { - if (set_chars_option(wp, &wp->w_p_lcs, true) != NULL) { + if (set_listchars_option(wp, wp->w_p_lcs, true) != NULL) { return e_conflicts_with_value_of_listchars; } - if (set_chars_option(wp, &wp->w_p_fcs, true) != NULL) { + if (set_fillchars_option(wp, wp->w_p_fcs, true) != NULL) { return e_conflicts_with_value_of_fillchars; } } -- cgit From 0d1ae6e1b7718d5b6bcd80f5e0f5a737070267e3 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 26 Apr 2023 12:23:10 +0100 Subject: vim-patch:9.0.1374: function for setting options not used consistently Problem: Function for setting options not used consistently. Solution: Use a function for 'encoding' and terminal options. (Yegappan Lakshmanan, closes vim/vim#12099) https://github.com/vim/vim/commit/c727b19e9f1df36e44321d933334c7b4961daa54 --- src/nvim/optionstr.c | 209 ++++++++++++++++++++++++++++----------------------- 1 file changed, 117 insertions(+), 92 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 2c38835625..96d383bbb1 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -757,8 +757,9 @@ const char *did_set_helpfile(optset_T *args FUNC_ATTR_UNUSED) const char *did_set_cursorlineopt(optset_T *args) { win_T *win = (win_T *)args->os_win; + char **varp = (char **)args->os_varp; - if (*args->os_varp == NUL || fill_culopt_flags(args->os_varp, win) != OK) { + if (**varp == NUL || fill_culopt_flags(*varp, win) != OK) { return e_invarg; } @@ -783,7 +784,9 @@ const char *did_set_helplang(optset_T *args FUNC_ATTR_UNUSED) /// The 'highlight' option is changed. const char *did_set_highlight(optset_T *args) { - if (strcmp(args->os_varp, HIGHLIGHT_INIT) != 0) { + char **varp = (char **)args->os_varp; + + if (strcmp(*varp, HIGHLIGHT_INIT) != 0) { return e_unsupportedoption; } return NULL; @@ -865,19 +868,25 @@ const char *did_set_background(optset_T *args FUNC_ATTR_UNUSED) /// The 'whichwrap' option is changed. const char *did_set_whichwrap(optset_T *args) { - return did_set_option_listflag(args->os_varp, WW_ALL, args->os_errbuf, args->os_errbuflen); + char **varp = (char **)args->os_varp; + + return did_set_option_listflag(*varp, WW_ALL, args->os_errbuf, args->os_errbuflen); } /// The 'shortmess' option is changed. const char *did_set_shortmess(optset_T *args) { - return did_set_option_listflag(args->os_varp, SHM_ALL, args->os_errbuf, args->os_errbuflen); + char **varp = (char **)args->os_varp; + + return did_set_option_listflag(*varp, SHM_ALL, args->os_errbuf, args->os_errbuflen); } /// The 'cpoptions' option is changed. const char *did_set_cpoptions(optset_T *args) { - return did_set_option_listflag(args->os_varp, CPO_VI, args->os_errbuf, args->os_errbuflen); + char **varp = (char **)args->os_varp; + + return did_set_option_listflag(*varp, CPO_VI, args->os_errbuf, args->os_errbuflen); } /// The 'clipboard' option is changed. @@ -895,19 +904,25 @@ const char *did_set_foldopen(optset_T *args FUNC_ATTR_UNUSED) /// The 'formatoptions' option is changed. const char *did_set_formatoptions(optset_T *args) { - return did_set_option_listflag(args->os_varp, FO_ALL, args->os_errbuf, args->os_errbuflen); + char **varp = (char **)args->os_varp; + + return did_set_option_listflag(*varp, FO_ALL, args->os_errbuf, args->os_errbuflen); } /// The 'concealcursor' option is changed. const char *did_set_concealcursor(optset_T *args) { - return did_set_option_listflag(args->os_varp, COCU_ALL, args->os_errbuf, args->os_errbuflen); + char **varp = (char **)args->os_varp; + + return did_set_option_listflag(*varp, COCU_ALL, args->os_errbuf, args->os_errbuflen); } /// The 'mouse' option is changed. const char *did_set_mouse(optset_T *args) { - return did_set_option_listflag(args->os_varp, MOUSE_ALL, args->os_errbuf, args->os_errbuflen); + char **varp = (char **)args->os_varp; + + return did_set_option_listflag(*varp, MOUSE_ALL, args->os_errbuf, args->os_errbuflen); } /// The 'wildmode' option is changed. @@ -943,21 +958,26 @@ const char *did_set_eadirection(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_strings(p_ead, p_ead_values, false); } -// 'encoding', 'fileencoding' and 'makeencoding' -static void did_set_encoding(buf_T *buf, char **varp, char **gvarp, int opt_flags, - const char **errmsg) +/// One of the 'encoding', 'fileencoding' or 'makeencoding' +/// options is changed. +const char *did_set_encoding(optset_T *args) { + buf_T *buf = (buf_T *)args->os_buf; + char **varp = (char **)args->os_varp; + int opt_flags = args->os_flags; + // Get the global option to compare with, otherwise we would have to check + // two values for all local options. + char **gvarp = (char **)get_option_varp_scope_from(args->os_idx, OPT_GLOBAL, buf, NULL); + if (gvarp == &p_fenc) { if (!MODIFIABLE(buf) && opt_flags != OPT_GLOBAL) { - *errmsg = e_modifiable; - return; + return e_modifiable; } if (vim_strchr(*varp, ',') != NULL) { // No comma allowed in 'fileencoding'; catches confusing it // with 'fileencodings'. - *errmsg = e_invarg; - return; + return e_invarg; } // May show a "+" in the title now. @@ -973,20 +993,21 @@ static void did_set_encoding(buf_T *buf, char **varp, char **gvarp, int opt_flag if (varp == &p_enc) { // only encoding=utf-8 allowed if (strcmp(p_enc, "utf-8") != 0) { - *errmsg = e_unsupportedoption; - return; + return e_unsupportedoption; } spell_reload(); } + return NULL; } /// The 'keymap' option has changed. const char *did_set_keymap(optset_T *args) { buf_T *buf = (buf_T *)args->os_buf; + char **varp = (char **)args->os_varp; int opt_flags = args->os_flags; - if (!valid_filetype(args->os_varp)) { + if (!valid_filetype(*varp)) { return e_invarg; } @@ -1035,11 +1056,12 @@ const char *did_set_keymap(optset_T *args) const char *did_set_fileformat(optset_T *args) { buf_T *buf = (buf_T *)args->os_buf; + char **varp = (char **)args->os_varp; const char *oldval = args->os_oldval.string; int opt_flags = args->os_flags; if (!MODIFIABLE(buf) && !(opt_flags & OPT_GLOBAL)) { return e_modifiable; - } else if (check_opt_strings(args->os_varp, p_ff_values, false) != OK) { + } else if (check_opt_strings(*varp, p_ff_values, false) != OK) { return e_invarg; } redraw_titles(); @@ -1062,7 +1084,9 @@ const char *did_set_fileformats(optset_T *args) /// The 'matchpairs' option is changed. const char *did_set_matchpairs(optset_T *args) { - for (char *p = args->os_varp; *p != NUL; p++) { + char **varp = (char **)args->os_varp; + + for (char *p = *varp; *p != NUL; p++) { int x2 = -1; int x3 = -1; @@ -1102,8 +1126,9 @@ const char *did_set_colorcolumn(optset_T *args) const char *did_set_comments(optset_T *args) { + char **varp = (char **)args->os_varp; char *errmsg = NULL; - for (char *s = args->os_varp; *s;) { + for (char *s = *varp; *s;) { while (*s && *s != ':') { if (vim_strchr(COM_ALL, (uint8_t)(*s)) == NULL && !ascii_isdigit(*s) && *s != '-') { @@ -1191,16 +1216,16 @@ const char *set_listchars_option(win_T *wp, char *val, int apply) const char *did_set_chars_option(optset_T *args) { win_T *win = (win_T *)args->os_win; + char **varp = (char **)args->os_varp; const char *errmsg = NULL; - if (args->os_varp == p_lcs // global 'listchars' - || args->os_varp == p_fcs) { // global 'fillchars' - errmsg = did_set_global_listfillchars(win, args->os_varp, - args->os_varp == p_lcs, args->os_flags); - } else if (args->os_varp == win->w_p_lcs) { // local 'listchars' - errmsg = set_listchars_option(win, args->os_varp, true); - } else if (args->os_varp == win->w_p_fcs) { // local 'fillchars' - errmsg = set_fillchars_option(win, args->os_varp, true); + if (varp == &p_lcs // global 'listchars' + || varp == &p_fcs) { // global 'fillchars' + errmsg = did_set_global_listfillchars(win, *varp, varp == &p_lcs, args->os_flags); + } else if (varp == &win->w_p_lcs) { // local 'listchars' + errmsg = set_listchars_option(win, *varp, true); + } else if (varp == &win->w_p_fcs) { // local 'fillchars' + errmsg = set_fillchars_option(win, *varp, true); } return errmsg; @@ -1284,7 +1309,9 @@ static const char *did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_old /// The 'showbreak' option is changed. const char *did_set_showbreak(optset_T *args) { - for (char *s = args->os_varp; *s;) { + char **varp = (char **)args->os_varp; + + for (char *s = *varp; *s;) { if (ptr2cells(s) != 1) { return e_showbreak_contains_unprintable_or_wide_character; } @@ -1296,8 +1323,10 @@ const char *did_set_showbreak(optset_T *args) /// The 'titlestring' or the 'iconstring' option is changed. static const char *did_set_titleiconstring(optset_T *args, int flagval) { + char **varp = (char **)args->os_varp; + // NULL => statusline syntax - if (vim_strchr(args->os_varp, '%') && check_stl_option(args->os_varp) == NULL) { + if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) { stl_syntax |= flagval; } else { stl_syntax &= ~flagval; @@ -1353,9 +1382,11 @@ const char *did_set_display(optset_T *args FUNC_ATTR_UNUSED) /// The 'spellfile' option is changed. const char *did_set_spellfile(optset_T *args) { + char **varp = (char **)args->os_varp; + // When there is a window for this buffer in which 'spell' // is set load the wordlists. - if ((!valid_spellfile(args->os_varp))) { + if ((!valid_spellfile(*varp))) { return e_invarg; } return did_set_spell_option(true); @@ -1363,9 +1394,11 @@ const char *did_set_spellfile(optset_T *args) const char *did_set_spelllang(optset_T *args) { + char **varp = (char **)args->os_varp; + // When there is a window for this buffer in which 'spell' // is set load the wordlists. - if (!valid_spelllang(args->os_varp)) { + if (!valid_spelllang(*varp)) { return e_invarg; } return did_set_spell_option(false); @@ -1461,6 +1494,7 @@ static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerf bool statuscolumn) { win_T *win = (win_T *)args->os_win; + char **varp = (char **)args->os_varp; if (rulerformat) { // reset ru_wid first ru_wid = 0; } else if (statuscolumn) { @@ -1468,7 +1502,7 @@ static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerf win->w_nrwidth_line_count = 0; } const char *errmsg = NULL; - char *s = args->os_varp; + char *s = *varp; if (rulerformat && *s == '%') { // set ru_wid if 'ruf' starts with "%99(" if (*++s == '-') { // ignore a '-' @@ -1530,8 +1564,10 @@ const char *did_set_scrollopt(optset_T *args FUNC_ATTR_UNUSED) /// The 'complete' option is changed. const char *did_set_complete(optset_T *args) { + char **varp = (char **)args->os_varp; + // check if it is a valid value for 'complete' -- Acevedo - for (char *s = args->os_varp; *s;) { + for (char *s = *varp; *s;) { while (*s == ',' || *s == ' ') { s++; } @@ -1597,8 +1633,9 @@ const char *did_set_showcmdloc(optset_T *args FUNC_ATTR_UNUSED) const char *did_set_signcolumn(optset_T *args) { win_T *win = (win_T *)args->os_win; + char **varp = (char **)args->os_varp; const char *oldval = args->os_oldval.string; - if (check_signcolumn(args->os_varp) != OK) { + if (check_signcolumn(*varp) != OK) { return e_invarg; } // When changing the 'signcolumn' to or from 'number', recompute the @@ -1614,7 +1651,8 @@ const char *did_set_signcolumn(optset_T *args) /// The 'foldcolumn' option is changed. const char *did_set_foldcolumn(optset_T *args) { - if (*args->os_varp == NUL || check_opt_strings(args->os_varp, p_fdc_values, false) != OK) { + char **varp = (char **)args->os_varp; + if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) { return e_invarg; } return NULL; @@ -1685,7 +1723,8 @@ const char *did_set_diffopt(optset_T *args FUNC_ATTR_UNUSED) const char *did_set_foldmethod(optset_T *args) { win_T *win = (win_T *)args->os_win; - if (check_opt_strings(args->os_varp, p_fdm_values, false) != OK + char **varp = (char **)args->os_varp; + if (check_opt_strings(*varp, p_fdm_values, false) != OK || *win->w_p_fdm == NUL) { return e_invarg; } @@ -1700,13 +1739,14 @@ const char *did_set_foldmethod(optset_T *args) const char *did_set_foldmarker(optset_T *args) { win_T *win = (win_T *)args->os_win; - char *p = vim_strchr(args->os_varp, ','); + char **varp = (char **)args->os_varp; + char *p = vim_strchr(*varp, ','); if (p == NULL) { return N_("E536: comma required"); } - if (p == args->os_varp || p[1] == NUL) { + if (p == *varp || p[1] == NUL) { return e_invarg; } @@ -1720,7 +1760,9 @@ const char *did_set_foldmarker(optset_T *args) /// The 'commentstring' option is changed. const char *did_set_commentstring(optset_T *args) { - if (*args->os_varp != NUL && strstr(args->os_varp, "%s") == NULL) { + char **varp = (char **)args->os_varp; + + if (**varp != NUL && strstr(*varp, "%s") == NULL) { return N_("E537: 'commentstring' must be empty or contain %s"); } return NULL; @@ -1787,8 +1829,9 @@ const char *did_set_wildoptions(optset_T *args FUNC_ATTR_UNUSED) /// The 'lispoptions' option is changed. const char *did_set_lispoptions(optset_T *args) { - if (*args->os_varp != NUL - && strcmp(args->os_varp, "expr:0") != 0 && strcmp(args->os_varp, "expr:1") != 0) { + char **varp = (char **)args->os_varp; + + if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) { return e_invarg; } return NULL; @@ -1797,8 +1840,10 @@ const char *did_set_lispoptions(optset_T *args) /// The 'rightleftcmd' option is changed. const char *did_set_rightleftcmd(optset_T *args) { + char **varp = (char **)args->os_varp; + // Currently only "search" is a supported value. - if (*args->os_varp != NUL && strcmp(args->os_varp, "search") != 0) { + if (**varp != NUL && strcmp(*varp, "search") != 0) { return e_invarg; } @@ -1808,11 +1853,13 @@ const char *did_set_rightleftcmd(optset_T *args) /// The 'filetype' or the 'syntax' option is changed. const char *did_set_filetype_or_syntax(optset_T *args) { - if (!valid_filetype(args->os_varp)) { + char **varp = (char **)args->os_varp; + + if (!valid_filetype(*varp)) { return e_invarg; } - args->os_value_changed = strcmp(args->os_oldval.string, args->os_varp) != 0; + args->os_value_changed = strcmp(args->os_oldval.string, *varp) != 0; // Since we check the value, there is no need to set P_INSECURE, // even when the value comes from a modeline. @@ -1834,24 +1881,25 @@ const char *did_set_winhl(optset_T *args) const char *did_set_varsofttabstop(optset_T *args) { buf_T *buf = (buf_T *)args->os_buf; + char **varp = (char **)args->os_varp; - if (!(args->os_varp[0]) || ((args->os_varp[0]) == '0' && !(args->os_varp[1]))) { + if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) { XFREE_CLEAR(buf->b_p_vsts_array); return NULL; } - for (char *cp = args->os_varp; *cp; cp++) { + for (char *cp = *varp; *cp; cp++) { if (ascii_isdigit(*cp)) { continue; } - if (*cp == ',' && cp > args->os_varp && *(cp - 1) != ',') { + if (*cp == ',' && cp > *varp && *(cp - 1) != ',') { continue; } return e_invarg; } long *oldarray = buf->b_p_vsts_array; - if (tabstop_set(args->os_varp, &(buf->b_p_vsts_array))) { + if (tabstop_set(*varp, &(buf->b_p_vsts_array))) { xfree(oldarray); } else { return e_invarg; @@ -1864,24 +1912,25 @@ const char *did_set_vartabstop(optset_T *args) { buf_T *buf = (buf_T *)args->os_buf; win_T *win = (win_T *)args->os_win; + char **varp = (char **)args->os_varp; - if (!(args->os_varp[0]) || ((args->os_varp[0]) == '0' && !(args->os_varp[1]))) { + if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) { XFREE_CLEAR(buf->b_p_vts_array); return NULL; } - for (char *cp = args->os_varp; *cp; cp++) { + for (char *cp = *varp; *cp; cp++) { if (ascii_isdigit(*cp)) { continue; } - if (*cp == ',' && cp > args->os_varp && *(cp - 1) != ',') { + if (*cp == ',' && cp > *varp && *(cp - 1) != ',') { continue; } return e_invarg; } long *oldarray = buf->b_p_vts_array; - if (tabstop_set(args->os_varp, &(buf->b_p_vts_array))) { + if (tabstop_set(*varp, &(buf->b_p_vts_array))) { xfree(oldarray); if (foldmethodIsIndent(win)) { foldUpdateAll(win); @@ -1895,35 +1944,23 @@ const char *did_set_vartabstop(optset_T *args) /// The 'nrformats' option is changed. const char *did_set_nrformats(optset_T *args) { - return did_set_opt_strings(args->os_varp, p_nf_values, true); -} + char **varp = (char **)args->os_varp; -/// Returns TRUE if the option pointed by "varp" or "gvarp" is one of the -/// '*expr' options: 'balloonexpr', 'diffexpr', 'foldexpr', 'foldtext', -/// 'formatexpr', 'includeexpr', 'indentexpr', 'patchexpr', 'printexpr' or -/// 'charconvert'. -static int is_expr_option(win_T *win, char **varp, char **gvarp) -{ - return (varp == &p_dex // 'diffexpr' - || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr' - || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext' - || gvarp == &p_fex // 'formatexpr' - || gvarp == &p_inex // 'includeexpr' - || gvarp == &p_inde // 'indentexpr' - || varp == &p_pex // 'patchexpr' - || varp == &p_ccv); // 'charconvert' + return did_set_opt_strings(*varp, p_nf_values, true); } /// One of the '*expr' options is changed:, 'diffexpr', 'foldexpr', 'foldtext', /// 'formatexpr', 'includeexpr', 'indentexpr', 'patchexpr' and 'charconvert'. const char *did_set_optexpr(optset_T *args) { + char **varp = (char **)args->os_varp; + // If the option value starts with or s:, then replace that with // the script identifier. - char *name = get_scriptlocal_funcname(args->os_varp); + char *name = get_scriptlocal_funcname(*varp); if (name != NULL) { - free_string_option(args->os_varp); - args->os_varp = name; + free_string_option(*varp); + *varp = name; } return NULL; } @@ -1946,9 +1983,9 @@ const char *did_set_foldclose(optset_T *args FUNC_ATTR_UNUSED) } /// An option which is a list of flags is set. Valid values are in 'flags'. -static const char *did_set_option_listflag(char *varp, char *flags, char *errbuf, size_t errbuflen) +static const char *did_set_option_listflag(char *val, char *flags, char *errbuf, size_t errbuflen) { - for (char *s = varp; *s; s++) { + for (char *s = val; *s; s++) { if (vim_strchr(flags, (uint8_t)(*s)) == NULL) { return illegal_char(errbuf, errbuflen, (uint8_t)(*s)); } @@ -2027,12 +2064,9 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx opt_did_set_cb_T did_set_cb = get_option_did_set_cb(opt_idx); bool value_changed = false; - // Get the global option to compare with, otherwise we would have to check - // two values for all local options. - char **gvarp = (char **)get_varp_scope(opt, OPT_GLOBAL); - optset_T args = { - .os_varp = *varp, + .os_varp = (char *)varp, + .os_idx = opt_idx, .os_flags = opt_flags, .os_oldval.string = oldval, .os_newval.string = value, @@ -2055,11 +2089,7 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx // Invoke the option specific callback function to validate and apply // the new option value. errmsg = did_set_cb(&args); - // When processing the '*expr' options (e.g. diffexpr, foldexpr, etc.), - // the did_set_cb() function may modify '*varp'. - if (errmsg == NULL && is_expr_option(curwin, varp, gvarp)) { - *varp = args.os_varp; - } + // The 'filetype' and 'syntax' option callback functions may change // the os_value_changed field. value_changed = args.os_value_changed; @@ -2071,10 +2101,6 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx restore_chartab = args.os_restore_chartab; } else if (varp == &p_shada) { // 'shada' errmsg = did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen); - } else if (varp == &p_enc // 'encoding' - || gvarp == &p_fenc // 'fileencoding' - || gvarp == &p_menc) { // 'makeencoding' - did_set_encoding(buf, varp, gvarp, opt_flags, &errmsg); } // If an error is detected, restore the previous value. @@ -2273,11 +2299,11 @@ static int get_encoded_char_adv(const char **p) /// Handle setting 'listchars' or 'fillchars'. /// Assume monocell characters /// -/// @param val points to either the global or the window-local value. +/// @param value points to either the global or the window-local value. /// @param opt_lcs is tue for "listchars" and FALSE for "fillchars". /// @param apply if false, do not store the flags, only check for errors. /// @return error message, NULL if it's OK. -static const char *set_chars_option(win_T *wp, const char *val, bool opt_lcs, bool apply) +static const char *set_chars_option(win_T *wp, const char *value, bool opt_lcs, bool apply) { const char *last_multispace = NULL; // Last occurrence of "multispace:" const char *last_lmultispace = NULL; // Last occurrence of "leadmultispace:" @@ -2327,7 +2353,6 @@ static const char *set_chars_option(win_T *wp, const char *val, bool opt_lcs, bo struct chars_tab *tab; int entries; - const char *value = val; if (is_listchars) { tab = lcs_tab; entries = ARRAY_SIZE(lcs_tab); -- cgit From b8d5586d5b0d1e2d25533ee398d16bb2e8412820 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 5 May 2023 08:18:36 +0800 Subject: refactor: using a different error number for 'mousescroll' Because E548 is linked to 'guicursor' in help. --- src/nvim/optionstr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 96d383bbb1..28c0e3f97d 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -514,7 +514,7 @@ const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) // Verify that only digits follow the colon. for (size_t i = 4; i < length; i++) { if (!ascii_isdigit(string[i])) { - return N_("E548: digit expected"); + return N_("E5080: Digit expected"); } } -- cgit From 88cfb49bee3c9102082c7010acb92244e4ad1348 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 5 May 2023 07:14:39 +0800 Subject: vim-patch:8.2.4890: inconsistent capitalization in error messages Problem: Inconsistent capitalization in error messages. Solution: Make capitalization consistent. (Doug Kearns) https://github.com/vim/vim/commit/cf030578b26460643dca4a40e7f2e3bc19c749aa Co-authored-by: Bram Moolenaar --- src/nvim/optionstr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 28c0e3f97d..1c75d5bd03 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -61,8 +61,10 @@ static const char e_unclosed_expression_sequence[] = N_("E540: Unclosed expression sequence"); +static const char e_comma_required[] + = N_("E536: Comma required"); static const char e_unbalanced_groups[] - = N_("E542: unbalanced groups"); + = N_("E542: Unbalanced groups"); static const char e_backupext_and_patchmode_are_equal[] = N_("E589: 'backupext' and 'patchmode' are equal"); static const char e_showbreak_contains_unprintable_or_wide_character[] @@ -1743,7 +1745,7 @@ const char *did_set_foldmarker(optset_T *args) char *p = vim_strchr(*varp, ','); if (p == NULL) { - return N_("E536: comma required"); + return e_comma_required; } if (p == *varp || p[1] == NUL) { -- cgit From 7ed4274f6978ecf610caa9c8a4b082cb3b643143 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 8 May 2023 23:29:02 +0800 Subject: vim-patch:9.0.1526: condition is always true (#23541) Problem: Condition is always true. Solution: Remove unnecessary condition. (closes vim/vim#12359) https://github.com/vim/vim/commit/d619d6a9c6fa0e4295c817a88f84f0bab9457bbe --- src/nvim/optionstr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 1c75d5bd03..d3f676379d 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -2301,17 +2301,17 @@ static int get_encoded_char_adv(const char **p) /// Handle setting 'listchars' or 'fillchars'. /// Assume monocell characters /// -/// @param value points to either the global or the window-local value. -/// @param opt_lcs is tue for "listchars" and FALSE for "fillchars". +/// @param value points to either the global or the window-local value. +/// @param is_listchars is true for "listchars" and false for "fillchars". /// @param apply if false, do not store the flags, only check for errors. /// @return error message, NULL if it's OK. -static const char *set_chars_option(win_T *wp, const char *value, bool opt_lcs, bool apply) +static const char *set_chars_option(win_T *wp, const char *value, const bool is_listchars, + const bool apply) { const char *last_multispace = NULL; // Last occurrence of "multispace:" const char *last_lmultispace = NULL; // Last occurrence of "leadmultispace:" int multispace_len = 0; // Length of lcs-multispace string int lead_multispace_len = 0; // Length of lcs-leadmultispace string - const bool is_listchars = opt_lcs; struct chars_tab { int *cp; ///< char value @@ -2358,13 +2358,13 @@ static const char *set_chars_option(win_T *wp, const char *value, bool opt_lcs, if (is_listchars) { tab = lcs_tab; entries = ARRAY_SIZE(lcs_tab); - if (opt_lcs && wp->w_p_lcs[0] == NUL) { + if (wp->w_p_lcs[0] == NUL) { value = p_lcs; // local value is empty, use the global value } } else { tab = fcs_tab; entries = ARRAY_SIZE(fcs_tab); - if (!opt_lcs && wp->w_p_fcs[0] == NUL) { + if (wp->w_p_fcs[0] == NUL) { value = p_fcs; // local value is empty, use the global value } } -- cgit From b3d5138fd0066fda26ef7724a542ae45eb42fc84 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Wed, 7 Jun 2023 06:05:16 +0600 Subject: refactor(options): remove `getoption_T` and introduce `OptVal` (#23850) Removes the `getoption_T` struct and also introduces the `OptVal` struct to unify the methods of getting/setting different option value types. This is the first of many PRs to reduce code duplication in the Vim option code as well as to make options easier to maintain. It also increases the flexibility and extensibility of options. Which opens the door for things like Array and Dictionary options. --- src/nvim/optionstr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index d3f676379d..53d58017f9 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -2250,7 +2250,7 @@ void save_clear_shm_value(void) if (++set_shm_recursive == 1) { STRCPY(shm_buf, p_shm); - set_option_value_give_err("shm", 0L, "", 0); + set_option_value_give_err("shm", STATIC_CSTR_AS_OPTVAL(""), 0); } } @@ -2258,7 +2258,7 @@ void save_clear_shm_value(void) void restore_shm_value(void) { if (--set_shm_recursive == 0) { - set_option_value_give_err("shm", 0L, shm_buf, 0); + set_option_value_give_err("shm", CSTR_AS_OPTVAL(shm_buf), 0); memset(shm_buf, 0, SHM_LEN); } } -- cgit From 3681b7bb3bb942462c4261ab477e8912ae35b1a9 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Tue, 20 Jun 2023 13:09:06 +0600 Subject: refactor(option): use `void *` for pointer to option value Option related code uses `char *` for pointer to option value, which is not the best way of representing a type-agnostic pointer. Solution: Make pointers to option value use `void *` instead. --- src/nvim/optionstr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 53d58017f9..a0ffecbad0 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -352,7 +352,7 @@ void set_string_option_direct(const char *name, int opt_idx, const char *val, in return; } - assert((void *)opt->var != (void *)&p_shada); + assert(opt->var != &p_shada); s = xstrdup(val); { @@ -2067,7 +2067,7 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx bool value_changed = false; optset_T args = { - .os_varp = (char *)varp, + .os_varp = varp, .os_idx = opt_idx, .os_flags = opt_flags, .os_oldval.string = oldval, -- cgit From 516b173780e39de3ce1e4525f0a8f0ff250c992b Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 13 Jul 2023 10:17:19 +0100 Subject: perf(rtp): reduce rtp scans (#24191) * perf(rtp): reduce rtp scans Problem: Scanning the filesystem is expensive and particularly affects startuptime. Solution: Reduce the amount of redundant directory scans by relying less on glob patterns and handle vim and lua sourcing lower down. --- src/nvim/optionstr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index a0ffecbad0..3750574613 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -2036,10 +2036,8 @@ static void do_spelllang_source(win_T *win) } } if (p > q) { - vim_snprintf(fname, sizeof(fname), "spell/%.*s.vim", (int)(p - q), q); - source_runtime(fname, DIP_ALL); - vim_snprintf(fname, sizeof(fname), "spell/%.*s.lua", (int)(p - q), q); - source_runtime(fname, DIP_ALL); + vim_snprintf(fname, sizeof(fname), "spell/%.*s.*", (int)(p - q), q); + source_runtime_vim_lua(fname, DIP_ALL); } } -- cgit From 881d17a11393da75a27c072faa3fd45f510175fe Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 17 Jul 2023 14:27:21 +0100 Subject: feat(options)!: remove compatible behaviours for vim 5.0 and earlier --- src/nvim/optionstr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 3750574613..f07c05c113 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1664,7 +1664,7 @@ const char *did_set_foldcolumn(optset_T *args) const char *did_set_backspace(optset_T *args FUNC_ATTR_UNUSED) { if (ascii_isdigit(*p_bs)) { - if (*p_bs > '3' || p_bs[1] != NUL) { + if (*p_bs != '2') { return e_invarg; } } else if (check_opt_strings(p_bs, p_bs_values, true) != OK) { -- cgit From 008154954791001efcc46c28146e21403f3a698b Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 21 Aug 2023 14:52:17 +0200 Subject: refactor(change): do API changes to buffer without curbuf switch Most of the messy things when changing a non-current buffer is not about the buffer, it is about windows. In particular, it is about `curwin`. When editing a non-current buffer which is displayed in some other window in the current tabpage, one such window will be "borrowed" as the curwin. But this means if two or more non-current windows displayed the buffers, one of them will be treated differenty. this is not desirable. In particular, with nvim_buf_set_text, cursor _column_ position was only corrected for one single window. Two new tests are added: the test with just one non-current window passes, but the one with two didn't. Two corresponding such tests were also added for nvim_buf_set_lines. This already worked correctly on master, but make sure this is well-tested for future refactors. Also, nvim_create_buf no longer invokes autocmds just because you happened to use `scratch=true`. No option value was changed, therefore OptionSet must not be fired. --- src/nvim/optionstr.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index f07c05c113..07e2e5eed1 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -406,6 +406,19 @@ void set_string_option_direct_in_win(win_T *wp, const char *name, int opt_idx, c unblock_autocmds(); } +/// Like set_string_option_direct(), but for a buffer-local option in "buf". +/// Blocks autocommands to avoid the old curwin becoming invalid. +void set_string_option_direct_in_buf(buf_T *buf, const char *name, int opt_idx, const char *val, + int opt_flags, int set_sid) +{ + buf_T *save_curbuf = curbuf; + + block_autocmds(); + curbuf = buf; + set_string_option_direct(name, opt_idx, val, opt_flags, set_sid); + curbuf = save_curbuf; + unblock_autocmds(); +} /// Set a string option to a new value, handling the effects /// /// @param[in] opt_idx Option to set. -- cgit From 3b02e1281ad9fff8f8817868996e83e9f69cb8a1 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 12 Jul 2023 13:56:33 +0100 Subject: refactor(option.c): remove did_set_string_option alias --- src/nvim/optionstr.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 07e2e5eed1..60ad246293 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -459,8 +459,8 @@ const char *set_string_option(const int opt_idx, const char *const value, const char *const saved_newval = xstrdup(s); int value_checked = false; - const char *const errmsg = did_set_string_option(opt_idx, varp, oldval, s, errbuf, errbuflen, - opt_flags, &value_checked); + const char *const errmsg = did_set_string_option(curbuf, curwin, opt_idx, varp, oldval, s, errbuf, + errbuflen, opt_flags, &value_checked); if (errmsg == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); } @@ -2066,9 +2066,9 @@ static void do_spelllang_source(win_T *win) /// @param value_checked value was checked to be safe, no need to set P_INSECURE /// /// @return NULL for success, or an untranslated error message for an error -static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char **varp, - char *oldval, const char *value, char *errbuf, - size_t errbuflen, int opt_flags, int *value_checked) +const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **varp, char *oldval, + const char *value, char *errbuf, size_t errbuflen, int opt_flags, + int *value_checked) { const char *errmsg = NULL; int restore_chartab = false; @@ -2186,13 +2186,6 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx return errmsg; } -const char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *value, char *errbuf, - size_t errbuflen, int opt_flags, int *value_checked) -{ - return did_set_string_option_for(curbuf, curwin, opt_idx, varp, oldval, value, errbuf, - errbuflen, opt_flags, value_checked); -} - /// Check an option that can be a range of string values. /// /// @param list when true: accept a list of values -- cgit From 9fdc4cdb64ee405c3d742b0397a7be6c963d09a0 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 12 Jul 2023 14:16:29 +0100 Subject: refactor(optionstr.c): remove redundant argument --- src/nvim/optionstr.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 60ad246293..18065f05d4 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -437,7 +437,6 @@ const char *set_string_option(const int opt_idx, const char *const value, const return NULL; } - char *const s = xstrdup(value); char **const varp = (char **)get_varp_scope(opt, ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 ? ((opt->indir & PV_BOTH) ? OPT_GLOBAL : OPT_LOCAL) @@ -451,15 +450,15 @@ const char *set_string_option(const int opt_idx, const char *const value, const oldval_g = *(char **)get_varp_scope(opt, OPT_GLOBAL); } - *varp = s; + *varp = xstrdup(value); char *const saved_oldval = xstrdup(oldval); char *const saved_oldval_l = (oldval_l != NULL) ? xstrdup(oldval_l) : 0; char *const saved_oldval_g = (oldval_g != NULL) ? xstrdup(oldval_g) : 0; - char *const saved_newval = xstrdup(s); + char *const saved_newval = xstrdup(*varp); int value_checked = false; - const char *const errmsg = did_set_string_option(curbuf, curwin, opt_idx, varp, oldval, s, errbuf, + const char *const errmsg = did_set_string_option(curbuf, curwin, opt_idx, varp, oldval, errbuf, errbuflen, opt_flags, &value_checked); if (errmsg == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); @@ -2067,8 +2066,7 @@ static void do_spelllang_source(win_T *win) /// /// @return NULL for success, or an untranslated error message for an error const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **varp, char *oldval, - const char *value, char *errbuf, size_t errbuflen, int opt_flags, - int *value_checked) + char *errbuf, size_t errbuflen, int opt_flags, int *value_checked) { const char *errmsg = NULL; int restore_chartab = false; @@ -2082,7 +2080,7 @@ const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **va .os_idx = opt_idx, .os_flags = opt_flags, .os_oldval.string = oldval, - .os_newval.string = value, + .os_newval.string = *varp, .os_value_checked = false, .os_value_changed = false, .os_restore_chartab = false, -- cgit From 804c828e681ec3e55f19614d78c2b098b2672f86 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 12 Jul 2023 14:21:27 +0100 Subject: fix(optionstr.c): incorrect use of curbuf/curwin --- src/nvim/optionstr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 18065f05d4..9e5226a46f 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -2086,8 +2086,8 @@ const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **va .os_restore_chartab = false, .os_errbuf = errbuf, .os_errbuflen = errbuflen, - .os_win = curwin, - .os_buf = curbuf, + .os_win = win, + .os_buf = buf, }; // Disallow changing some options from secure mode -- cgit From 354a1154423fc381dfcd7b045963e8076288e777 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 12 Jul 2023 14:54:13 +0100 Subject: refactor(option.c): call did_set_option for all types set_option_value() only called did_set_option() for string options, whereas do_set_option_value() called it for all types. This change makes set_option_value() call did_set_option() for all types and thus makes it more consistent with do_set_option_value(). --- src/nvim/optionstr.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 9e5226a46f..d5ab47cc84 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -428,7 +428,7 @@ void set_string_option_direct_in_buf(buf_T *buf, const char *name, int opt_idx, /// /// @return NULL on success, an untranslated error message on error. const char *set_string_option(const int opt_idx, const char *const value, const int opt_flags, - char *const errbuf, const size_t errbuflen) + int *value_checked, char *const errbuf, const size_t errbuflen) FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_WARN_UNUSED_RESULT { vimoption_T *opt = get_option(opt_idx); @@ -457,13 +457,8 @@ const char *set_string_option(const int opt_idx, const char *const value, const char *const saved_oldval_g = (oldval_g != NULL) ? xstrdup(oldval_g) : 0; char *const saved_newval = xstrdup(*varp); - int value_checked = false; const char *const errmsg = did_set_string_option(curbuf, curwin, opt_idx, varp, oldval, errbuf, - errbuflen, opt_flags, &value_checked); - if (errmsg == NULL) { - did_set_option(opt_idx, opt_flags, true, value_checked); - } - + errbuflen, opt_flags, value_checked); // call autocommand after handling side effects if (errmsg == NULL) { if (!starting) { -- cgit From 95c880ce310a6ab3e5b68d4b1d81d81da6786f00 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 13 Jul 2023 10:22:18 +0100 Subject: refactor(option): change some int to bool --- src/nvim/optionstr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index d5ab47cc84..f82919d77a 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -428,7 +428,7 @@ void set_string_option_direct_in_buf(buf_T *buf, const char *name, int opt_idx, /// /// @return NULL on success, an untranslated error message on error. const char *set_string_option(const int opt_idx, const char *const value, const int opt_flags, - int *value_checked, char *const errbuf, const size_t errbuflen) + bool *value_checked, char *const errbuf, const size_t errbuflen) FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_WARN_UNUSED_RESULT { vimoption_T *opt = get_option(opt_idx); @@ -2061,7 +2061,8 @@ static void do_spelllang_source(win_T *win) /// /// @return NULL for success, or an untranslated error message for an error const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **varp, char *oldval, - char *errbuf, size_t errbuflen, int opt_flags, int *value_checked) + char *errbuf, size_t errbuflen, int opt_flags, + bool *value_checked) { const char *errmsg = NULL; int restore_chartab = false; -- cgit From 9edd0f077eacde69512dcfbe8b58312036d02be4 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 13 Jul 2023 12:00:06 +0100 Subject: refactor(option): remove hidden option check --- src/nvim/optionstr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index f82919d77a..26a5ed8563 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -419,7 +419,9 @@ void set_string_option_direct_in_buf(buf_T *buf, const char *name, int opt_idx, curbuf = save_curbuf; unblock_autocmds(); } + /// Set a string option to a new value, handling the effects +/// Must not be called with a hidden option! /// /// @param[in] opt_idx Option to set. /// @param[in] value New value. @@ -433,10 +435,6 @@ const char *set_string_option(const int opt_idx, const char *const value, const { vimoption_T *opt = get_option(opt_idx); - if (opt->var == NULL) { // don't set hidden option - return NULL; - } - char **const varp = (char **)get_varp_scope(opt, ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 ? ((opt->indir & PV_BOTH) ? OPT_GLOBAL : OPT_LOCAL) -- cgit From ec0ca51886271b54e8776c17a9b06f3271b8c4f9 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 13 Jul 2023 12:08:43 +0100 Subject: refactor(option): further align set_string_option with do_set_option_string --- src/nvim/optionstr.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 26a5ed8563..40118a36d4 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -439,20 +439,25 @@ const char *set_string_option(const int opt_idx, const char *const value, const = (char **)get_varp_scope(opt, ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 ? ((opt->indir & PV_BOTH) ? OPT_GLOBAL : OPT_LOCAL) : opt_flags)); + char *origval_l = NULL; + char *origval_g = NULL; + + // The old value is kept until we are sure that the new value is valid. char *const oldval = *varp; - char *oldval_l = NULL; - char *oldval_g = NULL; if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) { - oldval_l = *(char **)get_varp_scope(opt, OPT_LOCAL); - oldval_g = *(char **)get_varp_scope(opt, OPT_GLOBAL); + origval_l = *(char **)get_varp_scope(opt, OPT_LOCAL); + origval_g = *(char **)get_varp_scope(opt, OPT_GLOBAL); } *varp = xstrdup(value); char *const saved_oldval = xstrdup(oldval); - char *const saved_oldval_l = (oldval_l != NULL) ? xstrdup(oldval_l) : 0; - char *const saved_oldval_g = (oldval_g != NULL) ? xstrdup(oldval_g) : 0; + char *const saved_oldval_l = (origval_l != NULL) ? xstrdup(origval_l) : 0; + char *const saved_oldval_g = (origval_g != NULL) ? xstrdup(origval_g) : 0; + + // newval (and varp) may become invalid if the buffer is closed by + // autocommands. char *const saved_newval = xstrdup(*varp); const char *const errmsg = did_set_string_option(curbuf, curwin, opt_idx, varp, oldval, errbuf, @@ -460,12 +465,12 @@ const char *set_string_option(const int opt_idx, const char *const value, const // call autocommand after handling side effects if (errmsg == NULL) { if (!starting) { - trigger_optionset_string(opt_idx, opt_flags, saved_oldval, saved_oldval_l, saved_oldval_g, - saved_newval); + trigger_optionset_string(opt_idx, opt_flags, saved_oldval, saved_oldval_l, + saved_oldval_g, saved_newval); } if (opt->flags & P_UI_OPTION) { ui_call_option_set(cstr_as_string(opt->fullname), - STRING_OBJ(cstr_as_string(saved_newval))); + CSTR_AS_OBJ(saved_newval)); } } xfree(saved_oldval); -- cgit From 3a45a0db4d5a3981f4fbd575d405a9c6e382b930 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 13 Jul 2023 12:21:54 +0100 Subject: refactor(option): further align set_string_option with do_set_option_string (2) --- src/nvim/optionstr.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 40118a36d4..c0a7bfa3f7 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -435,24 +435,46 @@ const char *set_string_option(const int opt_idx, const char *const value, const { vimoption_T *opt = get_option(opt_idx); - char **const varp - = (char **)get_varp_scope(opt, ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 - ? ((opt->indir & PV_BOTH) ? OPT_GLOBAL : OPT_LOCAL) - : opt_flags)); + char **varp = (char **)get_varp_scope(opt, ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 + ? ((opt->indir & PV_BOTH) ? OPT_GLOBAL : OPT_LOCAL) + : opt_flags)); char *origval_l = NULL; char *origval_g = NULL; + // When using ":set opt=val" for a global option + // with a local value the local value will be + // reset, use the global value here. + if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 + && ((int)opt->indir & PV_BOTH)) { + varp = (char **)opt->var; + } + // The old value is kept until we are sure that the new value is valid. char *const oldval = *varp; if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) { origval_l = *(char **)get_varp_scope(opt, OPT_LOCAL); origval_g = *(char **)get_varp_scope(opt, OPT_GLOBAL); + + // A global-local string option might have an empty option as value to + // indicate that the global value should be used. + if (((int)opt->indir & PV_BOTH) && origval_l == empty_option) { + origval_l = origval_g; + } + } + + char *origval; + // When setting the local value of a global option, the old value may be + // the global value. + if (((int)opt->indir & PV_BOTH) && (opt_flags & OPT_LOCAL)) { + origval = *(char **)get_varp_from(opt, curbuf, curwin); + } else { + origval = oldval; } *varp = xstrdup(value); - char *const saved_oldval = xstrdup(oldval); + char *const saved_origval = (origval != NULL) ? xstrdup(origval) : NULL; char *const saved_oldval_l = (origval_l != NULL) ? xstrdup(origval_l) : 0; char *const saved_oldval_g = (origval_g != NULL) ? xstrdup(origval_g) : 0; @@ -460,12 +482,26 @@ const char *set_string_option(const int opt_idx, const char *const value, const // autocommands. char *const saved_newval = xstrdup(*varp); + const int secure_saved = secure; + + // When an option is set in the sandbox, from a modeline or in secure + // mode, then deal with side effects in secure mode. Also when the + // value was set with the P_INSECURE flag and is not completely + // replaced. + if ((opt_flags & OPT_MODELINE) + || sandbox != 0) { + secure = 1; + } + const char *const errmsg = did_set_string_option(curbuf, curwin, opt_idx, varp, oldval, errbuf, errbuflen, opt_flags, value_checked); + + secure = secure_saved; + // call autocommand after handling side effects if (errmsg == NULL) { if (!starting) { - trigger_optionset_string(opt_idx, opt_flags, saved_oldval, saved_oldval_l, + trigger_optionset_string(opt_idx, opt_flags, saved_origval, saved_oldval_l, saved_oldval_g, saved_newval); } if (opt->flags & P_UI_OPTION) { @@ -473,7 +509,7 @@ const char *set_string_option(const int opt_idx, const char *const value, const CSTR_AS_OBJ(saved_newval)); } } - xfree(saved_oldval); + xfree(saved_origval); xfree(saved_oldval_l); xfree(saved_oldval_g); xfree(saved_newval); -- cgit From af3c667ac13e23b5ff838e720c8b26fa4a12644a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 13 Jul 2023 16:31:11 +0100 Subject: refactor(option): option clearing --- src/nvim/optionstr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index c0a7bfa3f7..c68ee65fcf 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -429,12 +429,16 @@ void set_string_option_direct_in_buf(buf_T *buf, const char *name, int opt_idx, /// #OPT_GLOBAL. /// /// @return NULL on success, an untranslated error message on error. -const char *set_string_option(const int opt_idx, const char *const value, const int opt_flags, +const char *set_string_option(const int opt_idx, const char *value, const int opt_flags, bool *value_checked, char *const errbuf, const size_t errbuflen) - FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_WARN_UNUSED_RESULT + FUNC_ATTR_WARN_UNUSED_RESULT { vimoption_T *opt = get_option(opt_idx); + if (value == NULL) { + value = ""; + } + char **varp = (char **)get_varp_scope(opt, ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 ? ((opt->indir & PV_BOTH) ? OPT_GLOBAL : OPT_LOCAL) : opt_flags)); -- cgit From 038ac39b8e3be4a41e763442c306680633806170 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 13 Jul 2023 16:46:05 +0100 Subject: refactor(option): pass varp to set_string_option --- src/nvim/optionstr.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index c68ee65fcf..17afd10ee3 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -429,19 +429,14 @@ void set_string_option_direct_in_buf(buf_T *buf, const char *name, int opt_idx, /// #OPT_GLOBAL. /// /// @return NULL on success, an untranslated error message on error. -const char *set_string_option(const int opt_idx, const char *value, const int opt_flags, - bool *value_checked, char *const errbuf, const size_t errbuflen) +const char *set_string_option(const int opt_idx, void *varp_arg, const char *value, + const int opt_flags, bool *value_checked, char *const errbuf, + const size_t errbuflen) FUNC_ATTR_WARN_UNUSED_RESULT { vimoption_T *opt = get_option(opt_idx); - if (value == NULL) { - value = ""; - } - - char **varp = (char **)get_varp_scope(opt, ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 - ? ((opt->indir & PV_BOTH) ? OPT_GLOBAL : OPT_LOCAL) - : opt_flags)); + void *varp = (char **)varp_arg; char *origval_l = NULL; char *origval_g = NULL; @@ -450,11 +445,11 @@ const char *set_string_option(const int opt_idx, const char *value, const int op // reset, use the global value here. if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 && ((int)opt->indir & PV_BOTH)) { - varp = (char **)opt->var; + varp = opt->var; } // The old value is kept until we are sure that the new value is valid. - char *const oldval = *varp; + char *oldval = *(char **)varp; if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) { origval_l = *(char **)get_varp_scope(opt, OPT_LOCAL); @@ -476,7 +471,7 @@ const char *set_string_option(const int opt_idx, const char *value, const int op origval = oldval; } - *varp = xstrdup(value); + *(char **)varp = xstrdup(value != NULL ? value : empty_option); char *const saved_origval = (origval != NULL) ? xstrdup(origval) : NULL; char *const saved_oldval_l = (origval_l != NULL) ? xstrdup(origval_l) : 0; @@ -484,7 +479,7 @@ const char *set_string_option(const int opt_idx, const char *value, const int op // newval (and varp) may become invalid if the buffer is closed by // autocommands. - char *const saved_newval = xstrdup(*varp); + char *const saved_newval = xstrdup(*(char **)varp); const int secure_saved = secure; -- cgit From f094db0e5ccaddca2b5db05bf9545d55f3eededf Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 21 Sep 2023 07:37:03 +0800 Subject: vim-patch:9.0.1921: not possible to use the jumplist like a stack (#25278) Problem: not possible to use the jumplist like a stack Solution: Add the 'jumpoptions' setting to make the jumplist a stack. Add an option for using jumplist like tag stack related: vim/vim#7738 closes: vim/vim#13134 ported from NeoVim: - https://neovim.io/doc/user/motion.html#jumplist-stack - neovim/neovim@39094b3 - https://vi.stackexchange.com/questions/18344/how-to-change-jumplist-behavior Based on the feedback in the previous PR, it looks like many people like this option. https://github.com/vim/vim/commit/87018255e3ad0f4dfa03e20318836d24af721caf Co-authored-by: Yegappan Lakshmanan Co-authored-by: butwerenotthereyet <58348703+butwerenotthereyet@users.noreply.github.com> --- src/nvim/optionstr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 17afd10ee3..cf8e6cf641 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -151,13 +151,13 @@ void didset_string_options(void) (void)opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true); (void)opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true); (void)opt_strings_flags(p_dy, p_dy_values, &dy_flags, true); + (void)opt_strings_flags(p_jop, p_jop_values, &jop_flags, true); (void)opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true); (void)opt_strings_flags(p_tc, p_tc_values, &tc_flags, false); (void)opt_strings_flags(p_tpf, p_tpf_values, &tpf_flags, true); (void)opt_strings_flags(p_ve, p_ve_values, &ve_flags, true); (void)opt_strings_flags(p_swb, p_swb_values, &swb_flags, true); (void)opt_strings_flags(p_wop, p_wop_values, &wop_flags, true); - (void)opt_strings_flags(p_jop, p_jop_values, &jop_flags, true); (void)opt_strings_flags(p_cb, p_cb_values, &cb_flags, true); } -- cgit From 68d425ac92599089047d98f1c533981ea917fed1 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 25 Sep 2023 12:26:01 +0200 Subject: refactor: remove 'shortmess' save/restore panic for ex commands This was only used to avoid the effect of SHM_OVERALL. This can easily be handled in isolation, instead of clearing out all of 'shortmess' which has unwanted side effects and mystifies what really is going on. --- src/nvim/optionstr.c | 32 -------------------------------- 1 file changed, 32 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index cf8e6cf641..2382219b55 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -69,8 +69,6 @@ static const char e_backupext_and_patchmode_are_equal[] = N_("E589: 'backupext' and 'patchmode' are equal"); static const char e_showbreak_contains_unprintable_or_wide_character[] = N_("E595: 'showbreak' contains unprintable or wide character"); -static const char e_internal_error_shortmess_too_long[] - = N_("E1336: Internal error: shortmess too long"); static char *(p_ambw_values[]) = { "single", "double", NULL }; static char *(p_bg_values[]) = { "light", "dark", NULL }; @@ -2269,36 +2267,6 @@ int check_ff_value(char *p) return check_opt_strings(p, p_ff_values, false); } -static char shm_buf[SHM_LEN]; -static int set_shm_recursive = 0; - -/// Save the actual shortmess Flags and clear them temporarily to avoid that -/// file messages overwrites any output from the following commands. -/// -/// Caller must make sure to first call save_clear_shm_value() and then -/// restore_shm_value() exactly the same number of times. -void save_clear_shm_value(void) -{ - if (strlen(p_shm) >= SHM_LEN) { - iemsg(e_internal_error_shortmess_too_long); - return; - } - - if (++set_shm_recursive == 1) { - STRCPY(shm_buf, p_shm); - set_option_value_give_err("shm", STATIC_CSTR_AS_OPTVAL(""), 0); - } -} - -/// Restore the shortmess Flags set from the save_clear_shm_value() function. -void restore_shm_value(void) -{ - if (--set_shm_recursive == 0) { - set_option_value_give_err("shm", CSTR_AS_OPTVAL(shm_buf), 0); - memset(shm_buf, 0, SHM_LEN); - } -} - static const char e_conflicts_with_value_of_listchars[] = N_("E834: Conflicts with value of 'listchars'"); static const char e_conflicts_with_value_of_fillchars[] -- cgit From c3d1d9445c70846d43d1f091ee0762e16513e225 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 25 Sep 2023 12:21:35 +0200 Subject: refactor(options)!: graduate some more shortmess flags A lot of updated places in the docs were already incorrect since long since they did not reflect the default behaviour. "[dos format]" could've been argued being better for discoverability but that ship has already sailed as it is no longer displayed by default. --- src/nvim/optionstr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 2382219b55..797c3cb554 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -132,11 +132,12 @@ static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelt static char *(p_sloc_values[]) = { "last", "statusline", "tabline", NULL }; /// All possible flags for 'shm'. -static char SHM_ALL[] = { SHM_RO, SHM_MOD, SHM_FILE, SHM_LAST, SHM_TEXT, SHM_LINES, SHM_NEW, +/// the literal chars before 0 are removed flags. these are safely ignored +static char SHM_ALL[] = { SHM_RO, SHM_MOD, SHM_LINES, SHM_WRI, SHM_ABBREVIATIONS, SHM_WRITE, SHM_TRUNC, SHM_TRUNCALL, SHM_OVER, SHM_OVERALL, SHM_SEARCH, SHM_ATTENTION, SHM_INTRO, SHM_COMPLETIONMENU, SHM_COMPLETIONSCAN, SHM_RECORDING, SHM_FILEINFO, - SHM_SEARCHCOUNT, 0, }; + SHM_SEARCHCOUNT, 'n', 'f', 'x', 'i', 0, }; /// After setting various option values: recompute variables that depend on /// option values. -- cgit From af7d317f3ff31d5ac5d8724b5057a422e1451b54 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Tue, 26 Sep 2023 22:36:08 +0200 Subject: refactor: remove long long is 32-bits even on 64-bit windows which makes the type suboptimal for a codebase meant to be cross-platform. --- src/nvim/optionstr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 797c3cb554..44d558312e 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -527,8 +527,8 @@ static bool valid_filetype(const char *val) /// @return error message, NULL if it's OK. const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) { - long vertical = -1; - long horizontal = -1; + OptInt vertical = -1; + OptInt horizontal = -1; char *string = p_mousescroll; @@ -542,7 +542,7 @@ const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) return e_invarg; } - long *direction; + OptInt *direction; if (memcmp(string, "ver:", 4) == 0) { direction = &vertical; @@ -1944,7 +1944,7 @@ const char *did_set_varsofttabstop(optset_T *args) return e_invarg; } - long *oldarray = buf->b_p_vsts_array; + colnr_T *oldarray = buf->b_p_vsts_array; if (tabstop_set(*varp, &(buf->b_p_vsts_array))) { xfree(oldarray); } else { @@ -1975,7 +1975,7 @@ const char *did_set_vartabstop(optset_T *args) return e_invarg; } - long *oldarray = buf->b_p_vts_array; + colnr_T *oldarray = buf->b_p_vts_array; if (tabstop_set(*varp, &(buf->b_p_vts_array))) { xfree(oldarray); if (foldmethodIsIndent(win)) { -- cgit From cf8b2c0e74fd5e723b0c15c2ce84e6900fd322d3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 30 Sep 2023 12:05:28 +0800 Subject: build(iwyu): add a few more _defs.h mappings (#25435) --- src/nvim/optionstr.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 44d558312e..bb35848905 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -28,29 +28,24 @@ #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/insexpand.h" -#include "nvim/keycodes.h" #include "nvim/macros.h" -#include "nvim/mapping.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/mouse.h" #include "nvim/move.h" -#include "nvim/ops.h" #include "nvim/option.h" #include "nvim/option_defs.h" #include "nvim/optionstr.h" #include "nvim/os/os.h" #include "nvim/pos.h" -#include "nvim/quickfix.h" #include "nvim/runtime.h" #include "nvim/spell.h" #include "nvim/spellfile.h" #include "nvim/spellsuggest.h" -#include "nvim/statusline.h" #include "nvim/strings.h" -#include "nvim/tag.h" +#include "nvim/types.h" #include "nvim/ui.h" #include "nvim/vim.h" #include "nvim/window.h" -- cgit From dc6d0d2daf69e2fdadda81feb97906dbc962a239 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 30 Sep 2023 14:41:34 +0800 Subject: refactor: reorganize option header files (#25437) - Move vimoption_T to option.h - option_defs.h is for option-related types - option_vars.h corresponds to Vim's option.h - option_defs.h and option_vars.h don't include each other --- src/nvim/optionstr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index bb35848905..3ab40b48c8 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -37,6 +37,7 @@ #include "nvim/move.h" #include "nvim/option.h" #include "nvim/option_defs.h" +#include "nvim/option_vars.h" #include "nvim/optionstr.h" #include "nvim/os/os.h" #include "nvim/pos.h" -- cgit From 2af9fac0a6ce3b01f22802511cf1ed7b0734cb2e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 30 Sep 2023 17:38:05 +0800 Subject: refactor: align set_chars_option() with Vim (#25438) Needed for completion of 'listchars'/'fillchars' values. --- src/nvim/optionstr.c | 137 +++++++++++++++++++++++++++++---------------------- 1 file changed, 77 insertions(+), 60 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 3ab40b48c8..62073a2323 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -2299,6 +2299,48 @@ static int get_encoded_char_adv(const char **p) return c; } +struct chars_tab { + int *cp; ///< char value + const char *name; ///< char id + int def; ///< default value + int fallback; ///< default value when "def" isn't single-width +}; + +static fcs_chars_T fcs_chars; +static const struct chars_tab fcs_tab[] = { + { &fcs_chars.stl, "stl", ' ', NUL }, + { &fcs_chars.stlnc, "stlnc", ' ', NUL }, + { &fcs_chars.wbr, "wbr", ' ', NUL }, + { &fcs_chars.horiz, "horiz", 0x2500, '-' }, // ─ + { &fcs_chars.horizup, "horizup", 0x2534, '-' }, // ┴ + { &fcs_chars.horizdown, "horizdown", 0x252c, '-' }, // ┬ + { &fcs_chars.vert, "vert", 0x2502, '|' }, // │ + { &fcs_chars.vertleft, "vertleft", 0x2524, '|' }, // ┤ + { &fcs_chars.vertright, "vertright", 0x251c, '|' }, // ├ + { &fcs_chars.verthoriz, "verthoriz", 0x253c, '+' }, // ┼ + { &fcs_chars.fold, "fold", 0x00b7, '-' }, // · + { &fcs_chars.foldopen, "foldopen", '-', NUL }, + { &fcs_chars.foldclosed, "foldclose", '+', NUL }, + { &fcs_chars.foldsep, "foldsep", 0x2502, '|' }, // │ + { &fcs_chars.diff, "diff", '-', NUL }, + { &fcs_chars.msgsep, "msgsep", ' ', NUL }, + { &fcs_chars.eob, "eob", '~', NUL }, + { &fcs_chars.lastline, "lastline", '@', NUL }, +}; + +static lcs_chars_T lcs_chars; +static const struct chars_tab lcs_tab[] = { + { &lcs_chars.eol, "eol", NUL, NUL }, + { &lcs_chars.ext, "extends", NUL, NUL }, + { &lcs_chars.nbsp, "nbsp", NUL, NUL }, + { &lcs_chars.prec, "precedes", NUL, NUL }, + { &lcs_chars.space, "space", NUL, NUL }, + { &lcs_chars.tab2, "tab", NUL, NUL }, + { &lcs_chars.lead, "lead", NUL, NUL }, + { &lcs_chars.trail, "trail", NUL, NUL }, + { &lcs_chars.conceal, "conceal", NUL, NUL }, +}; + /// Handle setting 'listchars' or 'fillchars'. /// Assume monocell characters /// @@ -2314,47 +2356,7 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ int multispace_len = 0; // Length of lcs-multispace string int lead_multispace_len = 0; // Length of lcs-leadmultispace string - struct chars_tab { - int *cp; ///< char value - char *name; ///< char id - int def; ///< default value - }; - - // XXX: Characters taking 2 columns is forbidden (TUI limitation?). Set old defaults in this case. - struct chars_tab fcs_tab[] = { - { &wp->w_p_fcs_chars.stl, "stl", ' ' }, - { &wp->w_p_fcs_chars.stlnc, "stlnc", ' ' }, - { &wp->w_p_fcs_chars.wbr, "wbr", ' ' }, - { &wp->w_p_fcs_chars.horiz, "horiz", char2cells(0x2500) == 1 ? 0x2500 : '-' }, // ─ - { &wp->w_p_fcs_chars.horizup, "horizup", char2cells(0x2534) == 1 ? 0x2534 : '-' }, // ┴ - { &wp->w_p_fcs_chars.horizdown, "horizdown", char2cells(0x252c) == 1 ? 0x252c : '-' }, // ┬ - { &wp->w_p_fcs_chars.vert, "vert", char2cells(0x2502) == 1 ? 0x2502 : '|' }, // │ - { &wp->w_p_fcs_chars.vertleft, "vertleft", char2cells(0x2524) == 1 ? 0x2524 : '|' }, // ┤ - { &wp->w_p_fcs_chars.vertright, "vertright", char2cells(0x251c) == 1 ? 0x251c : '|' }, // ├ - { &wp->w_p_fcs_chars.verthoriz, "verthoriz", char2cells(0x253c) == 1 ? 0x253c : '+' }, // ┼ - { &wp->w_p_fcs_chars.fold, "fold", char2cells(0x00b7) == 1 ? 0x00b7 : '-' }, // · - { &wp->w_p_fcs_chars.foldopen, "foldopen", '-' }, - { &wp->w_p_fcs_chars.foldclosed, "foldclose", '+' }, - { &wp->w_p_fcs_chars.foldsep, "foldsep", char2cells(0x2502) == 1 ? 0x2502 : '|' }, // │ - { &wp->w_p_fcs_chars.diff, "diff", '-' }, - { &wp->w_p_fcs_chars.msgsep, "msgsep", ' ' }, - { &wp->w_p_fcs_chars.eob, "eob", '~' }, - { &wp->w_p_fcs_chars.lastline, "lastline", '@' }, - }; - - struct chars_tab lcs_tab[] = { - { &wp->w_p_lcs_chars.eol, "eol", NUL }, - { &wp->w_p_lcs_chars.ext, "extends", NUL }, - { &wp->w_p_lcs_chars.nbsp, "nbsp", NUL }, - { &wp->w_p_lcs_chars.prec, "precedes", NUL }, - { &wp->w_p_lcs_chars.space, "space", NUL }, - { &wp->w_p_lcs_chars.tab2, "tab", NUL }, - { &wp->w_p_lcs_chars.lead, "lead", NUL }, - { &wp->w_p_lcs_chars.trail, "trail", NUL }, - { &wp->w_p_lcs_chars.conceal, "conceal", NUL }, - }; - - struct chars_tab *tab; + const struct chars_tab *tab; int entries; if (is_listchars) { tab = lcs_tab; @@ -2376,31 +2378,32 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ // After checking that the value is valid: set defaults for (int i = 0; i < entries; i++) { if (tab[i].cp != NULL) { - *(tab[i].cp) = tab[i].def; + // XXX: Characters taking 2 columns is forbidden (TUI limitation?). + // Set old defaults in this case. + *(tab[i].cp) = char2cells(tab[i].def) == 1 ? tab[i].def : tab[i].fallback; } } + if (is_listchars) { - wp->w_p_lcs_chars.tab1 = NUL; - wp->w_p_lcs_chars.tab3 = NUL; + lcs_chars.tab1 = NUL; + lcs_chars.tab3 = NUL; - xfree(wp->w_p_lcs_chars.multispace); if (multispace_len > 0) { - wp->w_p_lcs_chars.multispace = xmalloc(((size_t)multispace_len + 1) * sizeof(int)); - wp->w_p_lcs_chars.multispace[multispace_len] = NUL; + lcs_chars.multispace = xmalloc(((size_t)multispace_len + 1) * sizeof(int)); + lcs_chars.multispace[multispace_len] = NUL; } else { - wp->w_p_lcs_chars.multispace = NULL; + lcs_chars.multispace = NULL; } - xfree(wp->w_p_lcs_chars.leadmultispace); if (lead_multispace_len > 0) { - wp->w_p_lcs_chars.leadmultispace - = xmalloc(((size_t)lead_multispace_len + 1) * sizeof(int)); - wp->w_p_lcs_chars.leadmultispace[lead_multispace_len] = NUL; + lcs_chars.leadmultispace = xmalloc(((size_t)lead_multispace_len + 1) * sizeof(int)); + lcs_chars.leadmultispace[lead_multispace_len] = NUL; } else { - wp->w_p_lcs_chars.leadmultispace = NULL; + lcs_chars.leadmultispace = NULL; } } } + const char *p = value; while (*p) { int i; @@ -2415,7 +2418,7 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ return e_invarg; } int c2 = 0, c3 = 0; - if (tab[i].cp == &wp->w_p_lcs_chars.tab2) { + if (tab[i].cp == &lcs_chars.tab2) { if (*s == NUL) { return e_invarg; } @@ -2430,12 +2433,13 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ } } } + if (*s == ',' || *s == NUL) { if (round > 0) { - if (tab[i].cp == &wp->w_p_lcs_chars.tab2) { - wp->w_p_lcs_chars.tab1 = c1; - wp->w_p_lcs_chars.tab2 = c2; - wp->w_p_lcs_chars.tab3 = c3; + if (tab[i].cp == &lcs_chars.tab2) { + lcs_chars.tab1 = c1; + lcs_chars.tab2 = c2; + lcs_chars.tab3 = c3; } else if (tab[i].cp != NULL) { *(tab[i].cp) = c1; } @@ -2475,7 +2479,7 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ while (*s != NUL && *s != ',') { int c1 = get_encoded_char_adv(&s); if (p == last_multispace) { - wp->w_p_lcs_chars.multispace[multispace_pos++] = c1; + lcs_chars.multispace[multispace_pos++] = c1; } } p = s; @@ -2506,7 +2510,7 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ while (*s != NUL && *s != ',') { int c1 = get_encoded_char_adv(&s); if (p == last_lmultispace) { - wp->w_p_lcs_chars.leadmultispace[multispace_pos++] = c1; + lcs_chars.leadmultispace[multispace_pos++] = c1; } } p = s; @@ -2522,6 +2526,19 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ } } + if (apply) { + if (is_listchars) { + xfree(wp->w_p_lcs_chars.multispace); + xfree(wp->w_p_lcs_chars.leadmultispace); + wp->w_p_lcs_chars = lcs_chars; + } else { + wp->w_p_fcs_chars = fcs_chars; + } + } else if (is_listchars) { + xfree(lcs_chars.multispace); + xfree(lcs_chars.leadmultispace); + } + return NULL; // no error } -- cgit From 960170e4469b96c5c3d06ba1bb84c9edeaa04b8b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 30 Sep 2023 19:36:33 +0800 Subject: vim-patch:9.0.1366: functions for setting options are in random order (#25440) Problem: Functions for setting options are in random order. Solution: Sort functions alphabetically. (Yegappan Lakshmanan, closes vim/vim#12082) https://github.com/vim/vim/commit/ad60898aa47b44fdece12d28c471fb50df27fb50 Co-authored-by: Yegappan Lakshmanan --- src/nvim/optionstr.c | 1706 +++++++++++++++++++++++++------------------------- 1 file changed, 856 insertions(+), 850 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 62073a2323..750941da07 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -519,71 +519,6 @@ static bool valid_filetype(const char *val) return valid_name(val, ".-_"); } -/// Handle setting 'mousescroll'. -/// @return error message, NULL if it's OK. -const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) -{ - OptInt vertical = -1; - OptInt horizontal = -1; - - char *string = p_mousescroll; - - while (true) { - char *end = vim_strchr(string, ','); - size_t length = end ? (size_t)(end - string) : strlen(string); - - // Both "ver:" and "hor:" are 4 bytes long. - // They should be followed by at least one digit. - if (length <= 4) { - return e_invarg; - } - - OptInt *direction; - - if (memcmp(string, "ver:", 4) == 0) { - direction = &vertical; - } else if (memcmp(string, "hor:", 4) == 0) { - direction = &horizontal; - } else { - return e_invarg; - } - - // If the direction has already been set, this is a duplicate. - if (*direction != -1) { - return e_invarg; - } - - // Verify that only digits follow the colon. - for (size_t i = 4; i < length; i++) { - if (!ascii_isdigit(string[i])) { - return N_("E5080: Digit expected"); - } - } - - string += 4; - *direction = getdigits_int(&string, false, -1); - - // Num options are generally kept within the signed int range. - // We know this number won't be negative because we've already checked for - // a minus sign. We'll allow 0 as a means of disabling mouse scrolling. - if (*direction == -1) { - return e_invarg; - } - - if (!end) { - break; - } - - string = end + 1; - } - - // If a direction wasn't set, fallback to the default value. - p_mousescroll_vert = (vertical == -1) ? MOUSESCROLL_VERT_DFLT : vertical; - p_mousescroll_hor = (horizontal == -1) ? MOUSESCROLL_HOR_DFLT : horizontal; - - return NULL; -} - /// Handle setting 'signcolumn' for value 'val' /// /// @return OK when the value is valid, FAIL otherwise @@ -695,6 +630,81 @@ static bool check_illegal_path_names(char *val, uint32_t flags) && strpbrk(val, "*?[|;&<>\r\n") != NULL)); } +/// An option that accepts a list of flags is changed. +/// e.g. 'viewoptions', 'switchbuf', 'casemap', etc. +static const char *did_set_opt_flags(char *val, char **values, unsigned *flagp, bool list) +{ + if (opt_strings_flags(val, values, flagp, list) != OK) { + return e_invarg; + } + return NULL; +} + +/// An option that accepts a list of string values is changed. +/// e.g. 'nrformats', 'scrollopt', 'wildoptions', etc. +static const char *did_set_opt_strings(char *val, char **values, bool list) +{ + return did_set_opt_flags(val, values, NULL, list); +} + +/// An option which is a list of flags is set. Valid values are in "flags". +static const char *did_set_option_listflag(char *val, char *flags, char *errbuf, size_t errbuflen) +{ + for (char *s = val; *s; s++) { + if (vim_strchr(flags, (uint8_t)(*s)) == NULL) { + return illegal_char(errbuf, errbuflen, (uint8_t)(*s)); + } + } + + return NULL; +} + +/// The 'ambiwidth' option is changed. +const char *did_set_ambiwidth(optset_T *args FUNC_ATTR_UNUSED) +{ + if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) { + return e_invarg; + } + return check_chars_options(); +} + +/// The 'background' option is changed. +const char *did_set_background(optset_T *args FUNC_ATTR_UNUSED) +{ + if (check_opt_strings(p_bg, p_bg_values, false) != OK) { + return e_invarg; + } + + int dark = (*p_bg == 'd'); + + init_highlight(false, false); + + if (dark != (*p_bg == 'd') && get_var_value("g:colors_name") != NULL) { + // The color scheme must have set 'background' back to another + // value, that's not what we want here. Disable the color + // scheme and set the colors again. + do_unlet(S_LEN("g:colors_name"), true); + free_string_option(p_bg); + p_bg = xstrdup((dark ? "dark" : "light")); + check_string_option(&p_bg); + init_highlight(false, false); + } + return NULL; +} + +/// The 'backspace' option is changed. +const char *did_set_backspace(optset_T *args FUNC_ATTR_UNUSED) +{ + if (ascii_isdigit(*p_bs)) { + if (*p_bs != '2') { + return e_invarg; + } + } else if (check_opt_strings(p_bs, p_bs_values, true) != OK) { + return e_invarg; + } + return NULL; +} + /// The 'backupcopy' option is changed. const char *did_set_backupcopy(optset_T *args) { @@ -746,12 +756,6 @@ const char *did_set_belloff(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true); } -/// The 'termpastefilter' option is changed. -const char *did_set_termpastefilter(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true); -} - /// The 'breakindentopt' option is changed. const char *did_set_breakindentopt(optset_T *args) { @@ -767,160 +771,236 @@ const char *did_set_breakindentopt(optset_T *args) return NULL; } -/// The 'isident' or the 'iskeyword' or the 'isprint' or the 'isfname' option is -/// changed. -const char *did_set_isopt(optset_T *args) +/// The 'bufhidden' option is changed. +const char *did_set_bufhidden(optset_T *args) { buf_T *buf = (buf_T *)args->os_buf; - // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[] - // If the new option is invalid, use old value. - // 'lisp' option: refill g_chartab[] for '-' char - if (buf_init_chartab(buf, true) == FAIL) { - args->os_restore_chartab = true; // need to restore it below - return e_invarg; // error in value - } - return NULL; + return did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false); } -/// The 'helpfile' option is changed. -const char *did_set_helpfile(optset_T *args FUNC_ATTR_UNUSED) +/// The 'buftype' option is changed. +const char *did_set_buftype(optset_T *args) { - // May compute new values for $VIM and $VIMRUNTIME - if (didset_vim) { - vim_unsetenv_ext("VIM"); + buf_T *buf = (buf_T *)args->os_buf; + win_T *win = (win_T *)args->os_win; + // When 'buftype' is set, check for valid value. + if ((buf->terminal && buf->b_p_bt[0] != 't') + || (!buf->terminal && buf->b_p_bt[0] == 't') + || check_opt_strings(buf->b_p_bt, p_buftype_values, false) != OK) { + return e_invarg; } - if (didset_vimruntime) { - vim_unsetenv_ext("VIMRUNTIME"); + if (win->w_status_height || global_stl_height()) { + win->w_redr_status = true; + redraw_later(win, UPD_VALID); } + buf->b_help = (buf->b_p_bt[0] == 'h'); + redraw_titles(); return NULL; } -/// The 'cursorlineopt' option is changed. -const char *did_set_cursorlineopt(optset_T *args) +/// The 'casemap' option is changed. +const char *did_set_casemap(optset_T *args FUNC_ATTR_UNUSED) { - win_T *win = (win_T *)args->os_win; - char **varp = (char **)args->os_varp; + return did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true); +} - if (**varp == NUL || fill_culopt_flags(*varp, win) != OK) { - return e_invarg; +/// The global 'listchars' or 'fillchars' option is changed. +static const char *did_set_global_listfillchars(win_T *win, char *val, bool opt_lcs, int opt_flags) +{ + const char *errmsg = NULL; + char **local_ptr = opt_lcs ? &win->w_p_lcs : &win->w_p_fcs; + + // only apply the global value to "win" when it does not have a + // local value + if (opt_lcs) { + errmsg = set_listchars_option(win, val, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL)); + } else { + errmsg = set_fillchars_option(win, val, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL)); + } + if (errmsg != NULL) { + return errmsg; } - return NULL; -} + // If the current window is set to use the global + // 'listchars'/'fillchars' value, clear the window-local value. + if (!(opt_flags & OPT_GLOBAL)) { + clear_string_option(local_ptr); + } -/// The 'helplang' option is changed. -const char *did_set_helplang(optset_T *args FUNC_ATTR_UNUSED) -{ - // Check for "", "ab", "ab,cd", etc. - for (char *s = p_hlg; *s != NUL; s += 3) { - if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL)) { - return e_invarg; - } - if (s[2] == NUL) { - break; + FOR_ALL_TAB_WINDOWS(tp, wp) { + // If the current window has a local value need to apply it + // again, it was changed when setting the global value. + // If no error was returned above, we don't expect an error + // here, so ignore the return value. + if (opt_lcs) { + if (*wp->w_p_lcs == NUL) { + (void)set_listchars_option(wp, wp->w_p_lcs, true); + } + } else { + if (*wp->w_p_fcs == NUL) { + (void)set_fillchars_option(wp, wp->w_p_fcs, true); + } } } + + redraw_all_later(UPD_NOT_VALID); + return NULL; } -/// The 'highlight' option is changed. -const char *did_set_highlight(optset_T *args) +/// The 'fillchars' option or the 'listchars' option is changed. +const char *did_set_chars_option(optset_T *args) { + win_T *win = (win_T *)args->os_win; char **varp = (char **)args->os_varp; + const char *errmsg = NULL; - if (strcmp(*varp, HIGHLIGHT_INIT) != 0) { - return e_unsupportedoption; + if (varp == &p_lcs // global 'listchars' + || varp == &p_fcs) { // global 'fillchars' + errmsg = did_set_global_listfillchars(win, *varp, varp == &p_lcs, args->os_flags); + } else if (varp == &win->w_p_lcs) { // local 'listchars' + errmsg = set_listchars_option(win, *varp, true); + } else if (varp == &win->w_p_fcs) { // local 'fillchars' + errmsg = set_fillchars_option(win, *varp, true); } - return NULL; + + return errmsg; } -static const char *did_set_opt_flags(char *val, char **values, unsigned *flagp, bool list) +/// The 'cinoptions' option is changed. +const char *did_set_cinoptions(optset_T *args FUNC_ATTR_UNUSED) { - if (opt_strings_flags(val, values, flagp, list) != OK) { - return e_invarg; - } + // TODO(vim): recognize errors + parse_cino(curbuf); + return NULL; } -static const char *did_set_opt_strings(char *val, char **values, bool list) +/// The 'clipboard' option is changed. +const char *did_set_clipboard(optset_T *args FUNC_ATTR_UNUSED) { - return did_set_opt_flags(val, values, NULL, list); + return did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true); } -/// The 'selectmode' option is changed. -const char *did_set_selectmode(optset_T *args FUNC_ATTR_UNUSED) +/// The 'colorcolumn' option is changed. +const char *did_set_colorcolumn(optset_T *args) { - return did_set_opt_strings(p_slm, p_slm_values, true); + win_T *win = (win_T *)args->os_win; + return check_colorcolumn(win); } -/// The 'inccommand' option is changed. -const char *did_set_inccommand(optset_T *args FUNC_ATTR_UNUSED) +/// The 'comments' option is changed. +const char *did_set_comments(optset_T *args) { - return did_set_opt_strings(p_icm, p_icm_values, false); + char **varp = (char **)args->os_varp; + char *errmsg = NULL; + for (char *s = *varp; *s;) { + while (*s && *s != ':') { + if (vim_strchr(COM_ALL, (uint8_t)(*s)) == NULL + && !ascii_isdigit(*s) && *s != '-') { + errmsg = illegal_char(args->os_errbuf, args->os_errbuflen, (uint8_t)(*s)); + break; + } + s++; + } + if (*s++ == NUL) { + errmsg = N_("E524: Missing colon"); + } else if (*s == ',' || *s == NUL) { + errmsg = N_("E525: Zero length string"); + } + if (errmsg != NULL) { + break; + } + while (*s && *s != ',') { + if (*s == '\\' && s[1] != NUL) { + s++; + } + s++; + } + s = skip_to_option_part(s); + } + return errmsg; } -/// The 'sessionoptions' option is changed. -const char *did_set_sessionoptions(optset_T *args) +/// The 'commentstring' option is changed. +const char *did_set_commentstring(optset_T *args) { - if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true) != OK) { - return e_invarg; - } - if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) { - // Don't allow both "sesdir" and "curdir". - const char *oldval = args->os_oldval.string; - (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true); - return e_invarg; + char **varp = (char **)args->os_varp; + + if (**varp != NUL && strstr(*varp, "%s") == NULL) { + return N_("E537: 'commentstring' must be empty or contain %s"); } return NULL; } -/// The 'ambiwidth' option is changed. -const char *did_set_ambiwidth(optset_T *args FUNC_ATTR_UNUSED) +/// The 'complete' option is changed. +const char *did_set_complete(optset_T *args) { - if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) { - return e_invarg; + char **varp = (char **)args->os_varp; + + // check if it is a valid value for 'complete' -- Acevedo + for (char *s = *varp; *s;) { + while (*s == ',' || *s == ' ') { + s++; + } + if (!*s) { + break; + } + if (vim_strchr(".wbuksid]tU", (uint8_t)(*s)) == NULL) { + return illegal_char(args->os_errbuf, args->os_errbuflen, (uint8_t)(*s)); + } + if (*++s != NUL && *s != ',' && *s != ' ') { + if (s[-1] == 'k' || s[-1] == 's') { + // skip optional filename after 'k' and 's' + while (*s && *s != ',' && *s != ' ') { + if (*s == '\\' && s[1] != NUL) { + s++; + } + s++; + } + } else { + if (args->os_errbuf != NULL) { + vim_snprintf(args->os_errbuf, args->os_errbuflen, + _("E535: Illegal character after <%c>"), + *--s); + return args->os_errbuf; + } + return ""; + } + } } - return check_chars_options(); + return NULL; } -/// The 'background' option is changed. -const char *did_set_background(optset_T *args FUNC_ATTR_UNUSED) +/// The 'completeopt' option is changed. +const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED) { - if (check_opt_strings(p_bg, p_bg_values, false) != OK) { + if (check_opt_strings(p_cot, p_cot_values, true) != OK) { return e_invarg; } - - int dark = (*p_bg == 'd'); - - init_highlight(false, false); - - if (dark != (*p_bg == 'd') && get_var_value("g:colors_name") != NULL) { - // The color scheme must have set 'background' back to another - // value, that's not what we want here. Disable the color - // scheme and set the colors again. - do_unlet(S_LEN("g:colors_name"), true); - free_string_option(p_bg); - p_bg = xstrdup((dark ? "dark" : "light")); - check_string_option(&p_bg); - init_highlight(false, false); - } + completeopt_was_set(); return NULL; } -/// The 'whichwrap' option is changed. -const char *did_set_whichwrap(optset_T *args) +#ifdef BACKSLASH_IN_FILENAME +/// The 'completeslash' option is changed. +const char *did_set_completeslash(optset_T *args) { - char **varp = (char **)args->os_varp; - - return did_set_option_listflag(*varp, WW_ALL, args->os_errbuf, args->os_errbuflen); + buf_T *buf = (buf_T *)args->os_buf; + if (check_opt_strings(p_csl, p_csl_values, false) != OK + || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) { + return e_invarg; + } + return NULL; } +#endif -/// The 'shortmess' option is changed. -const char *did_set_shortmess(optset_T *args) +/// The 'concealcursor' option is changed. +const char *did_set_concealcursor(optset_T *args) { char **varp = (char **)args->os_varp; - return did_set_option_listflag(*varp, SHM_ALL, args->os_errbuf, args->os_errbuflen); + return did_set_option_listflag(*varp, COCU_ALL, args->os_errbuf, args->os_errbuflen); } /// The 'cpoptions' option is changed. @@ -931,66 +1011,42 @@ const char *did_set_cpoptions(optset_T *args) return did_set_option_listflag(*varp, CPO_VI, args->os_errbuf, args->os_errbuflen); } -/// The 'clipboard' option is changed. -const char *did_set_clipboard(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true); -} - -/// The 'foldopen' option is changed. -const char *did_set_foldopen(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true); -} - -/// The 'formatoptions' option is changed. -const char *did_set_formatoptions(optset_T *args) -{ - char **varp = (char **)args->os_varp; - - return did_set_option_listflag(*varp, FO_ALL, args->os_errbuf, args->os_errbuflen); -} - -/// The 'concealcursor' option is changed. -const char *did_set_concealcursor(optset_T *args) +/// The 'cursorlineopt' option is changed. +const char *did_set_cursorlineopt(optset_T *args) { + win_T *win = (win_T *)args->os_win; char **varp = (char **)args->os_varp; - return did_set_option_listflag(*varp, COCU_ALL, args->os_errbuf, args->os_errbuflen); -} - -/// The 'mouse' option is changed. -const char *did_set_mouse(optset_T *args) -{ - char **varp = (char **)args->os_varp; + if (**varp == NUL || fill_culopt_flags(*varp, win) != OK) { + return e_invarg; + } - return did_set_option_listflag(*varp, MOUSE_ALL, args->os_errbuf, args->os_errbuflen); + return NULL; } -/// The 'wildmode' option is changed. -const char *did_set_wildmode(optset_T *args FUNC_ATTR_UNUSED) +/// The 'debug' option is changed. +const char *did_set_debug(optset_T *args FUNC_ATTR_UNUSED) { - if (check_opt_wim() == FAIL) { - return e_invarg; - } - return NULL; + return did_set_opt_strings(p_debug, p_debug_values, false); } -/// The 'winaltkeys' option is changed. -const char *did_set_winaltkeys(optset_T *args FUNC_ATTR_UNUSED) +/// The 'diffopt' option is changed. +const char *did_set_diffopt(optset_T *args FUNC_ATTR_UNUSED) { - if (*p_wak == NUL || check_opt_strings(p_wak, p_wak_values, false) != OK) { + if (diffopt_changed() == FAIL) { return e_invarg; } return NULL; } -/// The 'eventignore' option is changed. -const char *did_set_eventignore(optset_T *args FUNC_ATTR_UNUSED) +/// The 'display' option is changed. +const char *did_set_display(optset_T *args FUNC_ATTR_UNUSED) { - if (check_ei() == FAIL) { + if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) { return e_invarg; } + (void)init_chartab(); + msg_grid_validate(); return NULL; } @@ -1042,22 +1098,245 @@ const char *did_set_encoding(optset_T *args) return NULL; } -/// The 'keymap' option has changed. -const char *did_set_keymap(optset_T *args) +/// The 'eventignore' option is changed. +const char *did_set_eventignore(optset_T *args FUNC_ATTR_UNUSED) +{ + if (check_ei() == FAIL) { + return e_invarg; + } + return NULL; +} + +/// The 'fileformat' option is changed. +const char *did_set_fileformat(optset_T *args) { buf_T *buf = (buf_T *)args->os_buf; char **varp = (char **)args->os_varp; + const char *oldval = args->os_oldval.string; int opt_flags = args->os_flags; + if (!MODIFIABLE(buf) && !(opt_flags & OPT_GLOBAL)) { + return e_modifiable; + } else if (check_opt_strings(*varp, p_ff_values, false) != OK) { + return e_invarg; + } + redraw_titles(); + // update flag in swap file + ml_setflags(buf); + // Redraw needed when switching to/from "mac": a CR in the text + // will be displayed differently. + if (get_fileformat(buf) == EOL_MAC || *oldval == 'm') { + redraw_buf_later(buf, UPD_NOT_VALID); + } + return NULL; +} + +/// The 'fileformats' option is changed. +const char *did_set_fileformats(optset_T *args) +{ + return did_set_opt_strings(p_ffs, p_ff_values, true); +} + +/// The 'filetype' or the 'syntax' option is changed. +const char *did_set_filetype_or_syntax(optset_T *args) +{ + char **varp = (char **)args->os_varp; if (!valid_filetype(*varp)) { return e_invarg; } - int secure_save = secure; + args->os_value_changed = strcmp(args->os_oldval.string, *varp) != 0; - // Reset the secure flag, since the value of 'keymap' has - // been checked to be safe. - secure = 0; + // Since we check the value, there is no need to set P_INSECURE, + // even when the value comes from a modeline. + args->os_value_checked = true; + + return NULL; +} + +/// The 'foldclose' option is changed. +const char *did_set_foldclose(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_strings(p_fcl, p_fcl_values, true); +} + +/// The 'foldcolumn' option is changed. +const char *did_set_foldcolumn(optset_T *args) +{ + char **varp = (char **)args->os_varp; + if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) { + return e_invarg; + } + return NULL; +} + +/// The 'foldexpr' option is changed. +const char *did_set_foldexpr(optset_T *args) +{ + win_T *win = (win_T *)args->os_win; + (void)did_set_optexpr(args); + if (foldmethodIsExpr(win)) { + foldUpdateAll(win); + } + return NULL; +} + +/// The 'foldignore' option is changed. +const char *did_set_foldignore(optset_T *args) +{ + win_T *win = (win_T *)args->os_win; + if (foldmethodIsIndent(win)) { + foldUpdateAll(win); + } + return NULL; +} + +/// The 'foldmarker' option is changed. +const char *did_set_foldmarker(optset_T *args) +{ + win_T *win = (win_T *)args->os_win; + char **varp = (char **)args->os_varp; + char *p = vim_strchr(*varp, ','); + + if (p == NULL) { + return e_comma_required; + } + + if (p == *varp || p[1] == NUL) { + return e_invarg; + } + + if (foldmethodIsMarker(win)) { + foldUpdateAll(win); + } + + return NULL; +} + +/// The 'foldmethod' option is changed. +const char *did_set_foldmethod(optset_T *args) +{ + win_T *win = (win_T *)args->os_win; + char **varp = (char **)args->os_varp; + if (check_opt_strings(*varp, p_fdm_values, false) != OK + || *win->w_p_fdm == NUL) { + return e_invarg; + } + foldUpdateAll(win); + if (foldmethodIsDiff(win)) { + newFoldLevel(); + } + return NULL; +} + +/// The 'foldopen' option is changed. +const char *did_set_foldopen(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true); +} + +/// The 'formatoptions' option is changed. +const char *did_set_formatoptions(optset_T *args) +{ + char **varp = (char **)args->os_varp; + + return did_set_option_listflag(*varp, FO_ALL, args->os_errbuf, args->os_errbuflen); +} + +/// The 'guicursor' option is changed. +const char *did_set_guicursor(optset_T *args FUNC_ATTR_UNUSED) +{ + return parse_shape_opt(SHAPE_CURSOR); +} + +/// The 'helpfile' option is changed. +const char *did_set_helpfile(optset_T *args FUNC_ATTR_UNUSED) +{ + // May compute new values for $VIM and $VIMRUNTIME + if (didset_vim) { + vim_unsetenv_ext("VIM"); + } + if (didset_vimruntime) { + vim_unsetenv_ext("VIMRUNTIME"); + } + return NULL; +} + +/// The 'helplang' option is changed. +const char *did_set_helplang(optset_T *args FUNC_ATTR_UNUSED) +{ + // Check for "", "ab", "ab,cd", etc. + for (char *s = p_hlg; *s != NUL; s += 3) { + if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL)) { + return e_invarg; + } + if (s[2] == NUL) { + break; + } + } + return NULL; +} + +/// The 'highlight' option is changed. +const char *did_set_highlight(optset_T *args) +{ + char **varp = (char **)args->os_varp; + + if (strcmp(*varp, HIGHLIGHT_INIT) != 0) { + return e_unsupportedoption; + } + return NULL; +} + +/// The 'iconstring' option is changed. +const char *did_set_iconstring(optset_T *args) +{ + return did_set_titleiconstring(args, STL_IN_ICON); +} + +/// The 'inccommand' option is changed. +const char *did_set_inccommand(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_strings(p_icm, p_icm_values, false); +} + +/// The 'isident' or the 'iskeyword' or the 'isprint' or the 'isfname' option is +/// changed. +const char *did_set_isopt(optset_T *args) +{ + buf_T *buf = (buf_T *)args->os_buf; + // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[] + // If the new option is invalid, use old value. + // 'lisp' option: refill g_chartab[] for '-' char + if (buf_init_chartab(buf, true) == FAIL) { + args->os_restore_chartab = true; // need to restore it below + return e_invarg; // error in value + } + return NULL; +} + +/// The 'jumpoptions' option is changed. +const char *did_set_jumpoptions(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true); +} + +/// The 'keymap' option has changed. +const char *did_set_keymap(optset_T *args) +{ + buf_T *buf = (buf_T *)args->os_buf; + char **varp = (char **)args->os_varp; + int opt_flags = args->os_flags; + + if (!valid_filetype(*varp)) { + return e_invarg; + } + + int secure_save = secure; + + // Reset the secure flag, since the value of 'keymap' has + // been checked to be safe. + secure = 0; // load or unload key mapping tables const char *errmsg = keymap_init(); @@ -1094,33 +1373,26 @@ const char *did_set_keymap(optset_T *args) return errmsg; } -/// The 'fileformat' option is changed. -const char *did_set_fileformat(optset_T *args) +/// The 'keymodel' option is changed. +const char *did_set_keymodel(optset_T *args FUNC_ATTR_UNUSED) { - buf_T *buf = (buf_T *)args->os_buf; - char **varp = (char **)args->os_varp; - const char *oldval = args->os_oldval.string; - int opt_flags = args->os_flags; - if (!MODIFIABLE(buf) && !(opt_flags & OPT_GLOBAL)) { - return e_modifiable; - } else if (check_opt_strings(*varp, p_ff_values, false) != OK) { + if (check_opt_strings(p_km, p_km_values, true) != OK) { return e_invarg; } - redraw_titles(); - // update flag in swap file - ml_setflags(buf); - // Redraw needed when switching to/from "mac": a CR in the text - // will be displayed differently. - if (get_fileformat(buf) == EOL_MAC || *oldval == 'm') { - redraw_buf_later(buf, UPD_NOT_VALID); - } + km_stopsel = (vim_strchr(p_km, 'o') != NULL); + km_startsel = (vim_strchr(p_km, 'a') != NULL); return NULL; } -/// The 'fileformats' option is changed. -const char *did_set_fileformats(optset_T *args) +/// The 'lispoptions' option is changed. +const char *did_set_lispoptions(optset_T *args) { - return did_set_opt_strings(p_ffs, p_ff_values, true); + char **varp = (char **)args->os_varp; + + if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) { + return e_invarg; + } + return NULL; } /// The 'matchpairs' option is changed. @@ -1150,433 +1422,135 @@ const char *did_set_matchpairs(optset_T *args) return NULL; } -/// The 'cinoptions' option is changed. -const char *did_set_cinoptions(optset_T *args FUNC_ATTR_UNUSED) +/// The 'mkspellmem' option is changed. +const char *did_set_mkspellmem(optset_T *args FUNC_ATTR_UNUSED) { - // TODO(vim): recognize errors - parse_cino(curbuf); - + if (spell_check_msm() != OK) { + return e_invarg; + } return NULL; } -/// The 'colorcolumn' option is changed. -const char *did_set_colorcolumn(optset_T *args) +/// The 'mouse' option is changed. +const char *did_set_mouse(optset_T *args) { - win_T *win = (win_T *)args->os_win; - return check_colorcolumn(win); + char **varp = (char **)args->os_varp; + + return did_set_option_listflag(*varp, MOUSE_ALL, args->os_errbuf, args->os_errbuflen); } -const char *did_set_comments(optset_T *args) +/// The 'mousemodel' option is changed. +const char *did_set_mousemodel(optset_T *args FUNC_ATTR_UNUSED) { - char **varp = (char **)args->os_varp; - char *errmsg = NULL; - for (char *s = *varp; *s;) { - while (*s && *s != ':') { - if (vim_strchr(COM_ALL, (uint8_t)(*s)) == NULL - && !ascii_isdigit(*s) && *s != '-') { - errmsg = illegal_char(args->os_errbuf, args->os_errbuflen, (uint8_t)(*s)); - break; - } - s++; - } - if (*s++ == NUL) { - errmsg = N_("E524: Missing colon"); - } else if (*s == ',' || *s == NUL) { - errmsg = N_("E525: Zero length string"); - } - if (errmsg != NULL) { - break; - } - while (*s && *s != ',') { - if (*s == '\\' && s[1] != NUL) { - s++; - } - s++; - } - s = skip_to_option_part(s); - } - return errmsg; + return did_set_opt_strings(p_mousem, p_mousem_values, false); } -/// The global 'listchars' or 'fillchars' option is changed. -static const char *did_set_global_listfillchars(win_T *win, char *val, bool opt_lcs, int opt_flags) +/// Handle setting 'mousescroll'. +/// @return error message, NULL if it's OK. +const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) { - const char *errmsg = NULL; - char **local_ptr = opt_lcs ? &win->w_p_lcs : &win->w_p_fcs; + OptInt vertical = -1; + OptInt horizontal = -1; - // only apply the global value to "win" when it does not have a - // local value - if (opt_lcs) { - errmsg = set_listchars_option(win, val, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL)); - } else { - errmsg = set_fillchars_option(win, val, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL)); - } - if (errmsg != NULL) { - return errmsg; - } + char *string = p_mousescroll; - // If the current window is set to use the global - // 'listchars'/'fillchars' value, clear the window-local value. - if (!(opt_flags & OPT_GLOBAL)) { - clear_string_option(local_ptr); - } + while (true) { + char *end = vim_strchr(string, ','); + size_t length = end ? (size_t)(end - string) : strlen(string); - FOR_ALL_TAB_WINDOWS(tp, wp) { - // If the current window has a local value need to apply it - // again, it was changed when setting the global value. - // If no error was returned above, we don't expect an error - // here, so ignore the return value. - if (opt_lcs) { - if (*wp->w_p_lcs == NUL) { - (void)set_listchars_option(wp, wp->w_p_lcs, true); - } - } else { - if (*wp->w_p_fcs == NUL) { - (void)set_fillchars_option(wp, wp->w_p_fcs, true); - } + // Both "ver:" and "hor:" are 4 bytes long. + // They should be followed by at least one digit. + if (length <= 4) { + return e_invarg; } - } - - redraw_all_later(UPD_NOT_VALID); - - return NULL; -} - -/// Handle the new value of 'fillchars'. -const char *set_fillchars_option(win_T *wp, char *val, int apply) -{ - return set_chars_option(wp, val, false, apply); -} - -/// Handle the new value of 'listchars'. -const char *set_listchars_option(win_T *wp, char *val, int apply) -{ - return set_chars_option(wp, val, true, apply); -} - -/// The 'fillchars' option or the 'listchars' option is changed. -const char *did_set_chars_option(optset_T *args) -{ - win_T *win = (win_T *)args->os_win; - char **varp = (char **)args->os_varp; - const char *errmsg = NULL; - - if (varp == &p_lcs // global 'listchars' - || varp == &p_fcs) { // global 'fillchars' - errmsg = did_set_global_listfillchars(win, *varp, varp == &p_lcs, args->os_flags); - } else if (varp == &win->w_p_lcs) { // local 'listchars' - errmsg = set_listchars_option(win, *varp, true); - } else if (varp == &win->w_p_fcs) { // local 'fillchars' - errmsg = set_fillchars_option(win, *varp, true); - } - - return errmsg; -} - -/// The 'verbosefile' option is changed. -const char *did_set_verbosefile(optset_T *args) -{ - verbose_stop(); - if (*p_vfile != NUL && verbose_open() == FAIL) { - return (char *)e_invarg; - } - return NULL; -} - -/// The 'viewoptions' option is changed. -const char *did_set_viewoptions(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, true); -} -static int shada_idx = -1; + OptInt *direction; -static const char *did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, - size_t errbuflen) -{ - // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo - // option. - *opt_idx = (((*opt)->fullname[0] == 'v') - ? (shada_idx == -1 ? ((shada_idx = findoption("shada"))) : shada_idx) - : *opt_idx); - *opt = get_option(*opt_idx); - // Update free_oldval now that we have the opt_idx for 'shada', otherwise - // there would be a disconnect between the check for P_ALLOCED at the start - // of the function and the set of P_ALLOCED at the end of the function. - *free_oldval = ((*opt)->flags & P_ALLOCED); - for (char *s = p_shada; *s;) { - // Check it's a valid character - if (vim_strchr("!\"%'/:<@cfhnrs", (uint8_t)(*s)) == NULL) { - return illegal_char(errbuf, errbuflen, (uint8_t)(*s)); + if (memcmp(string, "ver:", 4) == 0) { + direction = &vertical; + } else if (memcmp(string, "hor:", 4) == 0) { + direction = &horizontal; + } else { + return e_invarg; } - if (*s == 'n') { // name is always last one - break; - } else if (*s == 'r') { // skip until next ',' - while (*++s && *s != ',') {} - } else if (*s == '%') { - // optional number - while (ascii_isdigit(*++s)) {} - } else if (*s == '!' || *s == 'h' || *s == 'c') { - s++; // no extra chars - } else { // must have a number - while (ascii_isdigit(*++s)) {} - if (!ascii_isdigit(*(s - 1))) { - if (errbuf != NULL) { - vim_snprintf(errbuf, errbuflen, - _("E526: Missing number after <%s>"), - transchar_byte((uint8_t)(*(s - 1)))); - return errbuf; - } else { - return ""; - } - } + // If the direction has already been set, this is a duplicate. + if (*direction != -1) { + return e_invarg; } - if (*s == ',') { - s++; - } else if (*s) { - if (errbuf != NULL) { - return N_("E527: Missing comma"); - } else { - return ""; + + // Verify that only digits follow the colon. + for (size_t i = 4; i < length; i++) { + if (!ascii_isdigit(string[i])) { + return N_("E5080: Digit expected"); } } - } - if (*p_shada && get_shada_parameter('\'') < 0) { - return N_("E528: Must specify a ' value"); - } - return NULL; -} -/// The 'showbreak' option is changed. -const char *did_set_showbreak(optset_T *args) -{ - char **varp = (char **)args->os_varp; + string += 4; + *direction = getdigits_int(&string, false, -1); - for (char *s = *varp; *s;) { - if (ptr2cells(s) != 1) { - return e_showbreak_contains_unprintable_or_wide_character; + // Num options are generally kept within the signed int range. + // We know this number won't be negative because we've already checked for + // a minus sign. We'll allow 0 as a means of disabling mouse scrolling. + if (*direction == -1) { + return e_invarg; } - MB_PTR_ADV(s); - } - return NULL; -} -/// The 'titlestring' or the 'iconstring' option is changed. -static const char *did_set_titleiconstring(optset_T *args, int flagval) -{ - char **varp = (char **)args->os_varp; - - // NULL => statusline syntax - if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) { - stl_syntax |= flagval; - } else { - stl_syntax &= ~flagval; - } - did_set_title(); - - return NULL; -} - -/// The 'titlestring' option is changed. -const char *did_set_titlestring(optset_T *args) -{ - return did_set_titleiconstring(args, STL_IN_TITLE); -} - -/// The 'iconstring' option is changed. -const char *did_set_iconstring(optset_T *args) -{ - return did_set_titleiconstring(args, STL_IN_ICON); -} + if (!end) { + break; + } -/// The 'selection' option is changed. -const char *did_set_selection(optset_T *args FUNC_ATTR_UNUSED) -{ - if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, false) != OK) { - return e_invarg; + string = end + 1; } - return NULL; -} -/// The 'keymodel' option is changed. -const char *did_set_keymodel(optset_T *args FUNC_ATTR_UNUSED) -{ - if (check_opt_strings(p_km, p_km_values, true) != OK) { - return e_invarg; - } - km_stopsel = (vim_strchr(p_km, 'o') != NULL); - km_startsel = (vim_strchr(p_km, 'a') != NULL); - return NULL; -} + // If a direction wasn't set, fallback to the default value. + p_mousescroll_vert = (vertical == -1) ? MOUSESCROLL_VERT_DFLT : vertical; + p_mousescroll_hor = (horizontal == -1) ? MOUSESCROLL_HOR_DFLT : horizontal; -/// The 'display' option is changed. -const char *did_set_display(optset_T *args FUNC_ATTR_UNUSED) -{ - if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) { - return e_invarg; - } - (void)init_chartab(); - msg_grid_validate(); return NULL; } -/// The 'spellfile' option is changed. -const char *did_set_spellfile(optset_T *args) +/// The 'nrformats' option is changed. +const char *did_set_nrformats(optset_T *args) { char **varp = (char **)args->os_varp; - // When there is a window for this buffer in which 'spell' - // is set load the wordlists. - if ((!valid_spellfile(*varp))) { - return e_invarg; - } - return did_set_spell_option(true); + return did_set_opt_strings(*varp, p_nf_values, true); } -const char *did_set_spelllang(optset_T *args) +/// One of the '*expr' options is changed:, 'diffexpr', 'foldexpr', 'foldtext', +/// 'formatexpr', 'includeexpr', 'indentexpr', 'patchexpr' and 'charconvert'. +const char *did_set_optexpr(optset_T *args) { char **varp = (char **)args->os_varp; - // When there is a window for this buffer in which 'spell' - // is set load the wordlists. - if (!valid_spelllang(*varp)) { - return e_invarg; - } - return did_set_spell_option(false); -} - -/// The 'spellcapcheck' option is changed. -const char *did_set_spellcapcheck(optset_T *args) -{ - win_T *win = (win_T *)args->os_win; - // When 'spellcapcheck' is set compile the regexp program. - return compile_cap_prog(win->w_s); -} - -/// The 'spelloptions' option is changed. -const char *did_set_spelloptions(optset_T *args) -{ - win_T *win = (win_T *)args->os_win; - if (opt_strings_flags(win->w_s->b_p_spo, p_spo_values, &(win->w_s->b_p_spo_flags), - true) != OK) { - return e_invarg; - } - return NULL; -} - -/// The 'spellsuggest' option is changed. -const char *did_set_spellsuggest(optset_T *args FUNC_ATTR_UNUSED) -{ - if (spell_check_sps() != OK) { - return e_invarg; - } - return NULL; -} - -/// The 'splitkeep' option is changed. -const char *did_set_splitkeep(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_strings(p_spk, p_spk_values, false); -} - -/// The 'mkspellmem' option is changed. -const char *did_set_mkspellmem(optset_T *args FUNC_ATTR_UNUSED) -{ - if (spell_check_msm() != OK) { - return e_invarg; - } - return NULL; -} - -/// The 'mousemodel' option is changed. -const char *did_set_mousemodel(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_strings(p_mousem, p_mousem_values, false); -} - -/// The 'bufhidden' option is changed. -const char *did_set_bufhidden(optset_T *args) -{ - buf_T *buf = (buf_T *)args->os_buf; - return did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false); -} - -/// The 'buftype' option is changed. -const char *did_set_buftype(optset_T *args) -{ - buf_T *buf = (buf_T *)args->os_buf; - win_T *win = (win_T *)args->os_win; - // When 'buftype' is set, check for valid value. - if ((buf->terminal && buf->b_p_bt[0] != 't') - || (!buf->terminal && buf->b_p_bt[0] == 't') - || check_opt_strings(buf->b_p_bt, p_buftype_values, false) != OK) { - return e_invarg; - } - if (win->w_status_height || global_stl_height()) { - win->w_redr_status = true; - redraw_later(win, UPD_VALID); + // If the option value starts with or s:, then replace that with + // the script identifier. + char *name = get_scriptlocal_funcname(*varp); + if (name != NULL) { + free_string_option(*varp); + *varp = name; } - buf->b_help = (buf->b_p_bt[0] == 'h'); - redraw_titles(); return NULL; } -/// The 'casemap' option is changed. -const char *did_set_casemap(optset_T *args FUNC_ATTR_UNUSED) +/// The 'redrawdebug' option is changed. +const char *did_set_redrawdebug(optset_T *args FUNC_ATTR_UNUSED) { - return did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true); + return did_set_opt_flags(p_rdb, p_rdb_values, &rdb_flags, true); } -/// The 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn' option is changed. -/// -/// @param rulerformat true if the 'rulerformat' option is changed -/// @param statuscolumn true if the 'statuscolumn' option is changed -static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerformat, - bool statuscolumn) +/// The 'rightleftcmd' option is changed. +const char *did_set_rightleftcmd(optset_T *args) { - win_T *win = (win_T *)args->os_win; char **varp = (char **)args->os_varp; - if (rulerformat) { // reset ru_wid first - ru_wid = 0; - } else if (statuscolumn) { - // reset 'statuscolumn' width - win->w_nrwidth_line_count = 0; - } - const char *errmsg = NULL; - char *s = *varp; - if (rulerformat && *s == '%') { - // set ru_wid if 'ruf' starts with "%99(" - if (*++s == '-') { // ignore a '-' - s++; - } - int wid = getdigits_int(&s, true, 0); - if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL) { - ru_wid = wid; - } else { - errmsg = check_stl_option(p_ruf); - } - } else if (rulerformat || s[0] != '%' || s[1] != '!') { - // check 'statusline', 'winbar', 'tabline' or 'statuscolumn' - // only if it doesn't start with "%!" - errmsg = check_stl_option(s); - } - if (rulerformat && errmsg == NULL) { - comp_col(); - } - return errmsg; -} -/// The 'statusline' option is changed. -const char *did_set_statusline(optset_T *args) -{ - return did_set_statustabline_rulerformat(args, false, false); -} - -/// The 'tabline' option is changed. -const char *did_set_tabline(optset_T *args) -{ - return did_set_statustabline_rulerformat(args, false, false); + // Currently only "search" is a supported value. + if (**varp != NUL && strcmp(*varp, "search") != 0) { + return e_invarg; + } + + return NULL; } /// The 'rulerformat' option is changed. @@ -1585,85 +1559,121 @@ const char *did_set_rulerformat(optset_T *args) return did_set_statustabline_rulerformat(args, true, false); } -/// The 'winbar' option is changed. -const char *did_set_winbar(optset_T *args) +/// The 'scrollopt' option is changed. +const char *did_set_scrollopt(optset_T *args FUNC_ATTR_UNUSED) { - return did_set_statustabline_rulerformat(args, false, false); + return did_set_opt_strings(p_sbo, p_scbopt_values, true); } -/// The 'statuscolumn' option is changed. -const char *did_set_statuscolumn(optset_T *args) +/// The 'selection' option is changed. +const char *did_set_selection(optset_T *args FUNC_ATTR_UNUSED) { - return did_set_statustabline_rulerformat(args, false, true); + if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, false) != OK) { + return e_invarg; + } + return NULL; } -/// The 'scrollopt' option is changed. -const char *did_set_scrollopt(optset_T *args FUNC_ATTR_UNUSED) +/// The 'selectmode' option is changed. +const char *did_set_selectmode(optset_T *args FUNC_ATTR_UNUSED) { - return did_set_opt_strings(p_sbo, p_scbopt_values, true); + return did_set_opt_strings(p_slm, p_slm_values, true); } -/// The 'complete' option is changed. -const char *did_set_complete(optset_T *args) +/// The 'sessionoptions' option is changed. +const char *did_set_sessionoptions(optset_T *args) { - char **varp = (char **)args->os_varp; + if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true) != OK) { + return e_invarg; + } + if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) { + // Don't allow both "sesdir" and "curdir". + const char *oldval = args->os_oldval.string; + (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true); + return e_invarg; + } + return NULL; +} - // check if it is a valid value for 'complete' -- Acevedo - for (char *s = *varp; *s;) { - while (*s == ',' || *s == ' ') { - s++; +static const char *did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, + size_t errbuflen) +{ + static int shada_idx = -1; + // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo + // option. + *opt_idx = (((*opt)->fullname[0] == 'v') + ? (shada_idx == -1 ? ((shada_idx = findoption("shada"))) : shada_idx) + : *opt_idx); + *opt = get_option(*opt_idx); + // Update free_oldval now that we have the opt_idx for 'shada', otherwise + // there would be a disconnect between the check for P_ALLOCED at the start + // of the function and the set of P_ALLOCED at the end of the function. + *free_oldval = ((*opt)->flags & P_ALLOCED); + for (char *s = p_shada; *s;) { + // Check it's a valid character + if (vim_strchr("!\"%'/:<@cfhnrs", (uint8_t)(*s)) == NULL) { + return illegal_char(errbuf, errbuflen, (uint8_t)(*s)); } - if (!*s) { + if (*s == 'n') { // name is always last one break; - } - if (vim_strchr(".wbuksid]tU", (uint8_t)(*s)) == NULL) { - return illegal_char(args->os_errbuf, args->os_errbuflen, (uint8_t)(*s)); - } - if (*++s != NUL && *s != ',' && *s != ' ') { - if (s[-1] == 'k' || s[-1] == 's') { - // skip optional filename after 'k' and 's' - while (*s && *s != ',' && *s != ' ') { - if (*s == '\\' && s[1] != NUL) { - s++; - } - s++; + } else if (*s == 'r') { // skip until next ',' + while (*++s && *s != ',') {} + } else if (*s == '%') { + // optional number + while (ascii_isdigit(*++s)) {} + } else if (*s == '!' || *s == 'h' || *s == 'c') { + s++; // no extra chars + } else { // must have a number + while (ascii_isdigit(*++s)) {} + + if (!ascii_isdigit(*(s - 1))) { + if (errbuf != NULL) { + vim_snprintf(errbuf, errbuflen, + _("E526: Missing number after <%s>"), + transchar_byte((uint8_t)(*(s - 1)))); + return errbuf; + } else { + return ""; } + } + } + if (*s == ',') { + s++; + } else if (*s) { + if (errbuf != NULL) { + return N_("E527: Missing comma"); } else { - if (args->os_errbuf != NULL) { - vim_snprintf(args->os_errbuf, args->os_errbuflen, - _("E535: Illegal character after <%c>"), - *--s); - return args->os_errbuf; - } return ""; } } } + if (*p_shada && get_shada_parameter('\'') < 0) { + return N_("E528: Must specify a ' value"); + } return NULL; } -/// The 'completeopt' option is changed. -const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED) +/// The 'shortmess' option is changed. +const char *did_set_shortmess(optset_T *args) { - if (check_opt_strings(p_cot, p_cot_values, true) != OK) { - return e_invarg; - } - completeopt_was_set(); - return NULL; + char **varp = (char **)args->os_varp; + + return did_set_option_listflag(*varp, SHM_ALL, args->os_errbuf, args->os_errbuflen); } -#ifdef BACKSLASH_IN_FILENAME -/// The 'completeslash' option is changed. -const char *did_set_completeslash(optset_T *args) +/// The 'showbreak' option is changed. +const char *did_set_showbreak(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; - if (check_opt_strings(p_csl, p_csl_values, false) != OK - || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) { - return e_invarg; + char **varp = (char **)args->os_varp; + + for (char *s = *varp; *s;) { + if (ptr2cells(s) != 1) { + return e_showbreak_contains_unprintable_or_wide_character; + } + MB_PTR_ADV(s); } return NULL; } -#endif /// The 'showcmdloc' option is changed. const char *did_set_showcmdloc(optset_T *args FUNC_ATTR_UNUSED) @@ -1690,233 +1700,182 @@ const char *did_set_signcolumn(optset_T *args) return NULL; } -/// The 'foldcolumn' option is changed. -const char *did_set_foldcolumn(optset_T *args) -{ - char **varp = (char **)args->os_varp; - if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) { - return e_invarg; - } - return NULL; -} - -/// The 'backspace' option is changed. -const char *did_set_backspace(optset_T *args FUNC_ATTR_UNUSED) -{ - if (ascii_isdigit(*p_bs)) { - if (*p_bs != '2') { - return e_invarg; - } - } else if (check_opt_strings(p_bs, p_bs_values, true) != OK) { - return e_invarg; - } - return NULL; -} - -/// The 'switchbuf' option is changed. -const char *did_set_switchbuf(optset_T *args FUNC_ATTR_UNUSED) +/// The 'spellcapcheck' option is changed. +const char *did_set_spellcapcheck(optset_T *args) { - return did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true); + win_T *win = (win_T *)args->os_win; + // When 'spellcapcheck' is set compile the regexp program. + return compile_cap_prog(win->w_s); } -/// The 'tagcase' option is changed. -const char *did_set_tagcase(optset_T *args) +/// The 'spellfile' option is changed. +const char *did_set_spellfile(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; - int opt_flags = args->os_flags; - - unsigned *flags; - char *p; - - if (opt_flags & OPT_LOCAL) { - p = buf->b_p_tc; - flags = &buf->b_tc_flags; - } else { - p = p_tc; - flags = &tc_flags; - } + char **varp = (char **)args->os_varp; - if ((opt_flags & OPT_LOCAL) && *p == NUL) { - // make the local value empty: use the global value - *flags = 0; - } else if (*p == NUL - || opt_strings_flags(p, p_tc_values, flags, false) != OK) { + // When there is a window for this buffer in which 'spell' + // is set load the wordlists. + if ((!valid_spellfile(*varp))) { return e_invarg; } - return NULL; + return did_set_spell_option(true); } -/// The 'debug' option is changed. -const char *did_set_debug(optset_T *args FUNC_ATTR_UNUSED) +/// The 'spelllang' option is changed. +const char *did_set_spelllang(optset_T *args) { - return did_set_opt_strings(p_debug, p_debug_values, false); -} + char **varp = (char **)args->os_varp; -/// The 'diffopt' option is changed. -const char *did_set_diffopt(optset_T *args FUNC_ATTR_UNUSED) -{ - if (diffopt_changed() == FAIL) { + // When there is a window for this buffer in which 'spell' + // is set load the wordlists. + if (!valid_spelllang(*varp)) { return e_invarg; } - return NULL; + return did_set_spell_option(false); } -/// The 'foldmethod' option is changed. -const char *did_set_foldmethod(optset_T *args) +/// The 'spelloptions' option is changed. +const char *did_set_spelloptions(optset_T *args) { win_T *win = (win_T *)args->os_win; - char **varp = (char **)args->os_varp; - if (check_opt_strings(*varp, p_fdm_values, false) != OK - || *win->w_p_fdm == NUL) { + if (opt_strings_flags(win->w_s->b_p_spo, p_spo_values, &(win->w_s->b_p_spo_flags), + true) != OK) { return e_invarg; } - foldUpdateAll(win); - if (foldmethodIsDiff(win)) { - newFoldLevel(); - } return NULL; } -/// The 'foldmarker' option is changed. -const char *did_set_foldmarker(optset_T *args) +/// The 'spellsuggest' option is changed. +const char *did_set_spellsuggest(optset_T *args FUNC_ATTR_UNUSED) { - win_T *win = (win_T *)args->os_win; - char **varp = (char **)args->os_varp; - char *p = vim_strchr(*varp, ','); - - if (p == NULL) { - return e_comma_required; - } - - if (p == *varp || p[1] == NUL) { + if (spell_check_sps() != OK) { return e_invarg; } - - if (foldmethodIsMarker(win)) { - foldUpdateAll(win); - } - return NULL; } -/// The 'commentstring' option is changed. -const char *did_set_commentstring(optset_T *args) +/// The 'splitkeep' option is changed. +const char *did_set_splitkeep(optset_T *args FUNC_ATTR_UNUSED) { - char **varp = (char **)args->os_varp; + return did_set_opt_strings(p_spk, p_spk_values, false); +} - if (**varp != NUL && strstr(*varp, "%s") == NULL) { - return N_("E537: 'commentstring' must be empty or contain %s"); - } - return NULL; +/// The 'statuscolumn' option is changed. +const char *did_set_statuscolumn(optset_T *args) +{ + return did_set_statustabline_rulerformat(args, false, true); } -/// The 'foldignore' option is changed. -const char *did_set_foldignore(optset_T *args) +/// The 'statusline' option is changed. +const char *did_set_statusline(optset_T *args) { - win_T *win = (win_T *)args->os_win; - if (foldmethodIsIndent(win)) { - foldUpdateAll(win); - } - return NULL; + return did_set_statustabline_rulerformat(args, false, false); } -/// The 'virtualedit' option is changed. -const char *did_set_virtualedit(optset_T *args) +/// The 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn' option is changed. +/// +/// @param rulerformat true if the 'rulerformat' option is changed +/// @param statuscolumn true if the 'statuscolumn' option is changed +static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerformat, + bool statuscolumn) { win_T *win = (win_T *)args->os_win; - - char *ve = p_ve; - unsigned *flags = &ve_flags; - - if (args->os_flags & OPT_LOCAL) { - ve = win->w_p_ve; - flags = &win->w_ve_flags; + char **varp = (char **)args->os_varp; + if (rulerformat) { // reset ru_wid first + ru_wid = 0; + } else if (statuscolumn) { + // reset 'statuscolumn' width + win->w_nrwidth_line_count = 0; } - - if ((args->os_flags & OPT_LOCAL) && *ve == NUL) { - // make the local value empty: use the global value - *flags = 0; - } else { - if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) { - return e_invarg; - } else if (strcmp(ve, args->os_oldval.string) != 0) { - // Recompute cursor position in case the new 've' setting - // changes something. - validate_virtcol_win(win); - // XXX: this only works when win == curwin - coladvance(win->w_virtcol); + const char *errmsg = NULL; + char *s = *varp; + if (rulerformat && *s == '%') { + // set ru_wid if 'ruf' starts with "%99(" + if (*++s == '-') { // ignore a '-' + s++; + } + int wid = getdigits_int(&s, true, 0); + if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL) { + ru_wid = wid; + } else { + errmsg = check_stl_option(p_ruf); } + } else if (rulerformat || s[0] != '%' || s[1] != '!') { + // check 'statusline', 'winbar', 'tabline' or 'statuscolumn' + // only if it doesn't start with "%!" + errmsg = check_stl_option(s); } - return NULL; + if (rulerformat && errmsg == NULL) { + comp_col(); + } + return errmsg; } -/// The 'jumpoptions' option is changed. -const char *did_set_jumpoptions(optset_T *args FUNC_ATTR_UNUSED) +/// The 'switchbuf' option is changed. +const char *did_set_switchbuf(optset_T *args FUNC_ATTR_UNUSED) { - return did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true); + return did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true); } -/// The 'redrawdebug' option is changed. -const char *did_set_redrawdebug(optset_T *args FUNC_ATTR_UNUSED) +/// The 'tabline' option is changed. +const char *did_set_tabline(optset_T *args) { - return did_set_opt_flags(p_rdb, p_rdb_values, &rdb_flags, true); + return did_set_statustabline_rulerformat(args, false, false); } -/// The 'wildoptions' option is changed. -const char *did_set_wildoptions(optset_T *args FUNC_ATTR_UNUSED) +/// The 'tagcase' option is changed. +const char *did_set_tagcase(optset_T *args) { - return did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true); -} + buf_T *buf = (buf_T *)args->os_buf; + int opt_flags = args->os_flags; -/// The 'lispoptions' option is changed. -const char *did_set_lispoptions(optset_T *args) -{ - char **varp = (char **)args->os_varp; + unsigned *flags; + char *p; - if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) { + if (opt_flags & OPT_LOCAL) { + p = buf->b_p_tc; + flags = &buf->b_tc_flags; + } else { + p = p_tc; + flags = &tc_flags; + } + + if ((opt_flags & OPT_LOCAL) && *p == NUL) { + // make the local value empty: use the global value + *flags = 0; + } else if (*p == NUL + || opt_strings_flags(p, p_tc_values, flags, false) != OK) { return e_invarg; } return NULL; } -/// The 'rightleftcmd' option is changed. -const char *did_set_rightleftcmd(optset_T *args) +/// The 'termpastefilter' option is changed. +const char *did_set_termpastefilter(optset_T *args FUNC_ATTR_UNUSED) { - char **varp = (char **)args->os_varp; - - // Currently only "search" is a supported value. - if (**varp != NUL && strcmp(*varp, "search") != 0) { - return e_invarg; - } - - return NULL; + return did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true); } -/// The 'filetype' or the 'syntax' option is changed. -const char *did_set_filetype_or_syntax(optset_T *args) +/// The 'titlestring' or the 'iconstring' option is changed. +static const char *did_set_titleiconstring(optset_T *args, int flagval) { char **varp = (char **)args->os_varp; - if (!valid_filetype(*varp)) { - return e_invarg; + // NULL => statusline syntax + if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) { + stl_syntax |= flagval; + } else { + stl_syntax &= ~flagval; } - - args->os_value_changed = strcmp(args->os_oldval.string, *varp) != 0; - - // Since we check the value, there is no need to set P_INSECURE, - // even when the value comes from a modeline. - args->os_value_checked = true; + did_set_title(); return NULL; } -const char *did_set_winhl(optset_T *args) +/// The 'titlestring' option is changed. +const char *did_set_titlestring(optset_T *args) { - win_T *win = (win_T *)args->os_win; - if (!parse_winhl_opt(win)) { - return e_invarg; - } - return NULL; + return did_set_titleiconstring(args, STL_IN_TITLE); } /// The 'varsofttabstop' option is changed. @@ -1983,62 +1942,97 @@ const char *did_set_vartabstop(optset_T *args) return NULL; } -/// The 'nrformats' option is changed. -const char *did_set_nrformats(optset_T *args) +/// The 'verbosefile' option is changed. +const char *did_set_verbosefile(optset_T *args) { - char **varp = (char **)args->os_varp; + verbose_stop(); + if (*p_vfile != NUL && verbose_open() == FAIL) { + return (char *)e_invarg; + } + return NULL; +} - return did_set_opt_strings(*varp, p_nf_values, true); +/// The 'viewoptions' option is changed. +const char *did_set_viewoptions(optset_T *args FUNC_ATTR_UNUSED) +{ + return did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, true); } -/// One of the '*expr' options is changed:, 'diffexpr', 'foldexpr', 'foldtext', -/// 'formatexpr', 'includeexpr', 'indentexpr', 'patchexpr' and 'charconvert'. -const char *did_set_optexpr(optset_T *args) +/// The 'virtualedit' option is changed. +const char *did_set_virtualedit(optset_T *args) { - char **varp = (char **)args->os_varp; + win_T *win = (win_T *)args->os_win; - // If the option value starts with or s:, then replace that with - // the script identifier. - char *name = get_scriptlocal_funcname(*varp); - if (name != NULL) { - free_string_option(*varp); - *varp = name; + char *ve = p_ve; + unsigned *flags = &ve_flags; + + if (args->os_flags & OPT_LOCAL) { + ve = win->w_p_ve; + flags = &win->w_ve_flags; + } + + if ((args->os_flags & OPT_LOCAL) && *ve == NUL) { + // make the local value empty: use the global value + *flags = 0; + } else { + if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) { + return e_invarg; + } else if (strcmp(ve, args->os_oldval.string) != 0) { + // Recompute cursor position in case the new 've' setting + // changes something. + validate_virtcol_win(win); + // XXX: this only works when win == curwin + coladvance(win->w_virtcol); + } } return NULL; } -/// The 'foldexpr' option is changed. -const char *did_set_foldexpr(optset_T *args) +/// The 'whichwrap' option is changed. +const char *did_set_whichwrap(optset_T *args) { - win_T *win = (win_T *)args->os_win; - (void)did_set_optexpr(args); - if (foldmethodIsExpr(win)) { - foldUpdateAll(win); + char **varp = (char **)args->os_varp; + + return did_set_option_listflag(*varp, WW_ALL, args->os_errbuf, args->os_errbuflen); +} + +/// The 'wildmode' option is changed. +const char *did_set_wildmode(optset_T *args FUNC_ATTR_UNUSED) +{ + if (check_opt_wim() == FAIL) { + return e_invarg; } return NULL; } -/// The 'foldclose' option is changed. -const char *did_set_foldclose(optset_T *args FUNC_ATTR_UNUSED) +/// The 'wildoptions' option is changed. +const char *did_set_wildoptions(optset_T *args FUNC_ATTR_UNUSED) { - return did_set_opt_strings(p_fcl, p_fcl_values, true); + return did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true); } -/// An option which is a list of flags is set. Valid values are in 'flags'. -static const char *did_set_option_listflag(char *val, char *flags, char *errbuf, size_t errbuflen) +/// The 'winaltkeys' option is changed. +const char *did_set_winaltkeys(optset_T *args FUNC_ATTR_UNUSED) { - for (char *s = val; *s; s++) { - if (vim_strchr(flags, (uint8_t)(*s)) == NULL) { - return illegal_char(errbuf, errbuflen, (uint8_t)(*s)); - } + if (*p_wak == NUL || check_opt_strings(p_wak, p_wak_values, false) != OK) { + return e_invarg; } - return NULL; } -const char *did_set_guicursor(optset_T *args FUNC_ATTR_UNUSED) +/// The 'winbar' option is changed. +const char *did_set_winbar(optset_T *args) { - return parse_shape_opt(SHAPE_CURSOR); + return did_set_statustabline_rulerformat(args, false, false); +} + +const char *did_set_winhl(optset_T *args) +{ + win_T *win = (win_T *)args->os_win; + if (!parse_winhl_opt(win)) { + return e_invarg; + } + return NULL; } // When 'syntax' is set, load the syntax of that name @@ -2564,3 +2558,15 @@ const char *check_chars_options(void) } return NULL; } + +/// Handle the new value of 'fillchars'. +const char *set_fillchars_option(win_T *wp, char *val, bool apply) +{ + return set_chars_option(wp, val, false, apply); +} + +/// Handle the new value of 'listchars'. +const char *set_listchars_option(win_T *wp, char *val, bool apply) +{ + return set_chars_option(wp, val, true, apply); +} -- cgit From f06af5e66981095f3244f67d1587ce7e9853eb4c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 30 Sep 2023 08:13:58 +0800 Subject: vim-patch:9.0.1958: cannot complete option values Problem: cannot complete option values Solution: Add completion functions for several options Add cmdline tab-completion for setting string options Add tab-completion for setting string options on the cmdline using `:set=` (along with `:set+=` and `:set-=`). The existing tab completion for setting options currently only works when nothing is typed yet, and it only fills in with the existing value, e.g. when the user does `:set diffopt=` it will be completed to `set diffopt=internal,filler,closeoff` and nothing else. This isn't too useful as a user usually wants auto-complete to suggest all the possible values, such as 'iblank', or 'algorithm:patience'. For set= and set+=, this adds a new optional callback function for each option that can be invoked when doing completion. This allows for each option to have control over how completion works. For example, in 'diffopt', it will suggest the default enumeration, but if `algorithm:` is selected, it will further suggest different algorithm types like 'meyers' and 'patience'. When using set=, the existing option value will be filled in as the first choice to preserve the existing behavior. When using set+= this won't happen as it doesn't make sense. For flag list options (e.g. 'mouse' and 'guioptions'), completion will take into account existing typed values (and in the case of set+=, the existing option value) to make sure it doesn't suggest duplicates. For set-=, there is a new `ExpandSettingSubtract` function which will handle flag list and comma-separated options smartly, by only suggesting values that currently exist in the option. Note that Vim has some existing code that adds special handling for 'filetype', 'syntax', and misc dir options like 'backupdir'. This change preserves them as they already work, instead of converting to the new callback API for each option. closes: vim/vim#13182 https://github.com/vim/vim/commit/900894b09a95398dfc75599e9f0aa2ea25723384 Co-authored-by: Yee Cheng Chin --- src/nvim/optionstr.c | 650 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 635 insertions(+), 15 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 750941da07..f820a9fc49 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -11,6 +11,7 @@ #include "nvim/autocmd.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" +#include "nvim/cmdexpand.h" #include "nvim/cursor.h" #include "nvim/cursor_shape.h" #include "nvim/diff.h" @@ -41,6 +42,7 @@ #include "nvim/optionstr.h" #include "nvim/os/os.h" #include "nvim/pos.h" +#include "nvim/regexp.h" #include "nvim/runtime.h" #include "nvim/spell.h" #include "nvim/spellfile.h" @@ -72,12 +74,25 @@ static char *(p_bkc_values[]) = { "yes", "auto", "no", "breaksymlink", "breakhar static char *(p_bo_values[]) = { "all", "backspace", "cursor", "complete", "copy", "ctrlg", "error", "esc", "ex", "hangul", "lang", "mess", "showmatch", "operator", "register", "shell", "spell", "wildmode", NULL }; +// Note: Keep this in sync with briopt_check() +static char *(p_briopt_values[]) = { "shift:", "min:", "sbr", "list:", "column:", NULL }; +// Note: Keep this in sync with diffopt_changed() +static char *(p_dip_values[]) = { "filler", "context:", "iblank", "icase", + "iwhite", "iwhiteall", "iwhiteeol", "horizontal", "vertical", + "closeoff", "hiddenoff", "foldcolumn:", "followwrap", "internal", + "indent-heuristic", "linematch:", "algorithm:", NULL }; +static char *(p_dip_algorithm_values[]) = { "myers", "minimal", "patience", "histogram", NULL }; static char *(p_nf_values[]) = { "bin", "octal", "hex", "alpha", "unsigned", NULL }; static char *(p_ff_values[]) = { FF_UNIX, FF_DOS, FF_MAC, NULL }; +static char *(p_cb_values[]) = { "unnamed", "unnamedplus", NULL }; static char *(p_cmp_values[]) = { "internal", "keepascii", NULL }; +// Note: Keep this in sync with fill_culopt_flags() +static char *(p_culopt_values[]) = { "line", "screenline", "number", "both", NULL }; static char *(p_dy_values[]) = { "lastline", "truncate", "uhex", "msgsep", NULL }; static char *(p_fdo_values[]) = { "all", "block", "hor", "mark", "percent", "quickfix", "search", "tag", "insert", "undo", "jump", NULL }; +// Note: Keep this in sync with spell_check_sps() +static char *(p_sps_values[]) = { "best", "fast", "double", "expr:", "file:", "timeout:", NULL }; /// Also used for 'viewoptions'! Keep in sync with SSOP_ flags. static char *(p_ssop_values[]) = { "buffers", "winpos", "resize", "winsize", "localoptions", "options", "help", "blank", "globals", "slash", "unix", "sesdir", @@ -89,7 +104,9 @@ static char *(p_swb_values[]) = { "useopen", "usetab", "split", "newtab", "vspli static char *(p_spk_values[]) = { "cursor", "screen", "topline", NULL }; static char *(p_tc_values[]) = { "followic", "ignore", "match", "followscs", "smart", NULL }; static char *(p_ve_values[]) = { "block", "insert", "all", "onemore", "none", "NONE", NULL }; -static char *(p_wop_values[]) = { "tagfile", "pum", "fuzzy", NULL }; +// Note: Keep this in sync with check_opt_wim() +static char *(p_wim_values[]) = { "full", "longest", "list", "lastused", NULL }; +static char *(p_wop_values[]) = { "fuzzy", "tagfile", "pum", NULL }; static char *(p_wak_values[]) = { "yes", "menu", "no", NULL }; static char *(p_mousem_values[]) = { "extend", "popup", "popup_setpos", "mac", NULL }; static char *(p_sel_values[]) = { "inclusive", "exclusive", "old", NULL }; @@ -118,7 +135,6 @@ static char *(p_scl_values[]) = { "yes", "no", "auto", "auto:1", "auto:2", "auto static char *(p_fdc_values[]) = { "auto", "auto:1", "auto:2", "auto:3", "auto:4", "auto:5", "auto:6", "auto:7", "auto:8", "auto:9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL }; -static char *(p_cb_values[]) = { "unnamed", "unnamedplus", NULL }; static char *(p_spo_values[]) = { "camel", "noplainbuffer", NULL }; static char *(p_icm_values[]) = { "nosplit", "split", NULL }; static char *(p_jop_values[]) = { "stack", "view", NULL }; @@ -659,6 +675,116 @@ static const char *did_set_option_listflag(char *val, char *flags, char *errbuf, return NULL; } +/// Expand an option that accepts a list of string values. +int expand_set_opt_string(optexpand_T *args, char **values, size_t numValues, int *numMatches, + char ***matches) +{ + regmatch_T *regmatch = args->oe_regmatch; + bool include_orig_val = args->oe_include_orig_val; + char *option_val = args->oe_opt_value; + + // Assume numValues is small since they are fixed enums, so just allocate + // upfront instead of needing two passes to calculate output size. + *matches = xmalloc(sizeof(char *) * (numValues + 1)); + + int count = 0; + + if (include_orig_val && *option_val != NUL) { + (*matches)[count++] = xstrdup(option_val); + } + + for (char **val = values; *val != NULL; val++) { + if (include_orig_val && *option_val != NUL) { + if (strcmp(*val, option_val) == 0) { + continue; + } + } + if (vim_regexec(regmatch, *val, (colnr_T)0)) { + (*matches)[count++] = xstrdup(*val); + } + } + if (count == 0) { + XFREE_CLEAR(*matches); + return FAIL; + } + *numMatches = count; + return OK; +} + +static char *set_opt_callback_orig_option = NULL; +static char *((*set_opt_callback_func)(expand_T *, int)); + +/// Callback used by expand_set_opt_generic to also include the original value. +static char *expand_set_opt_callback(expand_T *xp, int idx) +{ + if (idx == 0) { + if (set_opt_callback_orig_option != NULL) { + return set_opt_callback_orig_option; + } else { + return ""; // empty strings are ignored + } + } + return set_opt_callback_func(xp, idx - 1); +} + +/// Expand an option with a callback that iterates through a list of possible names. +int expand_set_opt_generic(optexpand_T *args, CompleteListItemGetter func, int *numMatches, + char ***matches) +{ + set_opt_callback_orig_option = args->oe_include_orig_val ? args->oe_opt_value : NULL; + set_opt_callback_func = func; + + // not using fuzzy as currently EXPAND_STRING_SETTING doesn't use it + ExpandGeneric("", args->oe_xp, args->oe_regmatch, matches, numMatches, + expand_set_opt_callback, false); + + set_opt_callback_orig_option = NULL; + set_opt_callback_func = NULL; + return OK; +} + +/// Expand an option which is a list of flags. +int expand_set_opt_listflag(optexpand_T *args, char *flags, int *numMatches, char ***matches) +{ + char *option_val = args->oe_opt_value; + char *cmdline_val = args->oe_set_arg; + bool append = args->oe_append; + bool include_orig_val = args->oe_include_orig_val && (*option_val != NUL); + + size_t num_flags = strlen(flags); + + // Assume we only have small number of flags, so just allocate max size. + *matches = xmalloc(sizeof(char *) * (num_flags + 1)); + + int count = 0; + + if (include_orig_val) { + (*matches)[count++] = xstrdup(option_val); + } + + for (char *flag = flags; *flag != NUL; flag++) { + if (append && vim_strchr(option_val, *flag) != NULL) { + continue; + } + + if (vim_strchr(cmdline_val, *flag) == NULL) { + if (include_orig_val && option_val[1] == NUL && *flag == option_val[0]) { + // This value is already used as the first choice as it's the + // existing flag. Just skip it to avoid duplicate. + continue; + } + (*matches)[count++] = xstrnsave(flag, 1); + } + } + + if (count == 0) { + XFREE_CLEAR(*matches); + return FAIL; + } + *numMatches = count; + return OK; +} + /// The 'ambiwidth' option is changed. const char *did_set_ambiwidth(optset_T *args FUNC_ATTR_UNUSED) { @@ -668,6 +794,15 @@ const char *did_set_ambiwidth(optset_T *args FUNC_ATTR_UNUSED) return check_chars_options(); } +int expand_set_ambiwidth(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_ambw_values, + ARRAY_SIZE(p_ambw_values) - 1, + numMatches, + matches); +} + /// The 'background' option is changed. const char *did_set_background(optset_T *args FUNC_ATTR_UNUSED) { @@ -692,6 +827,15 @@ const char *did_set_background(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_background(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_bg_values, + ARRAY_SIZE(p_bg_values) - 1, + numMatches, + matches); +} + /// The 'backspace' option is changed. const char *did_set_backspace(optset_T *args FUNC_ATTR_UNUSED) { @@ -705,6 +849,15 @@ const char *did_set_backspace(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_backspace(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_bs_values, + ARRAY_SIZE(p_bs_values) - 1, + numMatches, + matches); +} + /// The 'backupcopy' option is changed. const char *did_set_backupcopy(optset_T *args) { @@ -739,6 +892,15 @@ const char *did_set_backupcopy(optset_T *args) return NULL; } +int expand_set_backupcopy(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_bkc_values, + ARRAY_SIZE(p_bkc_values) - 1, + numMatches, + matches); +} + /// The 'backupext' or the 'patchmode' option is changed. const char *did_set_backupext_or_patchmode(optset_T *args FUNC_ATTR_UNUSED) { @@ -756,6 +918,15 @@ const char *did_set_belloff(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true); } +int expand_set_belloff(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_bo_values, + ARRAY_SIZE(p_bo_values) - 1, + numMatches, + matches); +} + /// The 'breakindentopt' option is changed. const char *did_set_breakindentopt(optset_T *args) { @@ -771,6 +942,15 @@ const char *did_set_breakindentopt(optset_T *args) return NULL; } +int expand_set_breakindentopt(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_briopt_values, + ARRAY_SIZE(p_briopt_values) - 1, + numMatches, + matches); +} + /// The 'bufhidden' option is changed. const char *did_set_bufhidden(optset_T *args) { @@ -778,6 +958,15 @@ const char *did_set_bufhidden(optset_T *args) return did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false); } +int expand_set_bufhidden(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_bufhidden_values, + ARRAY_SIZE(p_bufhidden_values) - 1, + numMatches, + matches); +} + /// The 'buftype' option is changed. const char *did_set_buftype(optset_T *args) { @@ -798,12 +987,30 @@ const char *did_set_buftype(optset_T *args) return NULL; } +int expand_set_buftype(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_buftype_values, + ARRAY_SIZE(p_buftype_values) - 1, + numMatches, + matches); +} + /// The 'casemap' option is changed. const char *did_set_casemap(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true); } +int expand_set_casemap(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_cmp_values, + ARRAY_SIZE(p_cmp_values) - 1, + numMatches, + matches); +} + /// The global 'listchars' or 'fillchars' option is changed. static const char *did_set_global_listfillchars(win_T *win, char *val, bool opt_lcs, int opt_flags) { @@ -867,6 +1074,17 @@ const char *did_set_chars_option(optset_T *args) return errmsg; } +/// Expand 'fillchars' or 'listchars' option value. +int expand_set_chars_option(optexpand_T *args, int *numMatches, char ***matches) +{ + char **varp = (char **)args->oe_varp; + bool is_lcs = (varp == &p_lcs || varp == &curwin->w_p_lcs); + return expand_set_opt_generic(args, + is_lcs ? get_listchars_name : get_fillchars_name, + numMatches, + matches); +} + /// The 'cinoptions' option is changed. const char *did_set_cinoptions(optset_T *args FUNC_ATTR_UNUSED) { @@ -882,6 +1100,15 @@ const char *did_set_clipboard(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true); } +int expand_set_clipboard(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_cb_values, + ARRAY_SIZE(p_cb_values) - 1, + numMatches, + matches); +} + /// The 'colorcolumn' option is changed. const char *did_set_colorcolumn(optset_T *args) { @@ -972,6 +1199,18 @@ const char *did_set_complete(optset_T *args) return NULL; } +int expand_set_complete(optexpand_T *args, int *numMatches, char ***matches) +{ + static char *(p_cpt_values[]) = { + ".", "w", "b", "u", "k", "kspell", "s", "i", "d", "]", "t", "U", NULL + }; + return expand_set_opt_string(args, + p_cpt_values, + ARRAY_SIZE(p_cpt_values) - 1, + numMatches, + matches); +} + /// The 'completeopt' option is changed. const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED) { @@ -982,6 +1221,15 @@ const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_completeopt(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_cot_values, + ARRAY_SIZE(p_cot_values) - 1, + numMatches, + matches); +} + #ifdef BACKSLASH_IN_FILENAME /// The 'completeslash' option is changed. const char *did_set_completeslash(optset_T *args) @@ -993,6 +1241,15 @@ const char *did_set_completeslash(optset_T *args) } return NULL; } + +int expand_set_completeslash(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_csl_values, + ARRAY_SIZE(p_csl_values) - 1, + numMatches, + matches); +} #endif /// The 'concealcursor' option is changed. @@ -1003,6 +1260,11 @@ const char *did_set_concealcursor(optset_T *args) return did_set_option_listflag(*varp, COCU_ALL, args->os_errbuf, args->os_errbuflen); } +int expand_set_concealcursor(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_listflag(args, COCU_ALL, numMatches, matches); +} + /// The 'cpoptions' option is changed. const char *did_set_cpoptions(optset_T *args) { @@ -1011,12 +1273,18 @@ const char *did_set_cpoptions(optset_T *args) return did_set_option_listflag(*varp, CPO_VI, args->os_errbuf, args->os_errbuflen); } +int expand_set_cpoptions(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_listflag(args, CPO_VI, numMatches, matches); +} + /// The 'cursorlineopt' option is changed. const char *did_set_cursorlineopt(optset_T *args) { win_T *win = (win_T *)args->os_win; char **varp = (char **)args->os_varp; + // This could be changed to use opt_strings_flags() instead. if (**varp == NUL || fill_culopt_flags(*varp, win) != OK) { return e_invarg; } @@ -1024,12 +1292,30 @@ const char *did_set_cursorlineopt(optset_T *args) return NULL; } +int expand_set_cursorlineopt(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_culopt_values, + ARRAY_SIZE(p_culopt_values) - 1, + numMatches, + matches); +} + /// The 'debug' option is changed. const char *did_set_debug(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_strings(p_debug, p_debug_values, false); } +int expand_set_debug(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_debug_values, + ARRAY_SIZE(p_debug_values) - 1, + numMatches, + matches); +} + /// The 'diffopt' option is changed. const char *did_set_diffopt(optset_T *args FUNC_ATTR_UNUSED) { @@ -1039,6 +1325,31 @@ const char *did_set_diffopt(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_diffopt(optexpand_T *args, int *numMatches, char ***matches) +{ + expand_T *xp = args->oe_xp; + + if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern - 1) == ':') { + // Within "algorithm:", we have a subgroup of possible options. + const size_t algo_len = strlen("algorithm:"); + if (xp->xp_pattern - args->oe_set_arg >= (int)algo_len + && strncmp(xp->xp_pattern - algo_len, "algorithm:", algo_len) == 0) { + return expand_set_opt_string(args, + p_dip_algorithm_values, + ARRAY_SIZE(p_dip_algorithm_values) - 1, + numMatches, + matches); + } + return FAIL; + } + + return expand_set_opt_string(args, + p_dip_values, + ARRAY_SIZE(p_dip_values) - 1, + numMatches, + matches); +} + /// The 'display' option is changed. const char *did_set_display(optset_T *args FUNC_ATTR_UNUSED) { @@ -1050,12 +1361,30 @@ const char *did_set_display(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_display(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_dy_values, + ARRAY_SIZE(p_dy_values) - 1, + numMatches, + matches); +} + /// The 'eadirection' option is changed. const char *did_set_eadirection(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_strings(p_ead, p_ead_values, false); } +int expand_set_eadirection(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_ead_values, + ARRAY_SIZE(p_ead_values) - 1, + numMatches, + matches); +} + /// One of the 'encoding', 'fileencoding' or 'makeencoding' /// options is changed. const char *did_set_encoding(optset_T *args) @@ -1098,6 +1427,11 @@ const char *did_set_encoding(optset_T *args) return NULL; } +int expand_set_encoding(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_generic(args, get_encoding_name, numMatches, matches); +} + /// The 'eventignore' option is changed. const char *did_set_eventignore(optset_T *args FUNC_ATTR_UNUSED) { @@ -1107,6 +1441,21 @@ const char *did_set_eventignore(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +static char *get_eventignore_name(expand_T *xp, int idx) +{ + // 'eventignore' allows special keyword "all" in addition to + // all event names. + if (idx == 0) { + return "all"; + } + return get_event_name_no_group(xp, idx - 1); +} + +int expand_set_eventignore(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_generic(args, get_eventignore_name, numMatches, matches); +} + /// The 'fileformat' option is changed. const char *did_set_fileformat(optset_T *args) { @@ -1130,6 +1479,15 @@ const char *did_set_fileformat(optset_T *args) return NULL; } +int expand_set_fileformat(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_ff_values, + ARRAY_SIZE(p_ff_values) - 1, + numMatches, + matches); +} + /// The 'fileformats' option is changed. const char *did_set_fileformats(optset_T *args) { @@ -1160,6 +1518,15 @@ const char *did_set_foldclose(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_strings(p_fcl, p_fcl_values, true); } +int expand_set_foldclose(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_fcl_values, + ARRAY_SIZE(p_fcl_values) - 1, + numMatches, + matches); +} + /// The 'foldcolumn' option is changed. const char *did_set_foldcolumn(optset_T *args) { @@ -1229,12 +1596,30 @@ const char *did_set_foldmethod(optset_T *args) return NULL; } +int expand_set_foldmethod(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_fdm_values, + ARRAY_SIZE(p_fdm_values) - 1, + numMatches, + matches); +} + /// The 'foldopen' option is changed. const char *did_set_foldopen(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true); } +int expand_set_foldopen(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_fdo_values, + ARRAY_SIZE(p_fdo_values) - 1, + numMatches, + matches); +} + /// The 'formatoptions' option is changed. const char *did_set_formatoptions(optset_T *args) { @@ -1243,6 +1628,11 @@ const char *did_set_formatoptions(optset_T *args) return did_set_option_listflag(*varp, FO_ALL, args->os_errbuf, args->os_errbuflen); } +int expand_set_formatoptions(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_listflag(args, FO_ALL, numMatches, matches); +} + /// The 'guicursor' option is changed. const char *did_set_guicursor(optset_T *args FUNC_ATTR_UNUSED) { @@ -1321,6 +1711,15 @@ const char *did_set_jumpoptions(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true); } +int expand_set_jumpoptions(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_jop_values, + ARRAY_SIZE(p_jop_values) - 1, + numMatches, + matches); +} + /// The 'keymap' option has changed. const char *did_set_keymap(optset_T *args) { @@ -1384,6 +1783,15 @@ const char *did_set_keymodel(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_keymodel(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_km_values, + ARRAY_SIZE(p_km_values) - 1, + numMatches, + matches); +} + /// The 'lispoptions' option is changed. const char *did_set_lispoptions(optset_T *args) { @@ -1395,6 +1803,16 @@ const char *did_set_lispoptions(optset_T *args) return NULL; } +int expand_set_lispoptions(optexpand_T *args, int *numMatches, char ***matches) +{ + static char *(p_lop_values[]) = { "expr:0", "expr:1", NULL }; + return expand_set_opt_string(args, + p_lop_values, + ARRAY_SIZE(p_lop_values) - 1, + numMatches, + matches); +} + /// The 'matchpairs' option is changed. const char *did_set_matchpairs(optset_T *args) { @@ -1439,12 +1857,26 @@ const char *did_set_mouse(optset_T *args) return did_set_option_listflag(*varp, MOUSE_ALL, args->os_errbuf, args->os_errbuflen); } +int expand_set_mouse(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_listflag(args, MOUSE_ALL, numMatches, matches); +} + /// The 'mousemodel' option is changed. const char *did_set_mousemodel(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_strings(p_mousem, p_mousem_values, false); } +int expand_set_mousemodel(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_mousem_values, + ARRAY_SIZE(p_mousem_values) - 1, + numMatches, + matches); +} + /// Handle setting 'mousescroll'. /// @return error message, NULL if it's OK. const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) @@ -1518,6 +1950,15 @@ const char *did_set_nrformats(optset_T *args) return did_set_opt_strings(*varp, p_nf_values, true); } +int expand_set_nrformats(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_nf_values, + ARRAY_SIZE(p_nf_values) - 1, + numMatches, + matches); +} + /// One of the '*expr' options is changed:, 'diffexpr', 'foldexpr', 'foldtext', /// 'formatexpr', 'includeexpr', 'indentexpr', 'patchexpr' and 'charconvert'. const char *did_set_optexpr(optset_T *args) @@ -1553,6 +1994,16 @@ const char *did_set_rightleftcmd(optset_T *args) return NULL; } +int expand_set_rightleftcmd(optexpand_T *args, int *numMatches, char ***matches) +{ + static char *(p_rlc_values[]) = { "search", NULL }; + return expand_set_opt_string(args, + p_rlc_values, + ARRAY_SIZE(p_rlc_values) - 1, + numMatches, + matches); +} + /// The 'rulerformat' option is changed. const char *did_set_rulerformat(optset_T *args) { @@ -1565,6 +2016,15 @@ const char *did_set_scrollopt(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_strings(p_sbo, p_scbopt_values, true); } +int expand_set_scrollopt(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_scbopt_values, + ARRAY_SIZE(p_scbopt_values) - 1, + numMatches, + matches); +} + /// The 'selection' option is changed. const char *did_set_selection(optset_T *args FUNC_ATTR_UNUSED) { @@ -1574,12 +2034,30 @@ const char *did_set_selection(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_selection(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_sel_values, + ARRAY_SIZE(p_sel_values) - 1, + numMatches, + matches); +} + /// The 'selectmode' option is changed. const char *did_set_selectmode(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_strings(p_slm, p_slm_values, true); } +int expand_set_selectmode(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_slm_values, + ARRAY_SIZE(p_slm_values) - 1, + numMatches, + matches); +} + /// The 'sessionoptions' option is changed. const char *did_set_sessionoptions(optset_T *args) { @@ -1595,6 +2073,15 @@ const char *did_set_sessionoptions(optset_T *args) return NULL; } +int expand_set_sessionoptions(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_ssop_values, + ARRAY_SIZE(p_ssop_values) - 1, + numMatches, + matches); +} + static const char *did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, size_t errbuflen) { @@ -1661,6 +2148,11 @@ const char *did_set_shortmess(optset_T *args) return did_set_option_listflag(*varp, SHM_ALL, args->os_errbuf, args->os_errbuflen); } +int expand_set_shortmess(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_listflag(args, SHM_ALL, numMatches, matches); +} + /// The 'showbreak' option is changed. const char *did_set_showbreak(optset_T *args) { @@ -1681,6 +2173,15 @@ const char *did_set_showcmdloc(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_strings(p_sloc, p_sloc_values, true); } +int expand_set_showcmdloc(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_sloc_values, + ARRAY_SIZE(p_sloc_values) - 1, + numMatches, + matches); +} + /// The 'signcolumn' option is changed. const char *did_set_signcolumn(optset_T *args) { @@ -1700,6 +2201,15 @@ const char *did_set_signcolumn(optset_T *args) return NULL; } +int expand_set_signcolumn(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_scl_values, + ARRAY_SIZE(p_scl_values) - 1, + numMatches, + matches); +} + /// The 'spellcapcheck' option is changed. const char *did_set_spellcapcheck(optset_T *args) { @@ -1745,6 +2255,15 @@ const char *did_set_spelloptions(optset_T *args) return NULL; } +int expand_set_spelloptions(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_spo_values, + ARRAY_SIZE(p_spo_values) - 1, + numMatches, + matches); +} + /// The 'spellsuggest' option is changed. const char *did_set_spellsuggest(optset_T *args FUNC_ATTR_UNUSED) { @@ -1754,12 +2273,30 @@ const char *did_set_spellsuggest(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_spellsuggest(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_sps_values, + ARRAY_SIZE(p_sps_values) - 1, + numMatches, + matches); +} + /// The 'splitkeep' option is changed. const char *did_set_splitkeep(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_strings(p_spk, p_spk_values, false); } +int expand_set_splitkeep(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_spk_values, + ARRAY_SIZE(p_spk_values) - 1, + numMatches, + matches); +} + /// The 'statuscolumn' option is changed. const char *did_set_statuscolumn(optset_T *args) { @@ -1817,6 +2354,15 @@ const char *did_set_switchbuf(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true); } +int expand_set_switchbuf(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_swb_values, + ARRAY_SIZE(p_swb_values) - 1, + numMatches, + matches); +} + /// The 'tabline' option is changed. const char *did_set_tabline(optset_T *args) { @@ -1850,6 +2396,15 @@ const char *did_set_tagcase(optset_T *args) return NULL; } +int expand_set_tagcase(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_tc_values, + ARRAY_SIZE(p_tc_values) - 1, + numMatches, + matches); +} + /// The 'termpastefilter' option is changed. const char *did_set_termpastefilter(optset_T *args FUNC_ATTR_UNUSED) { @@ -1988,12 +2543,28 @@ const char *did_set_virtualedit(optset_T *args) return NULL; } +int expand_set_virtualedit(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_ve_values, + ARRAY_SIZE(p_ve_values) - 1, + numMatches, + matches); +} + /// The 'whichwrap' option is changed. const char *did_set_whichwrap(optset_T *args) { char **varp = (char **)args->os_varp; - return did_set_option_listflag(*varp, WW_ALL, args->os_errbuf, args->os_errbuflen); + // Add ',' to the list flags because 'whichwrap' is a flag + // list that is comma-separated. + return did_set_option_listflag(*varp, WW_ALL ",", args->os_errbuf, args->os_errbuflen); +} + +int expand_set_whichwrap(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_listflag(args, WW_ALL, numMatches, matches); } /// The 'wildmode' option is changed. @@ -2005,12 +2576,30 @@ const char *did_set_wildmode(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_wildmode(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_wim_values, + ARRAY_SIZE(p_wim_values) - 1, + numMatches, + matches); +} + /// The 'wildoptions' option is changed. const char *did_set_wildoptions(optset_T *args FUNC_ATTR_UNUSED) { return did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true); } +int expand_set_wildoptions(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_wop_values, + ARRAY_SIZE(p_wop_values) - 1, + numMatches, + matches); +} + /// The 'winaltkeys' option is changed. const char *did_set_winaltkeys(optset_T *args FUNC_ATTR_UNUSED) { @@ -2020,6 +2609,15 @@ const char *did_set_winaltkeys(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_winaltkeys(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_wak_values, + ARRAY_SIZE(p_wak_values) - 1, + numMatches, + matches); +} + /// The 'winbar' option is changed. const char *did_set_winbar(optset_T *args) { @@ -2536,6 +3134,40 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ return NULL; // no error } +/// Handle the new value of 'fillchars'. +const char *set_fillchars_option(win_T *wp, char *val, bool apply) +{ + return set_chars_option(wp, val, false, apply); +} + +/// Handle the new value of 'listchars'. +const char *set_listchars_option(win_T *wp, char *val, bool apply) +{ + return set_chars_option(wp, val, true, apply); +} + +/// Function given to ExpandGeneric() to obtain possible arguments of the +/// 'fillchars' option. +char *get_fillchars_name(expand_T *xp FUNC_ATTR_UNUSED, int idx) +{ + if (idx >= (int)ARRAY_SIZE(fcs_tab)) { + return NULL; + } + + return (char *)fcs_tab[idx].name; +} + +/// Function given to ExpandGeneric() to obtain possible arguments of the +/// 'listchars' option. +char *get_listchars_name(expand_T *xp FUNC_ATTR_UNUSED, int idx) +{ + if (idx >= (int)ARRAY_SIZE(lcs_tab)) { + return NULL; + } + + return (char *)lcs_tab[idx].name; +} + /// Check all global and local values of 'listchars' and 'fillchars'. /// May set different defaults in case character widths change. /// @@ -2558,15 +3190,3 @@ const char *check_chars_options(void) } return NULL; } - -/// Handle the new value of 'fillchars'. -const char *set_fillchars_option(win_T *wp, char *val, bool apply) -{ - return set_chars_option(wp, val, false, apply); -} - -/// Handle the new value of 'listchars'. -const char *set_listchars_option(win_T *wp, char *val, bool apply) -{ - return set_chars_option(wp, val, true, apply); -} -- cgit From 6a7d533444f3643c673812c2de46f9b3ee47ba18 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 1 Oct 2023 18:18:30 +0800 Subject: vim-patch:9.0.1960: Make CI checks more strict Problem: Make CI checks more strict Solution: Add -Wstrict-prototypes -Wmissing-prototypes to CI, fix uncovered problems Add -Wstrict-prototypes -Wmissing-prototypes warnings check to CI Add two new warnings to CI, silence some Perl related build-warnings: - `strict-prototypes` helps prevent declaring a function with an empty argument list, e.g. `int func()`. In C++, that's equivalent to `int func(void)`, but in C, that means a function that can take any number of arguments which is rarely what we want. - `missing-prototypes` makes sure we use `static` for file-only internal functions. Non-static functions should have been declared on a prototype file. - Add `no-compound-token-split-by-macro` to the perl cflags, since it throws out a bunch of perl-related warnings that make the CI log unnecessary verbose and hard to read. This seems to happen only with clang 12 and above. When applying those changes, it already uncovered a few warnings, so fix up the code as well (fix prototypes, make the code static, remove shadowed var declaration) GTK header needs to have #pragma warning suppressiong because GTK2 headers will warn on `-Wstrict-prototypes`, and it's included by gui.h and so we can't just turn off the warning in a couple files. closes: vim/vim#13223 closes: vim/vim#13226 https://github.com/vim/vim/commit/f7f746b1672909ae57d2eec97253d6627f6c0887 Co-authored-by: Yee Cheng Chin --- src/nvim/optionstr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index f820a9fc49..3ea73560c1 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -676,8 +676,8 @@ static const char *did_set_option_listflag(char *val, char *flags, char *errbuf, } /// Expand an option that accepts a list of string values. -int expand_set_opt_string(optexpand_T *args, char **values, size_t numValues, int *numMatches, - char ***matches) +static int expand_set_opt_string(optexpand_T *args, char **values, size_t numValues, + int *numMatches, char ***matches) { regmatch_T *regmatch = args->oe_regmatch; bool include_orig_val = args->oe_include_orig_val; @@ -728,8 +728,8 @@ static char *expand_set_opt_callback(expand_T *xp, int idx) } /// Expand an option with a callback that iterates through a list of possible names. -int expand_set_opt_generic(optexpand_T *args, CompleteListItemGetter func, int *numMatches, - char ***matches) +static int expand_set_opt_generic(optexpand_T *args, CompleteListItemGetter func, int *numMatches, + char ***matches) { set_opt_callback_orig_option = args->oe_include_orig_val ? args->oe_opt_value : NULL; set_opt_callback_func = func; @@ -744,7 +744,7 @@ int expand_set_opt_generic(optexpand_T *args, CompleteListItemGetter func, int * } /// Expand an option which is a list of flags. -int expand_set_opt_listflag(optexpand_T *args, char *flags, int *numMatches, char ***matches) +static int expand_set_opt_listflag(optexpand_T *args, char *flags, int *numMatches, char ***matches) { char *option_val = args->oe_opt_value; char *cmdline_val = args->oe_set_arg; -- cgit From 81be8407681cee350984299e1be03d4351e7bd14 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 1 Oct 2023 18:20:20 +0800 Subject: vim-patch:9.0.1961: 'listchars' completion misses "multispace" and "leadmultispace" Problem: Cmdline completion for 'listchars' fields doesn't include "multispace" and "leadmultispace" (after 9.0.1958). Solution: Include "multispace" and "leadmultispace" in lcstab. closes: vim/vim#13225 https://github.com/vim/vim/commit/1f025b01e29be6fce907d0379602b45031d6998f --- src/nvim/optionstr.c | 122 +++++++++++++++++++++++++-------------------------- 1 file changed, 61 insertions(+), 61 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 3ea73560c1..f6e7b429eb 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -2922,15 +2922,17 @@ static const struct chars_tab fcs_tab[] = { static lcs_chars_T lcs_chars; static const struct chars_tab lcs_tab[] = { - { &lcs_chars.eol, "eol", NUL, NUL }, - { &lcs_chars.ext, "extends", NUL, NUL }, - { &lcs_chars.nbsp, "nbsp", NUL, NUL }, - { &lcs_chars.prec, "precedes", NUL, NUL }, - { &lcs_chars.space, "space", NUL, NUL }, - { &lcs_chars.tab2, "tab", NUL, NUL }, - { &lcs_chars.lead, "lead", NUL, NUL }, - { &lcs_chars.trail, "trail", NUL, NUL }, - { &lcs_chars.conceal, "conceal", NUL, NUL }, + { &lcs_chars.eol, "eol", NUL, NUL }, + { &lcs_chars.ext, "extends", NUL, NUL }, + { &lcs_chars.nbsp, "nbsp", NUL, NUL }, + { &lcs_chars.prec, "precedes", NUL, NUL }, + { &lcs_chars.space, "space", NUL, NUL }, + { &lcs_chars.tab2, "tab", NUL, NUL }, + { &lcs_chars.lead, "lead", NUL, NUL }, + { &lcs_chars.trail, "trail", NUL, NUL }, + { &lcs_chars.conceal, "conceal", NUL, NUL }, + { NULL, "multispace", NUL, NUL }, + { NULL, "leadmultispace", NUL, NUL }, }; /// Handle setting 'listchars' or 'fillchars'. @@ -3001,54 +3003,13 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ int i; for (i = 0; i < entries; i++) { const size_t len = strlen(tab[i].name); - if (strncmp(p, tab[i].name, len) == 0 - && p[len] == ':' - && p[len + 1] != NUL) { - const char *s = p + len + 1; - int c1 = get_encoded_char_adv(&s); - if (c1 == 0 || char2cells(c1) > 1) { - return e_invarg; - } - int c2 = 0, c3 = 0; - if (tab[i].cp == &lcs_chars.tab2) { - if (*s == NUL) { - return e_invarg; - } - c2 = get_encoded_char_adv(&s); - if (c2 == 0 || char2cells(c2) > 1) { - return e_invarg; - } - if (!(*s == ',' || *s == NUL)) { - c3 = get_encoded_char_adv(&s); - if (c3 == 0 || char2cells(c3) > 1) { - return e_invarg; - } - } - } - - if (*s == ',' || *s == NUL) { - if (round > 0) { - if (tab[i].cp == &lcs_chars.tab2) { - lcs_chars.tab1 = c1; - lcs_chars.tab2 = c2; - lcs_chars.tab3 = c3; - } else if (tab[i].cp != NULL) { - *(tab[i].cp) = c1; - } - } - p = s; - break; - } + if (!(strncmp(p, tab[i].name, len) == 0 + && p[len] == ':' + && p[len + 1] != NUL)) { + continue; } - } - if (i == entries) { - const size_t len = strlen("multispace"); - const size_t len2 = strlen("leadmultispace"); - if (is_listchars - && strncmp(p, "multispace", len) == 0 - && p[len] == ':' - && p[len + 1] != NUL) { + if (is_listchars && strcmp(tab[i].name, "multispace") == 0) { const char *s = p + len + 1; if (round == 0) { // Get length of lcs-multispace string in the first round @@ -3076,11 +3037,11 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ } p = s; } - } else if (is_listchars - && strncmp(p, "leadmultispace", len2) == 0 - && p[len2] == ':' - && p[len2 + 1] != NUL) { - const char *s = p + len2 + 1; + break; + } + + if (is_listchars && strcmp(tab[i].name, "leadmultispace") == 0) { + const char *s = p + len + 1; if (round == 0) { // get length of lcs-leadmultispace string in first round last_lmultispace = p; @@ -3107,9 +3068,48 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ } p = s; } - } else { + break; + } + + const char *s = p + len + 1; + int c1 = get_encoded_char_adv(&s); + if (c1 == 0 || char2cells(c1) > 1) { return e_invarg; } + int c2 = 0, c3 = 0; + if (tab[i].cp == &lcs_chars.tab2) { + if (*s == NUL) { + return e_invarg; + } + c2 = get_encoded_char_adv(&s); + if (c2 == 0 || char2cells(c2) > 1) { + return e_invarg; + } + if (!(*s == ',' || *s == NUL)) { + c3 = get_encoded_char_adv(&s); + if (c3 == 0 || char2cells(c3) > 1) { + return e_invarg; + } + } + } + + if (*s == ',' || *s == NUL) { + if (round > 0) { + if (tab[i].cp == &lcs_chars.tab2) { + lcs_chars.tab1 = c1; + lcs_chars.tab2 = c2; + lcs_chars.tab3 = c3; + } else if (tab[i].cp != NULL) { + *(tab[i].cp) = c1; + } + } + p = s; + break; + } + } + + if (i == entries) { + return e_invarg; } if (*p == ',') { -- cgit From 5821c857e025a292c17bd80192366dc7bfb1fbc6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 1 Oct 2023 18:26:14 +0800 Subject: vim-patch:9.0.1968: cmdline completion should consider key option Problem: cmdline completion should consider key option Solution: Disable cmdline completion for key option, slightly refactor how P_NO_CMD_EXPAND is handled Harden crypto 'key' option: turn off cmdline completion, disable set-= "set-=" can be used maliciously with a crypto key, as it allows an attacker (who either has access to the computer or a plugin author) to guess a substring by observing the modified state. Simply turn off set+=/-=/^= for this option as there is no good reason for them to be used. Update docs to make that clear as well. Also, don't allow cmdline completion for 'key' as it just shows ***** which is not useful and confusing to the user what it means (if the user accidentally hits enter they will have replaced their key with "*****" instead). Move logic to better location, don't use above 32-bit for flags Move P_NO_CMD_EXPAND to use the unused 0x20 instead of going above 32-bits, as currently the flags parameter is only 32-bits on some systems. Left a comment to warn that future additions will need to change how the flags work either by making it 64-bit or split into two member vars. Also, move the logic for detecting P_NO_CMD_EXPAND earlier so it's not up to each handler to decide, and you won't see the temporary "..." that Vim shows while waiting for completion handler to complete. closes: vim/vim#13224 https://github.com/vim/vim/commit/6ee7b521fa7531ef356ececc8be7575c3800f872 Co-authored-by: Yee Cheng Chin --- src/nvim/optionstr.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index f6e7b429eb..a67b3a77bc 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -503,8 +503,9 @@ const char *set_string_option(const int opt_idx, void *varp_arg, const char *val secure = 1; } - const char *const errmsg = did_set_string_option(curbuf, curwin, opt_idx, varp, oldval, errbuf, - errbuflen, opt_flags, value_checked); + const char *const errmsg = did_set_string_option(curbuf, curwin, opt_idx, varp, oldval, + errbuf, errbuflen, + opt_flags, OP_NONE, value_checked); secure = secure_saved; @@ -2682,11 +2683,12 @@ static void do_spelllang_source(win_T *win) /// @param errbuf buffer for errors, or NULL /// @param errbuflen length of errors buffer /// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL +/// @param op OP_ADDING/OP_PREPENDING/OP_REMOVING /// @param value_checked value was checked to be safe, no need to set P_INSECURE /// /// @return NULL for success, or an untranslated error message for an error const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **varp, char *oldval, - char *errbuf, size_t errbuflen, int opt_flags, + char *errbuf, size_t errbuflen, int opt_flags, set_op_T op, bool *value_checked) { const char *errmsg = NULL; @@ -2700,6 +2702,7 @@ const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **va .os_varp = varp, .os_idx = opt_idx, .os_flags = opt_flags, + .os_op = op, .os_oldval.string = oldval, .os_newval.string = *varp, .os_value_checked = false, -- cgit From 01c51a491330bd10202c73aff92c0978984c0692 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 1 Oct 2023 19:07:16 +0800 Subject: feat(completion): support completing more string options --- src/nvim/optionstr.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index a67b3a77bc..c8a589f96a 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1538,6 +1538,15 @@ const char *did_set_foldcolumn(optset_T *args) return NULL; } +int expand_set_foldcolumn(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_fdc_values, + ARRAY_SIZE(p_fdc_values) - 1, + numMatches, + matches); +} + /// The 'foldexpr' option is changed. const char *did_set_foldexpr(optset_T *args) { @@ -1691,6 +1700,15 @@ const char *did_set_inccommand(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_strings(p_icm, p_icm_values, false); } +int expand_set_inccommand(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_icm_values, + ARRAY_SIZE(p_icm_values) - 1, + numMatches, + matches); +} + /// The 'isident' or the 'iskeyword' or the 'isprint' or the 'isfname' option is /// changed. const char *did_set_isopt(optset_T *args) @@ -1943,6 +1961,16 @@ const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) return NULL; } +int expand_set_mousescroll(optexpand_T *args, int *numMatches, char ***matches) +{ + static char *(p_mousescroll_values[]) = { "hor:", "ver:", NULL }; + return expand_set_opt_string(args, + p_mousescroll_values, + ARRAY_SIZE(p_mousescroll_values) - 1, + numMatches, + matches); +} + /// The 'nrformats' option is changed. const char *did_set_nrformats(optset_T *args) { @@ -2412,6 +2440,15 @@ const char *did_set_termpastefilter(optset_T *args FUNC_ATTR_UNUSED) return did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true); } +int expand_set_termpastefilter(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_string(args, + p_tpf_values, + ARRAY_SIZE(p_tpf_values) - 1, + numMatches, + matches); +} + /// The 'titlestring' or the 'iconstring' option is changed. static const char *did_set_titleiconstring(optset_T *args, int flagval) { @@ -2625,7 +2662,8 @@ const char *did_set_winbar(optset_T *args) return did_set_statustabline_rulerformat(args, false, false); } -const char *did_set_winhl(optset_T *args) +/// The 'winhighlight' option is changed. +const char *did_set_winhighlight(optset_T *args) { win_T *win = (win_T *)args->os_win; if (!parse_winhl_opt(win)) { @@ -2634,6 +2672,11 @@ const char *did_set_winhl(optset_T *args) return NULL; } +int expand_set_winhighlight(optexpand_T *args, int *numMatches, char ***matches) +{ + return expand_set_opt_generic(args, get_highlight_name, numMatches, matches); +} + // When 'syntax' is set, load the syntax of that name static void do_syntax_autocmd(buf_T *buf, bool value_changed) { -- cgit From 09a17f91d0d362c6e58bfdbe3ccdeacffb0b44b9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 2 Oct 2023 10:45:33 +0800 Subject: refactor: move cmdline completion types to cmdexpand_defs.h (#25465) --- src/nvim/optionstr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index c8a589f96a..6f41bba99b 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -12,6 +12,7 @@ #include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/cursor.h" #include "nvim/cursor_shape.h" #include "nvim/diff.h" -- cgit From 75b488d3ef2e9dafba43c72487839aa78950d453 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 15 Oct 2023 17:52:08 +0800 Subject: vim-patch:9.0.2025: no cmdline completion for ++opt args (#25657) Problem: no cmdline completion for ++opt args Solution: Add cmdline completion for :e ++opt=arg and :terminal [++options] closes: vim/vim#13319 https://github.com/vim/vim/commit/989426be6e9ae23d2413943890206cbe15d9df38 Co-authored-by: Yee Cheng Chin --- src/nvim/optionstr.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 6f41bba99b..88e7ebd991 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1490,6 +1490,17 @@ int expand_set_fileformat(optexpand_T *args, int *numMatches, char ***matches) matches); } +/// Function given to ExpandGeneric() to obtain the possible arguments of the +/// fileformat options. +char *get_fileformat_name(expand_T *xp FUNC_ATTR_UNUSED, int idx) +{ + if (idx >= (int)ARRAY_SIZE(p_ff_values)) { + return NULL; + } + + return p_ff_values[idx]; +} + /// The 'fileformats' option is changed. const char *did_set_fileformats(optset_T *args) { -- cgit From 93b9c889465ee6a55e71c1fd681c1c6b1d5ed060 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Wed, 27 Sep 2023 23:30:17 +0600 Subject: refactor(options): unify set_num_option and set_bool_option --- src/nvim/optionstr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 88e7ebd991..08618406e6 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -441,14 +441,13 @@ void set_string_option_direct_in_buf(buf_T *buf, const char *name, int opt_idx, /// #OPT_GLOBAL. /// /// @return NULL on success, an untranslated error message on error. -const char *set_string_option(const int opt_idx, void *varp_arg, const char *value, +const char *set_string_option(const int opt_idx, void *varp, const char *value, const int opt_flags, bool *value_checked, char *const errbuf, const size_t errbuflen) FUNC_ATTR_WARN_UNUSED_RESULT { vimoption_T *opt = get_option(opt_idx); - void *varp = (char **)varp_arg; char *origval_l = NULL; char *origval_g = NULL; -- cgit From 5df4fdf253f9c9cc35f9f5f16c6d0ba9d87b4c71 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sun, 8 Oct 2023 22:13:15 +0600 Subject: refactor(options)!: make OptionSet `v:` values use typval BREAKING CHANGE: This breaks the OptionSet autocommand, as the `v:` values associated with it (`v:option_new`, `v:option_old`, `v:option_oldlocal` and `v:option_oldglobal`) are now the same type as the option, instead of all option values being converted to strings. --- src/nvim/optionstr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 08618406e6..9a499c56fb 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -441,9 +441,8 @@ void set_string_option_direct_in_buf(buf_T *buf, const char *name, int opt_idx, /// #OPT_GLOBAL. /// /// @return NULL on success, an untranslated error message on error. -const char *set_string_option(const int opt_idx, void *varp, const char *value, - const int opt_flags, bool *value_checked, char *const errbuf, - const size_t errbuflen) +const char *set_string_option(const int opt_idx, void *varp, const char *value, const int opt_flags, + bool *value_checked, char *const errbuf, const size_t errbuflen) FUNC_ATTR_WARN_UNUSED_RESULT { vimoption_T *opt = get_option(opt_idx); -- cgit From 36e4901cbdb1c2b4b1d88cf9a7da157bf725fae4 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Wed, 11 Oct 2023 18:03:22 +0600 Subject: refactor(options): remove `os_op` --- src/nvim/optionstr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 9a499c56fb..4aa51db3f1 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -503,8 +503,7 @@ const char *set_string_option(const int opt_idx, void *varp, const char *value, } const char *const errmsg = did_set_string_option(curbuf, curwin, opt_idx, varp, oldval, - errbuf, errbuflen, - opt_flags, OP_NONE, value_checked); + errbuf, errbuflen, opt_flags, value_checked); secure = secure_saved; @@ -2741,7 +2740,7 @@ static void do_spelllang_source(win_T *win) /// /// @return NULL for success, or an untranslated error message for an error const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **varp, char *oldval, - char *errbuf, size_t errbuflen, int opt_flags, set_op_T op, + char *errbuf, size_t errbuflen, int opt_flags, bool *value_checked) { const char *errmsg = NULL; @@ -2755,7 +2754,6 @@ const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **va .os_varp = varp, .os_idx = opt_idx, .os_flags = opt_flags, - .os_op = op, .os_oldval.string = oldval, .os_newval.string = *varp, .os_value_checked = false, -- cgit From ca77089e2dae8d68209f26756774c73ad7ca018e Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Thu, 12 Oct 2023 20:09:52 +0600 Subject: refactor(options): deduplicate `do_set_option_string` Reduce code duplication between `do_set_option_string` and `set_string_option` by making the former call the latter within itself. --- src/nvim/optionstr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 4aa51db3f1..fba1615dee 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -442,7 +442,8 @@ void set_string_option_direct_in_buf(buf_T *buf, const char *name, int opt_idx, /// /// @return NULL on success, an untranslated error message on error. const char *set_string_option(const int opt_idx, void *varp, const char *value, const int opt_flags, - bool *value_checked, char *const errbuf, const size_t errbuflen) + const bool new_value, bool *value_checked, char *const errbuf, + const size_t errbuflen) FUNC_ATTR_WARN_UNUSED_RESULT { vimoption_T *opt = get_option(opt_idx); @@ -492,13 +493,12 @@ const char *set_string_option(const int opt_idx, void *varp, const char *value, char *const saved_newval = xstrdup(*(char **)varp); const int secure_saved = secure; + const uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags); - // When an option is set in the sandbox, from a modeline or in secure - // mode, then deal with side effects in secure mode. Also when the - // value was set with the P_INSECURE flag and is not completely - // replaced. - if ((opt_flags & OPT_MODELINE) - || sandbox != 0) { + // When an option is set in the sandbox, from a modeline or in secure mode, then deal with side + // effects in secure mode. Also when the value was set with the P_INSECURE flag and is not + // completely replaced. + if ((opt_flags & OPT_MODELINE) || sandbox != 0 || (!new_value && (*p & P_INSECURE))) { secure = 1; } -- cgit From af010e23f38a23bb74ea5b61e1b1a05e76410b5f Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Fri, 13 Oct 2023 20:16:15 +0600 Subject: refactor(options): rename `empty_option` to `empty_string_option` --- src/nvim/optionstr.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index fba1615dee..f8d70981b3 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -287,29 +287,28 @@ void check_buf_options(buf_T *buf) } /// Free the string allocated for an option. -/// Checks for the string being empty_option. This may happen if we're out of -/// memory, xstrdup() returned NULL, which was replaced by empty_option by -/// check_options(). +/// Checks for the string being empty_string_option. This may happen if we're out of memory, +/// xstrdup() returned NULL, which was replaced by empty_string_option by check_options(). /// Does NOT check for P_ALLOCED flag! void free_string_option(char *p) { - if (p != empty_option) { + if (p != empty_string_option) { xfree(p); } } void clear_string_option(char **pp) { - if (*pp != empty_option) { + if (*pp != empty_string_option) { xfree(*pp); } - *pp = empty_option; + *pp = empty_string_option; } void check_string_option(char **pp) { if (*pp == NULL) { - *pp = empty_option; + *pp = empty_string_option; } } @@ -385,7 +384,7 @@ void set_string_option_direct(const char *name, int opt_idx, const char *val, in // make the local value empty, so that the global value is used. if ((opt->indir & PV_BOTH) && both) { free_string_option(*varp); - *varp = empty_option; + *varp = empty_string_option; } if (set_sid != SID_NONE) { sctx_T script_ctx; @@ -468,7 +467,7 @@ const char *set_string_option(const int opt_idx, void *varp, const char *value, // A global-local string option might have an empty option as value to // indicate that the global value should be used. - if (((int)opt->indir & PV_BOTH) && origval_l == empty_option) { + if (((int)opt->indir & PV_BOTH) && origval_l == empty_string_option) { origval_l = origval_g; } } @@ -482,7 +481,7 @@ const char *set_string_option(const int opt_idx, void *varp, const char *value, origval = oldval; } - *(char **)varp = xstrdup(value != NULL ? value : empty_option); + *(char **)varp = xstrdup(value != NULL ? value : empty_string_option); char *const saved_origval = (origval != NULL) ? xstrdup(origval) : NULL; char *const saved_oldval_l = (origval_l != NULL) ? xstrdup(origval_l) : 0; @@ -2814,7 +2813,7 @@ const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **va // the local value and make it empty char *p = get_varp_scope(opt, OPT_LOCAL); free_string_option(*(char **)p); - *(char **)p = empty_option; + *(char **)p = empty_string_option; } else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL) { // May set global value for local option. set_string_option_global(opt, varp); -- cgit From f1a58a8dcc241e18305e7c103fb97cec64a3e46d Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sat, 14 Oct 2023 20:02:42 +0600 Subject: refactor(options): make `os_oldval` and `os_newval` use `OptValData` --- src/nvim/optionstr.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index f8d70981b3..936062b806 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -860,7 +860,7 @@ int expand_set_backspace(optexpand_T *args, int *numMatches, char ***matches) const char *did_set_backupcopy(optset_T *args) { buf_T *buf = (buf_T *)args->os_buf; - const char *oldval = args->os_oldval.string; + const char *oldval = args->os_oldval.string.data; int opt_flags = args->os_flags; char *bkc = p_bkc; unsigned *flags = &bkc_flags; @@ -1459,7 +1459,7 @@ const char *did_set_fileformat(optset_T *args) { buf_T *buf = (buf_T *)args->os_buf; char **varp = (char **)args->os_varp; - const char *oldval = args->os_oldval.string; + const char *oldval = args->os_oldval.string.data; int opt_flags = args->os_flags; if (!MODIFIABLE(buf) && !(opt_flags & OPT_GLOBAL)) { return e_modifiable; @@ -1512,7 +1512,7 @@ const char *did_set_filetype_or_syntax(optset_T *args) return e_invarg; } - args->os_value_changed = strcmp(args->os_oldval.string, *varp) != 0; + args->os_value_changed = strcmp(args->os_oldval.string.data, *varp) != 0; // Since we check the value, there is no need to set P_INSECURE, // even when the value comes from a modeline. @@ -2103,7 +2103,7 @@ const char *did_set_sessionoptions(optset_T *args) } if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) { // Don't allow both "sesdir" and "curdir". - const char *oldval = args->os_oldval.string; + const char *oldval = args->os_oldval.string.data; (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true); return e_invarg; } @@ -2224,7 +2224,7 @@ const char *did_set_signcolumn(optset_T *args) { win_T *win = (win_T *)args->os_win; char **varp = (char **)args->os_varp; - const char *oldval = args->os_oldval.string; + const char *oldval = args->os_oldval.string.data; if (check_signcolumn(*varp) != OK) { return e_invarg; } @@ -2578,7 +2578,7 @@ const char *did_set_virtualedit(optset_T *args) } else { if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) { return e_invarg; - } else if (strcmp(ve, args->os_oldval.string) != 0) { + } else if (strcmp(ve, args->os_oldval.string.data) != 0) { // Recompute cursor position in case the new 've' setting // changes something. validate_virtcol_win(win); @@ -2753,8 +2753,8 @@ const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **va .os_varp = varp, .os_idx = opt_idx, .os_flags = opt_flags, - .os_oldval.string = oldval, - .os_newval.string = *varp, + .os_oldval.string = cstr_as_string(oldval), + .os_newval.string = cstr_as_string(*varp), .os_value_checked = false, .os_value_changed = false, .os_restore_chartab = false, -- cgit From 3642f2fb44b6a3681e6a637671690258aa83cc62 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Mon, 16 Oct 2023 12:15:33 +0600 Subject: refactor(options): make `did_set_shada` a normal option callback --- src/nvim/optionstr.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 936062b806..2e90b6b4ae 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -2119,20 +2119,11 @@ int expand_set_sessionoptions(optexpand_T *args, int *numMatches, char ***matche matches); } -static const char *did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, - size_t errbuflen) -{ - static int shada_idx = -1; - // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo - // option. - *opt_idx = (((*opt)->fullname[0] == 'v') - ? (shada_idx == -1 ? ((shada_idx = findoption("shada"))) : shada_idx) - : *opt_idx); - *opt = get_option(*opt_idx); - // Update free_oldval now that we have the opt_idx for 'shada', otherwise - // there would be a disconnect between the check for P_ALLOCED at the start - // of the function and the set of P_ALLOCED at the end of the function. - *free_oldval = ((*opt)->flags & P_ALLOCED); +const char *did_set_shada(optset_T *args) +{ + char *errbuf = args->os_errbuf; + size_t errbuflen = args->os_errbuflen; + for (char *s = p_shada; *s;) { // Check it's a valid character if (vim_strchr("!\"%'/:<@cfhnrs", (uint8_t)(*s)) == NULL) { @@ -2784,8 +2775,6 @@ const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **va // The 'isident', 'iskeyword', 'isprint' and 'isfname' options may // change the character table. On failure, this needs to be restored. restore_chartab = args.os_restore_chartab; - } else if (varp == &p_shada) { // 'shada' - errmsg = did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen); } // If an error is detected, restore the previous value. -- cgit From ae4ca4edf89ece433b61e8bf92c412298b58d9ea Mon Sep 17 00:00:00 2001 From: glepnir Date: Fri, 13 Oct 2023 14:49:01 +0800 Subject: feat(complete): support f flag for complete buffer part --- src/nvim/optionstr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 2e90b6b4ae..63ceb07b48 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1171,7 +1171,7 @@ const char *did_set_complete(optset_T *args) if (!*s) { break; } - if (vim_strchr(".wbuksid]tU", (uint8_t)(*s)) == NULL) { + if (vim_strchr(".wbuksid]tUf", (uint8_t)(*s)) == NULL) { return illegal_char(args->os_errbuf, args->os_errbuflen, (uint8_t)(*s)); } if (*++s != NUL && *s != ',' && *s != ' ') { @@ -1200,7 +1200,7 @@ const char *did_set_complete(optset_T *args) int expand_set_complete(optexpand_T *args, int *numMatches, char ***matches) { static char *(p_cpt_values[]) = { - ".", "w", "b", "u", "k", "kspell", "s", "i", "d", "]", "t", "U", NULL + ".", "w", "b", "u", "k", "kspell", "s", "i", "d", "]", "t", "U", "f", NULL }; return expand_set_opt_string(args, p_cpt_values, -- cgit From e19cc9c9b715d8171f7940632b8855104b5290b6 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sat, 14 Oct 2023 22:19:11 +0600 Subject: refactor(options)!: unify `set_option` and `set_string_option` While the interfaces for setting number and boolean options are now unified by #25394, there is still a separate `set_string_option` function that is used for setting a string option. This PR removes that function and merges it with set_option. BREAKING CHANGE: `v:option_old` is now the old global value for all global-local options, instead of just string global-local options. Local value for a global-local number/boolean option is now unset when the option is set (e.g. using `:set` or `nvim_set_option_value`) without a scope, which means they now behave the same way as string options. Ref: #25672 --- src/nvim/optionstr.c | 317 +-------------------------------------------------- 1 file changed, 5 insertions(+), 312 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 63ceb07b48..b868c90108 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -173,51 +173,7 @@ void didset_string_options(void) (void)opt_strings_flags(p_cb, p_cb_values, &cb_flags, true); } -/// Trigger the OptionSet autocommand. -/// "opt_idx" is the index of the option being set. -/// "opt_flags" can be OPT_LOCAL etc. -/// "oldval" the old value -/// "oldval_l" the old local value (only non-NULL if global and local value are set) -/// "oldval_g" the old global value (only non-NULL if global and local value are set) -/// "newval" the new value -void trigger_optionset_string(int opt_idx, int opt_flags, char *oldval, char *oldval_l, - char *oldval_g, char *newval) -{ - // Don't do this recursively. - if (oldval == NULL || newval == NULL - || *get_vim_var_str(VV_OPTION_TYPE) != NUL) { - return; - } - - char buf_type[7]; - - vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s", - (opt_flags & OPT_LOCAL) ? "local" : "global"); - set_vim_var_string(VV_OPTION_OLD, oldval, -1); - set_vim_var_string(VV_OPTION_NEW, newval, -1); - set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); - if (opt_flags & OPT_LOCAL) { - set_vim_var_string(VV_OPTION_COMMAND, "setlocal", -1); - set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1); - } - if (opt_flags & OPT_GLOBAL) { - set_vim_var_string(VV_OPTION_COMMAND, "setglobal", -1); - set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1); - } - if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) { - set_vim_var_string(VV_OPTION_COMMAND, "set", -1); - set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1); - set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1); - } - if (opt_flags & OPT_MODELINE) { - set_vim_var_string(VV_OPTION_COMMAND, "modeline", -1); - set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1); - } - apply_autocmds(EVENT_OPTIONSET, get_option(opt_idx)->fullname, NULL, false, NULL); - reset_v_option_vars(); -} - -static char *illegal_char(char *errbuf, size_t errbuflen, int c) +char *illegal_char(char *errbuf, size_t errbuflen, int c) { if (errbuf == NULL) { return ""; @@ -340,7 +296,9 @@ static void set_string_option_global(vimoption_T *opt, char **varp) /// "set_sid" is SID_NONE don't set the scriptID. Otherwise set the scriptID to /// "set_sid". /// -/// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL +/// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL. +/// +/// TODO(famiu): Remove this and its win/buf variants. void set_string_option_direct(const char *name, int opt_idx, const char *val, int opt_flags, int set_sid) { @@ -431,100 +389,6 @@ void set_string_option_direct_in_buf(buf_T *buf, const char *name, int opt_idx, unblock_autocmds(); } -/// Set a string option to a new value, handling the effects -/// Must not be called with a hidden option! -/// -/// @param[in] opt_idx Option to set. -/// @param[in] value New value. -/// @param[in] opt_flags Option flags: expected to contain #OPT_LOCAL and/or -/// #OPT_GLOBAL. -/// -/// @return NULL on success, an untranslated error message on error. -const char *set_string_option(const int opt_idx, void *varp, const char *value, const int opt_flags, - const bool new_value, bool *value_checked, char *const errbuf, - const size_t errbuflen) - FUNC_ATTR_WARN_UNUSED_RESULT -{ - vimoption_T *opt = get_option(opt_idx); - - char *origval_l = NULL; - char *origval_g = NULL; - - // When using ":set opt=val" for a global option - // with a local value the local value will be - // reset, use the global value here. - if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 - && ((int)opt->indir & PV_BOTH)) { - varp = opt->var; - } - - // The old value is kept until we are sure that the new value is valid. - char *oldval = *(char **)varp; - - if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) { - origval_l = *(char **)get_varp_scope(opt, OPT_LOCAL); - origval_g = *(char **)get_varp_scope(opt, OPT_GLOBAL); - - // A global-local string option might have an empty option as value to - // indicate that the global value should be used. - if (((int)opt->indir & PV_BOTH) && origval_l == empty_string_option) { - origval_l = origval_g; - } - } - - char *origval; - // When setting the local value of a global option, the old value may be - // the global value. - if (((int)opt->indir & PV_BOTH) && (opt_flags & OPT_LOCAL)) { - origval = *(char **)get_varp_from(opt, curbuf, curwin); - } else { - origval = oldval; - } - - *(char **)varp = xstrdup(value != NULL ? value : empty_string_option); - - char *const saved_origval = (origval != NULL) ? xstrdup(origval) : NULL; - char *const saved_oldval_l = (origval_l != NULL) ? xstrdup(origval_l) : 0; - char *const saved_oldval_g = (origval_g != NULL) ? xstrdup(origval_g) : 0; - - // newval (and varp) may become invalid if the buffer is closed by - // autocommands. - char *const saved_newval = xstrdup(*(char **)varp); - - const int secure_saved = secure; - const uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags); - - // When an option is set in the sandbox, from a modeline or in secure mode, then deal with side - // effects in secure mode. Also when the value was set with the P_INSECURE flag and is not - // completely replaced. - if ((opt_flags & OPT_MODELINE) || sandbox != 0 || (!new_value && (*p & P_INSECURE))) { - secure = 1; - } - - const char *const errmsg = did_set_string_option(curbuf, curwin, opt_idx, varp, oldval, - errbuf, errbuflen, opt_flags, value_checked); - - secure = secure_saved; - - // call autocommand after handling side effects - if (errmsg == NULL) { - if (!starting) { - trigger_optionset_string(opt_idx, opt_flags, saved_origval, saved_oldval_l, - saved_oldval_g, saved_newval); - } - if (opt->flags & P_UI_OPTION) { - ui_call_option_set(cstr_as_string(opt->fullname), - CSTR_AS_OBJ(saved_newval)); - } - } - xfree(saved_origval); - xfree(saved_oldval_l); - xfree(saved_oldval_g); - xfree(saved_newval); - - return errmsg; -} - /// Return true if "val" is a valid 'filetype' name. /// Also used for 'syntax' and 'keymap'. static bool valid_filetype(const char *val) @@ -636,7 +500,7 @@ const char *check_stl_option(char *s) /// Check for a "normal" directory or file name in some options. Disallow a /// path separator (slash and/or backslash), wildcards and characters that are /// often illegal in a file name. Be more permissive if "secure" is off. -static bool check_illegal_path_names(char *val, uint32_t flags) +bool check_illegal_path_names(char *val, uint32_t flags) { return (((flags & P_NFNAME) && strpbrk(val, (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL) @@ -2676,177 +2540,6 @@ int expand_set_winhighlight(optexpand_T *args, int *numMatches, char ***matches) return expand_set_opt_generic(args, get_highlight_name, numMatches, matches); } -// When 'syntax' is set, load the syntax of that name -static void do_syntax_autocmd(buf_T *buf, bool value_changed) -{ - static int syn_recursive = 0; - - syn_recursive++; - // Only pass true for "force" when the value changed or not used - // recursively, to avoid endless recurrence. - apply_autocmds(EVENT_SYNTAX, buf->b_p_syn, buf->b_fname, - value_changed || syn_recursive == 1, buf); - buf->b_flags |= BF_SYN_SET; - syn_recursive--; -} - -static void do_spelllang_source(win_T *win) -{ - char fname[200]; - char *q = win->w_s->b_p_spl; - - // Skip the first name if it is "cjk". - if (strncmp(q, "cjk,", 4) == 0) { - q += 4; - } - - // Source the spell/LANG.{vim,lua} in 'runtimepath'. - // They could set 'spellcapcheck' depending on the language. - // Use the first name in 'spelllang' up to '_region' or - // '.encoding'. - char *p; - for (p = q; *p != NUL; p++) { - if (!ASCII_ISALNUM(*p) && *p != '-') { - break; - } - } - if (p > q) { - vim_snprintf(fname, sizeof(fname), "spell/%.*s.*", (int)(p - q), q); - source_runtime_vim_lua(fname, DIP_ALL); - } -} - -/// Handle string options that need some action to perform when changed. -/// The new value must be allocated. -/// -/// @param opt_idx index in options[] table -/// @param varp pointer to the option variable -/// @param oldval previous value of the option -/// @param errbuf buffer for errors, or NULL -/// @param errbuflen length of errors buffer -/// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL -/// @param op OP_ADDING/OP_PREPENDING/OP_REMOVING -/// @param value_checked value was checked to be safe, no need to set P_INSECURE -/// -/// @return NULL for success, or an untranslated error message for an error -const char *did_set_string_option(buf_T *buf, win_T *win, int opt_idx, char **varp, char *oldval, - char *errbuf, size_t errbuflen, int opt_flags, - bool *value_checked) -{ - const char *errmsg = NULL; - int restore_chartab = false; - vimoption_T *opt = get_option(opt_idx); - bool free_oldval = (opt->flags & P_ALLOCED); - opt_did_set_cb_T did_set_cb = get_option_did_set_cb(opt_idx); - bool value_changed = false; - - optset_T args = { - .os_varp = varp, - .os_idx = opt_idx, - .os_flags = opt_flags, - .os_oldval.string = cstr_as_string(oldval), - .os_newval.string = cstr_as_string(*varp), - .os_value_checked = false, - .os_value_changed = false, - .os_restore_chartab = false, - .os_errbuf = errbuf, - .os_errbuflen = errbuflen, - .os_win = win, - .os_buf = buf, - }; - - // Disallow changing some options from secure mode - if ((secure || sandbox != 0) && (opt->flags & P_SECURE)) { - errmsg = e_secure; - // Check for a "normal" directory or file name in some options. - } else if (check_illegal_path_names(*varp, opt->flags)) { - errmsg = e_invarg; - } else if (did_set_cb != NULL) { - // Invoke the option specific callback function to validate and apply - // the new option value. - errmsg = did_set_cb(&args); - - // The 'filetype' and 'syntax' option callback functions may change - // the os_value_changed field. - value_changed = args.os_value_changed; - // The 'keymap', 'filetype' and 'syntax' option callback functions - // may change the os_value_checked field. - *value_checked = args.os_value_checked; - // The 'isident', 'iskeyword', 'isprint' and 'isfname' options may - // change the character table. On failure, this needs to be restored. - restore_chartab = args.os_restore_chartab; - } - - // If an error is detected, restore the previous value. - if (errmsg != NULL) { - free_string_option(*varp); - *varp = oldval; - // When resetting some values, need to act on it. - if (restore_chartab) { - (void)buf_init_chartab(buf, true); - } - } else { - // Remember where the option was set. - set_option_sctx_idx(opt_idx, opt_flags, current_sctx); - // Free string options that are in allocated memory. - // Use "free_oldval", because recursiveness may change the flags under - // our fingers (esp. init_highlight()). - if (free_oldval) { - free_string_option(oldval); - } - opt->flags |= P_ALLOCED; - - if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 - && (opt->indir & PV_BOTH)) { - // global option with local value set to use global value; free - // the local value and make it empty - char *p = get_varp_scope(opt, OPT_LOCAL); - free_string_option(*(char **)p); - *(char **)p = empty_string_option; - } else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL) { - // May set global value for local option. - set_string_option_global(opt, varp); - } - - // Trigger the autocommand only after setting the flags. - if (varp == &buf->b_p_syn) { - do_syntax_autocmd(buf, value_changed); - } else if (varp == &buf->b_p_ft) { - // 'filetype' is set, trigger the FileType autocommand - // Skip this when called from a modeline - // Force autocmd when the filetype was changed - if (!(opt_flags & OPT_MODELINE) || value_changed) { - do_filetype_autocmd(buf, value_changed); - } - } else if (varp == &win->w_s->b_p_spl) { - do_spelllang_source(win); - } - } - - if (varp == &p_mouse) { - setmouse(); // in case 'mouse' changed - } - - if ((varp == &p_flp || varp == &(buf->b_p_flp)) - && win->w_briopt_list) { - // Changing Formatlistpattern when briopt includes the list setting: - // redraw - redraw_all_later(UPD_NOT_VALID); - } else if (varp == &p_wbr || varp == &(win->w_p_wbr)) { - // add / remove window bars for 'winbar' - set_winbar(true); - } - - if (win->w_curswant != MAXCOL - && (opt->flags & (P_CURSWANT | P_RALL)) != 0) { - win->w_set_curswant = true; - } - - check_redraw_for(buf, win, opt->flags); - - return errmsg; -} - /// Check an option that can be a range of string values. /// /// @param list when true: accept a list of values -- cgit From cd63a9addd6e1114c3524fa041ece560550cfe7b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 10 Nov 2023 08:39:21 +0800 Subject: refactor: change some xstrndup() and xstrnsave() to xmemdupz() (#25959) When the given length is exactly the number of bytes to copy, xmemdupz() makes the intention clearer. --- src/nvim/optionstr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index b868c90108..7aea47cfff 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -635,7 +635,7 @@ static int expand_set_opt_listflag(optexpand_T *args, char *flags, int *numMatch // existing flag. Just skip it to avoid duplicate. continue; } - (*matches)[count++] = xstrnsave(flag, 1); + (*matches)[count++] = xmemdupz(flag, 1); } } -- cgit From 9af03bcd47127a416aa6a125590b75adb5f53c3c Mon Sep 17 00:00:00 2001 From: Omar El Halabi Date: Fri, 10 Nov 2023 05:20:26 +0100 Subject: fix(options): do not change inccommand during preview (#25462) --- src/nvim/optionstr.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 7aea47cfff..be76688e92 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1569,6 +1569,9 @@ const char *did_set_iconstring(optset_T *args) /// The 'inccommand' option is changed. const char *did_set_inccommand(optset_T *args FUNC_ATTR_UNUSED) { + if (cmdpreview) { + return e_invarg; + } return did_set_opt_strings(p_icm, p_icm_values, false); } -- cgit From 8e58d37f2e15ac8540377148e55ed08a039aadb6 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sat, 11 Nov 2023 11:20:08 +0100 Subject: refactor: remove redundant casts --- src/nvim/optionstr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index be76688e92..80f879e9db 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -561,7 +561,7 @@ static int expand_set_opt_string(optexpand_T *args, char **values, size_t numVal continue; } } - if (vim_regexec(regmatch, *val, (colnr_T)0)) { + if (vim_regexec(regmatch, *val, 0)) { (*matches)[count++] = xstrdup(*val); } } -- cgit From 353a4be7e84fdc101318215bdcc8a7e780d737fe Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 12 Nov 2023 13:13:58 +0100 Subject: build: remove PVS We already have an extensive suite of static analysis tools we use, which causes a fair bit of redundancy as we get duplicate warnings. PVS is also prone to give false warnings which creates a lot of work to identify and disable. --- src/nvim/optionstr.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 80f879e9db..e363f02644 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include #include #include -- cgit From bb4b4576e384c71890b4df4fa4f1ae76fad3a59d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 16 Nov 2023 10:55:54 +0800 Subject: refactor: iwyu (#26062) --- src/nvim/optionstr.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index e363f02644..bee08940b4 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -3,7 +3,6 @@ #include #include -#include "nvim/api/private/helpers.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/buffer_defs.h" @@ -15,7 +14,6 @@ #include "nvim/diff.h" #include "nvim/digraph.h" #include "nvim/drawscreen.h" -#include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" @@ -32,7 +30,6 @@ #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/message.h" -#include "nvim/mouse.h" #include "nvim/move.h" #include "nvim/option.h" #include "nvim/option_defs.h" @@ -41,13 +38,11 @@ #include "nvim/os/os.h" #include "nvim/pos.h" #include "nvim/regexp.h" -#include "nvim/runtime.h" #include "nvim/spell.h" #include "nvim/spellfile.h" #include "nvim/spellsuggest.h" #include "nvim/strings.h" #include "nvim/types.h" -#include "nvim/ui.h" #include "nvim/vim.h" #include "nvim/window.h" -- cgit From ac1113ded5f8f09dd99a9894d7a7e795626fb728 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 13 Nov 2023 23:40:37 +0100 Subject: refactor: follow style guide - reduce variable scope - prefer initialization over declaration and assignment --- src/nvim/optionstr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index bee08940b4..0d36634d9e 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -294,7 +294,6 @@ static void set_string_option_global(vimoption_T *opt, char **varp) void set_string_option_direct(const char *name, int opt_idx, const char *val, int opt_flags, int set_sid) { - char *s; int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; int idx = opt_idx; @@ -315,7 +314,7 @@ void set_string_option_direct(const char *name, int opt_idx, const char *val, in assert(opt->var != &p_shada); - s = xstrdup(val); + char *s = xstrdup(val); { char **varp = (char **)get_varp_scope(opt, both ? OPT_LOCAL : opt_flags); if ((opt_flags & OPT_FREE) && (opt->flags & P_ALLOCED)) { -- cgit From 488038580934f301c1528a14548ec0cabd16c2cd Mon Sep 17 00:00:00 2001 From: dundargoc Date: Fri, 10 Nov 2023 14:06:04 +0100 Subject: build: adjust clang-tidy warning exclusion logic Enable all clang-tidy warnings by default instead of disabling them. This ensures that we don't miss useful warnings on each clang-tidy version upgrade. A drawback of this is that it will force us to either fix or adjust the warnings as soon as possible. --- src/nvim/optionstr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 0d36634d9e..000fbaba95 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -2566,7 +2566,7 @@ static int opt_strings_flags(const char *val, char **values, unsigned *flagp, bo if (strncmp(values[i], val, len) == 0 && ((list && val[len] == ',') || val[len] == NUL)) { val += len + (val[len] == ','); - assert(i < sizeof(1U) * 8); + assert(i < sizeof(new_flags) * 8); new_flags |= (1U << i); break; // check next item in val list } -- cgit From 585eeacb24e1aa0fed978e46063de100b16b8bdf Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Mon, 20 Nov 2023 02:27:16 +0100 Subject: refactor(sign): store 'signcolumn' width range when it is set Problem: Minimum and maximum signcolumn width is determined each redraw. Solution: Determine and store 'signcolumn' range when option is set. --- src/nvim/optionstr.c | 58 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 21 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 000fbaba95..56f44788b0 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -388,34 +388,53 @@ static bool valid_filetype(const char *val) return valid_name(val, ".-_"); } -/// Handle setting 'signcolumn' for value 'val' +/// Handle setting 'signcolumn' for value 'val'. Store minimum and maximum width. /// /// @return OK when the value is valid, FAIL otherwise -static int check_signcolumn(char *val) +int check_signcolumn(win_T *wp) { + char *val = wp->w_p_scl; if (*val == NUL) { return FAIL; } - // check for basic match + if (check_opt_strings(val, p_scl_values, false) == OK) { + if (!strncmp(val, "no", 2)) { // no + wp->w_minscwidth = wp->w_maxscwidth = SCL_NO; + } else if (!strncmp(val, "nu", 2) && (wp->w_p_nu || wp->w_p_rnu)) { // number + wp->w_minscwidth = wp->w_maxscwidth = SCL_NUM; + } else if (!strncmp(val, "yes:", 4)) { // yes: + wp->w_minscwidth = wp->w_maxscwidth = val[4] - '0'; + } else if (*val == 'y') { // yes + wp->w_minscwidth = wp->w_maxscwidth = 1; + } else if (!strncmp(val, "auto:", 5)) { // auto: + wp->w_minscwidth = 0; + wp->w_maxscwidth = val[5] - '0'; + } else { // auto + wp->w_minscwidth = 0; + wp->w_maxscwidth = 1; + } return OK; } - // check for 'auto:-' - if (strlen(val) == 8 - && !strncmp(val, "auto:", 5) - && ascii_isdigit(val[5]) - && val[6] == '-' - && ascii_isdigit(val[7])) { - int min = val[5] - '0'; - int max = val[7] - '0'; - if (min < 1 || max < 2 || min > 8 || max > 9 || min >= max) { - return FAIL; - } - return OK; + if (strncmp(val, "auto:", 5) != 0 + || strlen(val) != 8 + || !ascii_isdigit(val[5]) + || val[6] != '-' + || !ascii_isdigit(val[7])) { + return FAIL; } - return FAIL; + // auto:- + int min = val[5] - '0'; + int max = val[7] - '0'; + if (min < 1 || max < 2 || min > 8 || min >= max) { + return FAIL; + } + + wp->w_minscwidth = min; + wp->w_maxscwidth = max; + return OK; } /// Check validity of options with the 'statusline' format. @@ -2072,16 +2091,13 @@ int expand_set_showcmdloc(optexpand_T *args, int *numMatches, char ***matches) const char *did_set_signcolumn(optset_T *args) { win_T *win = (win_T *)args->os_win; - char **varp = (char **)args->os_varp; const char *oldval = args->os_oldval.string.data; - if (check_signcolumn(*varp) != OK) { + if (check_signcolumn(win) != OK) { return e_invarg; } // When changing the 'signcolumn' to or from 'number', recompute the // width of the number column if 'number' or 'relativenumber' is set. - if (((*oldval == 'n' && *(oldval + 1) == 'u') - || (*win->w_p_scl == 'n' && *(win->w_p_scl + 1) == 'u')) - && (win->w_p_nu || win->w_p_rnu)) { + if ((*oldval == 'n' && *(oldval + 1) == 'u') || win->w_minscwidth == SCL_NUM) { win->w_nrwidth_line_count = 0; } return NULL; -- cgit From fe94e04893274b9c5697fb179eb6b00bc1cd3a91 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Nov 2023 06:52:50 +0800 Subject: vim-patch:9.0.2126: unused assignments when checking 'listchars' (#26182) Problem: Unused assignments when checking the value of 'listchars'. Solution: Loop only once when just checking the value. Add a test to check that this change doesn't cause double-free. closes: vim/vim#13559 https://github.com/vim/vim/commit/00624a2fa08d04bdded240d474e9cfdc193dbe10 --- src/nvim/optionstr.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 56f44788b0..6c6fac84bf 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -2871,9 +2871,6 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_ } else { wp->w_p_fcs_chars = fcs_chars; } - } else if (is_listchars) { - xfree(lcs_chars.multispace); - xfree(lcs_chars.leadmultispace); } return NULL; // no error -- cgit From 8b428ca8b79ebb7b36c3e403ff3bcb6924a635a6 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 27 Nov 2023 16:00:21 +0100 Subject: build(IWYU): fix includes for func_attr.h --- src/nvim/optionstr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 6c6fac84bf..97c4fd4393 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -19,6 +19,7 @@ #include "nvim/eval/vars.h" #include "nvim/ex_getln.h" #include "nvim/fold.h" +#include "nvim/func_attr.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/highlight_group.h" -- cgit From f4aedbae4cb1f206f5b7c6142697b71dd473059b Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 27 Nov 2023 18:39:38 +0100 Subject: build(IWYU): fix includes for undo_defs.h --- src/nvim/optionstr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 97c4fd4393..04602e4283 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -37,7 +37,7 @@ #include "nvim/option_vars.h" #include "nvim/optionstr.h" #include "nvim/os/os.h" -#include "nvim/pos.h" +#include "nvim/pos_defs.h" #include "nvim/regexp.h" #include "nvim/spell.h" #include "nvim/spellfile.h" -- cgit From 6c14ae6bfaf51415b555e9a6b85d1d280976358d Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 27 Nov 2023 20:27:32 +0100 Subject: refactor: rename types.h to types_defs.h --- src/nvim/optionstr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 04602e4283..da9f0ae350 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -43,7 +43,7 @@ #include "nvim/spellfile.h" #include "nvim/spellsuggest.h" #include "nvim/strings.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/vim.h" #include "nvim/window.h" -- cgit From 79b6ff28ad1204fbb4199b9092f5c578d88cb28e Mon Sep 17 00:00:00 2001 From: dundargoc Date: Tue, 28 Nov 2023 20:31:00 +0100 Subject: refactor: fix headers with IWYU --- src/nvim/optionstr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/optionstr.c') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index da9f0ae350..281ec86171 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -3,7 +3,7 @@ #include #include -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/autocmd.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" @@ -26,7 +26,7 @@ #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/insexpand.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" @@ -44,7 +44,7 @@ #include "nvim/spellsuggest.h" #include "nvim/strings.h" #include "nvim/types_defs.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #include "nvim/window.h" #ifdef INCLUDE_GENERATED_DECLARATIONS -- cgit