aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/generators/gen_options_enum.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/generators/gen_options_enum.lua')
-rw-r--r--src/nvim/generators/gen_options_enum.lua129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/nvim/generators/gen_options_enum.lua b/src/nvim/generators/gen_options_enum.lua
new file mode 100644
index 0000000000..9a3953fcbc
--- /dev/null
+++ b/src/nvim/generators/gen_options_enum.lua
@@ -0,0 +1,129 @@
+-- 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` 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()