commit 960170e4469b96c5c3d06ba1bb84c9edeaa04b8b
parent 2af9fac0a6ce3b01f22802511cf1ed7b0734cb2e
Author: zeertzjq <zeertzjq@outlook.com>
Date: Sat, 30 Sep 2023 19:36:33 +0800
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 <yegappan@yahoo.com>
Diffstat:
| M | src/nvim/option.c | | | 1160 | ++++++++++++++++++++++++++++++++++++++++---------------------------------------- |
| M | src/nvim/optionstr.c | | | 1706 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
2 files changed, 1436 insertions(+), 1430 deletions(-)
diff --git a/src/nvim/option.c b/src/nvim/option.c
@@ -2037,74 +2037,149 @@ static const char *did_set_force_off(bool *doskip)
return NULL;
}
-/// Process the updated 'langremap' option value.
-static const char *did_set_langremap(optset_T *args FUNC_ATTR_UNUSED)
+/// Process the updated 'arabic' option value.
+static const char *did_set_arabic(optset_T *args)
{
- // 'langremap' -> !'langnoremap'
- p_lnr = !p_lrm;
+ win_T *win = (win_T *)args->os_win;
+ const char *errmsg = NULL;
+
+ if (win->w_p_arab) {
+ // 'arabic' is set, handle various sub-settings.
+ if (!p_tbidi) {
+ // set rightleft mode
+ if (!win->w_p_rl) {
+ win->w_p_rl = true;
+ changed_window_setting();
+ }
+
+ // Enable Arabic shaping (major part of what Arabic requires)
+ if (!p_arshape) {
+ p_arshape = true;
+ redraw_all_later(UPD_NOT_VALID);
+ }
+ }
+
+ // Arabic requires a utf-8 encoding, inform the user if it's not
+ // set.
+ if (strcmp(p_enc, "utf-8") != 0) {
+ static char *w_arabic = N_("W17: Arabic requires UTF-8, do ':set encoding=utf-8'");
+
+ msg_source(HL_ATTR(HLF_W));
+ msg(_(w_arabic), HL_ATTR(HLF_W));
+ set_vim_var_string(VV_WARNINGMSG, _(w_arabic), -1);
+ }
+
+ // set 'delcombine'
+ p_deco = true;
+
+ // Force-set the necessary keymap for arabic.
+ errmsg = set_option_value("keymap", STATIC_CSTR_AS_OPTVAL("arabic"), OPT_LOCAL);
+ } else {
+ // 'arabic' is reset, handle various sub-settings.
+ if (!p_tbidi) {
+ // reset rightleft mode
+ if (win->w_p_rl) {
+ win->w_p_rl = false;
+ changed_window_setting();
+ }
+
+ // 'arabicshape' isn't reset, it is a global option and
+ // another window may still need it "on".
+ }
+
+ // 'delcombine' isn't reset, it is a global option and another
+ // window may still want it "on".
+
+ // Revert to the default keymap
+ curbuf->b_p_iminsert = B_IMODE_NONE;
+ curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
+ }
+
+ return errmsg;
+}
+
+/// Process the updated 'autochdir' option value.
+static const char *did_set_autochdir(optset_T *args FUNC_ATTR_UNUSED)
+{
+ // Change directories when the 'acd' option is set now.
+ do_autochdir();
return NULL;
}
-/// Process the updated 'langnoremap' option value.
-static const char *did_set_langnoremap(optset_T *args FUNC_ATTR_UNUSED)
+/// Process the updated 'binary' option value.
+static const char *did_set_binary(optset_T *args)
{
- // 'langnoremap' -> !'langremap'
- p_lrm = !p_lnr;
+ buf_T *buf = (buf_T *)args->os_buf;
+
+ // when 'bin' is set also set some other options
+ set_options_bin((int)args->os_oldval.boolean, buf->b_p_bin, args->os_flags);
+ redraw_titles();
+
return NULL;
}
-/// Process the updated 'undofile' option value.
-static const char *did_set_undofile(optset_T *args)
+/// Called when the 'breakat' option changes value.
+static const char *did_set_breakat(optset_T *args FUNC_ATTR_UNUSED)
{
- // Only take action when the option was set.
- if (!curbuf->b_p_udf && !p_udf) {
- return NULL;
+ for (int i = 0; i < 256; i++) {
+ breakat_flags[i] = false;
}
- // When reset we do not delete the undo file, the option may be set again
- // without making any changes in between.
- uint8_t hash[UNDO_HASH_SIZE];
-
- FOR_ALL_BUFFERS(bp) {
- // When 'undofile' is set globally: for every buffer, otherwise
- // only for the current buffer: Try to read in the undofile,
- // if one exists, the buffer wasn't changed and the buffer was
- // loaded
- if ((curbuf == bp
- || (args->os_flags & OPT_GLOBAL) || args->os_flags == 0)
- && !bufIsChanged(bp) && bp->b_ml.ml_mfp != NULL) {
- u_compute_hash(bp, hash);
- u_read_undo(NULL, hash, bp->b_fname);
+ if (p_breakat != NULL) {
+ for (char *p = p_breakat; *p; p++) {
+ breakat_flags[(uint8_t)(*p)] = true;
}
}
return NULL;
}
-/// Process the updated 'readonly' option value.
-static const char *did_set_readonly(optset_T *args)
+/// Process the updated 'buflisted' option value.
+static const char *did_set_buflisted(optset_T *args)
{
- // when 'readonly' is reset globally, also reset readonlymode
- if (!curbuf->b_p_ro && (args->os_flags & OPT_LOCAL) == 0) {
- readonlymode = false;
+ buf_T *buf = (buf_T *)args->os_buf;
+
+ // when 'buflisted' changes, trigger autocommands
+ if (args->os_oldval.boolean != buf->b_p_bl) {
+ apply_autocmds(buf->b_p_bl ? EVENT_BUFADD : EVENT_BUFDELETE,
+ NULL, NULL, true, buf);
}
+ return NULL;
+}
- // when 'readonly' is set may give W10 again
- if (curbuf->b_p_ro) {
- curbuf->b_did_warn = false;
+/// Process the new 'cmdheight' option value.
+static const char *did_set_cmdheight(optset_T *args)
+{
+ OptInt old_value = args->os_oldval.number;
+
+ if (ui_has(kUIMessages)) {
+ p_ch = 0;
+ }
+ if (p_ch > Rows - min_rows() + 1) {
+ p_ch = Rows - min_rows() + 1;
}
- redraw_titles();
+ // if p_ch changed value, change the command line height
+ // Only compute the new window layout when startup has been
+ // completed. Otherwise the frame sizes may be wrong.
+ if ((p_ch != old_value
+ || tabline_height() + global_stl_height() + topframe->fr_height != Rows - p_ch)
+ && full_screen) {
+ command_height();
+ }
return NULL;
}
-/// Process the updated 'modifiable' option value.
-static const char *did_set_modifiable(optset_T *args FUNC_ATTR_UNUSED)
+/// Process the updated 'diff' option value.
+static const char *did_set_diff(optset_T *args)
{
- // when 'modifiable' is changed, redraw the window title
- redraw_titles();
-
+ win_T *win = (win_T *)args->os_win;
+ // May add or remove the buffer from the list of diff buffers.
+ diff_buf_adjust(win);
+ if (foldmethodIsDiff(win)) {
+ foldUpdateAll(win);
+ }
return NULL;
}
@@ -2117,76 +2192,205 @@ static const char *did_set_eof_eol_fixeol_bomb(optset_T *args FUNC_ATTR_UNUSED)
return NULL;
}
-/// Process the updated 'binary' option value.
-static const char *did_set_binary(optset_T *args)
+/// Process the updated 'equalalways' option value.
+static const char *did_set_equalalways(optset_T *args)
{
- buf_T *buf = (buf_T *)args->os_buf;
+ win_T *win = (win_T *)args->os_win;
+ if (p_ea && !args->os_oldval.boolean) {
+ win_equal(win, false, 0);
+ }
- // when 'bin' is set also set some other options
- set_options_bin((int)args->os_oldval.boolean, buf->b_p_bin, args->os_flags);
- redraw_titles();
+ return NULL;
+}
+/// Process the new 'foldlevel' option value.
+static const char *did_set_foldlevel(optset_T *args FUNC_ATTR_UNUSED)
+{
+ newFoldLevel();
return NULL;
}
-/// Process the updated 'buflisted' option value.
-static const char *did_set_buflisted(optset_T *args)
+/// Process the new 'foldminlines' option value.
+static const char *did_set_foldminlines(optset_T *args)
{
- buf_T *buf = (buf_T *)args->os_buf;
+ win_T *win = (win_T *)args->os_win;
+ foldUpdateAll(win);
+ return NULL;
+}
- // when 'buflisted' changes, trigger autocommands
- if (args->os_oldval.boolean != buf->b_p_bl) {
- apply_autocmds(buf->b_p_bl ? EVENT_BUFADD : EVENT_BUFDELETE,
- NULL, NULL, true, buf);
+/// Process the new 'foldnestmax' option value.
+static const char *did_set_foldnestmax(optset_T *args)
+{
+ win_T *win = (win_T *)args->os_win;
+ if (foldmethodIsSyntax(win) || foldmethodIsIndent(win)) {
+ foldUpdateAll(win);
}
return NULL;
}
-/// Process the updated 'swapfile' option value.
-static const char *did_set_swapfile(optset_T *args)
+/// Process the new 'helpheight' option value.
+static const char *did_set_helpheight(optset_T *args)
{
- buf_T *buf = (buf_T *)args->os_buf;
- // when 'swf' is set, create swapfile, when reset remove swapfile
- if (buf->b_p_swf && p_uc) {
- ml_open_file(buf); // create the swap file
- } else {
- // no need to reset curbuf->b_may_swap, ml_open_file() will check
- // buf->b_p_swf
- mf_close_file(buf, true); // remove the swap file
+ // Change window height NOW
+ if (!ONE_WINDOW) {
+ buf_T *buf = (buf_T *)args->os_buf;
+ win_T *win = (win_T *)args->os_win;
+ if (buf->b_help && win->w_height < p_hh) {
+ win_setheight((int)p_hh);
+ }
}
+
return NULL;
}
-/// Process the updated 'paste' option value.
-static const char *did_set_paste(optset_T *args FUNC_ATTR_UNUSED)
+/// Process the updated 'hlsearch' option value.
+static const char *did_set_hlsearch(optset_T *args FUNC_ATTR_UNUSED)
{
- static int old_p_paste = false;
- static int save_sm = 0;
- static int save_sta = 0;
- static int save_ru = 0;
- static int save_ri = 0;
+ // when 'hlsearch' is set or reset: reset no_hlsearch
+ set_no_hlsearch(false);
+ return NULL;
+}
- if (p_paste) {
- // Paste switched from off to on.
- // Save the current values, so they can be restored later.
- if (!old_p_paste) {
- // save options for each buffer
- FOR_ALL_BUFFERS(buf) {
- buf->b_p_tw_nopaste = buf->b_p_tw;
- buf->b_p_wm_nopaste = buf->b_p_wm;
- buf->b_p_sts_nopaste = buf->b_p_sts;
- buf->b_p_ai_nopaste = buf->b_p_ai;
- buf->b_p_et_nopaste = buf->b_p_et;
- if (buf->b_p_vsts_nopaste) {
- xfree(buf->b_p_vsts_nopaste);
- }
- buf->b_p_vsts_nopaste = buf->b_p_vsts && buf->b_p_vsts != empty_option
- ? xstrdup(buf->b_p_vsts)
- : NULL;
- }
+/// Process the updated 'ignorecase' option value.
+static const char *did_set_ignorecase(optset_T *args FUNC_ATTR_UNUSED)
+{
+ // when 'ignorecase' is set or reset and 'hlsearch' is set, redraw
+ if (p_hls) {
+ redraw_all_later(UPD_SOME_VALID);
+ }
+ return NULL;
+}
- // save global options
- save_sm = p_sm;
+/// Process the new 'iminset' option value.
+static const char *did_set_iminsert(optset_T *args FUNC_ATTR_UNUSED)
+{
+ showmode();
+ // Show/unshow value of 'keymap' in status lines.
+ status_redraw_curbuf();
+
+ return NULL;
+}
+
+/// Process the updated 'langnoremap' option value.
+static const char *did_set_langnoremap(optset_T *args FUNC_ATTR_UNUSED)
+{
+ // 'langnoremap' -> !'langremap'
+ p_lrm = !p_lnr;
+ return NULL;
+}
+
+/// Process the updated 'langremap' option value.
+static const char *did_set_langremap(optset_T *args FUNC_ATTR_UNUSED)
+{
+ // 'langremap' -> !'langnoremap'
+ p_lnr = !p_lrm;
+ return NULL;
+}
+
+/// Process the new 'laststatus' option value.
+static const char *did_set_laststatus(optset_T *args)
+{
+ OptInt old_value = args->os_oldval.number;
+ OptInt value = args->os_newval.number;
+
+ // When switching to global statusline, decrease topframe height
+ // Also clear the cmdline to remove the ruler if there is one
+ if (value == 3 && old_value != 3) {
+ frame_new_height(topframe, topframe->fr_height - STATUS_HEIGHT, false, false);
+ (void)win_comp_pos();
+ clear_cmdline = true;
+ }
+ // When switching from global statusline, increase height of topframe by STATUS_HEIGHT
+ // in order to to re-add the space that was previously taken by the global statusline
+ if (old_value == 3 && value != 3) {
+ frame_new_height(topframe, topframe->fr_height + STATUS_HEIGHT, false, false);
+ (void)win_comp_pos();
+ }
+
+ last_status(false); // (re)set last window status line.
+ return NULL;
+}
+
+/// Process the updated 'lisp' option value.
+static const char *did_set_lisp(optset_T *args)
+{
+ buf_T *buf = (buf_T *)args->os_buf;
+ // When 'lisp' option changes include/exclude '-' in keyword characters.
+ (void)buf_init_chartab(buf, false); // ignore errors
+ return NULL;
+}
+
+/// Process the updated 'modifiable' option value.
+static const char *did_set_modifiable(optset_T *args FUNC_ATTR_UNUSED)
+{
+ // when 'modifiable' is changed, redraw the window title
+ redraw_titles();
+
+ return NULL;
+}
+
+/// Process the updated 'modified' option value.
+static const char *did_set_modified(optset_T *args)
+{
+ buf_T *buf = (buf_T *)args->os_buf;
+ if (!args->os_newval.boolean) {
+ save_file_ff(buf); // Buffer is unchanged
+ }
+ redraw_titles();
+ modified_was_set = (int)args->os_newval.boolean;
+ return NULL;
+}
+
+/// Process the updated 'number' or 'relativenumber' option value.
+static const char *did_set_number_relativenumber(optset_T *args)
+{
+ win_T *win = (win_T *)args->os_win;
+ if (*win->w_p_stc != NUL) {
+ // When 'relativenumber'/'number' is changed and 'statuscolumn' is set, reset width.
+ win->w_nrwidth_line_count = 0;
+ }
+ return NULL;
+}
+
+/// Process the new 'numberwidth' option value.
+static const char *did_set_numberwidth(optset_T *args)
+{
+ win_T *win = (win_T *)args->os_win;
+ win->w_nrwidth_line_count = 0; // trigger a redraw
+
+ return NULL;
+}
+
+/// Process the updated 'paste' option value.
+static const char *did_set_paste(optset_T *args FUNC_ATTR_UNUSED)
+{
+ static int old_p_paste = false;
+ static int save_sm = 0;
+ static int save_sta = 0;
+ static int save_ru = 0;
+ static int save_ri = 0;
+
+ if (p_paste) {
+ // Paste switched from off to on.
+ // Save the current values, so they can be restored later.
+ if (!old_p_paste) {
+ // save options for each buffer
+ FOR_ALL_BUFFERS(buf) {
+ buf->b_p_tw_nopaste = buf->b_p_tw;
+ buf->b_p_wm_nopaste = buf->b_p_wm;
+ buf->b_p_sts_nopaste = buf->b_p_sts;
+ buf->b_p_ai_nopaste = buf->b_p_ai;
+ buf->b_p_et_nopaste = buf->b_p_et;
+ if (buf->b_p_vsts_nopaste) {
+ xfree(buf->b_p_vsts_nopaste);
+ }
+ buf->b_p_vsts_nopaste = buf->b_p_vsts && buf->b_p_vsts != empty_option
+ ? xstrdup(buf->b_p_vsts)
+ : NULL;
+ }
+
+ // save global options
+ save_sm = p_sm;
save_sta = p_sta;
save_ru = p_ru;
save_ri = p_ri;
@@ -2273,400 +2477,138 @@ static const char *did_set_paste(optset_T *args FUNC_ATTR_UNUSED)
p_tw = p_tw_nopaste;
p_wm = p_wm_nopaste;
if (p_vsts) {
- free_string_option(p_vsts);
- }
- p_vsts = p_vsts_nopaste ? xstrdup(p_vsts_nopaste) : empty_option;
- }
-
- old_p_paste = p_paste;
-
- // Remember where the dependent options were reset
- didset_options_sctx((OPT_LOCAL | OPT_GLOBAL), p_paste_dep_opts);
-
- return NULL;
-}
-
-/// Process the updated 'ignorecase' option value.
-static const char *did_set_ignorecase(optset_T *args FUNC_ATTR_UNUSED)
-{
- // when 'ignorecase' is set or reset and 'hlsearch' is set, redraw
- if (p_hls) {
- redraw_all_later(UPD_SOME_VALID);
- }
- return NULL;
-}
-
-/// Process the updated 'hlsearch' option value.
-static const char *did_set_hlsearch(optset_T *args FUNC_ATTR_UNUSED)
-{
- // when 'hlsearch' is set or reset: reset no_hlsearch
- set_no_hlsearch(false);
- return NULL;
-}
-
-/// Process the updated 'scrollbind' option value.
-static const char *did_set_scrollbind(optset_T *args)
-{
- win_T *win = (win_T *)args->os_win;
-
- // when 'scrollbind' is set: snapshot the current position to avoid a jump
- // at the end of normal_cmd()
- if (!win->w_p_scb) {
- return NULL;
- }
- do_check_scrollbind(false);
- win->w_scbind_pos = win->w_topline;
- return NULL;
-}
-
-/// Process the updated 'previewwindow' option value.
-static const char *did_set_previewwindow(optset_T *args)
-{
- win_T *win = (win_T *)args->os_win;
-
- if (!win->w_p_pvw) {
- return NULL;
- }
-
- // There can be only one window with 'previewwindow' set.
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_p_pvw && wp != win) {
- win->w_p_pvw = false;
- args->os_doskip = true;
- return e_preview_window_already_exists;
- }
- }
-
- return NULL;
-}
-
-/// Process the updated 'lisp' option value.
-static const char *did_set_lisp(optset_T *args)
-{
- buf_T *buf = (buf_T *)args->os_buf;
- // When 'lisp' option changes include/exclude '-' in keyword characters.
- (void)buf_init_chartab(buf, false); // ignore errors
- return NULL;
-}
-
-/// Process the updated 'title' or the 'icon' option value.
-static const char *did_set_title_icon(optset_T *args FUNC_ATTR_UNUSED)
-{
- // when 'title' changed, may need to change the title; same for 'icon'
- did_set_title();
- return NULL;
-}
-
-/// Process the updated 'modified' option value.
-static const char *did_set_modified(optset_T *args)
-{
- buf_T *buf = (buf_T *)args->os_buf;
- if (!args->os_newval.boolean) {
- save_file_ff(buf); // Buffer is unchanged
- }
- redraw_titles();
- modified_was_set = (int)args->os_newval.boolean;
- return NULL;
-}
-
-#ifdef BACKSLASH_IN_FILENAME
-/// Process the updated 'shellslash' option value.
-static const char *did_set_shellslash(optset_T *args FUNC_ATTR_UNUSED)
-{
- if (p_ssl) {
- psepc = '/';
- psepcN = '\\';
- pseps[0] = '/';
- } else {
- psepc = '\\';
- psepcN = '/';
- pseps[0] = '\\';
- }
-
- // need to adjust the file name arguments and buffer names.
- buflist_slash_adjust();
- alist_slash_adjust();
- scriptnames_slash_adjust();
- return NULL;
-}
-#endif
-
-/// Process the updated 'wrap' option value.
-static const char *did_set_wrap(optset_T *args)
-{
- win_T *win = (win_T *)args->os_win;
-
- // If 'wrap' is set, set w_leftcol to zero.
- if (win->w_p_wrap) {
- win->w_leftcol = 0;
- }
- return NULL;
-}
-
-/// Process the updated 'equalalways' option value.
-static const char *did_set_equalalways(optset_T *args)
-{
- win_T *win = (win_T *)args->os_win;
- if (p_ea && !args->os_oldval.boolean) {
- win_equal(win, false, 0);
- }
-
- return NULL;
-}
-
-/// Process the updated 'autochdir' option value.
-static const char *did_set_autochdir(optset_T *args FUNC_ATTR_UNUSED)
-{
- // Change directories when the 'acd' option is set now.
- do_autochdir();
- return NULL;
-}
-
-/// Process the updated 'diff' option value.
-static const char *did_set_diff(optset_T *args)
-{
- win_T *win = (win_T *)args->os_win;
- // May add or remove the buffer from the list of diff buffers.
- diff_buf_adjust(win);
- if (foldmethodIsDiff(win)) {
- foldUpdateAll(win);
- }
- return NULL;
-}
-
-/// Process the updated 'spell' option value.
-static const char *did_set_spell(optset_T *args)
-{
- win_T *win = (win_T *)args->os_win;
- if (win->w_p_spell) {
- return parse_spelllang(win);
- }
-
- return NULL;
-}
-
-/// Process the updated 'arabic' option value.
-static const char *did_set_arabic(optset_T *args)
-{
- win_T *win = (win_T *)args->os_win;
- const char *errmsg = NULL;
-
- if (win->w_p_arab) {
- // 'arabic' is set, handle various sub-settings.
- if (!p_tbidi) {
- // set rightleft mode
- if (!win->w_p_rl) {
- win->w_p_rl = true;
- changed_window_setting();
- }
-
- // Enable Arabic shaping (major part of what Arabic requires)
- if (!p_arshape) {
- p_arshape = true;
- redraw_all_later(UPD_NOT_VALID);
- }
- }
-
- // Arabic requires a utf-8 encoding, inform the user if it's not
- // set.
- if (strcmp(p_enc, "utf-8") != 0) {
- static char *w_arabic = N_("W17: Arabic requires UTF-8, do ':set encoding=utf-8'");
-
- msg_source(HL_ATTR(HLF_W));
- msg(_(w_arabic), HL_ATTR(HLF_W));
- set_vim_var_string(VV_WARNINGMSG, _(w_arabic), -1);
- }
-
- // set 'delcombine'
- p_deco = true;
-
- // Force-set the necessary keymap for arabic.
- errmsg = set_option_value("keymap", STATIC_CSTR_AS_OPTVAL("arabic"), OPT_LOCAL);
- } else {
- // 'arabic' is reset, handle various sub-settings.
- if (!p_tbidi) {
- // reset rightleft mode
- if (win->w_p_rl) {
- win->w_p_rl = false;
- changed_window_setting();
- }
-
- // 'arabicshape' isn't reset, it is a global option and
- // another window may still need it "on".
- }
-
- // 'delcombine' isn't reset, it is a global option and another
- // window may still want it "on".
-
- // Revert to the default keymap
- curbuf->b_p_iminsert = B_IMODE_NONE;
- curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
- }
-
- return errmsg;
-}
-
-/// Process the updated 'number' or 'relativenumber' option value.
-static const char *did_set_number_relativenumber(optset_T *args)
-{
- win_T *win = (win_T *)args->os_win;
- if (*win->w_p_stc != NUL) {
- // When 'relativenumber'/'number' is changed and 'statuscolumn' is set, reset width.
- win->w_nrwidth_line_count = 0;
- }
- return NULL;
-}
-
-/// Set the value of a boolean option, taking care of side effects
-///
-/// @param[in] opt_idx Option index in options[] table.
-/// @param[out] varp Pointer to the option variable.
-/// @param[in] value New value.
-/// @param[in] opt_flags OPT_LOCAL and/or OPT_GLOBAL.
-///
-/// @return NULL on success, error message on error.
-static const char *set_bool_option(const int opt_idx, char *const varp, const int value,
- const int opt_flags)
-{
- int old_value = *(int *)varp;
- int old_global_value = 0;
-
- // Disallow changing some options from secure mode
- if ((secure || sandbox != 0)
- && (options[opt_idx].flags & P_SECURE)) {
- return e_secure;
+ free_string_option(p_vsts);
+ }
+ p_vsts = p_vsts_nopaste ? xstrdup(p_vsts_nopaste) : empty_option;
}
- // Save the global value before changing anything. This is needed as for
- // a global-only option setting the "local value" in fact sets the global
- // value (since there is only one value).
- if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
- old_global_value = *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
- }
+ old_p_paste = p_paste;
- *(int *)varp = value; // set the new value
- // Remember where the option was set.
- set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
+ // Remember where the dependent options were reset
+ didset_options_sctx((OPT_LOCAL | OPT_GLOBAL), p_paste_dep_opts);
- // May set global value for local option.
- if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
- *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = value;
- }
+ return NULL;
+}
- // Handle side effects for changing a bool option.
- const char *errmsg = NULL;
- bool doskip = false;
- if ((int *)varp == &p_force_on) {
- errmsg = did_set_force_on(&doskip);
- } else if ((int *)varp == &p_force_off) {
- errmsg = did_set_force_off(&doskip);
- } else if (options[opt_idx].opt_did_set_cb != NULL) {
- optset_T args = {
- .os_varp = varp,
- .os_flags = opt_flags,
- .os_oldval.boolean = old_value,
- .os_newval.boolean = value,
- .os_doskip = false,
- .os_errbuf = NULL,
- .os_errbuflen = 0,
- .os_buf = curbuf,
- .os_win = curwin
- };
+/// Process the updated 'previewwindow' option value.
+static const char *did_set_previewwindow(optset_T *args)
+{
+ win_T *win = (win_T *)args->os_win;
- errmsg = options[opt_idx].opt_did_set_cb(&args);
- doskip = args.os_doskip;
- }
- if (doskip) {
- return errmsg;
+ if (!win->w_p_pvw) {
+ return NULL;
}
- // after handling side effects, call autocommand
-
- options[opt_idx].flags |= P_WAS_SET;
+ // There can be only one window with 'previewwindow' set.
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_p_pvw && wp != win) {
+ win->w_p_pvw = false;
+ args->os_doskip = true;
+ return e_preview_window_already_exists;
+ }
+ }
- apply_optionset_autocmd(opt_idx, opt_flags,
- (long)(old_value ? true : false),
- (long)(old_global_value ? true : false),
- (long)(value ? true : false), NULL);
+ return NULL;
+}
- if (options[opt_idx].flags & P_UI_OPTION) {
- ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
- BOOLEAN_OBJ(*varp));
- }
- if ((int *)varp == &p_ru || (int *)varp == &p_sc) {
- // in case 'ruler' or 'showcmd' changed
- comp_col();
- }
- if (curwin->w_curswant != MAXCOL
- && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) {
- curwin->w_set_curswant = true;
+/// Process the new 'pumblend' option value.
+static const char *did_set_pumblend(optset_T *args FUNC_ATTR_UNUSED)
+{
+ p_pb = MAX(MIN(p_pb, 100), 0);
+ hl_invalidate_blends();
+ pum_grid.blending = (p_pb > 0);
+ if (pum_drawn()) {
+ pum_redraw();
}
- check_redraw(options[opt_idx].flags);
- return errmsg;
+ return NULL;
}
-/// Process the new 'winheight' value.
-static const char *did_set_winheight(optset_T *args)
+/// Process the updated 'readonly' option value.
+static const char *did_set_readonly(optset_T *args)
{
- // Change window height NOW
- if (!ONE_WINDOW) {
- win_T *win = (win_T *)args->os_win;
- if (win->w_height < p_wh) {
- win_setheight((int)p_wh);
- }
+ // when 'readonly' is reset globally, also reset readonlymode
+ if (!curbuf->b_p_ro && (args->os_flags & OPT_LOCAL) == 0) {
+ readonlymode = false;
+ }
+
+ // when 'readonly' is set may give W10 again
+ if (curbuf->b_p_ro) {
+ curbuf->b_did_warn = false;
}
+ redraw_titles();
+
return NULL;
}
-/// Process the new 'helpheight' option value.
-static const char *did_set_helpheight(optset_T *args)
+/// Process the new 'scrollback' option value.
+static const char *did_set_scrollback(optset_T *args)
{
- // Change window height NOW
- if (!ONE_WINDOW) {
- buf_T *buf = (buf_T *)args->os_buf;
- win_T *win = (win_T *)args->os_win;
- if (buf->b_help && win->w_height < p_hh) {
- win_setheight((int)p_hh);
- }
- }
+ buf_T *buf = (buf_T *)args->os_buf;
+ OptInt old_value = args->os_oldval.number;
+ OptInt value = args->os_newval.number;
+ if (buf->terminal && value < old_value) {
+ // Force the scrollback to take immediate effect only when decreasing it.
+ on_scrollback_option_changed(buf->terminal);
+ }
return NULL;
}
-/// Process the new 'winwidth' option value.
-static const char *did_set_winwidth(optset_T *args)
+/// Process the updated 'scrollbind' option value.
+static const char *did_set_scrollbind(optset_T *args)
{
win_T *win = (win_T *)args->os_win;
- if (!ONE_WINDOW && win->w_width < p_wiw) {
- win_setwidth((int)p_wiw);
+ // when 'scrollbind' is set: snapshot the current position to avoid a jump
+ // at the end of normal_cmd()
+ if (!win->w_p_scb) {
+ return NULL;
}
+ do_check_scrollbind(false);
+ win->w_scbind_pos = win->w_topline;
return NULL;
}
-/// Process the new 'laststatus' option value.
-static const char *did_set_laststatus(optset_T *args)
+#ifdef BACKSLASH_IN_FILENAME
+/// Process the updated 'shellslash' option value.
+static const char *did_set_shellslash(optset_T *args FUNC_ATTR_UNUSED)
{
- OptInt old_value = args->os_oldval.number;
- OptInt value = args->os_newval.number;
+ if (p_ssl) {
+ psepc = '/';
+ psepcN = '\\';
+ pseps[0] = '/';
+ } else {
+ psepc = '\\';
+ psepcN = '/';
+ pseps[0] = '\\';
+ }
- // When switching to global statusline, decrease topframe height
- // Also clear the cmdline to remove the ruler if there is one
- if (value == 3 && old_value != 3) {
- frame_new_height(topframe, topframe->fr_height - STATUS_HEIGHT, false, false);
- (void)win_comp_pos();
- clear_cmdline = true;
+ // need to adjust the file name arguments and buffer names.
+ buflist_slash_adjust();
+ alist_slash_adjust();
+ scriptnames_slash_adjust();
+ return NULL;
+}
+#endif
+
+/// Process the new 'shiftwidth' or the 'tabstop' option value.
+static const char *did_set_shiftwidth_tabstop(optset_T *args)
+{
+ buf_T *buf = (buf_T *)args->os_buf;
+ win_T *win = (win_T *)args->os_win;
+ OptInt *pp = (OptInt *)args->os_varp;
+
+ if (foldmethodIsIndent(win)) {
+ foldUpdateAll(win);
}
- // When switching from global statusline, increase height of topframe by STATUS_HEIGHT
- // in order to to re-add the space that was previously taken by the global statusline
- if (old_value == 3 && value != 3) {
- frame_new_height(topframe, topframe->fr_height + STATUS_HEIGHT, false, false);
- (void)win_comp_pos();
+ // When 'shiftwidth' changes, or it's zero and 'tabstop' changes:
+ // parse 'cinoptions'.
+ if (pp == &buf->b_p_sw || buf->b_p_sw == 0) {
+ parse_cino(buf);
}
- last_status(false); // (re)set last window status line.
return NULL;
}
@@ -2691,68 +2633,47 @@ static const char *did_set_smoothscroll(optset_T *args FUNC_ATTR_UNUSED)
return NULL;
}
-/// Process the new 'foldlevel' option value.
-static const char *did_set_foldlevel(optset_T *args FUNC_ATTR_UNUSED)
-{
- newFoldLevel();
- return NULL;
-}
-
-/// Process the new 'foldminlines' option value.
-static const char *did_set_foldminlines(optset_T *args)
-{
- win_T *win = (win_T *)args->os_win;
- foldUpdateAll(win);
- return NULL;
-}
-
-/// Process the new 'foldnestmax' option value.
-static const char *did_set_foldnestmax(optset_T *args)
+/// Process the updated 'spell' option value.
+static const char *did_set_spell(optset_T *args)
{
win_T *win = (win_T *)args->os_win;
- if (foldmethodIsSyntax(win) || foldmethodIsIndent(win)) {
- foldUpdateAll(win);
+ if (win->w_p_spell) {
+ return parse_spelllang(win);
}
+
return NULL;
}
-/// Process the new 'shiftwidth' or the 'tabstop' option value.
-static const char *did_set_shiftwidth_tabstop(optset_T *args)
+/// Process the updated 'swapfile' option value.
+static const char *did_set_swapfile(optset_T *args)
{
buf_T *buf = (buf_T *)args->os_buf;
- win_T *win = (win_T *)args->os_win;
- OptInt *pp = (OptInt *)args->os_varp;
-
- if (foldmethodIsIndent(win)) {
- foldUpdateAll(win);
- }
- // When 'shiftwidth' changes, or it's zero and 'tabstop' changes:
- // parse 'cinoptions'.
- if (pp == &buf->b_p_sw || buf->b_p_sw == 0) {
- parse_cino(buf);
+ // when 'swf' is set, create swapfile, when reset remove swapfile
+ if (buf->b_p_swf && p_uc) {
+ ml_open_file(buf); // create the swap file
+ } else {
+ // no need to reset curbuf->b_may_swap, ml_open_file() will check
+ // buf->b_p_swf
+ mf_close_file(buf, true); // remove the swap file
}
-
- return NULL;
-}
-
-/// Process the new 'iminset' option value.
-static const char *did_set_iminsert(optset_T *args FUNC_ATTR_UNUSED)
-{
- showmode();
- // Show/unshow value of 'keymap' in status lines.
- status_redraw_curbuf();
-
return NULL;
}
-/// Process the new 'window' option value.
-static const char *did_set_window(optset_T *args FUNC_ATTR_UNUSED)
+/// Process the new 'textwidth' option value.
+static const char *did_set_textwidth(optset_T *args FUNC_ATTR_UNUSED)
{
- if (p_window < 1) {
- p_window = Rows - 1;
- } else if (p_window >= Rows) {
- p_window = Rows - 1;
+ FOR_ALL_TAB_WINDOWS(tp, wp) {
+ check_colorcolumn(wp);
}
+
+ return NULL;
+}
+
+/// Process the updated 'title' or the 'icon' option value.
+static const char *did_set_title_icon(optset_T *args FUNC_ATTR_UNUSED)
+{
+ // when 'title' changed, may need to change the title; same for 'icon'
+ did_set_title();
return NULL;
}
@@ -2769,51 +2690,29 @@ static const char *did_set_titlelen(optset_T *args)
return NULL;
}
-/// Process the new 'cmdheight' option value.
-static const char *did_set_cmdheight(optset_T *args)
-{
- OptInt old_value = args->os_oldval.number;
-
- if (ui_has(kUIMessages)) {
- p_ch = 0;
- }
- if (p_ch > Rows - min_rows() + 1) {
- p_ch = Rows - min_rows() + 1;
- }
-
- // if p_ch changed value, change the command line height
- // Only compute the new window layout when startup has been
- // completed. Otherwise the frame sizes may be wrong.
- if ((p_ch != old_value
- || tabline_height() + global_stl_height() + topframe->fr_height != Rows - p_ch)
- && full_screen) {
- command_height();
- }
-
- return NULL;
-}
-
-/// Process the new 'updatecount' option value.
-static const char *did_set_updatecount(optset_T *args)
+/// Process the updated 'undofile' option value.
+static const char *did_set_undofile(optset_T *args)
{
- OptInt old_value = args->os_oldval.number;
-
- // when 'updatecount' changes from zero to non-zero, open swap files
- if (p_uc && !old_value) {
- ml_open_files();
+ // Only take action when the option was set.
+ if (!curbuf->b_p_udf && !p_udf) {
+ return NULL;
}
- return NULL;
-}
+ // When reset we do not delete the undo file, the option may be set again
+ // without making any changes in between.
+ uint8_t hash[UNDO_HASH_SIZE];
-/// Process the new 'pumblend' option value.
-static const char *did_set_pumblend(optset_T *args FUNC_ATTR_UNUSED)
-{
- p_pb = MAX(MIN(p_pb, 100), 0);
- hl_invalidate_blends();
- pum_grid.blending = (p_pb > 0);
- if (pum_drawn()) {
- pum_redraw();
+ FOR_ALL_BUFFERS(bp) {
+ // When 'undofile' is set globally: for every buffer, otherwise
+ // only for the current buffer: Try to read in the undofile,
+ // if one exists, the buffer wasn't changed and the buffer was
+ // loaded
+ if ((curbuf == bp
+ || (args->os_flags & OPT_GLOBAL) || args->os_flags == 0)
+ && !bufIsChanged(bp) && bp->b_ml.ml_mfp != NULL) {
+ u_compute_hash(bp, hash);
+ u_read_undo(NULL, hash, bp->b_fname);
+ }
}
return NULL;
@@ -2840,34 +2739,29 @@ const char *did_set_buflocal_undolevels(buf_T *buf, OptInt value, OptInt old_val
return NULL;
}
-/// Process the new 'scrollback' option value.
-static const char *did_set_scrollback(optset_T *args)
+/// Process the new 'undolevels' option value.
+static const char *did_set_undolevels(optset_T *args)
{
buf_T *buf = (buf_T *)args->os_buf;
- OptInt old_value = args->os_oldval.number;
- OptInt value = args->os_newval.number;
+ OptInt *pp = (OptInt *)args->os_varp;
- if (buf->terminal && value < old_value) {
- // Force the scrollback to take immediate effect only when decreasing it.
- on_scrollback_option_changed(buf->terminal);
+ if (pp == &p_ul) { // global 'undolevels'
+ did_set_global_undolevels(args->os_newval.number, args->os_oldval.number);
+ } else if (pp == &curbuf->b_p_ul) { // buffer local 'undolevels'
+ did_set_buflocal_undolevels(buf, args->os_newval.number, args->os_oldval.number);
}
- return NULL;
-}
-
-/// Process the new 'numberwidth' option value.
-static const char *did_set_numberwidth(optset_T *args)
-{
- win_T *win = (win_T *)args->os_win;
- win->w_nrwidth_line_count = 0; // trigger a redraw
return NULL;
}
-/// Process the new 'textwidth' option value.
-static const char *did_set_textwidth(optset_T *args FUNC_ATTR_UNUSED)
+/// Process the new 'updatecount' option value.
+static const char *did_set_updatecount(optset_T *args)
{
- FOR_ALL_TAB_WINDOWS(tp, wp) {
- check_colorcolumn(wp);
+ OptInt old_value = args->os_oldval.number;
+
+ // when 'updatecount' changes from zero to non-zero, open swap files
+ if (p_uc && !old_value) {
+ ml_open_files();
}
return NULL;
@@ -2889,21 +2783,143 @@ static const char *did_set_winblend(optset_T *args)
return NULL;
}
-/// Process the new 'undolevels' option value.
-static const char *did_set_undolevels(optset_T *args)
+/// Process the new 'window' option value.
+static const char *did_set_window(optset_T *args FUNC_ATTR_UNUSED)
{
- buf_T *buf = (buf_T *)args->os_buf;
- OptInt *pp = (OptInt *)args->os_varp;
+ if (p_window < 1) {
+ p_window = Rows - 1;
+ } else if (p_window >= Rows) {
+ p_window = Rows - 1;
+ }
+ return NULL;
+}
- if (pp == &p_ul) { // global 'undolevels'
- did_set_global_undolevels(args->os_newval.number, args->os_oldval.number);
- } else if (pp == &curbuf->b_p_ul) { // buffer local 'undolevels'
- did_set_buflocal_undolevels(buf, args->os_newval.number, args->os_oldval.number);
+/// Process the new 'winheight' value.
+static const char *did_set_winheight(optset_T *args)
+{
+ // Change window height NOW
+ if (!ONE_WINDOW) {
+ win_T *win = (win_T *)args->os_win;
+ if (win->w_height < p_wh) {
+ win_setheight((int)p_wh);
+ }
}
return NULL;
}
+/// Process the new 'winwidth' option value.
+static const char *did_set_winwidth(optset_T *args)
+{
+ win_T *win = (win_T *)args->os_win;
+
+ if (!ONE_WINDOW && win->w_width < p_wiw) {
+ win_setwidth((int)p_wiw);
+ }
+ return NULL;
+}
+
+/// Process the updated 'wrap' option value.
+static const char *did_set_wrap(optset_T *args)
+{
+ win_T *win = (win_T *)args->os_win;
+
+ // If 'wrap' is set, set w_leftcol to zero.
+ if (win->w_p_wrap) {
+ win->w_leftcol = 0;
+ }
+ return NULL;
+}
+
+/// Set the value of a boolean option, taking care of side effects
+///
+/// @param[in] opt_idx Option index in options[] table.
+/// @param[out] varp Pointer to the option variable.
+/// @param[in] value New value.
+/// @param[in] opt_flags OPT_LOCAL and/or OPT_GLOBAL.
+///
+/// @return NULL on success, error message on error.
+static const char *set_bool_option(const int opt_idx, char *const varp, const int value,
+ const int opt_flags)
+{
+ int old_value = *(int *)varp;
+ int old_global_value = 0;
+
+ // Disallow changing some options from secure mode
+ if ((secure || sandbox != 0)
+ && (options[opt_idx].flags & P_SECURE)) {
+ return e_secure;
+ }
+
+ // Save the global value before changing anything. This is needed as for
+ // a global-only option setting the "local value" in fact sets the global
+ // value (since there is only one value).
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
+ old_global_value = *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
+ }
+
+ *(int *)varp = value; // set the new value
+ // Remember where the option was set.
+ set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
+
+ // May set global value for local option.
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
+ *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = value;
+ }
+
+ // Handle side effects for changing a bool option.
+ const char *errmsg = NULL;
+ bool doskip = false;
+ if ((int *)varp == &p_force_on) {
+ errmsg = did_set_force_on(&doskip);
+ } else if ((int *)varp == &p_force_off) {
+ errmsg = did_set_force_off(&doskip);
+ } else if (options[opt_idx].opt_did_set_cb != NULL) {
+ optset_T args = {
+ .os_varp = varp,
+ .os_flags = opt_flags,
+ .os_oldval.boolean = old_value,
+ .os_newval.boolean = value,
+ .os_doskip = false,
+ .os_errbuf = NULL,
+ .os_errbuflen = 0,
+ .os_buf = curbuf,
+ .os_win = curwin
+ };
+
+ errmsg = options[opt_idx].opt_did_set_cb(&args);
+ doskip = args.os_doskip;
+ }
+ if (doskip) {
+ return errmsg;
+ }
+
+ // after handling side effects, call autocommand
+
+ options[opt_idx].flags |= P_WAS_SET;
+
+ apply_optionset_autocmd(opt_idx, opt_flags,
+ (long)(old_value ? true : false),
+ (long)(old_global_value ? true : false),
+ (long)(value ? true : false), NULL);
+
+ if (options[opt_idx].flags & P_UI_OPTION) {
+ ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
+ BOOLEAN_OBJ(*varp));
+ }
+ if ((int *)varp == &p_ru || (int *)varp == &p_sc) {
+ // in case 'ruler' or 'showcmd' changed
+ comp_col();
+ }
+ if (curwin->w_curswant != MAXCOL
+ && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) {
+ curwin->w_set_curswant = true;
+ }
+ check_redraw(options[opt_idx].flags);
+
+ return errmsg;
+}
+
/// Check the bounds of numeric options.
static const char *check_num_option_bounds(OptInt *pp, OptInt old_value, long old_Rows,
char *errbuf, size_t errbuflen, const char *errmsg)
@@ -5744,22 +5760,6 @@ void reset_option_was_set(const char *name)
options[idx].flags &= ~P_WAS_SET;
}
-/// Called when the 'breakat' option changes value.
-static const char *did_set_breakat(optset_T *args FUNC_ATTR_UNUSED)
-{
- for (int i = 0; i < 256; i++) {
- breakat_flags[i] = false;
- }
-
- if (p_breakat != NULL) {
- for (char *p = p_breakat; *p; p++) {
- breakat_flags[(uint8_t)(*p)] = true;
- }
- }
-
- return NULL;
-}
-
/// fill_culopt_flags() -- called when 'culopt' changes value
int fill_culopt_flags(char *val, win_T *wp)
{
diff --git 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 <SID> 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 <SID> 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);
+}