mirror of
https://github.com/neovim/neovim.git
synced 2025-09-27 05:28:33 +00:00
refactor(options): reduce findoption()
usage
Problem: Many places in the code use `findoption()` to access an option using its name, even if the option index is available. This is very slow because it requires looping through the options array over and over. Solution: Use option index instead of name wherever possible. Also introduce an `OptIndex` enum which contains the index for every option as enum constants, this eliminates the need to pass static option names as strings.
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
# include "api/options.c.generated.h"
|
||||
#endif
|
||||
|
||||
static int validate_option_value_args(Dict(option) *opts, char *name, int *scope,
|
||||
static int validate_option_value_args(Dict(option) *opts, char *name, int *opt_idx, int *scope,
|
||||
OptReqScope *req_scope, void **from, char **filetype,
|
||||
Error *err)
|
||||
{
|
||||
@@ -79,7 +79,8 @@ static int validate_option_value_args(Dict(option) *opts, char *name, int *scope
|
||||
return FAIL;
|
||||
});
|
||||
|
||||
int flags = get_option_attrs(name);
|
||||
*opt_idx = findoption(name);
|
||||
int flags = get_option_attrs(*opt_idx);
|
||||
if (flags == 0) {
|
||||
// hidden or unknown option
|
||||
api_set_error(err, kErrorTypeValidation, "Unknown option '%s'", name);
|
||||
@@ -119,10 +120,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);
|
||||
@@ -152,12 +153,14 @@ static buf_T *do_ft_buf(char *filetype, aco_save_T *aco, Error *err)
|
||||
Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
|
||||
FUNC_API_SINCE(9)
|
||||
{
|
||||
int 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)) {
|
||||
if (!validate_option_value_args(opts, name.data, &opt_idx, &scope, &req_scope, &from, &filetype,
|
||||
err)) {
|
||||
return (Object)OBJECT_INIT;
|
||||
}
|
||||
|
||||
@@ -173,7 +176,6 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
|
||||
from = ftbuf;
|
||||
}
|
||||
|
||||
int opt_idx = findoption(name.data);
|
||||
OptVal value = get_option_value_for(opt_idx, scope, req_scope, from, err);
|
||||
bool hidden = is_option_hidden(opt_idx);
|
||||
|
||||
@@ -217,10 +219,11 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict(
|
||||
Error *err)
|
||||
FUNC_API_SINCE(9)
|
||||
{
|
||||
int 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;
|
||||
}
|
||||
|
||||
@@ -231,7 +234,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;
|
||||
}
|
||||
@@ -249,7 +252,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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -303,10 +306,12 @@ Dictionary nvim_get_all_options_info(Error *err)
|
||||
Dictionary nvim_get_option_info2(String name, Dict(option) *opts, Error *err)
|
||||
FUNC_API_SINCE(11)
|
||||
{
|
||||
int 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;
|
||||
}
|
||||
|
||||
@@ -382,19 +387,13 @@ static void restore_option_context(void *const ctx, OptReqScope req_scope)
|
||||
|
||||
/// Get attributes for an option.
|
||||
///
|
||||
/// @param name Option name.
|
||||
/// @param opt_idx Option index in options[] table.
|
||||
///
|
||||
/// @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 get_option_attrs(int opt_idx)
|
||||
{
|
||||
if (is_tty_option(name)) {
|
||||
return SOPT_GLOBAL;
|
||||
}
|
||||
|
||||
int opt_idx = findoption(name);
|
||||
|
||||
if (opt_idx < 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -422,14 +421,12 @@ int get_option_attrs(char *name)
|
||||
|
||||
/// Check if option has a value in the requested scope.
|
||||
///
|
||||
/// @param name Option name.
|
||||
/// @param opt_idx Option index in options[] table.
|
||||
/// @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)
|
||||
static bool option_has_scope(int opt_idx, OptReqScope req_scope)
|
||||
{
|
||||
int opt_idx = findoption(name);
|
||||
|
||||
if (opt_idx < 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -458,7 +455,7 @@ static bool option_has_scope(char *name, OptReqScope req_scope)
|
||||
|
||||
/// Get the option value in the requested scope.
|
||||
///
|
||||
/// @param name Option name.
|
||||
/// @param opt_idx Option index in options[] table.
|
||||
/// @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.
|
||||
@@ -466,17 +463,11 @@ static bool option_has_scope(char *name, OptReqScope req_scope)
|
||||
/// @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 get_option_value_strict(int opt_idx, OptReqScope req_scope, void *from, Error *err)
|
||||
{
|
||||
if (!option_has_scope(name, req_scope)) {
|
||||
if (opt_idx < 0 || !option_has_scope(opt_idx, req_scope)) {
|
||||
return NIL_OPTVAL;
|
||||
}
|
||||
if (is_tty_option(name)) {
|
||||
return get_tty_option(name);
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -533,14 +524,16 @@ OptVal get_option_value_for(int opt_idx, int scope, const OptReqScope req_scope,
|
||||
|
||||
/// Set option value for buffer / window.
|
||||
///
|
||||
/// @param[in] name Option name.
|
||||
/// @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 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,
|
||||
void set_option_value_for(const char *name, int opt_idx, OptVal value, const int opt_flags,
|
||||
const OptReqScope req_scope, void *const from, Error *err)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
switchwin_T switchwin;
|
||||
aco_save_T aco;
|
||||
@@ -552,7 +545,7 @@ void set_option_value_for(const char *const name, OptVal value, const int opt_fl
|
||||
return;
|
||||
}
|
||||
|
||||
const char *const errmsg = set_option_value(name, value, opt_flags);
|
||||
const char *const errmsg = set_option_value_handle_tty(name, opt_idx, value, opt_flags);
|
||||
if (errmsg) {
|
||||
api_set_error(err, kErrorTypeException, "%s", errmsg);
|
||||
}
|
||||
|
Reference in New Issue
Block a user