diff options
Diffstat (limited to 'src/nvim/generators/gen_options_enum.lua')
-rw-r--r-- | src/nvim/generators/gen_options_enum.lua | 129 |
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() |