aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/generators
diff options
context:
space:
mode:
authorFamiu Haque <famiuhaque@proton.me>2023-12-17 05:23:33 +0600
committerGitHub <noreply@github.com>2023-12-17 07:23:33 +0800
commit8f08b1efbd096850c04c2e8e2890d993bd4d9f95 (patch)
tree2fa91d7a39c1c82e9b6d0c578d74f17bb80b1827 /src/nvim/generators
parent2b1bc94b768cb13801e7166f6b02bd09caa3c18f (diff)
downloadrneovim-8f08b1efbd096850c04c2e8e2890d993bd4d9f95.tar.gz
rneovim-8f08b1efbd096850c04c2e8e2890d993bd4d9f95.tar.bz2
rneovim-8f08b1efbd096850c04c2e8e2890d993bd4d9f95.zip
refactor(options): use hashy for finding options (#26573)
Problem: `findoption()` searches through the options[] table linearly for option names, even though hashy can be used to generate a compile-time hash table for it. Solution: Use hashy to generate a compile time hash table for finding options. This also allows handling option aliases, so we don't need separate options[] table entries for things like 'viminfo'.
Diffstat (limited to 'src/nvim/generators')
-rw-r--r--src/nvim/generators/gen_options.lua19
-rw-r--r--src/nvim/generators/gen_options_enum.lua76
2 files changed, 77 insertions, 18 deletions
diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua
index 61d5df3c84..2fd11e4c58 100644
--- a/src/nvim/generators/gen_options.lua
+++ b/src/nvim/generators/gen_options.lua
@@ -1,5 +1,4 @@
local options_file = arg[1]
-local options_enum_file = arg[2]
local opt_fd = assert(io.open(options_file, 'w'))
@@ -171,7 +170,7 @@ local function dump_option(i, o)
end
if o.varname then
w(' .var=&' .. o.varname)
- -- Immutable options should directly point to the default value
+ -- Immutable options can directly point to the default value.
elseif o.immutable then
w((' .var=&options[%u].def_val'):format(i - 1))
elseif #o.scope == 1 and o.scope[1] == 'window' then
@@ -248,19 +247,3 @@ w('')
for _, v in ipairs(defines) do
w('#define ' .. v[1] .. ' ' .. v[2])
end
-
--- Generate options enum file
-opt_fd = assert(io.open(options_enum_file, 'w'))
-
-w('typedef enum {')
-w(' kOptInvalid = -1,')
-
-for i, o in ipairs(options.options) do
- w((' kOpt%s = %u,'):format(lowercase_to_titlecase(o.full_name), i - 1))
-end
-
-w(' // Option count, used when iterating through options')
-w('#define kOptIndexCount ' .. tostring(#options.options))
-w('} OptIndex;')
-
-opt_fd:close()
diff --git a/src/nvim/generators/gen_options_enum.lua b/src/nvim/generators/gen_options_enum.lua
new file mode 100644
index 0000000000..c3fe9baae6
--- /dev/null
+++ b/src/nvim/generators/gen_options_enum.lua
@@ -0,0 +1,76 @@
+-- Generates option index enum and map of option name to option index.
+-- Handles option full name, short name and aliases.
+
+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
+
+--- @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
+--- @type { [string]: string }
+local option_index = {}
+
+-- Generate option index enum and populate the `option_index` dictionary.
+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()