diff options
| author | Famiu Haque <famiuhaque@proton.me> | 2024-11-08 11:57:59 +0600 |
|---|---|---|
| committer | Famiu Haque <famiuhaque@proton.me> | 2024-12-26 20:55:13 +0600 |
| commit | 6257270040bc5c61a489f7fb9d4102223c36cf89 (patch) | |
| tree | a0db9a3bf31b56dedd9a240b54c5d47b02ce43ff /src | |
| parent | 98763ce4e93752f22d379e3f735f4c78ae49afad (diff) | |
| download | rneovim-6257270040bc5c61a489f7fb9d4102223c36cf89.tar.gz rneovim-6257270040bc5c61a489f7fb9d4102223c36cf89.tar.bz2 rneovim-6257270040bc5c61a489f7fb9d4102223c36cf89.zip | |
refactor(options): set option value for non-current context directly
Problem: Currently, we use `switch_option_context` to temporarily switch the current option context before setting an option for a different buffer / window. This is not ideal because we already support getting and setting option values for non-current contexts in the underlying implementation.
Solution: Set option value for non-current context by passing the context directly to the lower level functions. Also introduce a new `OptCtx` struct to store option context information, this will scale much better if we add more option scopes and other context information in the future.
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/api/deprecated.c | 10 | ||||
| -rw-r--r-- | src/nvim/api/options.c | 12 | ||||
| -rw-r--r-- | src/nvim/api/vim.c | 8 | ||||
| -rw-r--r-- | src/nvim/diff.c | 4 | ||||
| -rw-r--r-- | src/nvim/ex_docmd.c | 2 | ||||
| -rw-r--r-- | src/nvim/insexpand.c | 6 | ||||
| -rw-r--r-- | src/nvim/option.c | 760 | ||||
| -rw-r--r-- | src/nvim/option_defs.h | 18 | ||||
| -rw-r--r-- | src/nvim/optionstr.c | 60 | ||||
| -rw-r--r-- | src/nvim/tag.c | 2 | ||||
| -rw-r--r-- | src/nvim/winfloat.c | 4 |
11 files changed, 406 insertions, 480 deletions
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index d5eddb74de..47a49436ab 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -649,8 +649,8 @@ static Object get_option_from(void *from, OptScope scope, String name, Error *er OptVal value = NIL_OPTVAL; if (option_has_scope(opt_idx, scope)) { - value = get_option_value_for(opt_idx, scope == kOptScopeGlobal ? OPT_GLOBAL : OPT_LOCAL, - scope, from, err); + value = get_option_value_from(opt_idx, option_ctx_from(scope, from), + scope == kOptScopeGlobal ? OPT_GLOBAL : OPT_LOCAL); if (ERROR_SET(err)) { return (Object)OBJECT_INIT; } @@ -701,7 +701,11 @@ static void set_option_to(uint64_t channel_id, void *to, OptScope scope, String : ((scope == kOptScopeGlobal) ? OPT_GLOBAL : OPT_LOCAL); WITH_SCRIPT_CONTEXT(channel_id, { - set_option_value_for(name.data, opt_idx, optval, opt_flags, scope, to, err); + const char *errmsg + = set_option_value_for(opt_idx, optval, option_ctx_from(scope, to), opt_flags); + if (errmsg) { + api_set_error(err, kErrorTypeException, "%s", errmsg); + } }); } diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index 64f8a35d54..2bbbdbbe8c 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -157,8 +157,8 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) void *from = NULL; char *filetype = NULL; - if (!validate_option_value_args(opts, name.data, &opt_idx, &opt_flags, &scope, &from, - &filetype, err)) { + if (!validate_option_value_args(opts, name.data, &opt_idx, &opt_flags, &scope, &from, &filetype, + err)) { return (Object)OBJECT_INIT; } @@ -182,7 +182,7 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) from = ftbuf; } - OptVal value = get_option_value_for(opt_idx, opt_flags, scope, from, err); + OptVal value = get_option_value_from(opt_idx, option_ctx_from(scope, from), opt_flags); if (ftbuf != NULL) { // restore curwin/curbuf and a few other things @@ -257,7 +257,11 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict( }); WITH_SCRIPT_CONTEXT(channel_id, { - set_option_value_for(name.data, opt_idx, optval, opt_flags, scope, to, err); + const char *errmsg + = set_option_value_for(opt_idx, optval, option_ctx_from(scope, to), opt_flags); + if (errmsg) { + api_set_error(err, kErrorTypeException, "%s", errmsg); + } }); } diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 25f44bb4eb..108d1ee98d 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -982,10 +982,10 @@ Buffer nvim_create_buf(Boolean listed, Boolean scratch, Error *err) buf_copy_options(buf, BCO_ENTER | BCO_NOHELP); if (scratch) { - set_option_direct_for(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL, 0, - kOptScopeBuf, buf); - set_option_direct_for(kOptBuftype, STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL, 0, - kOptScopeBuf, buf); + set_option_direct_for(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("hide"), + option_ctx_from(kOptScopeBuf, buf), OPT_LOCAL, 0); + set_option_direct_for(kOptBuftype, STATIC_CSTR_AS_OPTVAL("nofile"), + option_ctx_from(kOptScopeBuf, buf), OPT_LOCAL, 0); assert(buf->b_ml.ml_mfp->mf_fd < 0); // ml_open() should not have opened swapfile already buf->b_p_swf = false; buf->b_p_ml = false; diff --git a/src/nvim/diff.c b/src/nvim/diff.c index bd98a31a71..ebeb9ba088 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -1391,8 +1391,8 @@ void diff_win_options(win_T *wp, bool addbuf) } wp->w_p_fdm_save = xstrdup(wp->w_p_fdm); } - set_option_direct_for(kOptFoldmethod, STATIC_CSTR_AS_OPTVAL("diff"), OPT_LOCAL, 0, - kOptScopeWin, wp); + set_option_direct_for(kOptFoldmethod, STATIC_CSTR_AS_OPTVAL("diff"), + option_ctx_from(kOptScopeWin, wp), OPT_LOCAL, 0); if (!wp->w_p_diff) { wp->w_p_fen_save = wp->w_p_fen; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 551e8fcb1d..8ee9967465 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5294,7 +5294,7 @@ static char *findfunc_find_file(char *findarg, size_t findarg_len, int count) /// Returns NULL on success and an error message on failure. const char *did_set_findfunc(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; + buf_T *buf = args->os_ctx.buf; int retval; if (args->os_flags & OPT_LOCAL) { diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 7245b0d6ce..908294872f 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -2398,7 +2398,7 @@ static void copy_global_to_buflocal_cb(Callback *globcb, Callback *bufcb) /// lambda expression. const char *did_set_completefunc(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; + buf_T *buf = args->os_ctx.buf; if (option_set_callback_func(buf->b_p_cfu, &cfu_cb) == FAIL) { return e_invarg; } @@ -2419,7 +2419,7 @@ void set_buflocal_cfu_callback(buf_T *buf) /// lambda expression. const char *did_set_omnifunc(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; + buf_T *buf = args->os_ctx.buf; if (option_set_callback_func(buf->b_p_ofu, &ofu_cb) == FAIL) { return e_invarg; } @@ -2440,7 +2440,7 @@ void set_buflocal_ofu_callback(buf_T *buf) /// lambda expression. const char *did_set_thesaurusfunc(optset_T *args FUNC_ATTR_UNUSED) { - buf_T *buf = (buf_T *)args->os_buf; + buf_T *buf = args->os_ctx.buf; int retval; if (args->os_flags & OPT_LOCAL) { diff --git a/src/nvim/option.c b/src/nvim/option.c index a59e55121f..b8f727cede 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1322,7 +1322,8 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char * return; } - *errmsg = set_option(opt_idx, newval, opt_flags, 0, false, op == OP_NONE, errbuf, errbuflen); + *errmsg = set_option_for(opt_idx, newval, option_ctx(), opt_flags, 0, false, + op == OP_NONE, errbuf, errbuflen); } /// Parse 'arg' for option settings. @@ -1842,7 +1843,7 @@ void set_option_sctx(OptIndex opt_idx, int opt_flags, sctx_T script_ctx) /// Apply the OptionSet autocommand. static void apply_optionset_autocmd(OptIndex opt_idx, int opt_flags, OptVal oldval, OptVal oldval_g, - OptVal oldval_l, OptVal newval, const char *errmsg) + OptVal oldval_l, OptVal newval, OptCtx ctx, const char *errmsg) { // Don't do this while starting up, failure or recursively. if (starting || errmsg != NULL || *get_vim_var_str(VV_OPTION_TYPE) != NUL) { @@ -1876,14 +1877,18 @@ static void apply_optionset_autocmd(OptIndex opt_idx, int opt_flags, OptVal oldv set_vim_var_string(VV_OPTION_COMMAND, "modeline", -1); set_vim_var_tv(VV_OPTION_OLDLOCAL, &oldval_tv); } - apply_autocmds(EVENT_OPTIONSET, options[opt_idx].fullname, NULL, false, NULL); + + WITH_AUCMD_CONTEXT(ctx, { + apply_autocmds(EVENT_OPTIONSET, options[opt_idx].fullname, NULL, false, NULL); + }); + reset_v_option_vars(); } /// Process the updated 'arabic' option value. static const char *did_set_arabic(optset_T *args) { - win_T *win = (win_T *)args->os_win; + win_T *win = args->os_ctx.win; const char *errmsg = NULL; if (win->w_p_arab) { @@ -1952,7 +1957,7 @@ static const char *did_set_autochdir(optset_T *args FUNC_ATTR_UNUSED) /// Process the updated 'binary' option value. static const char *did_set_binary(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; + buf_T *buf = args->os_ctx.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); @@ -1964,7 +1969,7 @@ static const char *did_set_binary(optset_T *args) /// Process the updated 'buflisted' option value. static const char *did_set_buflisted(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; + buf_T *buf = args->os_ctx.buf; // when 'buflisted' changes, trigger autocommands if (args->os_oldval.boolean != buf->b_p_bl) { @@ -1998,7 +2003,7 @@ static const char *did_set_cmdheight(optset_T *args) /// Process the updated 'diff' option value. static const char *did_set_diff(optset_T *args) { - win_T *win = (win_T *)args->os_win; + win_T *win = args->os_ctx.win; // May add or remove the buffer from the list of diff buffers. diff_buf_adjust(win); if (foldmethodIsDiff(win)) { @@ -2019,7 +2024,7 @@ static const char *did_set_eof_eol_fixeol_bomb(optset_T *args FUNC_ATTR_UNUSED) /// Process the updated 'equalalways' option value. static const char *did_set_equalalways(optset_T *args) { - win_T *win = (win_T *)args->os_win; + win_T *win = args->os_ctx.win; if (p_ea && !args->os_oldval.boolean) { win_equal(win, false, 0); } @@ -2037,7 +2042,7 @@ static const char *did_set_foldlevel(optset_T *args FUNC_ATTR_UNUSED) /// Process the new 'foldminlines' option value. static const char *did_set_foldminlines(optset_T *args) { - win_T *win = (win_T *)args->os_win; + win_T *win = args->os_ctx.win; foldUpdateAll(win); return NULL; } @@ -2045,7 +2050,7 @@ static const char *did_set_foldminlines(optset_T *args) /// Process the new 'foldnestmax' option value. static const char *did_set_foldnestmax(optset_T *args) { - win_T *win = (win_T *)args->os_win; + win_T *win = args->os_ctx.win; if (foldmethodIsSyntax(win) || foldmethodIsIndent(win)) { foldUpdateAll(win); } @@ -2174,7 +2179,7 @@ static const char *did_set_lines_or_columns(optset_T *args) /// Process the updated 'lisp' option value. static const char *did_set_lisp(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; + buf_T *buf = args->os_ctx.buf; // When 'lisp' option changes include/exclude '-' in keyword characters. buf_init_chartab(buf, false); // ignore errors return NULL; @@ -2192,7 +2197,7 @@ static const char *did_set_modifiable(optset_T *args FUNC_ATTR_UNUSED) /// Process the updated 'modified' option value. static const char *did_set_modified(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; + buf_T *buf = args->os_ctx.buf; if (!args->os_newval.boolean) { save_file_ff(buf); // Buffer is unchanged } @@ -2204,7 +2209,7 @@ static const char *did_set_modified(optset_T *args) /// 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; + win_T *win = args->os_ctx.win; if (*win->w_p_stc != NUL) { // When 'relativenumber'/'number' is changed and 'statuscolumn' is set, reset width. win->w_nrwidth_line_count = 0; @@ -2216,7 +2221,7 @@ static const char *did_set_number_relativenumber(optset_T *args) /// Process the new 'numberwidth' option value. static const char *did_set_numberwidth(optset_T *args) { - win_T *win = (win_T *)args->os_win; + win_T *win = args->os_ctx.win; win->w_nrwidth_line_count = 0; // trigger a redraw return NULL; @@ -2354,7 +2359,7 @@ static const char *did_set_paste(optset_T *args FUNC_ATTR_UNUSED) /// Process the updated 'previewwindow' option value. static const char *did_set_previewwindow(optset_T *args) { - win_T *win = (win_T *)args->os_win; + win_T *win = args->os_ctx.win; if (!win->w_p_pvw) { return NULL; @@ -2386,7 +2391,7 @@ static const char *did_set_pumblend(optset_T *args FUNC_ATTR_UNUSED) /// Process the updated 'readonly' option value. static const char *did_set_readonly(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; + buf_T *buf = args->os_ctx.buf; // when 'readonly' is reset globally, also reset readonlymode if (!buf->b_p_ro && (args->os_flags & OPT_LOCAL) == 0) { @@ -2406,7 +2411,7 @@ static const char *did_set_readonly(optset_T *args) /// Process the new 'scrollback' option value. static const char *did_set_scrollback(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; + buf_T *buf = args->os_ctx.buf; OptInt old_value = args->os_oldval.number; OptInt value = args->os_newval.number; @@ -2420,7 +2425,7 @@ static const char *did_set_scrollback(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; + win_T *win = args->os_ctx.win; // when 'scrollbind' is set: snapshot the current position to avoid a jump // at the end of normal_cmd() @@ -2457,8 +2462,8 @@ static const char *did_set_shellslash(optset_T *args FUNC_ATTR_UNUSED) /// 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; + buf_T *buf = args->os_ctx.buf; + win_T *win = args->os_ctx.win; OptInt *pp = (OptInt *)args->os_varp; if (foldmethodIsIndent(win)) { @@ -2484,7 +2489,7 @@ static const char *did_set_showtabline(optset_T *args FUNC_ATTR_UNUSED) /// Process the updated 'smoothscroll' option value. static const char *did_set_smoothscroll(optset_T *args FUNC_ATTR_UNUSED) { - win_T *win = (win_T *)args->os_win; + win_T *win = args->os_ctx.win; if (!win->w_p_sms) { win->w_skipcol = 0; } @@ -2495,7 +2500,7 @@ static const char *did_set_smoothscroll(optset_T *args FUNC_ATTR_UNUSED) /// Process the updated 'spell' option value. static const char *did_set_spell(optset_T *args) { - win_T *win = (win_T *)args->os_win; + win_T *win = args->os_ctx.win; if (win->w_p_spell) { return parse_spelllang(win); } @@ -2506,7 +2511,7 @@ static const char *did_set_spell(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; + buf_T *buf = args->os_ctx.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 @@ -2551,7 +2556,7 @@ static const char *did_set_titlelen(optset_T *args) /// Process the updated 'undofile' option value. static const char *did_set_undofile(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; + buf_T *buf = args->os_ctx.buf; // Only take action when the option was set. if (!buf->b_p_udf && !p_udf) { @@ -2602,7 +2607,7 @@ const char *did_set_buflocal_undolevels(buf_T *buf, OptInt value, OptInt old_val /// Process the new 'undolevels' option value. static const char *did_set_undolevels(optset_T *args) { - buf_T *buf = (buf_T *)args->os_buf; + buf_T *buf = args->os_ctx.buf; OptInt *pp = (OptInt *)args->os_varp; if (pp == &p_ul) { // global 'undolevels' @@ -2643,7 +2648,7 @@ static const char *did_set_wildchar(optset_T *args) /// Process the new 'winblend' option value. static const char *did_set_winblend(optset_T *args) { - win_T *win = (win_T *)args->os_win; + win_T *win = args->os_ctx.win; OptInt old_value = args->os_oldval.number; OptInt value = args->os_newval.number; @@ -2692,7 +2697,7 @@ static const char *did_set_winwidth(optset_T *args) /// Process the updated 'wrap' option value. static const char *did_set_wrap(optset_T *args) { - win_T *win = (win_T *)args->os_win; + win_T *win = args->os_ctx.win; // Set w_leftcol or w_skipcol to zero. if (win->w_p_wrap) { win->w_leftcol = 0; @@ -3143,12 +3148,6 @@ static OptValType option_get_type(const OptIndex opt_idx) OptVal optval_from_varp(OptIndex opt_idx, void *varp) FUNC_ATTR_NONNULL_ARG(2) { - // Special case: 'modified' is b_changed, but we also want to consider it set when 'ff' or 'fenc' - // changed. - if ((int *)varp == &curbuf->b_changed) { - return BOOLEAN_OPTVAL(curbufIsChanged()); - } - if (option_is_multitype(opt_idx)) { // Multitype options are stored as OptVal. return *(OptVal *)varp; @@ -3381,21 +3380,37 @@ uint32_t get_option_flags(OptIndex opt_idx) /// Gets the value for an option. /// /// @param opt_idx Option index in options[] table. +/// @param ctx Context to get the option value from. /// @param opt_flags Option flags (can be OPT_LOCAL, OPT_GLOBAL or a combination). /// /// @return [allocated] Option value. Returns NIL_OPTVAL for invalid option index. -OptVal get_option_value(OptIndex opt_idx, int opt_flags) +OptVal get_option_value_from(OptIndex opt_idx, OptCtx ctx, int opt_flags) { if (opt_idx == kOptInvalid) { // option not in the options[] table. return NIL_OPTVAL; } - vimoption_T *opt = &options[opt_idx]; - void *varp = get_varp_scope(opt, opt_flags); + // Special case: 'modified' is b_changed, but we also want to consider it set when 'ff' or 'fenc' + // changed. + if (opt_idx == kOptModified) { + return BOOLEAN_OPTVAL(bufIsChanged(ctx.buf)); + } + void * const varp = get_varp_scope_from(&options[opt_idx], opt_flags, ctx); return optval_copy(optval_from_varp(opt_idx, varp)); } +/// Gets the value for an option in the current context. +/// +/// @param opt_idx Option index in options[] table. +/// @param opt_flags Option flags (can be OPT_LOCAL, OPT_GLOBAL or a combination). +/// +/// @return [allocated] Option value. Returns NIL_OPTVAL for invalid option index. +OptVal get_option_value(OptIndex opt_idx, int opt_flags) +{ + return get_option_value_from(opt_idx, option_ctx(), opt_flags); +} + /// Return information for option at 'opt_idx' vimoption_T *get_option(OptIndex opt_idx) { @@ -3464,6 +3479,8 @@ static bool is_option_local_value_unset(OptIndex opt_idx) /// @param opt_idx Index in options[] table. Must not be kOptInvalid. /// @param[in] varp Option variable pointer, cannot be NULL. /// @param old_value Old option value. +/// @param new_value New option value. +/// @param ctx Context in which the option is set. /// @param opt_flags Option flags (can be OPT_LOCAL, OPT_GLOBAL or a combination). /// @param set_sid Script ID. Special values: /// 0: Use current script ID. @@ -3475,8 +3492,9 @@ static bool is_option_local_value_unset(OptIndex opt_idx) /// /// @return NULL on success, an untranslated error message on error. static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value, OptVal new_value, - int opt_flags, scid_T set_sid, const bool direct, - const bool value_replaced, char *errbuf, size_t errbuflen) + OptCtx ctx, int opt_flags, scid_T set_sid, const bool direct, + const bool value_replaced, char *errbuf, // NOLINT(readability-non-const-parameter) + size_t errbuflen) { vimoption_T *opt = &options[opt_idx]; const char *errmsg = NULL; @@ -3495,8 +3513,7 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value .os_restore_chartab = false, .os_errbuf = errbuf, .os_errbuflen = errbuflen, - .os_buf = curbuf, - .os_win = curwin + .os_ctx = ctx, }; if (direct) { @@ -3533,7 +3550,7 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value set_option_varp(opt_idx, varp, old_value, true); // When resetting some values, need to act on it. if (restore_chartab) { - buf_init_chartab(curbuf, true); + buf_init_chartab(ctx.buf, true); } return errmsg; @@ -3564,12 +3581,12 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value if (option_is_global_local(opt_idx)) { // Global option with local value set to use global value. // Free the local value and clear it. - void *varp_local = get_varp_scope(opt, OPT_LOCAL); + void *varp_local = get_varp_scope_from(opt, OPT_LOCAL, ctx); OptVal local_unset_value = get_option_unset_value(opt_idx); set_option_varp(opt_idx, varp_local, optval_copy(local_unset_value), true); } else { // May set global value for local option. - void *varp_global = get_varp_scope(opt, OPT_GLOBAL); + void *varp_global = get_varp_scope_from(opt, OPT_GLOBAL, ctx); set_option_varp(opt_idx, varp_global, optval_copy(new_value), true); } } @@ -3580,17 +3597,23 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value } // Trigger the autocommand only after setting the flags. - if (varp == &curbuf->b_p_syn) { - do_syntax_autocmd(curbuf, value_changed); - } else if (varp == &curbuf->b_p_ft) { + if (varp == &ctx.buf->b_p_syn) { + WITH_AUCMD_CONTEXT(ctx, { + do_syntax_autocmd(ctx.buf, value_changed); + }); + } else if (varp == &ctx.buf->b_p_ft) { // 'filetype' is set, trigger the FileType autocommand // Skip this when called from a modeline // Force autocmd when the filetype was changed if (!(opt_flags & OPT_MODELINE) || value_changed) { - do_filetype_autocmd(curbuf, value_changed); + WITH_AUCMD_CONTEXT(ctx, { + do_filetype_autocmd(ctx.buf, value_changed); + }); } - } else if (varp == &curwin->w_s->b_p_spl) { - do_spelllang_source(curwin); + } else if (varp == &ctx.win->w_s->b_p_spl) { + WITH_AUCMD_CONTEXT(ctx, { + do_spelllang_source(ctx.win); + }); } // In case 'ruler' or 'showcmd' or 'columns' or 'ls' changed. @@ -3598,25 +3621,25 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value if (varp == &p_mouse) { setmouse(); // in case 'mouse' changed - } else if ((varp == &p_flp || varp == &(curbuf->b_p_flp)) && curwin->w_briopt_list) { + } else if ((varp == &p_flp || varp == &(ctx.buf->b_p_flp)) && ctx.win->w_briopt_list) { // Changing Formatlistpattern when briopt includes the list setting: // redraw redraw_all_later(UPD_NOT_VALID); - } else if (varp == &p_wbr || varp == &(curwin->w_p_wbr)) { + } else if (varp == &p_wbr || varp == &(ctx.win->w_p_wbr)) { // add / remove window bars for 'winbar' set_winbar(true); } - if (curwin->w_curswant != MAXCOL + if (ctx.win->w_curswant != MAXCOL && (opt->flags & (kOptFlagCurswant | kOptFlagRedrAll)) != 0 && (opt->flags & kOptFlagHLOnly) == 0) { - curwin->w_set_curswant = true; + ctx.win->w_set_curswant = true; } - check_redraw(opt->flags); + check_redraw_for(ctx.buf, ctx.win, opt->flags); if (errmsg == NULL) { - uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags); + uint32_t *p = insecure_flag(ctx.win, opt_idx, opt_flags); opt->flags |= kOptFlagWasSet; // When an option is set in the sandbox, from a modeline or in secure mode set the kOptFlagInsecure @@ -3676,6 +3699,7 @@ static const char *validate_option_value(const OptIndex opt_idx, OptVal *newval, /// /// @param opt_idx Index in options[] table. Must not be kOptInvalid. /// @param value New option value. Might get freed. +/// @param ctx Context in which the option is set. /// @param opt_flags Option flags (can be OPT_LOCAL, OPT_GLOBAL or a combination). /// @param set_sid Script ID. Special values: /// 0: Use current script ID. @@ -3686,9 +3710,9 @@ static const char *validate_option_value(const OptIndex opt_idx, OptVal *newval, /// @param errbuflen Length of error buffer. /// /// @return NULL on success, an untranslated error message on error. -static const char *set_option(const OptIndex opt_idx, OptVal value, int opt_flags, scid_T set_sid, - const bool direct, const bool value_replaced, char *errbuf, - size_t errbuflen) +static const char *set_option_for(OptIndex opt_idx, OptVal value, OptCtx ctx, int opt_flags, + scid_T set_sid, const bool direct, const bool value_replaced, + char *errbuf, size_t errbuflen) { assert(opt_idx != kOptInvalid); @@ -3713,10 +3737,11 @@ static const char *set_option(const OptIndex opt_idx, OptVal value, int opt_flag // When using ":set opt=val" for a global option with a local value the local value will be reset, // use the global value in that case. - void *varp - = scope_both && option_is_global_local(opt_idx) ? opt->var : get_varp_scope(opt, opt_flags); - void *varp_local = get_varp_scope(opt, OPT_LOCAL); - void *varp_global = get_varp_scope(opt, OPT_GLOBAL); + void *varp = scope_both && option_is_global_local(opt_idx) + ? opt->var + : get_varp_scope_from(opt, opt_flags, ctx); + void *varp_local = get_varp_scope_from(opt, OPT_LOCAL, ctx); + void *varp_global = get_varp_scope_from(opt, OPT_GLOBAL, ctx); OptVal old_value = optval_from_varp(opt_idx, varp); OptVal old_global_value = optval_from_varp(opt_idx, varp_global); @@ -3729,7 +3754,7 @@ static const char *set_option(const OptIndex opt_idx, OptVal value, int opt_flag // unset. In every other case, it is the same as old_value. // This value is used instead of old_value when triggering the OptionSet autocommand. OptVal used_old_value = (scope_local && is_opt_local_unset) - ? optval_from_varp(opt_idx, get_varp(opt)) + ? optval_from_varp(opt_idx, get_varp_from(opt, ctx)) : old_value; // Save the old values and the new value in case they get changed. @@ -3739,7 +3764,7 @@ static const char *set_option(const OptIndex opt_idx, OptVal value, int opt_flag // New value (and varp) may become invalid if the buffer is closed by autocommands. OptVal saved_new_value = optval_copy(value); - uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags); + uint32_t *p = insecure_flag(ctx.win, opt_idx, opt_flags); const int secure_saved = secure; // When an option is set in the sandbox, from a modeline or in secure mode, then deal with side @@ -3752,7 +3777,7 @@ static const char *set_option(const OptIndex opt_idx, OptVal value, int opt_flag // Set option through its variable pointer. set_option_varp(opt_idx, varp, value, false); // Process any side effects. - errmsg = did_set_option(opt_idx, varp, old_value, value, opt_flags, set_sid, direct, + errmsg = did_set_option(opt_idx, varp, old_value, value, ctx, opt_flags, set_sid, direct, value_replaced, errbuf, errbuflen); secure = secure_saved; @@ -3760,7 +3785,7 @@ static const char *set_option(const OptIndex opt_idx, OptVal value, int opt_flag if (errmsg == NULL && !direct) { if (!starting) { apply_optionset_autocmd(opt_idx, opt_flags, saved_used_value, saved_old_global_value, - saved_old_local_value, saved_new_value, errmsg); + saved_old_local_value, saved_new_value, ctx, errmsg); } if (opt->flags & kOptFlagUIOption) { ui_call_option_set(cstr_as_string(opt->fullname), optval_as_object(saved_new_value)); @@ -3780,11 +3805,13 @@ static const char *set_option(const OptIndex opt_idx, OptVal value, int opt_flag /// /// @param opt_idx Option index in options[] table. /// @param value Option value. +/// @param ctx Context in which the option is set. /// @param opt_flags Option flags (can be OPT_LOCAL, OPT_GLOBAL or a combination). /// @param set_sid Script ID. Special values: /// 0: Use current script ID. /// SID_NONE: Don't set script ID. -void set_option_direct(OptIndex opt_idx, OptVal value, int opt_flags, scid_T set_sid) +void set_option_direct_for(OptIndex opt_idx, OptVal value, OptCtx ctx, int opt_flags, + scid_T set_sid) { static char errbuf[IOSIZE]; @@ -3792,57 +3819,35 @@ void set_option_direct(OptIndex opt_idx, OptVal value, int opt_flags, scid_T set return; } - const char *errmsg = set_option(opt_idx, optval_copy(value), opt_flags, set_sid, true, true, - errbuf, sizeof(errbuf)); + const char *errmsg = set_option_for(opt_idx, optval_copy(value), ctx, opt_flags, set_sid, true, + true, errbuf, sizeof(errbuf)); assert(errmsg == NULL); (void)errmsg; // ignore unused warning } -/// Set option value directly for buffer / window, without processing any side effects. +/// Set option value for current context directly, without processing any side effects. /// -/// @param opt_idx Option index in options[] table. -/// @param value Option value. -/// @param opt_flags Option flags (can be OPT_LOCAL, OPT_GLOBAL or a combination). -/// @param set_sid Script ID. Special values: -/// 0: Use current script ID. -/// SID_NONE: Don't set script ID. -/// @param scope Option scope. See OptScope in option.h. -/// @param[in] from Target buffer/window. -void set_option_direct_for(OptIndex opt_idx, OptVal value, int opt_flags, scid_T set_sid, - OptScope scope, void *const from) -{ - buf_T *save_curbuf = curbuf; - win_T *save_curwin = curwin; - - // Don't use switch_option_context(), as that calls aucmd_prepbuf(), which may have unintended - // side-effects when setting an option directly. Just change the values of curbuf and curwin if - // needed, no need to properly switch the window / buffer. - switch (scope) { - case kOptScopeGlobal: - break; - case kOptScopeWin: - curwin = (win_T *)from; - curbuf = curwin->w_buffer; - break; - case kOptScopeBuf: - curbuf = (buf_T *)from; - break; - } - - set_option_direct(opt_idx, value, opt_flags, set_sid); - - curwin = save_curwin; - curbuf = save_curbuf; +/// @param opt_idx Option index in options[] table. +/// @param value Option value. +/// @param ctx Context in which the option is set. +/// @param opt_flags Option flags (can be OPT_LOCAL, OPT_GLOBAL or a combination). +/// @param set_sid Script ID. Special values: +/// 0: Use current script ID. +/// SID_NONE: Don't set script ID. +void set_option_direct(OptIndex opt_idx, OptVal value, int opt_flags, scid_T set_sid) +{ + set_option_direct_for(opt_idx, value, option_ctx(), opt_flags, set_sid); } /// Set the value of an option. /// /// @param opt_idx Index in options[] table. Must not be kOptInvalid. /// @param[in] value Option value. If NIL_OPTVAL, the option value is cleared. +/// @param ctx Context to set option for. /// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both). /// /// @return NULL on success, an untranslated error message on error. -const char *set_option_value(const OptIndex opt_idx, const OptVal value, int opt_flags) +const char *set_option_value_for(OptIndex opt_idx, OptVal value, OptCtx ctx, int opt_flags) { assert(opt_idx != kOptInvalid); @@ -3854,7 +3859,21 @@ const char *set_option_value(const OptIndex opt_idx, const OptVal value, int opt return _(e_sandbox); } - return set_option(opt_idx, optval_copy(value), opt_flags, 0, false, true, errbuf, sizeof(errbuf)); + return set_option_for(opt_idx, optval_copy(value), ctx, opt_flags, 0, false, true, errbuf, + sizeof(errbuf)); +} + +/// Set the value of an option for current context. +/// +/// @param opt_idx Index in options[] table. Must not be kOptInvalid. +/// @param[in] value Option value. If NIL_OPTVAL, the option value is cleared. +/// @param ctx Context to set option for. +/// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both). +/// +/// @return NULL on success, an untranslated error message on error. +const char *set_option_value(OptIndex opt_idx, OptVal value, int opt_flags) +{ + return set_option_value_for(opt_idx, value, option_ctx(), opt_flags); } /// Unset the local value of a global-local option. @@ -3910,135 +3929,6 @@ void set_option_value_give_err(const OptIndex opt_idx, OptVal value, int opt_fla } } -/// Switch current context to get/set option value for window/buffer. -/// -/// @param[out] ctx Current context. switchwin_T for window and aco_save_T for buffer. -/// @param scope Option scope. See OptScope in option.h. -/// @param[in] from Target buffer/window. -/// @param[out] err Error message, if any. -/// -/// @return true if context was switched, false otherwise. -static bool switch_option_context(void *const ctx, OptScope scope, void *const from, Error *err) -{ - switch (scope) { - case kOptScopeGlobal: - return false; - case kOptScopeWin: { - win_T *const win = (win_T *)from; - switchwin_T *const switchwin = (switchwin_T *)ctx; - - if (win == curwin) { - return false; - } - - if (switch_win_noblock(switchwin, win, win_find_tabpage(win), true) - == FAIL) { - restore_win_noblock(switchwin, true); - - if (ERROR_SET(err)) { - return false; - } - api_set_error(err, kErrorTypeException, "Problem while switching windows"); - return false; - } - return true; - } - case kOptScopeBuf: { - buf_T *const buf = (buf_T *)from; - aco_save_T *const aco = (aco_save_T *)ctx; - - if (buf == curbuf) { - return false; - } - aucmd_prepbuf(aco, buf); - return true; - } - } - UNREACHABLE; -} - -/// Restore context after getting/setting option for window/buffer. See switch_option_context() for -/// params. -static void restore_option_context(void *const ctx, OptScope scope) -{ - switch (scope) { - case kOptScopeGlobal: - break; |