diff options
Diffstat (limited to 'src/nvim/api/options.c')
-rw-r--r-- | src/nvim/api/options.c | 344 |
1 files changed, 44 insertions, 300 deletions
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index c012a69c7b..d9bc0ccc92 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -9,24 +9,22 @@ #include "nvim/api/private/helpers.h" #include "nvim/api/private/validate.h" #include "nvim/autocmd.h" +#include "nvim/autocmd_defs.h" #include "nvim/buffer.h" -#include "nvim/eval/window.h" -#include "nvim/func_attr.h" +#include "nvim/buffer_defs.h" #include "nvim/globals.h" -#include "nvim/macros_defs.h" #include "nvim/memory.h" #include "nvim/option.h" -#include "nvim/option_vars.h" +#include "nvim/types_defs.h" #include "nvim/vim_defs.h" -#include "nvim/window.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/options.c.generated.h" #endif -static int validate_option_value_args(Dict(option) *opts, char *name, int *scope, - OptReqScope *req_scope, void **from, char **filetype, - Error *err) +static int validate_option_value_args(Dict(option) *opts, char *name, OptIndex *opt_idxp, + int *scope, OptReqScope *req_scope, void **from, + char **filetype, Error *err) { #define HAS_KEY_X(d, v) HAS_KEY(d, option, v) if (HAS_KEY_X(opts, scope)) { @@ -80,7 +78,8 @@ static int validate_option_value_args(Dict(option) *opts, char *name, int *scope return FAIL; }); - int flags = get_option_attrs(name); + *opt_idxp = find_option(name); + int flags = get_option_attrs(*opt_idxp); if (flags == 0) { // hidden or unknown option api_set_error(err, kErrorTypeValidation, "Unknown option '%s'", name); @@ -120,10 +119,10 @@ static buf_T *do_ft_buf(char *filetype, aco_save_T *aco, Error *err) aucmd_prepbuf(aco, ftbuf); TRY_WRAP(err, { - set_option_value("bufhidden", STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL); - set_option_value("buftype", STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL); - set_option_value("swapfile", BOOLEAN_OPTVAL(false), OPT_LOCAL); - set_option_value("modeline", BOOLEAN_OPTVAL(false), OPT_LOCAL); // 'nomodeline' + set_option_value(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL); + set_option_value(kOptBuftype, STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL); + set_option_value(kOptSwapfile, BOOLEAN_OPTVAL(false), OPT_LOCAL); + set_option_value(kOptModeline, BOOLEAN_OPTVAL(false), OPT_LOCAL); // 'nomodeline' ftbuf->b_p_ft = xstrdup(filetype); do_filetype_autocmd(ftbuf, false); @@ -151,25 +150,24 @@ static buf_T *do_ft_buf(char *filetype, aco_save_T *aco, Error *err) /// @param[out] err Error details, if any /// @return Option value Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) - FUNC_API_SINCE(9) + FUNC_API_SINCE(9) FUNC_API_RET_ALLOC { - Object rv = OBJECT_INIT; - OptVal value = NIL_OPTVAL; - + OptIndex opt_idx = 0; int scope = 0; OptReqScope req_scope = kOptReqGlobal; void *from = NULL; char *filetype = NULL; - if (!validate_option_value_args(opts, name.data, &scope, &req_scope, &from, &filetype, err)) { - goto err; + if (!validate_option_value_args(opts, name.data, &opt_idx, &scope, &req_scope, &from, &filetype, + err)) { + return (Object)OBJECT_INIT; } aco_save_T aco; buf_T *ftbuf = do_ft_buf(filetype, &aco, err); if (ERROR_SET(err)) { - goto err; + return (Object)OBJECT_INIT; } if (ftbuf != NULL) { @@ -177,8 +175,8 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) from = ftbuf; } - bool hidden; - value = get_option_value_for(name.data, NULL, scope, &hidden, req_scope, from, err); + OptVal value = get_option_value_for(opt_idx, scope, req_scope, from, err); + bool hidden = is_option_hidden(opt_idx); if (ftbuf != NULL) { // restore curwin/curbuf and a few other things @@ -199,7 +197,7 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) return optval_as_object(value); err: optval_free(value); - return rv; + return (Object)OBJECT_INIT; } /// Sets the value of an option. The behavior of this function matches that of @@ -220,10 +218,11 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict( Error *err) FUNC_API_SINCE(9) { + OptIndex opt_idx = 0; int scope = 0; OptReqScope req_scope = kOptReqGlobal; void *to = NULL; - if (!validate_option_value_args(opts, name.data, &scope, &req_scope, &to, NULL, err)) { + if (!validate_option_value_args(opts, name.data, &opt_idx, &scope, &req_scope, &to, NULL, err)) { return; } @@ -234,7 +233,7 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict( // // Then force scope to local since we don't want to change the global option if (req_scope == kOptReqWin && scope == 0) { - int flags = get_option_attrs(name.data); + int flags = get_option_attrs(opt_idx); if (flags & SOPT_GLOBAL) { scope = OPT_LOCAL; } @@ -252,7 +251,7 @@ 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, optval, scope, req_scope, to, err); + set_option_value_for(name.data, opt_idx, optval, scope, req_scope, to, err); }); } @@ -264,30 +263,30 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict( /// @see |nvim_get_commands()| /// /// @return dictionary of all options -Dictionary nvim_get_all_options_info(Error *err) +Dictionary nvim_get_all_options_info(Arena *arena, Error *err) FUNC_API_SINCE(7) { - return get_all_vimoptions(); + return get_all_vimoptions(arena); } /// Gets the option information for one option from arbitrary buffer or window /// /// Resulting dictionary has keys: -/// - name: Name of the option (like 'filetype') -/// - shortname: Shortened name of the option (like 'ft') -/// - type: type of option ("string", "number" or "boolean") -/// - default: The default value for the option -/// - was_set: Whether the option was set. +/// - name: Name of the option (like 'filetype') +/// - shortname: Shortened name of the option (like 'ft') +/// - type: type of option ("string", "number" or "boolean") +/// - default: The default value for the option +/// - was_set: Whether the option was set. /// -/// - last_set_sid: Last set script id (if any) -/// - last_set_linenr: line number where option was set -/// - last_set_chan: Channel where option was set (0 for local) +/// - last_set_sid: Last set script id (if any) +/// - last_set_linenr: line number where option was set +/// - last_set_chan: Channel where option was set (0 for local) /// -/// - scope: one of "global", "win", or "buf" -/// - global_local: whether win or buf option has a global value +/// - scope: one of "global", "win", or "buf" +/// - global_local: whether win or buf option has a global value /// -/// - commalist: List of comma separated values -/// - flaglist: List of single char flags +/// - commalist: List of comma separated values +/// - flaglist: List of single char flags /// /// When {scope} is not provided, the last set information applies to the local /// value in the current buffer or window if it is available, otherwise the @@ -303,275 +302,20 @@ Dictionary nvim_get_all_options_info(Error *err) /// Implies {scope} is "local". /// @param[out] err Error details, if any /// @return Option Information -Dictionary nvim_get_option_info2(String name, Dict(option) *opts, Error *err) +Dictionary nvim_get_option_info2(String name, Dict(option) *opts, Arena *arena, Error *err) FUNC_API_SINCE(11) { + OptIndex opt_idx = 0; int scope = 0; OptReqScope req_scope = kOptReqGlobal; void *from = NULL; - if (!validate_option_value_args(opts, name.data, &scope, &req_scope, &from, NULL, err)) { + if (!validate_option_value_args(opts, name.data, &opt_idx, &scope, &req_scope, &from, NULL, + err)) { return (Dictionary)ARRAY_DICT_INIT; } buf_T *buf = (req_scope == kOptReqBuf) ? (buf_T *)from : curbuf; win_T *win = (req_scope == kOptReqWin) ? (win_T *)from : curwin; - return get_vimoption(name, scope, buf, win, err); -} - -/// 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 req_scope Requested option scope. See OptReqScope 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, OptReqScope req_scope, void *const from, - Error *err) -{ - switch (req_scope) { - case kOptReqWin: { - 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 (try_end(err)) { - return false; - } - api_set_error(err, kErrorTypeException, "Problem while switching windows"); - return false; - } - return true; - } - case kOptReqBuf: { - 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; - } - case kOptReqGlobal: - return false; - } - UNREACHABLE; -} - -/// Restore context after getting/setting option for window/buffer. See switch_option_context() for -/// params. -static void restore_option_context(void *const ctx, OptReqScope req_scope) -{ - switch (req_scope) { - case kOptReqWin: - restore_win_noblock((switchwin_T *)ctx, true); - break; - case kOptReqBuf: - aucmd_restbuf((aco_save_T *)ctx); - break; - case kOptReqGlobal: - break; - } -} - -/// Get attributes for an option. -/// -/// @param name Option name. -/// -/// @return Option attributes. -/// 0 for hidden or unknown option. -/// See SOPT_* in option_defs.h for other flags. -int get_option_attrs(char *name) -{ - int opt_idx = findoption(name); - - if (opt_idx < 0) { - return 0; - } - - vimoption_T *opt = get_option(opt_idx); - - if (is_tty_option(opt->fullname)) { - return SOPT_STRING | SOPT_GLOBAL; - } - - // Hidden option - if (opt->var == NULL) { - return 0; - } - - int attrs = 0; - - if (opt->flags & P_BOOL) { - attrs |= SOPT_BOOL; - } else if (opt->flags & P_NUM) { - attrs |= SOPT_NUM; - } else if (opt->flags & P_STRING) { - attrs |= SOPT_STRING; - } - - if (opt->indir == PV_NONE || (opt->indir & PV_BOTH)) { - attrs |= SOPT_GLOBAL; - } - if (opt->indir & PV_WIN) { - attrs |= SOPT_WIN; - } else if (opt->indir & PV_BUF) { - attrs |= SOPT_BUF; - } - - return attrs; -} - -/// Check if option has a value in the requested scope. -/// -/// @param name Option name. -/// @param req_scope Requested option scope. See OptReqScope in option.h. -/// -/// @return true if option has a value in the requested scope, false otherwise. -static bool option_has_scope(char *name, OptReqScope req_scope) -{ - int opt_idx = findoption(name); - - if (opt_idx < 0) { - return false; - } - - vimoption_T *opt = get_option(opt_idx); - - // Hidden option. - if (opt->var == NULL) { - return false; - } - // TTY option. - if (is_tty_option(opt->fullname)) { - return req_scope == kOptReqGlobal; - } - - switch (req_scope) { - case kOptReqGlobal: - return opt->var != VAR_WIN; - case kOptReqBuf: - return opt->indir & PV_BUF; - case kOptReqWin: - return opt->indir & PV_WIN; - } - UNREACHABLE; -} - -/// Get the option value in the requested scope. -/// -/// @param name Option name. -/// @param req_scope Requested option scope. See OptReqScope in option.h. -/// @param[in] from Pointer to buffer or window for local option value. -/// @param[out] err Error message, if any. -/// -/// @return Option value in the requested scope. Returns a Nil option value if option is not found, -/// hidden or if it isn't present in the requested scope. (i.e. has no global, window-local or -/// buffer-local value depending on opt_scope). -OptVal get_option_value_strict(char *name, OptReqScope req_scope, void *from, Error *err) -{ - OptVal retv = NIL_OPTVAL; - - if (!option_has_scope(name, req_scope)) { - return retv; - } - if (get_tty_option(name, &retv.data.string.data)) { - retv.type = kOptValTypeString; - return retv; - } - - int opt_idx = findoption(name); - assert(opt_idx != 0); // option_has_scope() already verifies if option name is valid. - - vimoption_T *opt = get_option(opt_idx); - switchwin_T switchwin; - aco_save_T aco; - void *ctx = req_scope == kOptReqWin ? (void *)&switchwin - : (req_scope == kOptReqBuf ? (void *)&aco : NULL); - bool switched = switch_option_context(ctx, req_scope, from, err); - if (ERROR_SET(err)) { - return retv; - } - - char *varp = get_varp_scope(opt, req_scope == kOptReqGlobal ? OPT_GLOBAL : OPT_LOCAL); - retv = optval_from_varp(opt_idx, varp); - - if (switched) { - restore_option_context(ctx, req_scope); - } - - return retv; -} - -/// Get option value for buffer / window. -/// -/// @param[in] name Option name. -/// @param[out] flagsp Set to the option flags (P_xxxx) (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 req_scope Requested option scope. See OptReqScope 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(const char *const name, uint32_t *flagsp, int scope, bool *hidden, - const OptReqScope req_scope, void *const from, Error *err) -{ - switchwin_T switchwin; - aco_save_T aco; - void *ctx = req_scope == kOptReqWin ? (void *)&switchwin - : (req_scope == kOptReqBuf ? (void *)&aco : NULL); - - bool switched = switch_option_context(ctx, req_scope, from, err); - if (ERROR_SET(err)) { - return NIL_OPTVAL; - } - - OptVal retv = get_option_value(name, flagsp, scope, hidden); - - if (switched) { - restore_option_context(ctx, req_scope); - } - - return retv; -} - -/// Set option value for buffer / window. -/// -/// @param[in] name Option name. -/// @param[in] value Option value. -/// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both). -/// @param req_scope Requested option scope. See OptReqScope in option.h. -/// @param[in] from Target buffer/window. -/// @param[out] err Error message, if any. -void set_option_value_for(const char *const name, OptVal value, const int opt_flags, - const OptReqScope req_scope, void *const from, Error *err) -{ - switchwin_T switchwin; - aco_save_T aco; - void *ctx = req_scope == kOptReqWin ? (void *)&switchwin - : (req_scope == kOptReqBuf ? (void *)&aco : NULL); - - bool switched = switch_option_context(ctx, req_scope, from, err); - if (ERROR_SET(err)) { - return; - } - - const char *const errmsg = set_option_value(name, value, opt_flags); - if (errmsg) { - api_set_error(err, kErrorTypeException, "%s", errmsg); - } - - if (switched) { - restore_option_context(ctx, req_scope); - } + return get_vimoption(name, scope, buf, win, arena, err); } |