diff options
-rw-r--r-- | src/nvim/option.c | 12 | ||||
-rw-r--r-- | src/nvim/options.lua | 6 | ||||
-rw-r--r-- | src/nvim/optionstr.c | 119 | ||||
-rw-r--r-- | test/old/testdir/test_options.vim | 8 |
4 files changed, 95 insertions, 50 deletions
diff --git a/src/nvim/option.c b/src/nvim/option.c index b941160e8a..729636d80a 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1854,10 +1854,10 @@ static void didset_options2(void) highlight_changed(); // Parse default for 'fillchars'. - (void)set_chars_option(curwin, &curwin->w_p_fcs, true); + (void)set_fillchars_option(curwin, curwin->w_p_fcs, true); // Parse default for 'listchars'. - (void)set_chars_option(curwin, &curwin->w_p_lcs, true); + (void)set_listchars_option(curwin, curwin->w_p_lcs, true); // Parse default for 'wildmode'. check_opt_wim(); @@ -4164,12 +4164,12 @@ void unset_global_local_option(char *name, void *from) break; case PV_LCS: clear_string_option(&((win_T *)from)->w_p_lcs); - set_chars_option((win_T *)from, &((win_T *)from)->w_p_lcs, true); + set_listchars_option((win_T *)from, ((win_T *)from)->w_p_lcs, true); redraw_later((win_T *)from, UPD_NOT_VALID); break; case PV_FCS: clear_string_option(&((win_T *)from)->w_p_fcs); - set_chars_option((win_T *)from, &((win_T *)from)->w_p_fcs, true); + set_fillchars_option((win_T *)from, ((win_T *)from)->w_p_fcs, true); redraw_later((win_T *)from, UPD_NOT_VALID); break; case PV_VE: @@ -4749,8 +4749,8 @@ void didset_window_options(win_T *wp, bool valid_cursor) check_colorcolumn(wp); briopt_check(wp); fill_culopt_flags(NULL, wp); - set_chars_option(wp, &wp->w_p_fcs, true); - set_chars_option(wp, &wp->w_p_lcs, true); + set_fillchars_option(wp, wp->w_p_fcs, true); + set_listchars_option(wp, wp->w_p_lcs, true); parse_winhl_opt(wp); // sets w_hl_needs_update also for w_p_winbl check_blending(wp); set_winbar_win(wp, false, valid_cursor); diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 7ab3e7e27e..aeef336686 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -832,7 +832,8 @@ return { alloced=true, redraw={'current_window'}, varname='p_fcs', - defaults={if_true=''} + defaults={if_true=''}, + cb='did_set_chars_option' }, { full_name='fixendofline', abbreviation='fixeol', @@ -1485,7 +1486,8 @@ return { alloced=true, redraw={'current_window'}, varname='p_lcs', - defaults={if_true="tab:> ,trail:-,nbsp:+"} + defaults={if_true="tab:> ,trail:-,nbsp:+"}, + cb='did_set_chars_option' }, { full_name='loadplugins', abbreviation='lpl', 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; } } diff --git a/test/old/testdir/test_options.vim b/test/old/testdir/test_options.vim index e4cdf539e2..769aa1c35f 100644 --- a/test/old/testdir/test_options.vim +++ b/test/old/testdir/test_options.vim @@ -1480,18 +1480,18 @@ func Test_string_option_revert_on_failure() if has('win32') && has('terminal') call add(optlist, ['termwintype', 'winpty', 'a123']) endif - if has('+toolbar') + if exists('+toolbar') call add(optlist, ['toolbar', 'text', 'a123']) call add(optlist, ['toolbariconsize', 'medium', 'a123']) endif - if has('+mouse') + if exists('+ttymouse') && !has('gui') call add(optlist, ['ttymouse', 'xterm', 'a123']) endif - if has('+vartabs') + if exists('+vartabs') call add(optlist, ['varsofttabstop', '12', 'a123']) call add(optlist, ['vartabstop', '4,20', '4,']) endif - if has('gui') + if exists('+winaltkeys') call add(optlist, ['winaltkeys', 'no', 'a123']) endif for opt in optlist |