aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2025-01-09 12:32:25 +0800
committerGitHub <noreply@github.com>2025-01-09 12:32:25 +0800
commit19c9572d3626cde8503ee9061fa334b73f257b03 (patch)
tree9ac8478d974b5abd3a3a662348a4c7f58cc645db
parent822313e42b5b8d51ea0b3f1f97c47026f2c7e2e2 (diff)
downloadrneovim-19c9572d3626cde8503ee9061fa334b73f257b03.tar.gz
rneovim-19c9572d3626cde8503ee9061fa334b73f257b03.tar.bz2
rneovim-19c9572d3626cde8503ee9061fa334b73f257b03.zip
Revert "refactor(options): set option value for non-current context directly" (#31924)
Reverts #31112
-rw-r--r--src/nvim/api/deprecated.c10
-rw-r--r--src/nvim/api/options.c12
-rw-r--r--src/nvim/api/vim.c8
-rw-r--r--src/nvim/autocmd.c172
-rw-r--r--src/nvim/autocmd_defs.h22
-rw-r--r--src/nvim/diff.c4
-rw-r--r--src/nvim/ex_docmd.c2
-rw-r--r--src/nvim/insexpand.c6
-rw-r--r--src/nvim/option.c760
-rw-r--r--src/nvim/option_defs.h18
-rw-r--r--src/nvim/optionstr.c60
-rw-r--r--src/nvim/tag.c2
-rw-r--r--src/nvim/winfloat.c4
-rw-r--r--test/functional/lua/with_spec.lua6
14 files changed, 557 insertions, 529 deletions
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c
index 47a49436ab..d5eddb74de 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_from(opt_idx, option_ctx_from(scope, from),
- scope == kOptScopeGlobal ? OPT_GLOBAL : OPT_LOCAL);
+ value = get_option_value_for(opt_idx, scope == kOptScopeGlobal ? OPT_GLOBAL : OPT_LOCAL,
+ scope, from, err);
if (ERROR_SET(err)) {
return (Object)OBJECT_INIT;
}
@@ -701,11 +701,7 @@ 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, {
- 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);
- }
+ set_option_value_for(name.data, opt_idx, optval, opt_flags, scope, to, err);
});
}
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c
index 2bbbdbbe8c..64f8a35d54 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_from(opt_idx, option_ctx_from(scope, from), opt_flags);
+ OptVal value = get_option_value_for(opt_idx, opt_flags, scope, from, err);
if (ftbuf != NULL) {
// restore curwin/curbuf and a few other things
@@ -257,11 +257,7 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict(
});
WITH_SCRIPT_CONTEXT(channel_id, {
- 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);
- }
+ set_option_value_for(name.data, opt_idx, optval, opt_flags, scope, to, err);
});
}
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 46e6b24c75..e3e69f4ff6 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -983,10 +983,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"),
- 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);
+ 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);
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/autocmd.c b/src/nvim/autocmd.c
index aab09de6b4..eb7c8c2880 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -1251,82 +1251,56 @@ bool check_nomodeline(char **argp)
return true;
}
-/// Prepare for executing autocommands for (hidden) buffer `buf` on window `win`
-/// If the buffer of `win` is not `buf`, switch the buffer of `win` to `buf` temporarily.
+/// Prepare for executing autocommands for (hidden) buffer `buf`.
+/// If the current buffer is not in any visible window, put it in a temporary
+/// floating window using an entry in `aucmd_win[]`.
+/// Set `curbuf` and `curwin` to match `buf`.
///
-/// @param aco Structure to save values in.
-/// @param buf New curbuf.
-/// @param win New curwin.
-void aucmd_prepbuf_win(aco_save_T *aco, buf_T *buf, win_T *win)
+/// @param aco structure to save values in
+/// @param buf new curbuf
+void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
{
- bool need_append = false; // Append `aucmd_win` to the window list.
- int auc_idx = -1; // Index of aucmd_win[] to use. -1 if not using aucmd_win[].
-
- aco->save_curtab_handle = -1;
- aco->save_buf_handle = -1;
+ win_T *win;
+ bool need_append = true; // Append `aucmd_win` to the window list.
- if (win == NULL) {
- // Window not provided. Find a window that is for the new buffer
- if (buf == curbuf) { // be quick when buf is curbuf
- win = curwin;
- } else {
- win = NULL;
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer == buf) {
- win = wp;
- break;
- }
+ // Find a window that is for the new buffer
+ if (buf == curbuf) { // be quick when buf is curbuf
+ win = curwin;
+ } else {
+ win = NULL;
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_buffer == buf) {
+ win = wp;
+ break;
}
}
+ }
- // Allocate a window when needed.
- if (win == NULL) {
- for (auc_idx = 0; auc_idx < AUCMD_WIN_COUNT; auc_idx++) {
- if (!aucmd_win[auc_idx].auc_win_used) {
- break;
- }
- }
-
- if (auc_idx == AUCMD_WIN_COUNT) {
- kv_push(aucmd_win_vec, ((aucmdwin_T){
- .auc_win = NULL,
- .auc_win_used = false,
- }));
- }
-
- if (aucmd_win[auc_idx].auc_win == NULL) {
- win_alloc_aucmd_win(auc_idx);
- } else {
- need_append = true;
+ // Allocate a window when needed.
+ win_T *auc_win = NULL;
+ int auc_idx = AUCMD_WIN_COUNT;
+ if (win == NULL) {
+ for (auc_idx = 0; auc_idx < AUCMD_WIN_COUNT; auc_idx++) {
+ if (!aucmd_win[auc_idx].auc_win_used) {
+ break;
}
- win = aucmd_win[auc_idx].auc_win;
- aucmd_win[auc_idx].auc_win_used = true;
}
- } else {
- tabpage_T *tp = win_find_tabpage(win);
- // If the window is in another tab page, switch to that tab page temporarily.
- if (tp != curtab) {
- aco->save_curtab_handle = curtab->handle;
- unuse_tabpage(curtab);
- use_tabpage(tp);
+ if (auc_idx == AUCMD_WIN_COUNT) {
+ kv_push(aucmd_win_vec, ((aucmdwin_T){
+ .auc_win = NULL,
+ .auc_win_used = false,
+ }));
}
- }
- // If the buffer of the window is not the target buffer, switch to it temporarily.
- if (win->w_buffer != buf) {
- if (auc_idx == -1) {
- // No need to store old buffer for aucmd_win[].
- aco->save_buf_handle = win->w_buffer->handle;
- win->w_buffer->b_nwindows--;
+ if (aucmd_win[auc_idx].auc_win == NULL) {
+ win_alloc_aucmd_win(auc_idx);
+ need_append = false;
}
-
- win->w_buffer = buf;
- win->w_s = &buf->b_s;
- buf->b_nwindows++;
+ auc_win = aucmd_win[auc_idx].auc_win;
+ aucmd_win[auc_idx].auc_win_used = true;
}
- aco->use_aucmd_win_idx = auc_idx;
aco->save_curwin_handle = curwin->handle;
aco->save_prevwin_handle = prevwin == NULL ? 0 : prevwin->handle;
aco->save_State = State;
@@ -1334,15 +1308,26 @@ void aucmd_prepbuf_win(aco_save_T *aco, buf_T *buf, win_T *win)
aco->save_prompt_insert = curbuf->b_prompt_insert;
}
- if (auc_idx >= 0) {
- // There is no window for "buf", use "win". To minimize the side effects, insert it in the
- // current tab page. Anything related to a window (e.g., setting folds) may have unexpected
- // results.
- win_init_empty(win); // Set cursor and topline to safe values.
+ if (win != NULL) {
+ // There is a window for "buf" in the current tab page, make it the
+ // curwin. This is preferred, it has the least side effects (esp. if
+ // "buf" is curbuf).
+ aco->use_aucmd_win_idx = -1;
+ curwin = win;
+ } else {
+ // There is no window for "buf", use "auc_win". To minimize the side
+ // effects, insert it in the current tab page.
+ // Anything related to a window (e.g., setting folds) may have
+ // unexpected results.
+ aco->use_aucmd_win_idx = auc_idx;
+ auc_win->w_buffer = buf;
+ auc_win->w_s = &buf->b_s;
+ buf->b_nwindows++;
+ win_init_empty(auc_win); // set cursor and topline to safe values
- // Make sure w_localdir, tp_localdir and globaldir are NULL to avoid a chdir() in
- // win_enter_ext().
- XFREE_CLEAR(win->w_localdir);
+ // Make sure w_localdir, tp_localdir and globaldir are NULL to avoid a
+ // chdir() in win_enter_ext().
+ XFREE_CLEAR(auc_win->w_localdir);
aco->tp_localdir = curtab->tp_localdir;
curtab->tp_localdir = NULL;
aco->globaldir = globaldir;
@@ -1350,43 +1335,30 @@ void aucmd_prepbuf_win(aco_save_T *aco, buf_T *buf, win_T *win)
block_autocmds(); // We don't want BufEnter/WinEnter autocommands.
if (need_append) {
- win_append(lastwin, win, NULL);
- pmap_put(int)(&window_handles, win->handle, win);
- win_config_float(win, win->w_config);
+ win_append(lastwin, auc_win, NULL);
+ pmap_put(int)(&window_handles, auc_win->handle, auc_win);
+ win_config_float(auc_win, auc_win->w_config);
}
// Prevent chdir() call in win_enter_ext(), through do_autochdir()
const int save_acd = p_acd;
p_acd = false;
- // No redrawing and don't set the window title
+ // no redrawing and don't set the window title
RedrawingDisabled++;
- win_enter(win, false);
+ win_enter(auc_win, false);
RedrawingDisabled--;
p_acd = save_acd;
unblock_autocmds();
+ curwin = auc_win;
}
-
- curwin = win;
curbuf = buf;
aco->new_curwin_handle = curwin->handle;
set_bufref(&aco->new_curbuf, curbuf);
- // Disable the Visual area, the position may be invalid in another buffer
+ // disable the Visual area, the position may be invalid in another buffer
aco->save_VIsual_active = VIsual_active;
VIsual_active = false;
}
-/// Prepare for executing autocommands for (hidden) buffer `buf`.
-/// If the current buffer is not in any visible window, put it in a temporary
-/// floating window using an entry in `aucmd_win[]`.
-/// Set `curbuf` and `curwin` to match `buf`.
-///
-/// @param aco structure to save values in
-/// @param buf new curbuf
-void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
-{
- aucmd_prepbuf_win(aco, buf, NULL);
-}
-
/// Cleanup after executing autocommands for a (hidden) buffer.
/// Restore the window as it was (if possible).
///
@@ -1475,19 +1447,6 @@ win_found:
curwin->w_topfill = 0;
}
} else {
- // Restore old buffer of new window if it was changed.
- if (aco->save_buf_handle != -1) {
- win_T *new_win = win_find_by_handle(aco->new_curwin_handle);
- buf_T *new_win_buf = handle_get_buffer(aco->save_buf_handle);
-
- if (new_win != NULL && new_win_buf != NULL) {
- new_win->w_buffer->b_nwindows--;
- new_win->w_buffer = new_win_buf;
- new_win->w_s = &new_win_buf->b_s;
- new_win_buf->b_nwindows++;
- }
- }
-
// Restore curwin. Use the window ID, a window may have been closed
// and the memory re-used for another one.
win_T *const save_curwin = win_find_by_handle(aco->save_curwin_handle);
@@ -1523,13 +1482,6 @@ win_found:
if (VIsual_active) {
check_pos(curbuf, &VIsual);
}
-
- // Switch back to the original tab page if it was switched.
- if (aco->save_curtab_handle != -1) {
- tabpage_T *save_curtab = handle_get_tabpage(aco->save_curtab_handle);
- unuse_tabpage(curtab);
- use_tabpage(save_curtab);
- }
}
/// Execute autocommands for "event" and file name "fname".
diff --git a/src/nvim/autocmd_defs.h b/src/nvim/autocmd_defs.h
index 777ee7b87a..cba947e85f 100644
--- a/src/nvim/autocmd_defs.h
+++ b/src/nvim/autocmd_defs.h
@@ -14,18 +14,16 @@
/// Struct to save values in before executing autocommands for a buffer that is
/// not the current buffer.
typedef struct {
- int use_aucmd_win_idx; ///< index in aucmd_win[] if >= 0
- handle_T save_curwin_handle; ///< ID of saved curwin
- handle_T save_curtab_handle; ///< ID of saved curtab. -1 if not switched.
- handle_T new_curwin_handle; ///< ID of new curwin
- handle_T save_buf_handle; ///< ID of saved buffer of new curwin. -1 if not switched.
- handle_T save_prevwin_handle; ///< ID of saved prevwin
- bufref_T new_curbuf; ///< new curbuf
- char *tp_localdir; ///< saved value of tp_localdir
- char *globaldir; ///< saved value of globaldir
- bool save_VIsual_active; ///< saved VIsual_active
- int save_State; ///< saved State
- int save_prompt_insert; ///< saved b_prompt_insert
+ int use_aucmd_win_idx; ///< index in aucmd_win[] if >= 0
+ handle_T save_curwin_handle; ///< ID of saved curwin
+ handle_T new_curwin_handle; ///< ID of new curwin
+ handle_T save_prevwin_handle; ///< ID of saved prevwin
+ bufref_T new_curbuf; ///< new curbuf
+ char *tp_localdir; ///< saved value of tp_localdir
+ char *globaldir; ///< saved value of globaldir
+ bool save_VIsual_active; ///< saved VIsual_active
+ int save_State; ///< saved State
+ int save_prompt_insert; ///< saved b_prompt_insert
} aco_save_T;
typedef struct {
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index ebeb9ba088..bd98a31a71 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"),
- option_ctx_from(kOptScopeWin, wp), OPT_LOCAL, 0);
+ set_option_direct_for(kOptFoldmethod, STATIC_CSTR_AS_OPTVAL("diff"), OPT_LOCAL, 0,
+ kOptScopeWin, wp);
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 ceb3a074b4..6f9f0f07c9 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 = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
int retval;
if (args->os_flags & OPT_LOCAL) {
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
index 98487be523..419c806592 100644
--- a/src/nvim/insexpand.c
+++ b/src/nvim/insexpand.c
@@ -2409,7 +2409,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 = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
if (option_set_callback_func(buf->b_p_cfu, &cfu_cb) == FAIL) {
return e_invarg;
}
@@ -2430,7 +2430,7 @@ void set_buflocal_cfu_callback(buf_T *buf)
/// lambda expression.
const char *did_set_omnifunc(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
if (option_set_callback_func(buf->b_p_ofu, &ofu_cb) == FAIL) {
return e_invarg;
}
@@ -2451,7 +2451,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 = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
int retval;
if (args->os_flags & OPT_LOCAL) {
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 2b102fe1bb..551ea0be20 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -1324,8 +1324,7 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char *
return;
}
- *errmsg = set_option_for(opt_idx, newval, option_ctx(), opt_flags, 0, false,
- op == OP_NONE, errbuf, errbuflen);
+ *errmsg = set_option(opt_idx, newval, opt_flags, 0, false, op == OP_NONE, errbuf, errbuflen);
}
/// Parse 'arg' for option settings.
@@ -1845,7 +1844,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, OptCtx ctx, const char *errmsg)
+ OptVal oldval_l, OptVal newval, 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) {
@@ -1879,18 +1878,14 @@ 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);
}
-
- WITH_AUCMD_CONTEXT(ctx, {
- apply_autocmds(EVENT_OPTIONSET, options[opt_idx].fullname, NULL, false, NULL);
- });
-
+ 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 = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
const char *errmsg = NULL;
if (win->w_p_arab) {
@@ -1959,7 +1954,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 = args->os_ctx.buf;
+ 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);
@@ -1971,7 +1966,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 = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
// when 'buflisted' changes, trigger autocommands
if (args->os_oldval.boolean != buf->b_p_bl) {
@@ -2005,7 +2000,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 = args->os_ctx.win;
+ 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)) {
@@ -2026,7 +2021,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 = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
if (p_ea && !args->os_oldval.boolean) {
win_equal(win, false, 0);
}
@@ -2044,7 +2039,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 = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
foldUpdateAll(win);
return NULL;
}
@@ -2052,7 +2047,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 = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
if (foldmethodIsSyntax(win) || foldmethodIsIndent(win)) {
foldUpdateAll(win);
}
@@ -2181,7 +2176,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 = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
// When 'lisp' option changes include/exclude '-' in keyword characters.
buf_init_chartab(buf, false); // ignore errors
return NULL;
@@ -2199,7 +2194,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 = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
if (!args->os_newval.boolean) {
save_file_ff(buf); // Buffer is unchanged
}
@@ -2211,7 +2206,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 = args->os_ctx.win;
+ 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;
@@ -2223,7 +2218,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 = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
win->w_nrwidth_line_count = 0; // trigger a redraw
return NULL;
@@ -2361,7 +2356,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 = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
if (!win->w_p_pvw) {
return NULL;
@@ -2393,7 +2388,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 = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
// when 'readonly' is reset globally, also reset readonlymode
if (!buf->b_p_ro && (args->os_flags & OPT_LOCAL) == 0) {
@@ -2413,7 +2408,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 = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
OptInt old_value = args->os_oldval.number;
OptInt value = args->os_newval.number;
@@ -2427,7 +2422,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 = args->os_ctx.win;
+ 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()
@@ -2464,8 +2459,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 = args->os_ctx.buf;
- win_T *win = args->os_ctx.win;
+ 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)) {
@@ -2491,7 +2486,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 = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
if (!win->w_p_sms) {
win->w_skipcol = 0;
}
@@ -2502,7 +2497,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 = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
if (win->w_p_spell) {
return parse_spelllang(win);
}
@@ -2513,7 +2508,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 = args->os_ctx.buf;
+ 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
@@ -2558,7 +2553,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 = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
// Only take action when the option was set.
if (!buf->b_p_udf && !p_udf) {
@@ -2609,7 +2604,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 = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
OptInt *pp = (OptInt *)args->os_varp;
if (pp == &p_ul) { // global 'undolevels'
@@ -2650,7 +2645,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 = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
OptInt old_value = args->os_oldval.number;
OptInt value = args->os_newval.number;
@@ -2699,7 +2694,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 = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
// Set w_leftcol or w_skipcol to zero.
if (win->w_p_wrap) {
win->w_leftcol = 0;
@@ -3148,6 +3143,12 @@ 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;
@@ -3380,37 +3381,21 @@ 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_from(OptIndex opt_idx, OptCtx ctx, int opt_flags)
+OptVal get_option_value(OptIndex opt_idx, int opt_flags)
{
if (opt_idx == kOptInvalid) { // option not in the options[] table.
return NIL_OPTVAL;
}
- // 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));
- }
+ vimoption_T *opt = &options[opt_idx];
+ void *varp = get_varp_scope(opt, opt_flags);
- 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)
{
@@ -3479,8 +3464,6 @@ 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.
@@ -3492,9 +3475,8 @@ 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,
- 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)
+ int opt_flags, scid_T set_sid, const bool direct,
+ const bool value_replaced, char *errbuf, size_t errbuflen)
{
vimoption_T *opt = &options[opt_idx];
const char *errmsg = NULL;
@@ -3513,7 +3495,8 @@ 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_ctx = ctx,
+ .os_buf = curbuf,
+ .os_win = curwin
};
if (direct) {
@@ -3550,7 +3533,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(ctx.buf, true);
+ buf_init_chartab(curbuf, true);
}
return errmsg;
@@ -3581,12 +3564,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_from(opt, OPT_LOCAL, ctx);
+ void *varp_local = get_varp_scope(opt, OPT_LOCAL);
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_from(opt, OPT_GLOBAL, ctx);
+ void *varp_global = get_varp_scope(opt, OPT_GLOBAL);
set_option_varp(opt_idx, varp_global, optval_copy(new_value), true);
}
}
@@ -3597,23 +3580,17 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value
}
// Trigger the autocommand only after setting the flags.
- 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) {
+ if (varp == &curbuf->b_p_syn) {
+ do_syntax_autocmd(curbuf, value_changed);
+ } else if (varp == &curbuf->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) {
- WITH_AUCMD_CONTEXT(ctx, {
- do_filetype_autocmd(ctx.buf, value_changed);
- });
+ do_filetype_autocmd(curbuf, value_changed);
}
- } else if (varp == &ctx.win->w_s->b_p_spl) {
- WITH_AUCMD_CONTEXT(ctx, {
- do_spelllang_source(ctx.win);
- });
+ } else if (varp == &curwin->w_s->b_p_spl) {
+ do_spelllang_source(curwin);
}
// In case 'ruler' or 'showcmd' or 'columns' or 'ls' changed.
@@ -3621,25 +3598,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 == &(ctx.buf->b_p_flp)) && ctx.win->w_briopt_list) {
+ } else if ((varp == &p_flp || varp == &(curbuf->b_p_flp)) && curwin->w_briopt_list) {
// Changing Formatlistpattern when briopt includes the list setting:
// redraw
redraw_all_later(UPD_NOT_VALID);
- } else if (varp == &p_wbr || varp == &(ctx.win->w_p_wbr)) {
+ } else if (varp == &p_wbr || varp == &(curwin->w_p_wbr)) {
// add / remove window bars for 'winbar'
set_winbar(true);
}
- if (ctx.win->w_curswant != MAXCOL
+ if (curwin->w_curswant != MAXCOL
&& (opt->flags & (kOptFlagCurswant | kOptFlagRedrAll)) != 0
&& (opt->flags & kOptFlagHLOnly) == 0) {
- ctx.win->w_set_curswant = true;
+ curwin->w_set_curswant = true;
}
- check_redraw_for(ctx.buf, ctx.win, opt->flags);
+ check_redraw(opt->flags);
if (errmsg == NULL) {
- uint32_t *p = insecure_flag(ctx.win, opt_idx, opt_flags);
+ uint32_t *p = insecure_flag(curwin, 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
@@ -3699,7 +3676,6 @@ 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.
@@ -3710,9 +3686,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_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)
+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)
{
assert(opt_idx != kOptInvalid);
@@ -3737,11 +3713,10 @@ static const char *set_option_for(OptIndex opt_idx, OptVal value, OptCtx ctx, in
// 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_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);
+ 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);
OptVal old_value = optval_from_varp(opt_idx, varp);
OptVal old_global_value = optval_from_varp(opt_idx, varp_global);
@@ -3754,7 +3729,7 @@ static const char *set_option_for(OptIndex opt_idx, OptVal value, OptCtx ctx, in
// 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_from(opt, ctx))
+ ? optval_from_varp(opt_idx, get_varp(opt))
: old_value;
// Save the old values and the new value in case they get changed.
@@ -3764,7 +3739,7 @@ static const char *set_option_for(OptIndex opt_idx, OptVal value, OptCtx ctx, in
// 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(ctx.win, opt_idx, opt_flags);
+ uint32_t *p = insecure_flag(curwin, 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
@@ -3777,7 +3752,7 @@ static const char *set_option_for(OptIndex opt_idx, OptVal value, OptCtx ctx, in
// 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, ctx, opt_flags, set_sid, direct,
+ errmsg = did_set_option(opt_idx, varp, old_value, value, opt_flags, set_sid, direct,
value_replaced, errbuf, errbuflen);
secure = secure_saved;
@@ -3785,7 +3760,7 @@ static const char *set_option_for(OptIndex opt_idx, OptVal value, OptCtx ctx, in
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, ctx, errmsg);
+ saved_old_local_value, saved_new_value, errmsg);
}
if (opt->flags & kOptFlagUIOption) {
ui_call_option_set(cstr_as_string(opt->fullname), optval_as_object(saved_new_value));
@@ -3805,13 +3780,11 @@ static const char *set_option_for(OptIndex opt_idx, OptVal value, OptCtx ctx, in
///
/// @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_for(OptIndex opt_idx, OptVal value, OptCtx ctx, int opt_flags,
- scid_T set_sid)
+void set_option_direct(OptIndex opt_idx, OptVal value, int opt_flags, scid_T set_sid)
{
static char errbuf[IOSIZE];
@@ -3819,35 +3792,57 @@ void set_option_direct_for(OptIndex opt_idx, OptVal value, OptCtx ctx, int opt_f
return;
}
- const char *errmsg = set_option_for(opt_idx, optval_copy(value), ctx, opt_flags, set_sid, true,
- true, errbuf, sizeof(errbuf));
+ const char *errmsg = set_option(opt_idx, optval_copy(value), opt_flags, set_sid, true, true,
+ errbuf, sizeof(errbuf));
assert(errmsg == NULL);
(void)errmsg; // ignore unused warning
}
-/// Set option value for current context directly, without processing any side effects.
+/// Set option value directly for buffer / window, without processing any side effects.
///
-/// @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);
+/// @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;
}
/// 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_for(OptIndex opt_idx, OptVal value, OptCtx ctx, int opt_flags)
+const char *set_option_value(const OptIndex opt_idx, const OptVal value, int opt_flags)
{
assert(opt_idx != kOptInvalid);
@@ -3859,21 +3854,7 @@ const char *set_option_value_for(OptIndex opt_idx, OptVal value, OptCtx ctx, int
return _(e_sandbox);
}
- 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);
+ return set_option(opt_idx, optval_copy(value), opt_flags, 0, false, true, errbuf, sizeof(errbuf));
}
/// Unset the local value of a global-local option.
@@ -3929,6 +3910,135 @@ 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;
+ case kOptScopeWin:
+ restore_win_noblock((switchwin_T *)ctx, true);
+ break;
+ case kOptScopeBuf:
+ aucmd_restbuf((aco_save_T *)ctx);
+ break;
+ }
+}
+
+/// Get option value for buffer / window.
+///
+/// @param opt_idx Option index in options[] table.
+/// @param[out] flagsp Set to the option flags (see OptFlags) (if not NULL).
+/// @param[in] scope Option scope (can be OPT_LOCAL, OPT_GLOBAL or a combination).
+/// @param[out] hidden Whether option is hidden.
+/// @param scope Option scope. See OptScope in option.h.
+/// @param[in] from Target buffer/window.
+/// @param[out] err Error message, if any.
+///
+/// @return Option value. Must be freed by caller.
+OptVal get_option_value_for(OptIndex opt_idx, int opt_flags, const OptScope scope, void *const from,
+ Error *err)
+{
+ switchwin_T switchwin;
+ aco_save_T aco;
+ void *ctx = scope == kOptScopeWin ? (void *)&switchwin
+ : (scope == kOptScopeBuf ? (void *)&aco : NULL);
+
+ bool switched = switch_option_context(ctx, scope, from, err);
+ if (ERROR_SET(err)) {
+ return NIL_OPTVAL;
+ }
+
+ OptVal retv = get_option_value(opt_idx, opt_flags);
+
+ if (switched) {
+ restore_option_context(ctx, scope);
+ }
+
+ return retv;
+}
+
+/// Set option value for buffer / window.
+///
+/// @param name Option name.
+/// @param opt_idx Option index in options[] table.
+/// @param[in] value Option value.
+/// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both).
+/// @param scope Option scope. See OptScope in option.h.
+/// @param[in] from Target buffer/window.
+/// @param[out] err Error message, if any.
+void set_option_value_for(const char *name, OptIndex opt_idx, OptVal value, const int opt_flags,
+ const OptScope scope, void *const from, Error *err)
+ FUNC_ATTR_NONNULL_ARG(1)
+{
+ switchwin_T switchwin;
+ aco_save_T aco;
+ void *ctx = scope == kOptScopeWin ? (void *)&switchwin
+ : (scope == kOptScopeBuf ? (void *)&aco : NULL);
+
+ bool switched = switch_option_context(ctx, scope, from, err);
+ if (ERROR_SET(err)) {
+ return;
+ }
+
+ const char *const errmsg = set_option_value_handle_tty(name, opt_idx, value, opt_flags);
+ if (errmsg) {
+ api_set_error(err, kErrorTypeException, "%s", errmsg);
+ }
+
+ if (switched) {
+ restore_option_context(ctx, scope);
+ }
+}
+
/// if 'all' == false: show changed options
/// if 'all' == true: show all normal options
///
@@ -4344,13 +4454,13 @@ static int put_set(FILE *fd, char *cmd, OptIndex opt_idx, void *varp)
return OK;
}
-void *get_varp_scope_from(vimoption_T *p, int opt_flags, OptCtx ctx)
+void *get_varp_scope_from(vimoption_T *p, int opt_flags, buf_T *buf, win_T *win)
{
OptIndex opt_idx = get_opt_idx(p);
if ((opt_flags & OPT_GLOBAL) && !option_is_global_only(opt_idx)) {
if (option_is_window_local(opt_idx)) {
- return GLOBAL_WO(get_varp_from(p, ctx));
+ return GLOBAL_WO(get_varp_from(p, buf, win));
}
return p->var;
}
@@ -4358,73 +4468,88 @@ void *get_varp_scope_from(vimoption_T *p, int opt_flags, OptCtx ctx)
if ((opt_flags & OPT_LOCAL) && option_is_global_local(opt_idx)) {
switch (opt_idx) {
case kOptFormatprg:
- return &(ctx.buf->b_p_fp);
+ return &(buf->b_p_fp);
case kOptFindfunc:
- return &(ctx.buf->b_p_ffu);
+ return &(buf->b_p_ffu);
case kOptErrorformat:
- return &(ctx.buf->b_p_efm);
+ return &(buf->b_p_efm);
case kOptGrepprg:
- return &(ctx.buf->b_p_gp);
+ return &(buf->b_p_gp);
case kOptMakeprg:
- return &(ctx.buf->b_p_mp);
+ return &(buf->b_p_mp);
case kOptEqualprg:
- return &(ctx.buf->b_p_ep);
+ return &(buf->b_p_ep);
case kOptKeywordprg:
- return &(ctx.buf->b_p_kp);
+ return &(buf->b_p_kp);
case kOptPath:
- return &(ctx.buf->b_p_path);
+ return &(buf->b_p_path);
case kOptAutoread:
- return &(ctx.buf->b_p_ar);
+ return &(buf->b_p_ar);
case kOptTags:
- return &(ctx.buf->b_p_tags);
+ return &(buf->b_p_tags);
case kOptTagcase:
- return &(ctx.buf->b_p_tc);
+ return &(buf->b_p_tc);
case kOptSidescrolloff:
- return &(ctx.win->w_p_siso);
+ return &(win->w_p_siso);
case kOptScrolloff:
- return &(ctx.win->w_p_so);
+ return &(win->w_p_so);
case kOptDefine:
- return &(ctx.buf->b_p_def);
+ return &(buf->b_p_def);
case kOptInclude:
- return &(ctx.buf->b_p_inc);
+ return &(buf->b_p_inc);
case kOptCompleteopt:
- return &(ctx.buf->b_p_cot);
+ return &(buf->b_p_cot);
case kOptDictionary:
- return &(ctx.buf->b_p_dict);
+ return &(buf->b_p_dict);
case kOptThesaurus:
- return &(ctx.buf->b_p_tsr);
+ return &(buf->b_p_tsr);
case kOptThesaurusfunc:
- return &(ctx.buf->b_p_tsrfu);
+ return &(buf->b_p_tsrfu);
case kOptTagfunc:
- return &(ctx.buf->b_p_tfu);
+ return &(buf->b_p_tfu);
case kOptShowbreak:
- return &(ctx.win->w_p_sbr);
+ return &(win->w_p_sbr);
case kOptStatusline:
- return &(ctx.win->w_p_stl);
+ return &(win->w_p_stl);
case kOptWinbar:
- return &(ctx.win->w_p_wbr);
+ return &(win->w_p_wbr);
case kOptUndolevels:
- return &(ctx.buf->b_p_ul);
+ return &(buf->b_p_ul);
case kOptLispwords:
- return &(ctx.buf->b_p_lw);
+ return &(buf->b_p_lw);
case kOptBackupcopy:
- return &(ctx.buf->b_p_bkc);
+ return &(buf->b_p_bkc);
case kOptMakeencoding:
- return &(ctx.buf->b_p_menc);
+ return &(buf->b_p_menc);
case kOptFillchars:
- return &(ctx.win->w_p_fcs);
+ return &(win->w_p_fcs);
case kOptListchars:
- return &(ctx.win->w_p_lcs);
+ return &(win->w_p_lcs);
case kOptVirtualedit:
- return &(ctx.win->w_p_ve);
+ return &(win->w_p_ve);
default:
abort();
}
}
- return get_varp_from(p, ctx);
+ return get_varp_from(p, buf, win);
+}
+
+/// Get pointer to option variable, depending on local or global scope.
+///
+/// @param opt_flags Option flags (can be OPT_LOCAL, OPT_GLOBAL or a combination).
+void *get_varp_scope(vimoption_T *p, int opt_flags)
+{
+ return get_varp_scope_from(p, opt_flags, curbuf, curwin);
}
-void *get_varp_from(vimoption_T *p, OptCtx ctx)
+/// Get pointer to option variable at 'opt_idx', depending on local or global
+/// scope.
+void *get_option_varp_scope_from(OptIndex opt_idx, int opt_flags, buf_T *buf, win_T *win)
+{
+ return get_varp_scope_from(&(options[opt_idx]), opt_flags, buf, win);
+}
+
+void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
{
OptIndex opt_idx = get_opt_idx(p);
@@ -4436,330 +4561,299 @@ void *get_varp_from(vimoption_T *p, OptCtx ctx)
switch (opt_idx) {
// global option with local value: use local value if it's been set
case kOptEqualprg:
- return *ctx.buf->b_p_ep != NUL ? &ctx.buf->b_p_ep : p->var;
+ return *buf->b_p_ep != NUL ? &buf->b_p_ep : p->var;
case kOptKeywordprg:
- return *ctx.buf->b_p_kp != NUL ? &ctx.buf->b_p_kp : p->var;
+ return *buf->b_p_kp != NUL ? &buf->b_p_kp : p->var;
case kOptPath:
- return *ctx.buf->b_p_path != NUL ? &(ctx.buf->b_p_path) : p->var;
+ return *buf->b_p_path != NUL ? &(buf->b_p_path) : p->var;
case kOptAutoread:
- return ctx.buf->b_p_ar >= 0 ? &(ctx.buf->b_p_ar) : p->var;
+ return buf->b_p_ar >= 0 ? &(buf->b_p_ar) : p->var;
case kOptTags:
- return *ctx.buf->b_p_tags != NUL ? &(ctx.buf->b_p_tags) : p->var;
+ return *buf->b_p_tags != NUL ? &(buf->b_p_tags) : p->var;
case kOptTagcase:
- return *ctx.buf->b_p_tc != NUL ? &(ctx.buf->b_p_tc) : p->var;
+ return *buf->b_p_tc != NUL ? &(buf->b_p_tc) : p->var;
case kOptSidescrolloff:
- return ctx.win->w_p_siso >= 0 ? &(ctx.win->w_p_siso) : p->var;
+ return win->w_p_siso >= 0 ? &(win->w_p_siso) : p->var;
case kOptScrolloff:
- return ctx.win->w_p_so >= 0 ? &(ctx.win->w_p_so) : p->var;
+ return win->w_p_so >= 0 ? &(win->w_p_so) : p->var;
case kOptBackupcopy:
- return *ctx.buf->b_p_bkc != NUL ? &(ctx.buf->b_p_bkc) : p->var;
+ return *buf->b_p_bkc != NUL ? &(buf->b_p_bkc) : p->var;
case kOptDefine:
- return *ctx.buf->b_p_def != NUL ? &(ctx.buf->b_p_def) : p->var;
+ return *buf->b_p_def != NUL ? &(buf->b_p_def) : p->var;
case kOptInclude:
- return *ctx.buf->b_p_inc != NUL ? &(ctx.buf->b_p_inc) : p->var;
+ return *buf->b_p_inc != NUL ? &(buf->b_p_inc) : p->var;
case kOptCompleteopt:
- return *ctx.buf->b_p_cot != NUL ? &(ctx.buf->b_p_cot) : p->var;
+ return *buf->b_p_cot != NUL ? &(buf->b_p_cot) : p->var;
case kOptDictionary:
- return *ctx.buf->b_p_dict != NUL ? &(ctx.buf->b_p_dict) : p->var;
+ return *buf->b_p_dict != NUL ? &(buf->b_p_dict) : p->var;
case kOptThesaurus:
- return *ctx.buf->b_p_tsr != NUL ? &(ctx.buf->b_p_tsr) : p->var;
+ return *buf->b_p_tsr != NUL ? &(buf->b_p_tsr) : p->var;
case kOptThesaurusfunc:
- return *ctx.buf->b_p_tsrfu != NUL ? &(ctx.buf->b_p_tsrfu) : p->var;
+ return *buf->b_p_tsrfu != NUL ? &(buf->b_p_tsrfu) : p->var;
case kOptFormatprg:
- return *ctx.buf->b_p_fp != NUL ? &(ctx.buf->b_p_fp) : p->var;
+ return *buf->b_p_fp != NUL ? &(buf->b_p_fp) : p->var;
case kOptFindfunc:
- return *ctx.buf->b_p_ffu != NUL ? &(ctx.buf->b_p_ffu) : p->var;
+ return *buf->b_p_ffu != NUL ? &(buf->b_p_ffu) : p->var;
case kOptErrorformat:
- return *ctx.buf->b_p_efm != NUL ? &(ctx.buf->b_p_efm) : p->var;
+ return *buf->b_p_efm != NUL ? &(buf->b_p_efm) : p->var;
case kOptGrepprg:
- return *ctx.buf->b_p_gp != NUL ? &(ctx.buf->b_p_gp) : p->var;
+ return *buf->b_p_gp != NUL ? &(buf->b_p_gp) : p->var;
case kOptMakeprg:
- return *ctx.buf->b_p_mp != NUL ? &(ctx.buf->b_p_mp) : p->var;
+ return *buf->b_p_mp != NUL ? &(buf->b_p_mp) : p->var;
case kOptShowbreak:
- return *ctx.win->w_p_sbr != NUL ? &(ctx.win->w_p_sbr) : p->var;
+ return *win->w_p_sbr != NUL ? &(win->w_p_sbr) : p->var;
case kOptStatusline:
- return *ctx.win->w_p_stl != NUL ? &(ctx.win->w_p_stl) : p->var;
+ return *win->w_p_stl != NUL ? &(win->w_p_stl) : p->var;
case kOptWinbar:
- return *ctx.win->w_p_wbr != NUL ? &(ctx.win->w_p_wbr) : p->var;
+ return *win->w_p_wbr != NUL ? &(win->w_p_wbr) : p->var;
case kOptUndolevels:
- return ctx.buf->b_p_ul != NO_LOCAL_UNDOLEVEL ? &(ctx.buf->b_p_ul) : p->var;
+ return buf->b_p_ul != NO_LOCAL_UNDOLEVEL ? &(buf->b_p_ul) : p->var;
case kOptLispwords:
- return *ctx.buf->b_p_lw != NUL ? &(ctx.buf->b_p_lw) : p->var;
+ return *buf->b_p_lw != NUL ? &(buf->b_p_lw) : p->var;
case kOptMakeencoding:
- return *ctx.buf->b_p_menc != NUL ? &(ctx.buf->b_p_menc) : p->var;
+ return *buf->b_p_menc != NUL ? &(buf->b_p_menc) : p->var;
case kOptFillchars:
- return *ctx.win->w_p_fcs != NUL ? &(ctx.win->w_p_fcs) : p->var;
+ return *win->w_p_fcs != NUL ? &(win->w_p_fcs) : p->var;
case kOptListchars:
- return *ctx.win->w_p_lcs != NUL ? &(ctx.win->w_p_lcs) : p->var;
+ return *win->w_p_lcs != NUL ? &(win->w_p_lcs) : p->var;
case kOptVirtualedit:
- return *ctx.win->w_p_ve != NUL ? &ctx.win->w_p_ve : p->var;
+ return *win->w_p_ve != NUL ? &win->w_p_ve : p->var;
case kOptArabic:
- return &(ctx.win->w_p_arab);
+ return &(win->w_p_arab);
case kOptList:
- return &(ctx.win->w_p_list);
+ return &(win->w_p_list);
case kOptSpell:
- return &(ctx.win->w_p_spell);
+ return &(win->w_p_spell);
case kOptCursorcolumn:
- return &(ctx.win->w_p_cuc);
+ return &(win->w_p_cuc);
case kOptCursorline:
- return &(ctx.win->w_p_cul);
+ return &(win->w_p_cul);
case kOptCursorlineopt:
- return &(ctx.win->w_p_culopt);
+ return &(win->w_p_culopt);
case kOptColorcolumn:
- return &(ctx.win->w_p_cc);
+ return &(win->w_p_cc);
case kOptDiff:
- return &(ctx.win->w_p_diff);
+ return &(win->w_p_diff);
case kOptFoldcolumn:
- return &(ctx.win->w_p_fdc);
+ return &(win->w_p_fdc);
case kOptFoldenable:
- return &(ctx.win->w_p_fen);
+ return &(win->w_p_fen);
case kOptFoldignore:
- return &(ctx.win->w_p_fdi);
+ return &(win->w_p_fdi);
case kOptFoldlevel:
- return &(ctx.win->w_p_fdl);
+ return &(win->w_p_fdl);
case kOptFoldmethod:
- return &(ctx.win->w_p_fdm);
+ return &(win->w_p_fdm);
case kOptFoldminlines:
- return &(ctx.win->w_p_fml);
+ return &(win->w_p_fml);
case kOptFoldnestmax:
- return &(ctx.win->w_p_fdn);
+ return &(win->w_p_fdn);
case kOptFoldexpr:
- return &(ctx.win->w_p_fde);
+ return &(win->w_p_fde);
case kOptFoldtext:
- return &(ctx.win->w_p_fdt);
+ return &(win->w_p_fdt);
case kOptFoldmarker:
- return &(ctx.win->w_p_fmr);
+ return &(win->w_p_fmr);
case kOptNumber:
- return &(ctx.win->w_p_nu);
+ return &(win->w_p_nu);
case kOptRelativenumber:
- return &(ctx.win->w_p_rnu);
+ return &(win->w_p_rnu);
case kOptNumberwidth:
- return &(ctx.win->w_p_nuw);
+ return &(win->w_p_nuw);
case kOptWinfixbuf:
- return &(ctx.win->w_p_wfb);
+ return &(win->w_p_wfb);
case kOptWinfixheight:
- return &(ctx.win->w_p_wfh);
+ return &(win->w_p_wfh);
case kOptWinfixwidth:
- return &(ctx.win->w_p_wfw);
+ return &(win->w_p_wfw);
case kOptPreviewwindow:
- return &(ctx.win->w_p_pvw);
+ return &(win->w_p_pvw);
case kOptRightleft:
- return &(ctx.win->w_p_rl);
+ return &(win->w_p_rl);
case kOptRightleftcmd:
- return &(ctx.win->w_p_rlc);
+ return &(win->w_p_rlc);
case kOptScroll:
- return &(ctx.win->w_p_scr);
+ return &(win->w_p_scr);
case kOptSmoothscroll:
- return &(ctx.win->w_p_sms);
+ return &(win->w_p_sms);
case kOptWrap:
- return &(ctx.win->w_p_wrap);
+ return &(win->w_p_wrap);
case kOptLinebreak:
- return &(ctx.win->w_p_lbr);
+ return &(win->w_p_lbr);
case kOptBreakindent:
- return &(ctx.win->w_p_bri);
+ return &(win->w_p_bri);
case kOptBreakindentopt:
- return &(ctx.win->w_p_briopt);
+ return &(win->w_p_briopt);
case kOptScrollbind:
- return &(ctx.win->w_p_scb);
+ return &(win->w_p_scb);
case kOptCursorbind:
- return &(ctx.win->w_p_crb);
+ return &(win->w_p_crb);
case kOptConcealcursor:
- return &(ctx.win->w_p_cocu);
+ return &(win->w_p_cocu);
case kOptConceallevel:
- return &(ctx.win->w_p_cole);
+ return &(win->w_p_cole);
case kOptAutoindent:
- return &(ctx.buf->b_p_ai);
+ return &(buf->b_p_ai);
case kOptBinary:
- return &(ctx.buf->b_p_bin);
+ return &(buf->b_p_bin);
case kOptBomb:
- return &(ctx.buf->b_p_bomb);
+ return &(buf->b_p_bomb);
case kOptBufhidden:
- return &(ctx.buf->b_p_bh);
+ return &(buf->b_p_bh);
case kOptBuftype:
- return &(ctx.buf->b_p_bt);
+ return &(buf->b_p_bt);
case kOptBuflisted:
- return &(ctx.buf->b_p_bl);
+ return &(buf->b_p_bl);
case kOptChannel:
- return &(ctx.buf->b_p_channel);
+ return &(buf->b_p_channel);
case kOptCopyindent:
- return &(ctx.buf->b_p_ci);
+ return &(buf->b_p_ci);
case kOptCindent:
- return &(ctx.buf->b_p_cin);
+ return &(buf->b_p_cin);
case kOptCinkeys:
- return &(ctx.buf->b_p_cink);
+ return &(buf->b_p_cink);
case kOptCinoptions:
- return &(ctx.buf->b_p_cino);
+ return &(buf->b_p_cino);
case kOptCinscopedecls:
- return &(ctx.buf->b_p_cinsd);
+ return &(buf->b_p_cinsd);
case kOptCinwords:
- return &(ctx.buf->b_p_cinw);
+ return &(buf->b_p_cinw);
case kOptComments:
- return &(ctx.buf->b_p_com);
+ return &(buf->b_p_com);
case kOptCommentstring:
- return &(ctx.buf->b_p_cms);
+ return &(buf->b_p_cms);
case kOptComplete:
- return &(ctx.buf->b_p_cpt);
+ return &(buf->b_p_cpt);
#ifdef BACKSLASH_IN_FILENAME
case kOptCompleteslash:
- return &(ctx.buf->b_p_csl);
+ return &(buf->b_p_csl);
#endif
case kOptCompletefunc:
- return &(ctx.buf->b_p_cfu);
+ return &(buf->b_p_cfu);
case kOptOmnifunc:
- return &(ctx.buf->b_p_ofu);
+ return &(buf->b_p_ofu);
case kOptEndoffile:
- return &(ctx.buf->b_p_eof);
+ return &(buf->b_p_eof);
case kOptEndofline:
- return &(ctx.buf->b_p_eol);
+ return &(buf->b_p_eol);
case kOptFixendofline:
- return &(ctx.buf->b_p_fixeol);
+ return &(buf->b_p_fixeol);
case kOptExpandtab:
- return &(ctx.buf->b_p_et);
+ return &(buf->b_p_et);
case kOptFileencoding:
- return &(ctx.buf->b_p_fenc);
+ return &(buf->b_p_fenc);
case kOptFileformat:
- return &(ctx.buf->b_p_ff);
+ return &(buf->b_p_ff);
case kOptFiletype:
- return &(ctx.buf->b_p_ft);
+ return &(buf->b_p_ft);
case kOptFormatoptions:
- return &(ctx.buf->b_p_fo);
+ return &(buf->b_p_fo);
case kOptFormatlistpat:
- return &(ctx.buf->b_p_flp);
+ return &(buf->b_p_flp);
case kOptIminsert:
- return &(ctx.buf->b_p_iminsert);
+ return &(buf->b_p_iminsert);
case kOptImsearch:
- return &(ctx.buf->b_p_imsearch);
+ return &(buf->b_p_imsearch);
case kOptInfercase:
- return &(ctx.buf->b_p_inf);
+ return &(buf->b_p_inf);
case kOptIskeyword:
- return &(ctx.buf->b_p_isk);
+ return &(buf->b_p_isk);
case kOptIncludeexpr:
- return &(ctx.buf->b_p_inex);
+ return &(buf->b_p_inex);
case kOptIndentexpr:
- return &(ctx.buf->b_p_inde);
+ return &(buf->b_p_inde);
case kOptIndentkeys:
- return &(ctx.buf->b_p_indk);
+ return &(buf->b_p_indk);
case kOptFormatexpr:
- return &(ctx.buf->b_p_fex);
+ return &(buf->b_p_fex);
case kOptLisp:
- return &(ctx.buf->b_p_lisp);
+ return &(buf->b_p_lisp);
case kOptLispoptions:
- return &(ctx.buf->b_p_lop);
+ return &(buf->b_p_lop);
case kOptModeline:
- return &(ctx.buf->b_p_ml);
+ return &(buf->b_p_ml);
case kOptMatchpairs:
- return &(ctx.buf->b_p_mps);
+ return &(buf->b_p_mps);
case kOptModifiable:
- return &(ctx.buf->b_p_ma);
+ return &(buf->b_p_ma);
case kOptModified:
- return &(ctx.buf->b_changed);
+ return &(buf->b_changed);
case kOptNrformats:
- return &(ctx.buf->b_p_nf);
+ return &(buf->b_p_nf);
case kOptPreserveindent:
- return &(ctx.buf->b_p_pi);
+ return &(buf->b_p_pi);
case kOptQuoteescape:
- return &(ctx.buf->b_p_qe);
+ return &(buf->b_p_qe);
case kOptReadonly:
- return &(ctx.buf->b_p_ro);
+ return &(buf->b_p_ro);
case kOptScrollback:
- return &(ctx.buf->b_p_scbk);
+ return &(buf->b_p_scbk);
case kOptSmartindent:
- return &(ctx.buf->b_p_si);
+ return &(buf->b_p_si);
case kOptSofttabstop:
- return &(ctx.buf->b_p_sts);
+ return &(buf->b_p_sts);
case kOptSuffixesadd:
- return &(ctx.buf->b_p_sua);
+ return &(buf->b_p_sua);
case kOptSwapfile:
- return &(ctx.buf->b_p_swf);
+ return &(buf->b_p_swf);
case kOptSynmaxcol:
- return &(ctx.buf->b_p_smc);
+ return &(buf->b_p_smc);
case kOptSyntax:
- return &(ctx.buf->b_p_syn);
+ return &(buf->b_p_syn);
case kOptSpellcapcheck:
- return &(ctx.win->w_s->b_p_spc);
+ return &(win->w_s->b_p_spc);
case kOptSpellfile:
- return &(ctx.win->w_s->b_p_spf);
+ return &(win->w_s->b_p_spf);
case kOptSpelllang:
- return &(ctx.win->w_s->b_p_spl);
+ return &(win->w_s->b_p_spl);
case kOptSpelloptions:
- return &(ctx.win->w_s->b_p_spo);
+ return &(win->w_s->b_p_spo);
case kOptShiftwidth:
- return &(ctx.buf->b_p_sw);
+ return &(buf->b_p_sw);
case kOptTagfunc:
- return &(ctx.buf->b_p_tfu);
+ return &(buf->b_p_tfu);
case kOptTabstop:
- return &(ctx.buf->b_p_ts);
+ return &(buf->b_p_ts);
case kOptTextwidth:
- return &(ctx.buf->b_p_tw);
+ return &(buf->b_p_tw);
case kOptUndofile:
- return &(ctx.buf->b_p_udf);
+ return &(buf->b_p_udf);
case kOptWrapmargin:
- return &(ctx.buf->b_p_wm);
+ return &(buf->b_p_wm);
case kOptVarsofttabstop:
- return &(ctx.buf->b_p_vsts);
+ return &(buf->b_p_vsts);
case kOptVartabstop:
- return &(ctx.buf->b_p_vts);
+ return &(buf->b_p_vts);
case kOptKeymap:
- return &(ctx.buf->b_p_keymap);
+ return &(buf->b_p_keymap);
case kOptSigncolumn:
- return &(ctx.win->w_p_scl);
+ return &(win->w_p_scl);
case kOptWinhighlight:
- return &(ctx.win->w_p_winhl);
+ return &(win->w_p_winhl);
case kOptWinblend:
- return &(ctx.win->w_p_winbl);
+ return &(win->w_p_winbl);
case kOptStatuscolumn:
- return &(ctx.win->w_p_stc);
+ return &(win->w_p_stc);
default:
iemsg(_("E356: get_varp ERROR"));
}
// always return a valid pointer to avoid a crash!
- return &(ctx.buf->b_p_wm);
+ return &(buf->b_p_wm);
}
-/// Get the current context for options.
-OptCtx option_ctx(void)
-{
- return (OptCtx){ .buf = curbuf, .win = curwin };
-}
-
-/// Get the context for options from a scope and pointer to target.
-///
-/// @param scope Option scope. See OptScope in option.h.
-/// @param from Pointer to target buffer/window/etc.
-OptCtx option_ctx_from(OptScope scope, void *from)
-{
- switch (scope) {
- case kOptScopeGlobal:
- return option_ctx();
- case kOptScopeBuf:
- return (OptCtx){ .buf = (buf_T *)from, .win = curwin };
- case kOptScopeWin:
- return (OptCtx){ .buf = ((win_T *)from)->w_buffer, .win = (win_T *)from };
- }
- UNREACHABLE;
-}
-
-/// Get pointer to option variable, depending on local or global scope.
-///
-/// @param opt_flags Option flags (can be OPT_LOCAL, OPT_GLOBAL or a combination).
-void *get_varp_scope(vimoption_T *p, int opt_flags)
+/// Get option index from option pointer
+static inline OptIndex get_opt_idx(vimoption_T *opt)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
- return get_varp_scope_from(p, opt_flags, option_ctx());
+ return (OptIndex)(opt - options);
}
/// Get pointer to option variable.
static inline void *get_varp(vimoption_T *p)
{
- return get_varp_from(p, option_ctx());
-}
-
-/// Get option index from option pointer
-static inline OptIndex get_opt_idx(vimoption_T *opt)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
-{
- return (OptIndex)(opt - options);
+ return get_varp_from(p, curbuf, curwin);
}
/// Get the value of 'equalprg', either the buffer-local one or the global one.
@@ -5705,7 +5799,9 @@ int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, c
return ExpandOldSetting(numMatches, matches);
}
- char *option_val = *(char **)get_varp_scope(get_option(expand_option_idx), expand_option_flags);
+ char *option_val = *(char **)get_option_varp_scope_from(expand_option_idx,
+ expand_option_flags,
+ curbuf, curwin);
uint32_t option_flags = options[expand_option_idx].flags;
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index b76532b1eb..832e03148a 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -81,12 +81,6 @@ typedef struct {
OptValData data;
} OptVal;
-/// Context that an option is being set for.
-typedef struct {
- win_T *win;
- buf_T *buf;
-} OptCtx;
-
/// :set operator types
typedef enum {
OP_NONE = 0,
@@ -128,7 +122,8 @@ typedef struct {
/// length of the error buffer
size_t os_errbuflen;
- OptCtx os_ctx;
+ void *os_win;
+ void *os_buf;
} optset_T;
/// Type for the callback function that is invoked after an option value is
@@ -197,12 +192,3 @@ typedef struct {
OptVal def_val; ///< default value
LastSet last_set; ///< script in which the option was last set
} vimoption_T;
-
-/// Execute code with autocmd context
-#define WITH_AUCMD_CONTEXT(ctx, code) \
- do { \
- aco_save_T _aco; \
- aucmd_prepbuf_win(&_aco, ctx.buf, ctx.win); \
- code; \
- aucmd_restbuf(&_aco); \
- } while (0)
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index 632b4af573..9b7b50ae04 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -567,7 +567,7 @@ int expand_set_backspace(optexpand_T *args, int *numMatches, char ***matches)
/// The 'backupcopy' option is changed.
const char *did_set_backupcopy(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
const char *oldval = args->os_oldval.string.data;
int opt_flags = args->os_flags;
char *bkc = p_bkc;
@@ -655,7 +655,7 @@ const char *did_set_breakat(optset_T *args FUNC_ATTR_UNUSED)
/// The 'breakindentopt' option is changed.
const char *did_set_breakindentopt(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
char **varp = (char **)args->os_varp;
if (briopt_check(*varp, varp == &win->w_p_briopt ? win : NULL) == FAIL) {
@@ -682,7 +682,7 @@ int expand_set_breakindentopt(optexpand_T *args, int *numMatches, char ***matche
/// The 'bufhidden' option is changed.
const char *did_set_bufhidden(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
return did_set_opt_strings(buf->b_p_bh, opt_bh_values, false);
}
@@ -698,8 +698,8 @@ int expand_set_bufhidden(optexpand_T *args, int *numMatches, char ***matches)
/// The 'buftype' option is changed.
const char *did_set_buftype(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
- win_T *win = args->os_ctx.win;
+ 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')
@@ -780,7 +780,7 @@ static const char *did_set_global_chars_option(win_T *win, char *val, CharsOptio
/// The 'fillchars' option or the 'listchars' option is changed.
const char *did_set_chars_option(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
char **varp = (char **)args->os_varp;
const char *errmsg = NULL;
@@ -815,7 +815,7 @@ int expand_set_chars_option(optexpand_T *args, int *numMatches, char ***matches)
/// The 'cinoptions' option is changed.
const char *did_set_cinoptions(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
// TODO(vim): recognize errors
parse_cino(buf);
@@ -840,7 +840,7 @@ int expand_set_clipboard(optexpand_T *args, int *numMatches, char ***matches)
/// The 'colorcolumn' option is changed.
const char *did_set_colorcolumn(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
char **varp = (char **)args->os_varp;
return check_colorcolumn(*varp, varp == &win->w_p_cc ? win : NULL);
}
@@ -985,7 +985,7 @@ const char *did_set_completeitemalign(optset_T *args)
/// The 'completeopt' option is changed.
const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED)
{
- buf_T *buf = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
char *cot = p_cot;
unsigned *flags = &cot_flags;
@@ -1021,7 +1021,7 @@ int expand_set_completeopt(optexpand_T *args, int *numMatches, char ***matches)
/// The 'completeslash' option is changed.
const char *did_set_completeslash(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
if (check_opt_strings(p_csl, opt_csl_values, false) != OK
|| check_opt_strings(buf->b_p_csl, opt_csl_values, false) != OK) {
return e_invarg;
@@ -1068,7 +1068,7 @@ int expand_set_cpoptions(optexpand_T *args, int *numMatches, char ***matches)
/// The 'cursorlineopt' option is changed.
const char *did_set_cursorlineopt(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
char **varp = (char **)args->os_varp;
// This could be changed to use opt_strings_flags() instead.
@@ -1176,12 +1176,12 @@ int expand_set_eadirection(optexpand_T *args, int *numMatches, char ***matches)
/// options is changed.
const char *did_set_encoding(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
char **varp = (char **)args->os_varp;
int opt_flags = args->os_flags;
// Get the global option to compare with, otherwise we would have to check
// two values for all local options.
- char **gvarp = (char **)get_varp_scope_from(get_option(args->os_idx), OPT_GLOBAL, args->os_ctx);
+ char **gvarp = (char **)get_option_varp_scope_from(args->os_idx, OPT_GLOBAL, buf, NULL);
if (gvarp == &p_fenc) {
if (!MODIFIABLE(buf) && opt_flags != OPT_GLOBAL) {
@@ -1246,7 +1246,7 @@ int expand_set_eventignore(optexpand_T *args, int *numMatches, char ***matches)
/// The 'fileformat' option is changed.
const char *did_set_fileformat(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
char **varp = (char **)args->os_varp;
const char *oldval = args->os_oldval.string.data;
int opt_flags = args->os_flags;
@@ -1347,7 +1347,7 @@ int expand_set_foldcolumn(optexpand_T *args, int *numMatches, char ***matches)
/// The 'foldexpr' option is changed.
const char *did_set_foldexpr(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
did_set_optexpr(args);
if (foldmethodIsExpr(win)) {
foldUpdateAll(win);
@@ -1358,7 +1358,7 @@ const char *did_set_foldexpr(optset_T *args)
/// The 'foldignore' option is changed.
const char *did_set_foldignore(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
if (foldmethodIsIndent(win)) {
foldUpdateAll(win);
}
@@ -1368,7 +1368,7 @@ const char *did_set_foldignore(optset_T *args)
/// The 'foldmarker' option is changed.
const char *did_set_foldmarker(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
char **varp = (char **)args->os_varp;
char *p = vim_strchr(*varp, ',');
@@ -1390,7 +1390,7 @@ const char *did_set_foldmarker(optset_T *args)
/// The 'foldmethod' option is changed.
const char *did_set_foldmethod(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
char **varp = (char **)args->os_varp;
if (check_opt_strings(*varp, opt_fdm_values, false) != OK || **varp == NUL) {
return e_invarg;
@@ -1536,7 +1536,7 @@ const char *did_set_iskeyword(optset_T *args)
/// changed.
const char *did_set_isopt(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
+ 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
@@ -1565,7 +1565,7 @@ int expand_set_jumpoptions(optexpand_T *args, int *numMatches, char ***matches)
/// The 'keymap' option has changed.
const char *did_set_keymap(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
char **varp = (char **)args->os_varp;
int opt_flags = args->os_flags;
@@ -2053,7 +2053,7 @@ int expand_set_showcmdloc(optexpand_T *args, int *numMatches, char ***matches)
/// The 'signcolumn' option is changed.
const char *did_set_signcolumn(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
char **varp = (char **)args->os_varp;
const char *oldval = args->os_oldval.string.data;
if (check_signcolumn(*varp, varp == &win->w_p_scl ? win : NULL) != OK) {
@@ -2079,7 +2079,7 @@ int expand_set_signcolumn(optexpand_T *args, int *numMatches, char ***matches)
/// The 'spellcapcheck' option is changed.
const char *did_set_spellcapcheck(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
// When 'spellcapcheck' is set compile the regexp program.
return compile_cap_prog(win->w_s);
}
@@ -2113,7 +2113,7 @@ const char *did_set_spelllang(optset_T *args)
/// The 'spelloptions' option is changed.
const char *did_set_spelloptions(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
int opt_flags = args->os_flags;
const char *val = args->os_newval.string.data;
@@ -2189,7 +2189,7 @@ const char *did_set_statusline(optset_T *args)
static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerformat,
bool statuscolumn)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
char **varp = (char **)args->os_varp;
if (rulerformat) { // reset ru_wid first
ru_wid = 0;
@@ -2264,7 +2264,7 @@ const char *did_set_tabline(optset_T *args)
/// The 'tagcase' option is changed.
const char *did_set_tagcase(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
int opt_flags = args->os_flags;
unsigned *flags;
@@ -2337,7 +2337,7 @@ const char *did_set_titlestring(optset_T *args)
/// The 'varsofttabstop' option is changed.
const char *did_set_varsofttabstop(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
char **varp = (char **)args->os_varp;
if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
@@ -2367,8 +2367,8 @@ const char *did_set_varsofttabstop(optset_T *args)
/// The 'varstabstop' option is changed.
const char *did_set_vartabstop(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
- win_T *win = args->os_ctx.win;
+ buf_T *buf = (buf_T *)args->os_buf;
+ win_T *win = (win_T *)args->os_win;
char **varp = (char **)args->os_varp;
if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
@@ -2417,7 +2417,7 @@ const char *did_set_viewoptions(optset_T *args FUNC_ATTR_UNUSED)
/// The 'virtualedit' option is changed.
const char *did_set_virtualedit(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
char *ve = p_ve;
unsigned *flags = &ve_flags;
@@ -2527,7 +2527,7 @@ const char *did_set_winbar(optset_T *args)
/// The 'winhighlight' option is changed.
const char *did_set_winhighlight(optset_T *args)
{
- win_T *win = args->os_ctx.win;
+ win_T *win = (win_T *)args->os_win;
char **varp = (char **)args->os_varp;
if (!parse_winhl_opt(*varp, varp == &win->w_p_winhl ? win : NULL)) {
return e_invarg;
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 9375629abc..c676b00986 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -228,7 +228,7 @@ static Callback tfu_cb; // 'tagfunc' callback function
/// a function (string), or function(<name>) or funcref(<name>) or a lambda.
const char *did_set_tagfunc(optset_T *args)
{
- buf_T *buf = args->os_ctx.buf;
+ buf_T *buf = (buf_T *)args->os_buf;
callback_free(&tfu_cb);
callback_free(&buf->b_tfu_cb);
diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c
index 78f3551087..3e791e2beb 100644
--- a/src/nvim/winfloat.c
+++ b/src/nvim/winfloat.c
@@ -411,8 +411,8 @@ win_T *win_float_create(bool enter, bool new_buf)
return handle_error_and_cleanup(wp, &err);
}
buf->b_p_bl = false; // unlist
- set_option_direct_for(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("wipe"),
- option_ctx_from(kOptScopeBuf, buf), OPT_LOCAL, 0);
+ set_option_direct_for(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("wipe"), OPT_LOCAL, 0,
+ kOptScopeBuf, buf);
win_set_buf(wp, buf, &err);
if (ERROR_SET(&err)) {
return handle_error_and_cleanup(wp, &err);
diff --git a/test/functional/lua/with_spec.lua b/test/functional/lua/with_spec.lua
index a68a7722a4..92e798e7f3 100644
--- a/test/functional/lua/with_spec.lua
+++ b/test/functional/lua/with_spec.lua
@@ -882,7 +882,11 @@ describe('vim._with', function()
eq({
bo = { cms_cur = '// %s', cms_other = '-- %s', ul_cur = 250, ul_other = -123456 },
wo = { ve_cur = 'insert', ve_other = 'block', winbl_cur = 25, winbl_other = 10 },
- go = { cms = '-- %s', ul = 0, ve = 'none', winbl = 50, lmap = 'xy,yx' },
+ -- Global `winbl` inside context ideally should be untouched and equal
+ -- to 50. It seems to be equal to 0 because `context.buf` uses
+ -- `aucmd_prepbuf` C approach which has no guarantees about window or
+ -- window option values inside context.
+ go = { cms = '-- %s', ul = 0, ve = 'none', winbl = 0, lmap = 'xy,yx' },
}, out.inner)
eq(out.before, out.after)
end)