aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/generators
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-11-25 19:15:05 +0000
committerJosh Rahm <joshuarahm@gmail.com>2024-11-25 19:27:38 +0000
commitc5d770d311841ea5230426cc4c868e8db27300a8 (patch)
treedd21f70127b4b8b5f109baefc8ecc5016f507c91 /src/nvim/generators
parent9be89f131f87608f224f0ee06d199fcd09d32176 (diff)
parent081beb3659bd6d8efc3e977a160b1e72becbd8a2 (diff)
downloadrneovim-c5d770d311841ea5230426cc4c868e8db27300a8.tar.gz
rneovim-c5d770d311841ea5230426cc4c868e8db27300a8.tar.bz2
rneovim-c5d770d311841ea5230426cc4c868e8db27300a8.zip
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'src/nvim/generators')
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua2
-rw-r--r--src/nvim/generators/gen_api_ui_events.lua4
-rw-r--r--src/nvim/generators/gen_options.lua347
-rw-r--r--src/nvim/generators/gen_options_enum.lua129
4 files changed, 254 insertions, 228 deletions
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)
diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua
index 591a6b93df..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,30 +14,29 @@ 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
-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',
-}
-
-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',
-}
+--- 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
@@ -41,6 +44,120 @@ 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',
+ tabline = 'kOptFlagRedrTabl',
+ statuslines = 'kOptFlagRedrStat',
+ current_window = 'kOptFlagRedrWin',
+ current_buffer = 'kOptFlagRedrBuf',
+ all_windows = 'kOptFlagRedrAll',
+ curswant = 'kOptFlagCurswant',
+ highlight_only = 'kOptFlagHLOnly',
+}
+
+local list_flags = {
+ comma = 'kOptFlagComma',
+ onecomma = 'kOptFlagOneComma',
+ commacolon = 'kOptFlagComma|kOptFlagColon',
+ onecommacolon = 'kOptFlagOneComma|kOptFlagColon',
+ flags = 'kOptFlagFlagList',
+ flagscomma = 'kOptFlagComma|kOptFlagFlagList',
+}
+
--- @param o vim.option_meta
--- @return string
local function get_flags(o)
@@ -61,28 +178,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({
- { 'alloced' },
- { '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
@@ -90,6 +206,18 @@ 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 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)
@@ -99,12 +227,41 @@ 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
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
@@ -125,32 +282,49 @@ 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][]
-local defines = {}
-
--- @param i integer
--- @param o vim.option_meta
local function dump_option(i, o)
@@ -161,48 +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
- -- An option cannot be both hidden and immutable.
- assert(not o.hidden or not o.immutable)
+ local is_window_local = #o.scope == 1 and o.scope[1] == 'win'
- 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.
- w((' .var=&options[%u].def_val'):format(i - 1))
- elseif #o.scope == 1 and o.scope[1] == 'window' then
- w(' .var=VAR_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
- has_var = false
+ w(' .var=NULL')
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')
- 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
@@ -211,27 +365,33 @@ local function dump_option(i, o)
end
if o.enable_if then
w('#else')
- w(' .var=NULL')
- w(' .indir=PV_NONE')
+ -- 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('#endif')
end
if o.defaults then
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
+-- Generate options[] array.
w([[
+#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/insexpand.h"
#include "nvim/mapping.h"
@@ -248,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()