From b922b7d6d7889cce863540df7b0da7d512f8a2a1 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Fri, 25 Oct 2024 20:10:40 +0600 Subject: refactor(options)!: use OptVal for option defaults #26691 Problem: We use `void *` for option default values, which is confusing and can cause problems with type-correctness. It also doesn't accomodate for multitype options. On top of that, it also leads to default boolean option values not behaving correctly on big endian systems. Solution: Use `OptVal` for option default values. BREAKING CHANGE: - `:set {option}<` removes the local value for all global-local options instead of just string global-local options. - `:setlocal {option}<` copies the global value to the local value for number and boolean global-local options instead of removing the local value. --- src/nvim/generators/gen_options.lua | 71 ++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 21 deletions(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index 591a6b93df..24121d7938 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -90,6 +90,12 @@ local function get_flags(o) return flags end +--- @param opt_type vim.option_type +--- @return string +local function opt_type_enum(opt_type) + return ('kOptValType%s'):format(lowercase_to_titlecase(opt_type)) +end + --- @param o vim.option_meta --- @return string local function get_type_flags(o) @@ -99,7 +105,7 @@ local function get_type_flags(o) for _, opt_type in ipairs(opt_types) do assert(type(opt_type) == 'string') - type_flags = ('%s | (1 << kOptValType%s)'):format(type_flags, lowercase_to_titlecase(opt_type)) + type_flags = ('%s | (1 << %s)'):format(type_flags, opt_type_enum(opt_type)) end return type_flags @@ -125,27 +131,48 @@ local function get_cond(c, base_string) return cond_string end +--- @param s string +--- @return string +local static_cstr_as_string = function(s) + return ('{ .data = %s, .size = sizeof(%s) - 1 }'):format(s, s) +end + +--- @param v vim.option_value|function +--- @return string +local get_opt_val = function(v) + --- @type vim.option_type + local v_type + + if type(v) == 'function' then + v, v_type = v() --[[ @as string, vim.option_type ]] + + if v_type == 'string' then + v = static_cstr_as_string(v) + end + else + v_type = type(v) --[[ @as vim.option_type ]] + + if v_type == 'boolean' then + v = v and 'true' or 'false' + elseif v_type == 'number' then + v = ('%iL'):format(v) + elseif v_type == 'string' then + v = static_cstr_as_string(cstr(v)) + end + end + + return ('{ .type = %s, .data.%s = %s }'):format(opt_type_enum(v_type), v_type, v) +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") end - - local value_dumpers = { - ['function'] = function(v) - return v() - end, - string = function(v) - return '.string=' .. cstr(v) - end, - boolean = function(v) - return '.boolean=' .. (v and 'true' or 'false') - end, - number = function(v) - return ('.number=%iL'):format(v) - end, - } - - return value_dumpers[type(d)](d) + return get_opt_val(d) end --- @type [string,string][] @@ -173,7 +200,7 @@ local function dump_option(i, o) w(' .var=&' .. o.varname) elseif o.hidden or o.immutable then -- Hidden and immutable options can directly point to the default value. - w((' .var=&options[%u].def_val'):format(i - 1)) + w((' .var=&options[%u].def_val.data'):format(i - 1)) elseif #o.scope == 1 and o.scope[1] == 'window' then w(' .var=VAR_WIN') else @@ -219,14 +246,16 @@ local function dump_option(i, o) if o.defaults.condition then w(get_cond(o.defaults.condition)) end - w(' .def_val' .. get_defaults(o.defaults.if_true, o.full_name)) + w(' .def_val=' .. get_defaults(o.defaults.if_true, o.full_name)) if o.defaults.condition then if o.defaults.if_false then w('#else') - w(' .def_val' .. get_defaults(o.defaults.if_false, o.full_name)) + w(' .def_val=' .. get_defaults(o.defaults.if_false, o.full_name)) end w('#endif') end + else + w(' .def_val=NIL_OPTVAL') end w(' },') end -- cgit From b136a9ee4c5689c655713ab006be84ae9e7a313a Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sun, 27 Oct 2024 19:09:24 +0600 Subject: refactor(options): always allocate option values (#30917) Instead of keeping `P_ALLOCED` and `P_DEF_ALLOCED` flags to check if an option value is allocated, always allocate option values to simplify the logic. Ref: #25672 --- src/nvim/generators/gen_options.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index 24121d7938..b1018c1283 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -67,7 +67,6 @@ local function get_flags(o) end end for _, flag_desc in ipairs({ - { 'alloced' }, { 'nodefault' }, { 'no_mkrc' }, { 'secure' }, -- cgit From 34c44c355646311aa67fe53e1e5ce040789430c6 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Mon, 28 Oct 2024 19:49:16 +0600 Subject: refactor(options): option flags enum #30961 Problem: Currently we use macros with hardcoded flag values for option flags, which is messy and requires a lot of mental math for adding / removing option flags. Using macros for option flags also means that they cannot be used inside debuggers. Solution: Create a new `OptFlags` enum that stores all the option flags in an organized way that is easier to understand. --- src/nvim/generators/gen_options.lua | 52 ++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index b1018c1283..0cb5fa8e95 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -16,23 +16,23 @@ local options = require('options') local cstr = options.cstr local redraw_flags = { - ui_option = 'P_UI_OPTION', - tabline = 'P_RTABL', - statuslines = 'P_RSTAT', - current_window = 'P_RWIN', - current_buffer = 'P_RBUF', - all_windows = 'P_RALL', - curswant = 'P_CURSWANT', - highlight_only = 'P_HLONLY', + ui_option = 'kOptFlagUIOption', + tabline = 'kOptFlagRedrTabl', + statuslines = 'kOptFlagRedrStat', + current_window = 'kOptFlagRedrWin', + current_buffer = 'kOptFlagRedrBuf', + all_windows = 'kOptFlagRedrAll', + curswant = 'kOptFlagCurswant', + highlight_only = 'kOptFlagHLOnly', } local list_flags = { - comma = 'P_COMMA', - onecomma = 'P_ONECOMMA', - commacolon = 'P_COMMA|P_COLON', - onecommacolon = 'P_ONECOMMA|P_COLON', - flags = 'P_FLAGLIST', - flagscomma = 'P_COMMA|P_FLAGLIST', + comma = 'kOptFlagComma', + onecomma = 'kOptFlagOneComma', + commacolon = 'kOptFlagComma|kOptFlagColon', + onecommacolon = 'kOptFlagOneComma|kOptFlagColon', + flags = 'kOptFlagFlagList', + flagscomma = 'kOptFlagComma|kOptFlagFlagList', } --- @param s string @@ -61,27 +61,27 @@ local function get_flags(o) end end if o.expand then - add_flag('P_EXPAND') + add_flag('kOptFlagExpand') if o.expand == 'nodefault' then - add_flag('P_NO_DEF_EXP') + add_flag('kOptFlagNoDefExp') end end for _, flag_desc in ipairs({ - { 'nodefault' }, - { 'no_mkrc' }, + { 'nodefault', 'NoDefault' }, + { 'no_mkrc', 'NoMkrc' }, { 'secure' }, { 'gettext' }, - { 'noglob' }, - { 'normal_fname_chars', 'P_NFNAME' }, - { 'normal_dname_chars', 'P_NDNAME' }, - { 'pri_mkrc' }, - { 'deny_in_modelines', 'P_NO_ML' }, - { 'deny_duplicates', 'P_NODUP' }, - { 'modelineexpr', 'P_MLE' }, + { 'noglob', 'NoGlob' }, + { 'normal_fname_chars', 'NFname' }, + { 'normal_dname_chars', 'NDname' }, + { 'pri_mkrc', 'PriMkrc' }, + { 'deny_in_modelines', 'NoML' }, + { 'deny_duplicates', 'NoDup' }, + { 'modelineexpr', 'MLE' }, { 'func' }, }) do local key_name = flag_desc[1] - local def_name = flag_desc[2] or ('P_' .. key_name:upper()) + local def_name = 'kOptFlag' .. (flag_desc[2] or lowercase_to_titlecase(key_name)) if o[key_name] then add_flag(def_name) end -- cgit From 3075c69ff02faf396e5efbdcb4a255b0b0309649 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 3 Nov 2024 10:06:41 +0800 Subject: vim-patch:9.1.0831: 'findexpr' can't be used as lambad or Funcref (#31058) Problem: 'findexpr' can't be used for lambads (Justin Keyes) Solution: Replace the findexpr option with the findfunc option (Yegappan Lakshmanan) related: vim/vim#15905 closes: vim/vim#15976 https://github.com/vim/vim/commit/a13f3a4f5de9c150f70298850e34747838904995 Co-authored-by: Yegappan Lakshmanan --- src/nvim/generators/gen_options.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index 0cb5fa8e95..8397a434e4 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -260,6 +260,7 @@ local function dump_option(i, o) end w([[ +#include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" #include "nvim/insexpand.h" #include "nvim/mapping.h" -- cgit From a27419f3fc540f66567f4559a796cd6758f1bb1f Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Mon, 4 Nov 2024 19:00:12 +0600 Subject: feat(options)!: disallow setting hidden options #28400 Problem: There are three different ways of marking an option as hidden, `enable_if = false`, `hidden = true` and `immutable = true`. These also have different behaviors. Options hidden with `enable_if = false` can't have their value fetched using Vim script or the API, but options hidden with `hidden = true` or `immutable = true` can. On the other hand, options with `hidden = true` do not error when trying to set their value, but options with `immutable = true` do. Solution: Remove `enable_if = false`, remove the `hidden` property for options, and use `immutable = true` to mark an option as hidden instead. Also make hidden option variable pointers always point to the default value, which allows fetching the value of every hidden option using Vim script and the API. This does also mean that trying to set a hidden option will now give an error instead of just being ignored. --- src/nvim/generators/gen_options.lua | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index 8397a434e4..92349b5298 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -191,23 +191,17 @@ local function dump_option(i, o) w(get_cond(o.enable_if)) end - -- An option cannot be both hidden and immutable. - assert(not o.hidden or not o.immutable) - - local has_var = true if o.varname then w(' .var=&' .. o.varname) - elseif o.hidden or o.immutable then - -- Hidden and immutable options can directly point to the default value. + 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') else - has_var = false + -- Option must be immutable or have a variable. + assert(false) end - -- `enable_if = false` should be present iff there is no variable. - assert((o.enable_if == false) == not has_var) - w(' .hidden=' .. (o.hidden and 'true' or 'false')) w(' .immutable=' .. (o.immutable and 'true' or 'false')) if #o.scope == 1 and o.scope[1] == 'global' then w(' .indir=PV_NONE') @@ -237,7 +231,10 @@ local function dump_option(i, o) end if o.enable_if then w('#else') - w(' .var=NULL') + -- Hidden option directly points to default value. + 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 -- cgit From de48fbbd5f8800bd7f1909a6fb41e53e871cf74c Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Thu, 20 Jun 2024 14:48:06 +0200 Subject: fix(messages)!: vim.ui_attach message callbacks are unsafe Problem: Lua callbacks for "msg_show" events with vim.ui_attach() are executed when it is not safe. Solution: Disallow non-fast API calls for "msg_show" event callbacks. Automatically detach callback after excessive errors. Make sure fast APIs do not modify Nvim state. --- src/nvim/generators/gen_api_dispatch.lua | 2 +- src/nvim/generators/gen_api_ui_events.lua | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index 9e0aa407a1..a78f746fee 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -750,7 +750,7 @@ local function process_function(fn) write_shifted_output( [[ if (!nlua_is_deferred_safe()) { - return luaL_error(lstate, e_luv_api_disabled, "%s"); + return luaL_error(lstate, e_fast_api_disabled, "%s"); } ]], fn.name diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua index 3e8ae19c9a..30a83330eb 100644 --- a/src/nvim/generators/gen_api_ui_events.lua +++ b/src/nvim/generators/gen_api_ui_events.lua @@ -136,8 +136,8 @@ for i = 1, #events do call_output:write(' }\n') call_output:write(' entered = true;\n') write_arglist(call_output, ev) - call_output:write(' ui_call_event("' .. ev.name .. '", ' .. args .. ');\n') - call_output:write(' entered = false;\n') + call_output:write((' ui_call_event("%s", %s, %s)'):format(ev.name, tostring(ev.fast), args)) + call_output:write(';\n entered = false;\n') elseif ev.compositor_impl then call_output:write(' ui_comp_' .. ev.name) write_signature(call_output, ev, '', true) -- cgit From 29ded889579a9d590e8ea885a9a402ff4bae87be Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sun, 17 Nov 2024 02:56:16 +0600 Subject: refactor(options): remove `.indir`, redesign option scopes #31066 Problem: The way option scopes currently work is inflexible and does not allow for nested option scopes or easily finding the value of an option at any arbitrary scope without having to do long handwritten switch-case statements like in `get_varp()`. `.indir` is also confusing and redundant since option indices for each scope can be autogenerated. Solution: Expand option scopes in such a way that an option can support any amount of scopes using a set of scope flags, similarly to how it's already done for option types. Also make options contain information about its index at each scope it supports. This allows for massively simplifying `get_varp()` and `get_varp_scope()` in the future by just using a struct for options at each scope. This would be done by creating a table that stores the offset of an option's variable at a scope by using the option's index at that scope as a key. This PR also autogenerates enums for option indices at each scope to remove the need for `.indir` entirely, and also to allow easily iterating over options all options that support any scope. Ref: #29314 --- src/nvim/generators/gen_options.lua | 219 ++++++++++++++++++++++++------- src/nvim/generators/gen_options_enum.lua | 129 ------------------ 2 files changed, 174 insertions(+), 174 deletions(-) delete mode 100644 src/nvim/generators/gen_options_enum.lua (limited to 'src/nvim/generators') 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 +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 +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() -- cgit