aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/api/options.c')
-rw-r--r--src/nvim/api/options.c344
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);
}