diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | src/nvim/api/deprecated.c | 60 | ||||
| -rw-r--r-- | src/nvim/api/options.c | 42 | ||||
| -rw-r--r-- | src/nvim/api/vim.c | 8 | ||||
| -rw-r--r-- | src/nvim/buffer_defs.h | 4 | ||||
| -rw-r--r-- | src/nvim/diff.c | 4 | ||||
| -rw-r--r-- | src/nvim/eval.c | 2 | ||||
| -rw-r--r-- | src/nvim/file_search.c | 2 | ||||
| -rw-r--r-- | src/nvim/fold.c | 2 | ||||
| -rw-r--r-- | src/nvim/generators/gen_options.lua | 219 | ||||
| -rw-r--r-- | src/nvim/generators/gen_options_enum.lua | 129 | ||||
| -rw-r--r-- | src/nvim/indent.c | 2 | ||||
| -rw-r--r-- | src/nvim/option.c | 803 | ||||
| -rw-r--r-- | src/nvim/option.h | 57 | ||||
| -rw-r--r-- | src/nvim/option_defs.h | 41 | ||||
| -rw-r--r-- | src/nvim/options.lua | 287 | ||||
| -rw-r--r-- | src/nvim/textformat.c | 2 | ||||
| -rw-r--r-- | src/nvim/window.c | 4 | ||||
| -rw-r--r-- | src/nvim/winfloat.c | 4 |
19 files changed, 795 insertions, 887 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index cb71144130..344b4bef00 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -308,7 +308,6 @@ set(GENERATOR_C_GRAMMAR ${GENERATOR_DIR}/c_grammar.lua) set(GENERATOR_HASHY ${GENERATOR_DIR}/hashy.lua) set(GENERATOR_PRELOAD ${GENERATOR_DIR}/preload.lua) set(HEADER_GENERATOR ${GENERATOR_DIR}/gen_declarations.lua) -set(OPTIONS_ENUM_GENERATOR ${GENERATOR_DIR}/gen_options_enum.lua) set(OPTIONS_GENERATOR ${GENERATOR_DIR}/gen_options.lua) # GENERATED_DIR and GENERATED_INCLUDES_DIR @@ -687,16 +686,11 @@ add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} DEPENDS ${LUA_GEN_DEPS} ${EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/auevents.lua ) -add_custom_command(OUTPUT ${GENERATED_OPTIONS} - COMMAND ${LUA_GEN} ${OPTIONS_GENERATOR} ${GENERATED_OPTIONS} +add_custom_command(OUTPUT ${GENERATED_OPTIONS} ${GENERATED_OPTIONS_ENUM} ${GENERATED_OPTIONS_MAP} + COMMAND ${LUA_GEN} ${OPTIONS_GENERATOR} ${GENERATED_OPTIONS} ${GENERATED_OPTIONS_ENUM} ${GENERATED_OPTIONS_MAP} DEPENDS ${LUA_GEN_DEPS} ${OPTIONS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/options.lua ) -add_custom_command(OUTPUT ${GENERATED_OPTIONS_ENUM} ${GENERATED_OPTIONS_MAP} - COMMAND ${LUA_GEN} ${OPTIONS_ENUM_GENERATOR} ${GENERATED_OPTIONS_ENUM} ${GENERATED_OPTIONS_MAP} - DEPENDS ${LUA_GEN_DEPS} ${OPTIONS_ENUM_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/options.lua -) - # NVIM_GENERATED_FOR_SOURCES and NVIM_GENERATED_FOR_HEADERS must be mutually exclusive. foreach(hfile ${NVIM_GENERATED_FOR_HEADERS}) list(FIND NVIM_GENERATED_FOR_SOURCES ${hfile} hfile_idx) diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index b3ba832fec..b38a7d4173 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -533,7 +533,7 @@ void nvim_set_option(uint64_t channel_id, String name, Object value, Error *err) FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(11) { - set_option_to(channel_id, NULL, kOptReqGlobal, name, value, err); + set_option_to(channel_id, NULL, kOptScopeGlobal, name, value, err); } /// Gets the global value of an option. @@ -546,7 +546,7 @@ Object nvim_get_option(String name, Error *err) FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(11) { - return get_option_from(NULL, kOptReqGlobal, name, err); + return get_option_from(NULL, kOptScopeGlobal, name, err); } /// Gets a buffer option value @@ -566,7 +566,7 @@ Object nvim_buf_get_option(Buffer buffer, String name, Error *err) return (Object)OBJECT_INIT; } - return get_option_from(buf, kOptReqBuf, name, err); + return get_option_from(buf, kOptScopeBuf, name, err); } /// Sets a buffer option value. Passing `nil` as value deletes the option (only @@ -588,7 +588,7 @@ void nvim_buf_set_option(uint64_t channel_id, Buffer buffer, String name, Object return; } - set_option_to(channel_id, buf, kOptReqBuf, name, value, err); + set_option_to(channel_id, buf, kOptScopeBuf, name, value, err); } /// Gets a window option value @@ -608,7 +608,7 @@ Object nvim_win_get_option(Window window, String name, Error *err) return (Object)OBJECT_INIT; } - return get_option_from(win, kOptReqWin, name, err); + return get_option_from(win, kOptScopeWin, name, err); } /// Sets a window option value. Passing `nil` as value deletes the option (only @@ -630,48 +630,18 @@ void nvim_win_set_option(uint64_t channel_id, Window window, String name, Object return; } - set_option_to(channel_id, win, kOptReqWin, name, value, err); -} - -/// Check if option has a value in the requested scope. -/// -/// @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(OptIndex opt_idx, OptReqScope req_scope) -{ - if (opt_idx == kOptInvalid) { - return false; - } - - vimoption_T *opt = get_option(opt_idx); - - // 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; + set_option_to(channel_id, win, kOptScopeWin, name, value, err); } /// Gets the value of a global or local (buffer, window) option. /// /// @param[in] from Pointer to buffer or window for local option value. -/// @param req_scope Requested option scope. See OptReqScope in option.h. +/// @param req_scope Requested option scope. See OptScope in option.h. /// @param name The option name. /// @param[out] err Details of an error that may have occurred. /// /// @return the option value. -static Object get_option_from(void *from, OptReqScope req_scope, String name, Error *err) +static Object get_option_from(void *from, OptScope req_scope, String name, Error *err) { VALIDATE_S(name.size > 0, "option name", "<empty>", { return (Object)OBJECT_INIT; @@ -681,7 +651,7 @@ static Object get_option_from(void *from, OptReqScope req_scope, String name, Er OptVal value = NIL_OPTVAL; if (option_has_scope(opt_idx, req_scope)) { - value = get_option_value_for(opt_idx, req_scope == kOptReqGlobal ? OPT_GLOBAL : OPT_LOCAL, + value = get_option_value_for(opt_idx, req_scope == kOptScopeGlobal ? OPT_GLOBAL : OPT_LOCAL, req_scope, from, err); if (ERROR_SET(err)) { return (Object)OBJECT_INIT; @@ -698,11 +668,11 @@ static Object get_option_from(void *from, OptReqScope req_scope, String name, Er /// Sets the value of a global or local (buffer, window) option. /// /// @param[in] to Pointer to buffer or window for local option value. -/// @param req_scope Requested option scope. See OptReqScope in option.h. +/// @param req_scope Requested option scope. See OptScope in option.h. /// @param name The option name. /// @param value New option value. /// @param[out] err Details of an error that may have occurred. -static void set_option_to(uint64_t channel_id, void *to, OptReqScope req_scope, String name, +static void set_option_to(uint64_t channel_id, void *to, OptScope req_scope, String name, Object value, Error *err) { VALIDATE_S(name.size > 0, "option name", "<empty>", { @@ -725,12 +695,12 @@ static void set_option_to(uint64_t channel_id, void *to, OptReqScope req_scope, return; }); - int attrs = get_option_attrs(opt_idx); // For global-win-local options -> setlocal // For win-local options -> setglobal and setlocal (opt_flags == 0) - const int opt_flags = (req_scope == kOptReqWin && !(attrs & SOPT_GLOBAL)) - ? 0 - : (req_scope == kOptReqGlobal) ? OPT_GLOBAL : OPT_LOCAL; + const int opt_flags + = (req_scope == kOptScopeWin && !option_has_scope(opt_idx, kOptScopeGlobal)) + ? 0 + : ((req_scope == kOptScopeGlobal) ? OPT_GLOBAL : OPT_LOCAL); WITH_SCRIPT_CONTEXT(channel_id, { set_option_value_for(name.data, opt_idx, optval, opt_flags, req_scope, to, err); diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index 96866d80ba..bbfd00f2ea 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -23,8 +23,8 @@ #endif 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) + int *scope, OptScope *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)) { @@ -39,14 +39,14 @@ static int validate_option_value_args(Dict(option) *opts, char *name, OptIndex * } } - *req_scope = kOptReqGlobal; + *req_scope = kOptScopeGlobal; if (filetype != NULL && HAS_KEY_X(opts, filetype)) { *filetype = opts->filetype.data; } if (HAS_KEY_X(opts, win)) { - *req_scope = kOptReqWin; + *req_scope = kOptScopeWin; *from = find_window_by_handle(opts->win, err); if (ERROR_SET(err)) { return FAIL; @@ -59,7 +59,7 @@ static int validate_option_value_args(Dict(option) *opts, char *name, OptIndex * return FAIL; }); *scope = OPT_LOCAL; - *req_scope = kOptReqBuf; + *req_scope = kOptScopeBuf; *from = find_buffer_by_handle(opts->buf, err); if (ERROR_SET(err)) { return FAIL; @@ -78,18 +78,17 @@ static int validate_option_value_args(Dict(option) *opts, char *name, OptIndex * }); *opt_idxp = find_option(name); - int flags = get_option_attrs(*opt_idxp); - if (flags == 0) { + if (*opt_idxp == kOptInvalid) { // unknown option api_set_error(err, kErrorTypeValidation, "Unknown option '%s'", name); - } else if (*req_scope == kOptReqBuf || *req_scope == kOptReqWin) { + } else if (*req_scope == kOptScopeBuf || *req_scope == kOptScopeWin) { // if 'buf' or 'win' is passed, make sure the option supports it - int req_flags = *req_scope == kOptReqBuf ? SOPT_BUF : SOPT_WIN; - if (!(flags & req_flags)) { - char *tgt = *req_scope & kOptReqBuf ? "buf" : "win"; - char *global = flags & SOPT_GLOBAL ? "global " : ""; - char *req = flags & SOPT_BUF ? "buffer-local " - : flags & SOPT_WIN ? "window-local " : ""; + if (!option_has_scope(*opt_idxp, *req_scope)) { + char *tgt = *req_scope == kOptScopeBuf ? "buf" : "win"; + char *global = option_has_scope(*opt_idxp, kOptScopeGlobal) ? "global " : ""; + char *req = option_has_scope(*opt_idxp, kOptScopeBuf) + ? "buffer-local " + : (option_has_scope(*opt_idxp, kOptScopeWin) ? "window-local " : ""); api_set_error(err, kErrorTypeValidation, "'%s' cannot be passed for %s%soption '%s'", tgt, global, req, name); @@ -153,7 +152,7 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) { OptIndex opt_idx = 0; int scope = 0; - OptReqScope req_scope = kOptReqGlobal; + OptScope req_scope = kOptScopeGlobal; void *from = NULL; char *filetype = NULL; @@ -218,7 +217,7 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict( { OptIndex opt_idx = 0; int scope = 0; - OptReqScope req_scope = kOptReqGlobal; + OptScope req_scope = kOptScopeGlobal; void *to = NULL; if (!validate_option_value_args(opts, name.data, &opt_idx, &scope, &req_scope, &to, NULL, err)) { return; @@ -230,9 +229,8 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict( // - option is global or local to window (global-local) // // 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(opt_idx); - if (flags & SOPT_GLOBAL) { + if (req_scope == kOptScopeWin && scope == 0) { + if (option_has_scope(opt_idx, kOptScopeGlobal)) { scope = OPT_LOCAL; } } @@ -305,15 +303,15 @@ Dict nvim_get_option_info2(String name, Dict(option) *opts, Arena *arena, Error { OptIndex opt_idx = 0; int scope = 0; - OptReqScope req_scope = kOptReqGlobal; + OptScope req_scope = kOptScopeGlobal; void *from = NULL; if (!validate_option_value_args(opts, name.data, &opt_idx, &scope, &req_scope, &from, NULL, err)) { return (Dict)ARRAY_DICT_INIT; } - buf_T *buf = (req_scope == kOptReqBuf) ? (buf_T *)from : curbuf; - win_T *win = (req_scope == kOptReqWin) ? (win_T *)from : curwin; + buf_T *buf = (req_scope == kOptScopeBuf) ? (buf_T *)from : curbuf; + win_T *win = (req_scope == kOptScopeWin) ? (win_T *)from : curwin; return get_vimoption(name, scope, buf, win, arena, err); } diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index e6ec88c5e8..199b9a9690 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1004,10 +1004,10 @@ Buffer nvim_create_buf(Boolean listed, Boolean scratch, Error *err) buf_copy_options(buf, BCO_ENTER | BCO_NOHELP); if (scratch) { - set_option_direct_for(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL, 0, kOptReqBuf, - buf); - set_option_direct_for(kOptBuftype, STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL, 0, kOptReqBuf, - buf); + 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/buffer_defs.h b/src/nvim/buffer_defs.h index e6bd63f4f8..d33734ccfe 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -206,7 +206,7 @@ typedef struct { OptInt wo_winbl; #define w_p_winbl w_onebuf_opt.wo_winbl // 'winblend' - LastSet wo_script_ctx[WV_COUNT]; // SCTXs for window-local options + LastSet wo_script_ctx[kWinOptCount]; // SCTXs for window-local options #define w_p_script_ctx w_onebuf_opt.wo_script_ctx } winopt_T; @@ -512,7 +512,7 @@ struct file_buffer { // or contents of the file being edited. bool b_p_initialized; // set when options initialized - LastSet b_p_script_ctx[BV_COUNT]; // SCTXs for buffer-local options + LastSet b_p_script_ctx[kBufOptCount]; // SCTXs for buffer-local options int b_p_ai; ///< 'autoindent' int b_p_ai_nopaste; ///< b_p_ai saved for paste mode diff --git a/src/nvim/diff.c b/src/nvim/diff.c index a690c70875..f1dd08f0e6 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -1390,8 +1390,8 @@ void diff_win_options(win_T *wp, bool addbuf) } wp->w_p_fdm_save = xstrdup(wp->w_p_fdm); } - set_option_direct_for(kOptFoldmethod, STATIC_CSTR_AS_OPTVAL("diff"), OPT_LOCAL, 0, kOptReqWin, - wp); + 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/eval.c b/src/nvim/eval.c index 9acbc05fdf..ab6115f145 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1368,7 +1368,7 @@ int eval_foldexpr(win_T *wp, int *cp) const bool use_sandbox = was_set_insecurely(wp, kOptFoldexpr, OPT_LOCAL); char *arg = skipwhite(wp->w_p_fde); - current_sctx = wp->w_p_script_ctx[WV_FDE].script_ctx; + current_sctx = wp->w_p_script_ctx[kWinOptFoldexpr].script_ctx; emsg_off++; if (use_sandbox) { diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index aeaf448a05..d183978d2d 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -1648,7 +1648,7 @@ static char *eval_includeexpr(const char *const ptr, const size_t len) { const sctx_T save_sctx = current_sctx; set_vim_var_string(VV_FNAME, ptr, (ptrdiff_t)len); - current_sctx = curbuf->b_p_script_ctx[BV_INEX].script_ctx; + current_sctx = curbuf->b_p_script_ctx[kBufOptIncludeexpr].script_ctx; char *res = eval_to_string_safe(curbuf->b_p_inex, was_set_insecurely(curwin, kOptIncludeexpr, OPT_LOCAL), diff --git a/src/nvim/fold.c b/src/nvim/fold.c index e7231c31ab..c9699cb161 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -1731,7 +1731,7 @@ char *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldinfo curwin = wp; curbuf = wp->w_buffer; - current_sctx = wp->w_p_script_ctx[WV_FDT].script_ctx; + current_sctx = wp->w_p_script_ctx[kWinOptFoldtext].script_ctx; emsg_off++; // handle exceptions, but don't display errors diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index 92349b5298..02f3ac3257 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -1,6 +1,10 @@ local options_file = arg[1] +local options_enum_file = arg[2] +local options_map_file = arg[3] local opt_fd = assert(io.open(options_file, 'w')) +local opt_enum_fd = assert(io.open(options_enum_file, 'w')) +local opt_map_fd = assert(io.open(options_map_file, 'w')) local w = function(s) if s:match('^ %.') then @@ -10,10 +14,129 @@ local w = function(s) end end +--- @param s string +local function enum_w(s) + opt_enum_fd:write(s .. '\n') +end + +--- @param s string +local function map_w(s) + opt_map_fd:write(s .. '\n') +end + --- @module 'nvim.options' local options = require('options') +local options_meta = options.options local cstr = options.cstr +local valid_scopes = options.valid_scopes + +--- Options for each scope. +--- @type table<string, vim.option_meta[]> +local scope_options = {} +for _, scope in ipairs(valid_scopes) do + scope_options[scope] = {} +end + +--- @param s string +--- @return string +local lowercase_to_titlecase = function(s) + return s:sub(1, 1):upper() .. s:sub(2) +end + +-- Generate options enum file +enum_w('// IWYU pragma: private, include "nvim/option_defs.h"') +enum_w('') + +--- Map of option name to option index +--- @type table<string, string> +local option_index = {} + +-- Generate option index enum and populate the `option_index` and `scope_option` dicts. +enum_w('typedef enum {') +enum_w(' kOptInvalid = -1,') + +for i, o in ipairs(options_meta) do + local enum_val_name = 'kOpt' .. lowercase_to_titlecase(o.full_name) + enum_w((' %s = %u,'):format(enum_val_name, i - 1)) + + option_index[o.full_name] = enum_val_name + + if o.abbreviation then + option_index[o.abbreviation] = enum_val_name + end + + if o.alias then + o.alias = type(o.alias) == 'string' and { o.alias } or o.alias + + for _, v in ipairs(o.alias) do + option_index[v] = enum_val_name + end + end + + for _, scope in ipairs(o.scope) do + table.insert(scope_options[scope], o) + end +end + +enum_w(' // Option count') +enum_w('#define kOptCount ' .. tostring(#options_meta)) +enum_w('} OptIndex;') + +--- @param scope string +--- @param option_name string +--- @return string +local get_scope_option = function(scope, option_name) + return ('k%sOpt%s'):format(lowercase_to_titlecase(scope), lowercase_to_titlecase(option_name)) +end + +-- Generate option index enum for each scope +for _, scope in ipairs(valid_scopes) do + enum_w('') + + local scope_name = lowercase_to_titlecase(scope) + enum_w('typedef enum {') + enum_w((' %s = -1,'):format(get_scope_option(scope, 'Invalid'))) + + for idx, option in ipairs(scope_options[scope]) do + enum_w((' %s = %u,'):format(get_scope_option(scope, option.full_name), idx - 1)) + end + + enum_w((' // %s option count'):format(scope_name)) + enum_w(('#define %s %d'):format(get_scope_option(scope, 'Count'), #scope_options[scope])) + enum_w(('} %sOptIndex;'):format(scope_name)) +end + +-- Generate reverse lookup from option scope index to option index for each scope. +for _, scope in ipairs(valid_scopes) do + enum_w('') + enum_w(('EXTERN const OptIndex %s_opt_idx[] INIT( = {'):format(scope)) + for _, option in ipairs(scope_options[scope]) do + local idx = option_index[option.full_name] + enum_w((' [%s] = %s,'):format(get_scope_option(scope, option.full_name), idx)) + end + enum_w('});') +end + +opt_enum_fd:close() + +-- Generate option index map. +local hashy = require('generators.hashy') +local neworder, hashfun = hashy.hashy_hash('find_option', vim.tbl_keys(option_index), function(idx) + return ('option_hash_elems[%s].name'):format(idx) +end) + +map_w('static const struct { const char *name; OptIndex opt_idx; } option_hash_elems[] = {') + +for _, name in ipairs(neworder) do + assert(option_index[name] ~= nil) + map_w((' { .name = "%s", .opt_idx = %s },'):format(name, option_index[name])) +end + +map_w('};\n') +map_w('static ' .. hashfun) + +opt_map_fd:close() local redraw_flags = { ui_option = 'kOptFlagUIOption', @@ -35,12 +158,6 @@ local list_flags = { flagscomma = 'kOptFlagComma|kOptFlagFlagList', } ---- @param s string ---- @return string -local lowercase_to_titlecase = function(s) - return s:sub(1, 1):upper() .. s:sub(2) -end - --- @param o vim.option_meta --- @return string local function get_flags(o) @@ -95,6 +212,12 @@ local function opt_type_enum(opt_type) return ('kOptValType%s'):format(lowercase_to_titlecase(opt_type)) end +--- @param scope vim.option_scope +--- @return string +local function opt_scope_enum(scope) + return ('kOptScope%s'):format(lowercase_to_titlecase(scope)) +end + --- @param o vim.option_meta --- @return string local function get_type_flags(o) @@ -110,6 +233,35 @@ local function get_type_flags(o) return type_flags end +--- @param o vim.option_meta +--- @return string +local function get_scope_flags(o) + local scope_flags = '0' + + for _, scope in ipairs(o.scope) do + scope_flags = ('%s | (1 << %s)'):format(scope_flags, opt_scope_enum(scope)) + end + + return scope_flags +end + +--- @param o vim.option_meta +--- @return string +local function get_scope_idx(o) + --- @type string[] + local strs = {} + + for _, scope in pairs(valid_scopes) do + local has_scope = vim.tbl_contains(o.scope, scope) + strs[#strs + 1] = (' [%s] = %s'):format( + opt_scope_enum(scope), + get_scope_option(scope, has_scope and o.full_name or 'Invalid') + ) + end + + return ('{\n%s\n }'):format(table.concat(strs, ',\n')) +end + --- @param c string|string[] --- @param base_string? string --- @return string @@ -166,7 +318,6 @@ end --- @param d vim.option_value|function --- @param n string --- @return string - local get_defaults = function(d, n) if d == nil then error("option '" .. n .. "' should have a default value") @@ -174,9 +325,6 @@ local get_defaults = function(d, n) return get_opt_val(d) end ---- @type [string,string][] -local defines = {} - --- @param i integer --- @param o vim.option_meta local function dump_option(i, o) @@ -187,42 +335,28 @@ local function dump_option(i, o) end w(' .flags=' .. get_flags(o)) w(' .type_flags=' .. get_type_flags(o)) + w(' .scope_flags=' .. get_scope_flags(o)) + w(' .scope_idx=' .. get_scope_idx(o)) if o.enable_if then w(get_cond(o.enable_if)) end - if o.varname then - w(' .var=&' .. o.varname) - elseif o.immutable then - -- Immutable options can directly point to the default value. - w((' .var=&options[%u].def_val.data'):format(i - 1)) - elseif #o.scope == 1 and o.scope[1] == 'window' then - w(' .var=VAR_WIN') + local is_window_local = #o.scope == 1 and o.scope[1] == 'win' + + if not is_window_local then + if o.varname then + w(' .var=&' .. o.varname) + elseif o.immutable then + -- Immutable options can directly point to the default value. + w((' .var=&options[%u].def_val.data'):format(i - 1)) + else + -- Option must be immutable or have a variable. + assert(false) + end else - -- Option must be immutable or have a variable. - assert(false) + w(' .var=NULL') end w(' .immutable=' .. (o.immutable and 'true' or 'false')) - if #o.scope == 1 and o.scope[1] == 'global' then - w(' .indir=PV_NONE') - else - assert(#o.scope == 1 or #o.scope == 2) - assert(#o.scope == 1 or o.scope[1] == 'global') - local min_scope = o.scope[#o.scope] - local varname = o.pv_name or o.varname or ('p_' .. (o.abbreviation or o.full_name)) - local pv_name = ( - 'OPT_' - .. min_scope:sub(1, 3):upper() - .. '(' - .. (min_scope:sub(1, 1):upper() .. 'V_' .. varname:sub(3):upper()) - .. ')' - ) - if #o.scope == 2 then - pv_name = 'OPT_BOTH(' .. pv_name .. ')' - end - table.insert(defines, { 'PV_' .. varname:sub(3):upper(), pv_name }) - w(' .indir=' .. pv_name) - end if o.cb then w(' .opt_did_set_cb=' .. o.cb) end @@ -235,7 +369,6 @@ local function dump_option(i, o) w((' .var=&options[%u].def_val.data'):format(i - 1)) -- Option is always immutable on the false branch of `enable_if`. w(' .immutable=true') - w(' .indir=PV_NONE') w('#endif') end if o.defaults then @@ -256,6 +389,7 @@ local function dump_option(i, o) w(' },') end +-- Generate options[] array. w([[ #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" @@ -274,8 +408,3 @@ for i, o in ipairs(options.options) do dump_option(i, o) end w('};') -w('') - -for _, v in ipairs(defines) do - w('#define ' .. v[1] .. ' ' .. v[2]) -end diff --git a/src/nvim/generators/gen_options_enum.lua b/src/nvim/generators/gen_options_enum.lua deleted file mode 100644 index d1419137d3..0000000000 --- a/src/nvim/generators/gen_options_enum.lua +++ /dev/null @@ -1,129 +0,0 @@ --- Generates option index enum and map of option name to option index. --- Handles option full name, short name and aliases. --- Also generates BV_ and WV_ enum constants. - -local options_enum_file = arg[1] -local options_map_file = arg[2] -local options_enum_fd = assert(io.open(options_enum_file, 'w')) -local options_map_fd = assert(io.open(options_map_file, 'w')) - ---- @param s string -local function enum_w(s) - options_enum_fd:write(s .. '\n') -end - ---- @param s string -local function map_w(s) - options_map_fd:write(s .. '\n') -end - -enum_w('// IWYU pragma: private, include "nvim/option_defs.h"') -enum_w('') - ---- @param s string ---- @return string -local lowercase_to_titlecase = function(s) - return s:sub(1, 1):upper() .. s:sub(2) -end - ---- @type vim.option_meta[] -local options = require('options').options - --- Generate BV_ enum constants. -enum_w('/// "indir" values for buffer-local options.') -enum_w('/// These need to be defined globally, so that the BV_COUNT can be used with') -enum_w('/// b_p_script_stx[].') -enum_w('enum {') - -local bv_val = 0 - -for _, o in ipairs(options) do - assert(#o.scope == 1 or #o.scope == 2) - assert(#o.scope == 1 or o.scope[1] == 'global') - local min_scope = o.scope[#o.scope] - if min_scope == 'buffer' then - local varname = o.pv_name or o.varname or ('p_' .. (o.abbreviation or o.full_name)) - local bv_name = 'BV_' .. varname:sub(3):upper() - enum_w((' %s = %u,'):format(bv_name, bv_val)) - bv_val = bv_val + 1 - end -end - -enum_w((' BV_COUNT = %u, ///< must be the last one'):format(bv_val)) -enum_w('};') -enum_w('') - --- Generate WV_ enum constants. -enum_w('/// "indir" values for window-local options.') -enum_w('/// These need to be defined globally, so that the WV_COUNT can be used in the') -enum_w('/// window structure.') -enum_w('enum {') - -local wv_val = 0 - -for _, o in ipairs(options) do - assert(#o.scope == 1 or #o.scope == 2) - assert(#o.scope == 1 or o.scope[1] == 'global') - local min_scope = o.scope[#o.scope] - if min_scope == 'window' then - local varname = o.pv_name or o.varname or ('p_' .. (o.abbreviation or o.full_name)) - local wv_name = 'WV_' .. varname:sub(3):upper() - enum_w((' %s = %u,'):format(wv_name, wv_val)) - wv_val = wv_val + 1 - end -end - -enum_w((' WV_COUNT = %u, ///< must be the last one'):format(wv_val)) -enum_w('};') -enum_w('') - ---- @type { [string]: string } -local option_index = {} - --- Generate option index enum and populate the `option_index` dict. -enum_w('typedef enum {') -enum_w(' kOptInvalid = -1,') - -for i, o in ipairs(options) do - local enum_val_name = 'kOpt' .. lowercase_to_titlecase(o.full_name) - enum_w((' %s = %u,'):format(enum_val_name, i - 1)) - - option_index[o.full_name] = enum_val_name - - if o.abbreviation then - option_index[o.abbreviation] = enum_val_name - end - - if o.alias then - o.alias = type(o.alias) == 'string' and { o.alias } or o.alias - - for _, v in ipairs(o.alias) do - option_index[v] = enum_val_name - end - end -end - -enum_w(' // Option count, used when iterating through options') -enum_w('#define kOptIndexCount ' .. tostring(#options)) -enum_w('} OptIndex;') -enum_w('') - -options_enum_fd:close() - ---- Generate option index map. -local hashy = require('generators.hashy') -local neworder, hashfun = hashy.hashy_hash('find_option', vim.tbl_keys(option_index), function(idx) - return ('option_hash_elems[%s].name'):format(idx) -end) - -map_w('static const struct { const char *name; OptIndex opt_idx; } option_hash_elems[] = {') - -for _, name in ipairs(neworder) do - assert(option_index[name] ~= nil) - map_w((' { .name = "%s", .opt_idx = %s },'):format(name, option_index[name])) -end - -map_w('};\n') -map_w('static ' .. hashfun) - -options_map_fd:close() diff --git a/src/nvim/indent.c b/src/nvim/indent.c index 58215f738c..e487728901 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -1182,7 +1182,7 @@ int get_expr_indent(void) sandbox++; } textlock++; - current_sctx = curbuf->b_p_script_ctx[BV_INDE].script_ctx; + current_sctx = curbuf->b_p_script_ctx[kBufOptIndentexpr].script_ctx; // Need to make a copy, the 'indentexpr' option could be changed while // evaluating it. diff --git a/src/nvim/option.c b/src/nvim/option.c index efd52f9233..8e94c342f7 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -303,7 +303,7 @@ static void set_init_default_cdpath(void) /// them. static void set_init_expand_env(void) { - for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) { + for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) { vimoption_T *opt = &options[opt_idx]; if (opt->flags & kOptFlagNoDefExp) { continue; @@ -435,7 +435,7 @@ void set_init_1(bool clean_arg) static OptVal get_option_default(const OptIndex opt_idx, int opt_flags) { vimoption_T *opt = &options[opt_idx]; - bool is_global_local_option = opt->indir & PV_BOTH; + bool is_global_local_option = option_is_global_local(opt_idx); #ifdef UNIX if (opt_idx == kOptModeline && getuid() == ROOT_UID) { @@ -461,7 +461,7 @@ static OptVal get_option_default(const OptIndex opt_idx, int opt_flags) /// This ensures that we don't need to always check if the option default is allocated or not. static void alloc_options_default(void) { - for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) { + for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) { options[opt_idx].def_val = optval_copy(options[opt_idx].def_val); } } @@ -500,7 +500,7 @@ static void set_option_default(const OptIndex opt_idx, int opt_flags) /// @param opt_flags Option flags. static void set_options_default(int opt_flags) { - for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) { + for (OptIndex opt_idx = 0; opt_idx < kOptCount; opt_idx++) { |