From 543e0256c19f397921a332e06b423215fd9aecb5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 30 Nov 2023 15:51:05 +0800 Subject: build: don't define FUNC_ATTR_* as empty in headers (#26317) FUNC_ATTR_* should only be used in .c files with generated headers. Defining FUNC_ATTR_* as empty in headers causes misuses of them to be silently ignored. Instead don't define them by default, and only define them as empty after a .c file has included its generated header. --- src/nvim/generators/gen_api_dispatch.lua | 4 ++-- src/nvim/generators/gen_declarations.lua | 30 ++++++++++++++++++------------ 2 files changed, 20 insertions(+), 14 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 9720cca477..81b5096557 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -752,9 +752,9 @@ for _, fn in ipairs(functions) do end output:write(string.format([[ -void nlua_add_api_functions(lua_State *lstate); // silence -Wmissing-prototypes void nlua_add_api_functions(lua_State *lstate) - FUNC_ATTR_NONNULL_ALL + REAL_FATTR_NONNULL_ALL; +void nlua_add_api_functions(lua_State *lstate) { lua_createtable(lstate, 0, %u); ]], #lua_c_functions)) diff --git a/src/nvim/generators/gen_declarations.lua b/src/nvim/generators/gen_declarations.lua index f9e9c6b0a8..fecca5191e 100644 --- a/src/nvim/generators/gen_declarations.lua +++ b/src/nvim/generators/gen_declarations.lua @@ -164,7 +164,7 @@ if fname == '--help' then print([[ Usage: - gendeclarations.lua definitions.c static.h non-static.h definitions.i + gen_declarations.lua definitions.c static.h non-static.h definitions.i Generates declarations for a C file definitions.c, putting declarations for static functions into static.h and declarations for non-static functions into @@ -202,17 +202,10 @@ local text = preproc_f:read("*all") preproc_f:close() -local header = [[ +local non_static = [[ #define DEFINE_FUNC_ATTRIBUTES #include "nvim/func_attr.h" #undef DEFINE_FUNC_ATTRIBUTES -]] - -local footer = [[ -#include "nvim/func_attr.h" -]] - -local non_static = header .. [[ #ifndef DLLEXPORT # ifdef MSWIN # define DLLEXPORT __declspec(dllexport) @@ -222,7 +215,20 @@ local non_static = header .. [[ #endif ]] -local static = header +local static = [[ +#define DEFINE_FUNC_ATTRIBUTES +#include "nvim/func_attr.h" +#undef DEFINE_FUNC_ATTRIBUTES +]] + +local non_static_footer = [[ +#include "nvim/func_attr.h" +]] + +local static_footer = [[ +#define DEFINE_EMPTY_ATTRIBUTES +#include "nvim/func_attr.h" // IWYU pragma: export +]] if fname:find('.*/src/nvim/.*%.c$') then -- Add an IWYU pragma comment if the corresponding .h file exists. @@ -307,8 +313,8 @@ while init ~= nil do end end -non_static = non_static .. footer -static = static .. footer +non_static = non_static .. non_static_footer +static = static .. static_footer local F F = io.open(static_fname, 'w') -- cgit From 45fe4d11add933df76a2ea4bf52ce8904f4a778b Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 4 Dec 2023 13:31:57 -0800 Subject: build: enable lintlua for src/ dir #26395 Problem: Not all Lua code is checked by stylua. Automating code-style is an important mechanism for reducing time spent on accidental (non-essential) complexity. Solution: - Enable lintlua for `src/` directory. followup to 517f0cc634b985057da5b95cf4ad659ee456a77e --- src/nvim/generators/c_grammar.lua | 90 +++-- src/nvim/generators/dump_bin_array.lua | 4 +- src/nvim/generators/gen_api_dispatch.lua | 507 ++++++++++++++++++++--------- src/nvim/generators/gen_api_ui_events.lua | 110 ++++--- src/nvim/generators/gen_char_blob.lua | 31 +- src/nvim/generators/gen_declarations.lua | 154 ++++----- src/nvim/generators/gen_eval.lua | 43 ++- src/nvim/generators/gen_events.lua | 10 +- src/nvim/generators/gen_ex_cmds.lua | 81 +++-- src/nvim/generators/gen_options.lua | 107 +++--- src/nvim/generators/gen_unicode_tables.lua | 33 +- src/nvim/generators/gen_vimvim.lua | 16 +- src/nvim/generators/hashy.lua | 83 ++--- src/nvim/generators/preload.lua | 4 +- 14 files changed, 760 insertions(+), 513 deletions(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/c_grammar.lua b/src/nvim/generators/c_grammar.lua index f33da452ff..1720b32919 100644 --- a/src/nvim/generators/c_grammar.lua +++ b/src/nvim/generators/c_grammar.lua @@ -17,50 +17,70 @@ local fill = ws ^ 0 local c_comment = P('//') * (not_nl ^ 0) local c_preproc = P('#') * (not_nl ^ 0) local dllexport = P('DLLEXPORT') * (ws ^ 1) -local typed_container = - (P('ArrayOf(') + P('DictionaryOf(') + P('Dict(')) * ((any - P(')')) ^ 1) * P(')') -local c_id = ( - typed_container + - (letter * (alpha ^ 0)) -) +local typed_container = (P('ArrayOf(') + P('DictionaryOf(') + P('Dict(')) + * ((any - P(')')) ^ 1) + * P(')') +local c_id = (typed_container + (letter * (alpha ^ 0))) local c_void = P('void') local c_param_type = ( - ((P('Error') * fill * P('*') * fill) * Cc('error')) + - ((P('Arena') * fill * P('*') * fill) * Cc('arena')) + - ((P('lua_State') * fill * P('*') * fill) * Cc('lstate')) + - C((P('const ') ^ -1) * (c_id) * (ws ^ 1) * P('*')) + - (C(c_id) * (ws ^ 1)) - ) + ((P('Error') * fill * P('*') * fill) * Cc('error')) + + ((P('Arena') * fill * P('*') * fill) * Cc('arena')) + + ((P('lua_State') * fill * P('*') * fill) * Cc('lstate')) + + C((P('const ') ^ -1) * c_id * (ws ^ 1) * P('*')) + + (C(c_id) * (ws ^ 1)) +) local c_type = (C(c_void) * (ws ^ 1)) + c_param_type local c_param = Ct(c_param_type * C(c_id)) local c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) local c_params = Ct(c_void + c_param_list) local c_proto = Ct( - (dllexport ^ -1) * - Cg(c_type, 'return_type') * Cg(c_id, 'name') * - fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * - Cg(Cc(false), 'fast') * - (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) * - (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(num ^ 1)) * P(')'), - 'deprecated_since') ^ -1) * - (fill * Cg((P('FUNC_API_FAST') * Cc(true)), 'fast') ^ -1) * - (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) * - (fill * Cg((P('FUNC_API_REMOTE_ONLY') * Cc(true)), 'remote_only') ^ -1) * - (fill * Cg((P('FUNC_API_LUA_ONLY') * Cc(true)), 'lua_only') ^ -1) * - (fill * (Cg(P('FUNC_API_TEXTLOCK_ALLOW_CMDWIN') * Cc(true), 'textlock_allow_cmdwin') + - Cg(P('FUNC_API_TEXTLOCK') * Cc(true), 'textlock')) ^ -1) * - (fill * Cg((P('FUNC_API_REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1) * - (fill * Cg((P('FUNC_API_COMPOSITOR_IMPL') * Cc(true)), 'compositor_impl') ^ -1) * - (fill * Cg((P('FUNC_API_CLIENT_IMPL') * Cc(true)), 'client_impl') ^ -1) * - (fill * Cg((P('FUNC_API_CLIENT_IGNORE') * Cc(true)), 'client_ignore') ^ -1) * - fill * P(';') - ) + (dllexport ^ -1) + * Cg(c_type, 'return_type') + * Cg(c_id, 'name') + * fill + * P('(') + * fill + * Cg(c_params, 'parameters') + * fill + * P(')') + * Cg(Cc(false), 'fast') + * (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) + * (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(num ^ 1)) * P(')'), 'deprecated_since') ^ -1) + * (fill * Cg((P('FUNC_API_FAST') * Cc(true)), 'fast') ^ -1) + * (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) + * (fill * Cg((P('FUNC_API_REMOTE_ONLY') * Cc(true)), 'remote_only') ^ -1) + * (fill * Cg((P('FUNC_API_LUA_ONLY') * Cc(true)), 'lua_only') ^ -1) + * (fill * (Cg(P('FUNC_API_TEXTLOCK_ALLOW_CMDWIN') * Cc(true), 'textlock_allow_cmdwin') + Cg( + P('FUNC_API_TEXTLOCK') * Cc(true), + 'textlock' + )) ^ -1) + * (fill * Cg((P('FUNC_API_REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1) + * (fill * Cg((P('FUNC_API_COMPOSITOR_IMPL') * Cc(true)), 'compositor_impl') ^ -1) + * (fill * Cg((P('FUNC_API_CLIENT_IMPL') * Cc(true)), 'client_impl') ^ -1) + * (fill * Cg((P('FUNC_API_CLIENT_IGNORE') * Cc(true)), 'client_ignore') ^ -1) + * fill + * P(';') +) local c_field = Ct(Cg(c_id, 'type') * ws * Cg(c_id, 'name') * fill * P(';') * fill) local c_keyset = Ct( - P('typedef') * ws * P('struct') * fill * P('{') * fill * - Cg(Ct(c_field ^ 1), 'fields') * - P('}') * fill * P('Dict') * fill * P('(') * Cg(c_id, 'keyset_name') * fill * P(')') * P(';')) + P('typedef') + * ws + * P('struct') + * fill + * P('{') + * fill + * Cg(Ct(c_field ^ 1), 'fields') + * P('}') + * fill + * P('Dict') + * fill + * P('(') + * Cg(c_id, 'keyset_name') + * fill + * P(')') + * P(';') +) local grammar = Ct((c_proto + c_comment + c_preproc + ws + c_keyset) ^ 1) -return {grammar=grammar, typed_container=typed_container} +return { grammar = grammar, typed_container = typed_container } diff --git a/src/nvim/generators/dump_bin_array.lua b/src/nvim/generators/dump_bin_array.lua index bee5aba73f..c6cda25e73 100644 --- a/src/nvim/generators/dump_bin_array.lua +++ b/src/nvim/generators/dump_bin_array.lua @@ -1,10 +1,10 @@ local function dump_bin_array(output, name, data) output:write([[ - static const uint8_t ]]..name..[[[] = { + static const uint8_t ]] .. name .. [[[] = { ]]) for i = 1, #data do - output:write(string.byte(data, i)..', ') + output:write(string.byte(data, i) .. ', ') if i % 10 == 0 then output:write('\n ') end diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index 81b5096557..7cec118243 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -1,6 +1,6 @@ local mpack = vim.mpack -local hashy = require'generators.hashy' +local hashy = require 'generators.hashy' assert(#arg >= 5) -- output h file with generated dispatch functions (dispatch_wrappers.generated.h) @@ -23,16 +23,20 @@ local function_names = {} local c_grammar = require('generators.c_grammar') -local function startswith(String,Start) - return string.sub(String,1,string.len(Start))==Start +local function startswith(String, Start) + return string.sub(String, 1, string.len(Start)) == Start end local function add_function(fn) - local public = startswith(fn.name, "nvim_") or fn.deprecated_since + local public = startswith(fn.name, 'nvim_') or fn.deprecated_since if public and not fn.noexport then functions[#functions + 1] = fn function_names[fn.name] = true - if #fn.parameters >= 2 and fn.parameters[2][1] == 'Array' and fn.parameters[2][2] == 'uidata' then + if + #fn.parameters >= 2 + and fn.parameters[2][1] == 'Array' + and fn.parameters[2][2] == 'uidata' + then -- function receives the "args" as a parameter fn.receives_array_args = true -- remove the args parameter @@ -70,7 +74,7 @@ local function add_keyset(val) local types = {} local is_set_name = 'is_set__' .. val.keyset_name .. '_' local has_optional = false - for i,field in ipairs(val.fields) do + for i, field in ipairs(val.fields) do if field.type ~= 'Object' then types[field.name] = field.type end @@ -80,14 +84,17 @@ local function add_keyset(val) if i > 1 then error("'is_set__{type}_' must be first if present") elseif field.name ~= is_set_name then - error(val.keyset_name..": name of first key should be "..is_set_name) + error(val.keyset_name .. ': name of first key should be ' .. is_set_name) elseif field.type ~= 'OptionalKeys' then - error("'"..is_set_name.."' must have type 'OptionalKeys'") + error("'" .. is_set_name .. "' must have type 'OptionalKeys'") end has_optional = true end end - table.insert(keysets, {name=val.keyset_name, keys=keys, types=types, has_optional=has_optional}) + table.insert( + keysets, + { name = val.keyset_name, keys = keys, types = types, has_optional = has_optional } + ) end -- read each input file, parse and append to the api metadata @@ -97,7 +104,7 @@ for i = 6, #arg do for part in string.gmatch(full_path, '[^/]+') do parts[#parts + 1] = part end - headers[#headers + 1] = parts[#parts - 1]..'/'..parts[#parts] + headers[#headers + 1] = parts[#parts - 1] .. '/' .. parts[#parts] local input = io.open(full_path, 'rb') @@ -123,14 +130,14 @@ end -- Export functions under older deprecated names. -- These will be removed eventually. -local deprecated_aliases = require("api.dispatch_deprecated") -for _,f in ipairs(shallowcopy(functions)) do +local deprecated_aliases = require('api.dispatch_deprecated') +for _, f in ipairs(shallowcopy(functions)) do local ismethod = false - if startswith(f.name, "nvim_") then - if startswith(f.name, "nvim__") or f.name == "nvim_error_event" then + if startswith(f.name, 'nvim_') then + if startswith(f.name, 'nvim__') or f.name == 'nvim_error_event' then f.since = -1 elseif f.since == nil then - print("Function "..f.name.." lacks since field.\n") + print('Function ' .. f.name .. ' lacks since field.\n') os.exit(1) end f.since = tonumber(f.since) @@ -138,16 +145,16 @@ for _,f in ipairs(shallowcopy(functions)) do f.deprecated_since = tonumber(f.deprecated_since) end - if startswith(f.name, "nvim_buf_") then + if startswith(f.name, 'nvim_buf_') then ismethod = true - elseif startswith(f.name, "nvim_win_") then + elseif startswith(f.name, 'nvim_win_') then ismethod = true - elseif startswith(f.name, "nvim_tabpage_") then + elseif startswith(f.name, 'nvim_tabpage_') then ismethod = true end f.remote = f.remote_only or not f.lua_only f.lua = f.lua_only or not f.remote_only - f.eval = (not f.lua_only) and (not f.remote_only) + f.eval = (not f.lua_only) and not f.remote_only else f.deprecated_since = tonumber(f.deprecated_since) assert(f.deprecated_since == 1) @@ -159,56 +166,59 @@ for _,f in ipairs(shallowcopy(functions)) do if newname ~= nil then if function_names[newname] then -- duplicate - print("Function "..f.name.." has deprecated alias\n" - ..newname.." which has a separate implementation.\n".. - "Please remove it from src/nvim/api/dispatch_deprecated.lua") + print( + 'Function ' + .. f.name + .. ' has deprecated alias\n' + .. newname + .. ' which has a separate implementation.\n' + .. 'Please remove it from src/nvim/api/dispatch_deprecated.lua' + ) os.exit(1) end local newf = shallowcopy(f) newf.name = newname - if newname == "ui_try_resize" then + if newname == 'ui_try_resize' then -- The return type was incorrectly set to Object in 0.1.5. -- Keep it that way for clients that rely on this. - newf.return_type = "Object" + newf.return_type = 'Object' end newf.impl_name = f.name newf.lua = false newf.eval = false newf.since = 0 newf.deprecated_since = 1 - functions[#functions+1] = newf + functions[#functions + 1] = newf end end -- don't expose internal attributes like "impl_name" in public metadata -local exported_attributes = {'name', 'return_type', 'method', - 'since', 'deprecated_since'} +local exported_attributes = { 'name', 'return_type', 'method', 'since', 'deprecated_since' } local exported_functions = {} -for _,f in ipairs(functions) do - if not (startswith(f.name, "nvim__") or f.name == "nvim_error_event" or f.name == "redraw") then +for _, f in ipairs(functions) do + if not (startswith(f.name, 'nvim__') or f.name == 'nvim_error_event' or f.name == 'redraw') then local f_exported = {} - for _,attr in ipairs(exported_attributes) do + for _, attr in ipairs(exported_attributes) do f_exported[attr] = f[attr] end f_exported.parameters = {} - for i,param in ipairs(f.parameters) do - if param[1] == "DictionaryOf(LuaRef)" then - param = {"Dictionary", param[2]} - elseif startswith(param[1], "Dict(") then - param = {"Dictionary", param[2]} + for i, param in ipairs(f.parameters) do + if param[1] == 'DictionaryOf(LuaRef)' then + param = { 'Dictionary', param[2] } + elseif startswith(param[1], 'Dict(') then + param = { 'Dictionary', param[2] } end f_exported.parameters[i] = param end - exported_functions[#exported_functions+1] = f_exported + exported_functions[#exported_functions + 1] = f_exported end end - -- serialize the API metadata using msgpack and embed into the resulting -- binary for easy querying by clients local funcs_metadata_output = io.open(funcs_metadata_outputf, 'wb') local packed = mpack.encode(exported_functions) -local dump_bin_array = require("generators.dump_bin_array") +local dump_bin_array = require('generators.dump_bin_array') dump_bin_array(funcs_metadata_output, 'funcs_metadata', packed) funcs_metadata_output:close() @@ -246,67 +256,81 @@ output:write([[ ]]) -for _,k in ipairs(keysets) do +for _, k in ipairs(keysets) do local c_name = {} - for i = 1,#k.keys do + for i = 1, #k.keys do -- some keys, like "register" are c keywords and get -- escaped with a trailing _ in the struct. - if vim.endswith(k.keys[i], "_") then + if vim.endswith(k.keys[i], '_') then local orig = k.keys[i] - k.keys[i] = string.sub(k.keys[i],1, #(k.keys[i]) - 1) + k.keys[i] = string.sub(k.keys[i], 1, #k.keys[i] - 1) c_name[k.keys[i]] = orig k.types[k.keys[i]] = k.types[orig] end end - local neworder, hashfun = hashy.hashy_hash(k.name, k.keys, function (idx) - return k.name.."_table["..idx.."].str" + local neworder, hashfun = hashy.hashy_hash(k.name, k.keys, function(idx) + return k.name .. '_table[' .. idx .. '].str' end) - keysets_defs:write("extern KeySetLink "..k.name.."_table[];\n") + keysets_defs:write('extern KeySetLink ' .. k.name .. '_table[];\n') local function typename(type) if type ~= nil then - return "kObjectType"..type + return 'kObjectType' .. type else - return "kObjectTypeNil" + return 'kObjectTypeNil' end end - output:write("KeySetLink "..k.name.."_table[] = {\n") + output:write('KeySetLink ' .. k.name .. '_table[] = {\n') for i, key in ipairs(neworder) do local ind = -1 if k.has_optional then ind = i - keysets_defs:write("#define KEYSET_OPTIDX_"..k.name.."__"..key.." "..ind.."\n") - end - output:write(' {"'..key..'", offsetof(KeyDict_'..k.name..", "..(c_name[key] or key).."), "..typename(k.types[key])..", "..ind.."},\n") + keysets_defs:write('#define KEYSET_OPTIDX_' .. k.name .. '__' .. key .. ' ' .. ind .. '\n') + end + output:write( + ' {"' + .. key + .. '", offsetof(KeyDict_' + .. k.name + .. ', ' + .. (c_name[key] or key) + .. '), ' + .. typename(k.types[key]) + .. ', ' + .. ind + .. '},\n' + ) end - output:write(' {NULL, 0, kObjectTypeNil, -1},\n') - output:write("};\n\n") + output:write(' {NULL, 0, kObjectTypeNil, -1},\n') + output:write('};\n\n') output:write(hashfun) output:write([[ -KeySetLink *KeyDict_]]..k.name..[[_get_field(const char *str, size_t len) +KeySetLink *KeyDict_]] .. k.name .. [[_get_field(const char *str, size_t len) { - int hash = ]]..k.name..[[_hash(str, len); + int hash = ]] .. k.name .. [[_hash(str, len); if (hash == -1) { return NULL; } - return &]]..k.name..[[_table[hash]; + return &]] .. k.name .. [[_table[hash]; } ]]) - keysets_defs:write("#define api_free_keydict_"..k.name.."(x) api_free_keydict(x, "..k.name.."_table)\n") + keysets_defs:write( + '#define api_free_keydict_' .. k.name .. '(x) api_free_keydict(x, ' .. k.name .. '_table)\n' + ) end local function real_type(type) local rv = type - local rmatch = string.match(type, "Dict%(([_%w]+)%)") + local rmatch = string.match(type, 'Dict%(([_%w]+)%)') if rmatch then - return "KeyDict_"..rmatch + return 'KeyDict_' .. rmatch elseif c_grammar.typed_container:match(rv) then if rv:match('Array') then rv = 'Array' @@ -333,24 +357,30 @@ for i = 1, #functions do if fn.impl_name == nil and fn.remote then local args = {} - output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Arena* arena, Error *error)') + output:write( + 'Object handle_' .. fn.name .. '(uint64_t channel_id, Array args, Arena* arena, Error *error)' + ) output:write('\n{') output:write('\n#ifdef NVIM_LOG_DEBUG') - output:write('\n DLOG("RPC: ch %" PRIu64 ": invoke '..fn.name..'", channel_id);') + output:write('\n DLOG("RPC: ch %" PRIu64 ": invoke ' .. fn.name .. '", channel_id);') output:write('\n#endif') output:write('\n Object ret = NIL;') -- Declare/initialize variables that will hold converted arguments for j = 1, #fn.parameters do local param = fn.parameters[j] local rt = real_type(param[1]) - local converted = 'arg_'..j - output:write('\n '..rt..' '..converted..';') + local converted = 'arg_' .. j + output:write('\n ' .. rt .. ' ' .. converted .. ';') end output:write('\n') if not fn.receives_array_args then - output:write('\n if (args.size != '..#fn.parameters..') {') - output:write('\n api_set_error(error, kErrorTypeException, \ - "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);') + output:write('\n if (args.size != ' .. #fn.parameters .. ') {') + output:write( + '\n api_set_error(error, kErrorTypeException, \ + "Wrong number of arguments: expecting ' + .. #fn.parameters + .. ' but got %zu", args.size);' + ) output:write('\n goto cleanup;') output:write('\n }\n') end @@ -359,55 +389,121 @@ for i = 1, #functions do for j = 1, #fn.parameters do local converted, param param = fn.parameters[j] - converted = 'arg_'..j + converted = 'arg_' .. j local rt = real_type(param[1]) if rt == 'Object' then - output:write('\n '..converted..' = args.items['..(j - 1)..'];\n') + output:write('\n ' .. converted .. ' = args.items[' .. (j - 1) .. '];\n') elseif rt:match('^KeyDict_') then converted = '&' .. converted - output:write('\n if (args.items['..(j - 1)..'].type == kObjectTypeDictionary) {') --luacheck: ignore 631 - output:write('\n memset('..converted..', 0, sizeof(*'..converted..'));') -- TODO: neeeee - output:write('\n if (!api_dict_to_keydict('..converted..', '..rt..'_get_field, args.items['..(j - 1)..'].data.dictionary, error)) {') + output:write('\n if (args.items[' .. (j - 1) .. '].type == kObjectTypeDictionary) {') --luacheck: ignore 631 + output:write('\n memset(' .. converted .. ', 0, sizeof(*' .. converted .. '));') -- TODO: neeeee + output:write( + '\n if (!api_dict_to_keydict(' + .. converted + .. ', ' + .. rt + .. '_get_field, args.items[' + .. (j - 1) + .. '].data.dictionary, error)) {' + ) output:write('\n goto cleanup;') output:write('\n }') - output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeArray && args.items['..(j - 1)..'].data.array.size == 0) {') --luacheck: ignore 631 - output:write('\n memset('..converted..', 0, sizeof(*'..converted..'));') + output:write( + '\n } else if (args.items[' + .. (j - 1) + .. '].type == kObjectTypeArray && args.items[' + .. (j - 1) + .. '].data.array.size == 0) {' + ) --luacheck: ignore 631 + output:write('\n memset(' .. converted .. ', 0, sizeof(*' .. converted .. '));') output:write('\n } else {') - output:write('\n api_set_error(error, kErrorTypeException, \ - "Wrong type for argument '..j..' when calling '..fn.name..', expecting '..param[1]..'");') + output:write( + '\n api_set_error(error, kErrorTypeException, \ + "Wrong type for argument ' + .. j + .. ' when calling ' + .. fn.name + .. ', expecting ' + .. param[1] + .. '");' + ) output:write('\n goto cleanup;') output:write('\n }\n') else if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') then -- Buffer, Window, and Tabpage have a specific type, but are stored in integer - output:write('\n if (args.items['.. - (j - 1)..'].type == kObjectType'..rt..' && args.items['..(j - 1)..'].data.integer >= 0) {') - output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') + output:write( + '\n if (args.items[' + .. (j - 1) + .. '].type == kObjectType' + .. rt + .. ' && args.items[' + .. (j - 1) + .. '].data.integer >= 0) {' + ) + output:write( + '\n ' .. converted .. ' = (handle_T)args.items[' .. (j - 1) .. '].data.integer;' + ) else - output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {') - output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..attr_name(rt)..';') + output:write('\n if (args.items[' .. (j - 1) .. '].type == kObjectType' .. rt .. ') {') + output:write( + '\n ' + .. converted + .. ' = args.items[' + .. (j - 1) + .. '].data.' + .. attr_name(rt) + .. ';' + ) end - if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then + if + rt:match('^Buffer$') + or rt:match('^Window$') + or rt:match('^Tabpage$') + or rt:match('^Boolean$') + then -- accept nonnegative integers for Booleans, Buffers, Windows and Tabpages - output:write('\n } else if (args.items['.. - (j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer >= 0) {') - output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') + output:write( + '\n } else if (args.items[' + .. (j - 1) + .. '].type == kObjectTypeInteger && args.items[' + .. (j - 1) + .. '].data.integer >= 0) {' + ) + output:write( + '\n ' .. converted .. ' = (handle_T)args.items[' .. (j - 1) .. '].data.integer;' + ) end if rt:match('^Float$') then -- accept integers for Floats - output:write('\n } else if (args.items['.. - (j - 1)..'].type == kObjectTypeInteger) {') - output:write('\n '..converted..' = (Float)args.items['..(j - 1)..'].data.integer;') + output:write('\n } else if (args.items[' .. (j - 1) .. '].type == kObjectTypeInteger) {') + output:write( + '\n ' .. converted .. ' = (Float)args.items[' .. (j - 1) .. '].data.integer;' + ) end -- accept empty lua tables as empty dictionaries if rt:match('^Dictionary') then - output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeArray && args.items['..(j - 1)..'].data.array.size == 0) {') --luacheck: ignore 631 - output:write('\n '..converted..' = (Dictionary)ARRAY_DICT_INIT;') + output:write( + '\n } else if (args.items[' + .. (j - 1) + .. '].type == kObjectTypeArray && args.items[' + .. (j - 1) + .. '].data.array.size == 0) {' + ) --luacheck: ignore 631 + output:write('\n ' .. converted .. ' = (Dictionary)ARRAY_DICT_INIT;') end output:write('\n } else {') - output:write('\n api_set_error(error, kErrorTypeException, \ - "Wrong type for argument '..j..' when calling '..fn.name..', expecting '..param[1]..'");') + output:write( + '\n api_set_error(error, kErrorTypeException, \ + "Wrong type for argument ' + .. j + .. ' when calling ' + .. fn.name + .. ', expecting ' + .. param[1] + .. '");' + ) output:write('\n goto cleanup;') output:write('\n }\n') end @@ -431,11 +527,11 @@ for i = 1, #functions do output:write('\n ') if fn.return_type ~= 'void' then -- has a return value, prefix the call with a declaration - output:write(fn.return_type..' rv = ') + output:write(fn.return_type .. ' rv = ') end -- write the function name and the opening parenthesis - output:write(fn.name..'(') + output:write(fn.name .. '(') if fn.receives_channel_id then -- if the function receives the channel id, pass it as first argument @@ -455,7 +551,7 @@ for i = 1, #functions do else if fn.receives_array_args then if #args > 0 or fn.call_fail then - output:write('args, '..call_args) + output:write('args, ' .. call_args) else output:write('args') end @@ -465,7 +561,7 @@ for i = 1, #functions do end if fn.arena_return then - output:write(', arena') + output:write(', arena') end if fn.has_lua_imp then @@ -492,36 +588,45 @@ for i = 1, #functions do end if fn.return_type ~= 'void' then - output:write('\n ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);') + output:write('\n ret = ' .. string.upper(real_type(fn.return_type)) .. '_OBJ(rv);') end - output:write('\n\ncleanup:'); + output:write('\n\ncleanup:') - output:write('\n return ret;\n}\n\n'); + output:write('\n return ret;\n}\n\n') end end local remote_fns = {} -for _,fn in ipairs(functions) do +for _, fn in ipairs(functions) do if fn.remote then remote_fns[fn.name] = fn end end -remote_fns.redraw = {impl_name="ui_client_redraw", fast=true} +remote_fns.redraw = { impl_name = 'ui_client_redraw', fast = true } local names = vim.tbl_keys(remote_fns) table.sort(names) -local hashorder, hashfun = hashy.hashy_hash("msgpack_rpc_get_handler_for", names, function (idx) - return "method_handlers["..idx.."].name" +local hashorder, hashfun = hashy.hashy_hash('msgpack_rpc_get_handler_for', names, function(idx) + return 'method_handlers[' .. idx .. '].name' end) -output:write("const MsgpackRpcRequestHandler method_handlers[] = {\n") +output:write('const MsgpackRpcRequestHandler method_handlers[] = {\n') for n, name in ipairs(hashorder) do local fn = remote_fns[name] - fn.handler_id = n-1 - output:write(' { .name = "'..name..'", .fn = handle_'.. (fn.impl_name or fn.name).. - ', .fast = '..tostring(fn.fast)..', .arena_return = '..tostring(not not fn.arena_return)..'},\n') + fn.handler_id = n - 1 + output:write( + ' { .name = "' + .. name + .. '", .fn = handle_' + .. (fn.impl_name or fn.name) + .. ', .fast = ' + .. tostring(fn.fast) + .. ', .arena_return = ' + .. tostring(not not fn.arena_return) + .. '},\n' + ) end -output:write("};\n\n") +output:write('};\n\n') output:write(hashfun) output:close() @@ -534,7 +639,7 @@ mpack_output:close() local function include_headers(output_handle, headers_to_include) for i = 1, #headers_to_include do if headers_to_include[i]:sub(-12) ~= '.generated.h' then - output_handle:write('\n#include "nvim/'..headers_to_include[i]..'"') + output_handle:write('\n#include "nvim/' .. headers_to_include[i] .. '"') end end end @@ -572,7 +677,10 @@ local lua_c_functions = {} local function process_function(fn) local lua_c_function_name = ('nlua_api_%s'):format(fn.name) - write_shifted_output(output, string.format([[ + write_shifted_output( + output, + string.format( + [[ static int %s(lua_State *lstate) { @@ -582,71 +690,108 @@ local function process_function(fn) api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s"); goto exit_0; } - ]], lua_c_function_name, #fn.parameters, #fn.parameters, - (#fn.parameters == 1) and '' or 's')) + ]], + lua_c_function_name, + #fn.parameters, + #fn.parameters, + (#fn.parameters == 1) and '' or 's' + ) + ) lua_c_functions[#lua_c_functions + 1] = { - binding=lua_c_function_name, - api=fn.name + binding = lua_c_function_name, + api = fn.name, } if not fn.fast then - write_shifted_output(output, string.format([[ + write_shifted_output( + output, + string.format( + [[ if (!nlua_is_deferred_safe()) { return luaL_error(lstate, e_luv_api_disabled, "%s"); } - ]], fn.name)) + ]], + fn.name + ) + ) end if fn.textlock then - write_shifted_output(output, [[ + write_shifted_output( + output, + [[ if (text_locked()) { api_set_error(&err, kErrorTypeException, "%s", get_text_locked_msg()); goto exit_0; } - ]]) + ]] + ) elseif fn.textlock_allow_cmdwin then - write_shifted_output(output, [[ + write_shifted_output( + output, + [[ if (textlock != 0 || expr_map_locked()) { api_set_error(&err, kErrorTypeException, "%s", e_textlock); goto exit_0; } - ]]) + ]] + ) end local cparams = '' local free_code = {} - for j = #fn.parameters,1,-1 do + for j = #fn.parameters, 1, -1 do local param = fn.parameters[j] local cparam = string.format('arg%u', j) local param_type = real_type(param[1]) local lc_param_type = real_type(param[1]):lower() - local extra = param_type == "Dictionary" and "false, " or "" - if param[1] == "Object" or param[1] == "DictionaryOf(LuaRef)" then - extra = "true, " + local extra = param_type == 'Dictionary' and 'false, ' or '' + if param[1] == 'Object' or param[1] == 'DictionaryOf(LuaRef)' then + extra = 'true, ' end local errshift = 0 local seterr = '' if string.match(param_type, '^KeyDict_') then - write_shifted_output(output, string.format([[ - %s %s = { 0 }; nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &err);]], param_type, cparam, cparam, param_type)) - cparam = '&'..cparam + write_shifted_output( + output, + string.format( + [[ + %s %s = { 0 }; nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &err);]], + param_type, + cparam, + cparam, + param_type + ) + ) + cparam = '&' .. cparam errshift = 1 -- free incomplete dict on error else - write_shifted_output(output, string.format([[ - const %s %s = nlua_pop_%s(lstate, %s&err);]], param[1], cparam, param_type, extra)) + write_shifted_output( + output, + string.format( + [[ + const %s %s = nlua_pop_%s(lstate, %s&err);]], + param[1], + cparam, + param_type, + extra + ) + ) seterr = [[ - err_param = "]]..param[2]..[[";]] + err_param = "]] .. param[2] .. [[";]] end - write_shifted_output(output, string.format([[ + write_shifted_output( + output, + string.format([[ - if (ERROR_SET(&err)) {]]..seterr..[[ + if (ERROR_SET(&err)) {]] .. seterr .. [[ goto exit_%u; } - ]], #fn.parameters - j + errshift)) - free_code[#free_code + 1] = ('api_free_%s(%s);'):format( - lc_param_type, cparam) + ]], #fn.parameters - j + errshift) + ) + free_code[#free_code + 1] = ('api_free_%s(%s);'):format(lc_param_type, cparam) cparams = cparam .. ', ' .. cparams end if fn.receives_channel_id then @@ -654,9 +799,12 @@ local function process_function(fn) end if fn.arena_return then cparams = cparams .. '&arena, ' - write_shifted_output(output, [[ + write_shifted_output( + output, + [[ Arena arena = ARENA_EMPTY; - ]]) + ]] + ) end if fn.has_lua_imp then @@ -675,8 +823,7 @@ local function process_function(fn) if i == 1 and not string.match(real_type(fn.parameters[1][1]), '^KeyDict_') then free_at_exit_code = free_at_exit_code .. ('\n %s'):format(code) else - free_at_exit_code = free_at_exit_code .. ('\n exit_%u:\n %s'):format( - rev_i, code) + free_at_exit_code = free_at_exit_code .. ('\n exit_%u:\n %s'):format(rev_i, code) end end local err_throw_code = [[ @@ -704,45 +851,86 @@ local function process_function(fn) end local free_retval if fn.arena_return then - free_retval = "arena_mem_free(arena_finish(&arena));" + free_retval = 'arena_mem_free(arena_finish(&arena));' else - free_retval = "api_free_"..return_type:lower().."(ret);" + free_retval = 'api_free_' .. return_type:lower() .. '(ret);' end - write_shifted_output(output, string.format([[ + write_shifted_output( + output, + string.format( + [[ const %s ret = %s(%s); - ]], fn.return_type, fn.name, cparams)) + ]], + fn.return_type, + fn.name, + cparams + ) + ) if fn.has_lua_imp then -- only push onto the Lua stack if we haven't already - write_shifted_output(output, string.format([[ + write_shifted_output( + output, + string.format( + [[ if (lua_gettop(lstate) == 0) { nlua_push_%s(lstate, ret, true); } - ]], return_type)) + ]], + return_type + ) + ) else local special = (fn.since ~= nil and fn.since < 11) - write_shifted_output(output, string.format([[ + write_shifted_output( + output, + string.format( + [[ nlua_push_%s(lstate, ret, %s); - ]], return_type, tostring(special))) + ]], + return_type, + tostring(special) + ) + ) end - write_shifted_output(output, string.format([[ + write_shifted_output( + output, + string.format( + [[ %s %s %s return 1; - ]], free_retval, free_at_exit_code, err_throw_code)) + ]], + free_retval, + free_at_exit_code, + err_throw_code + ) + ) else - write_shifted_output(output, string.format([[ + write_shifted_output( + output, + string.format( + [[ %s(%s); %s %s return 0; - ]], fn.name, cparams, free_at_exit_code, err_throw_code)) + ]], + fn.name, + cparams, + free_at_exit_code, + err_throw_code + ) + ) end - write_shifted_output(output, [[ + write_shifted_output( + output, + [[ } - ]]) + ]] + ) end for _, fn in ipairs(functions) do @@ -751,18 +939,25 @@ for _, fn in ipairs(functions) do end end -output:write(string.format([[ +output:write(string.format( + [[ void nlua_add_api_functions(lua_State *lstate) REAL_FATTR_NONNULL_ALL; void nlua_add_api_functions(lua_State *lstate) { lua_createtable(lstate, 0, %u); -]], #lua_c_functions)) +]], + #lua_c_functions +)) for _, func in ipairs(lua_c_functions) do - output:write(string.format([[ + output:write(string.format( + [[ lua_pushcfunction(lstate, &%s); - lua_setfield(lstate, -2, "%s");]], func.binding, func.api)) + lua_setfield(lstate, -2, "%s");]], + func.binding, + func.api + )) end output:write([[ diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua index e2af5f8d44..89f8c654f4 100644 --- a/src/nvim/generators/gen_api_ui_events.lua +++ b/src/nvim/generators/gen_api_ui_events.lua @@ -10,11 +10,11 @@ local client_output = io.open(arg[5], 'wb') local c_grammar = require('generators.c_grammar') local events = c_grammar.grammar:match(input:read('*all')) -local hashy = require'generators.hashy' +local hashy = require 'generators.hashy' local function write_signature(output, ev, prefix, notype) - output:write('('..prefix) - if prefix == "" and #ev.parameters == 0 then + output:write('(' .. prefix) + if prefix == '' and #ev.parameters == 0 then output:write('void') end for j = 1, #ev.parameters do @@ -23,7 +23,7 @@ local function write_signature(output, ev, prefix, notype) end local param = ev.parameters[j] if not notype then - output:write(param[1]..' ') + output:write(param[1] .. ' ') end output:write(param[2]) end @@ -35,26 +35,28 @@ local function write_arglist(output, ev) local param = ev.parameters[j] local kind = string.upper(param[1]) output:write(' ADD_C(args, ') - output:write(kind..'_OBJ('..param[2]..')') + output:write(kind .. '_OBJ(' .. param[2] .. ')') output:write(');\n') end end local function call_ui_event_method(output, ev) - output:write('void ui_client_event_'..ev.name..'(Array args)\n{\n') + output:write('void ui_client_event_' .. ev.name .. '(Array args)\n{\n') local hlattrs_args_count = 0 if #ev.parameters > 0 then - output:write(' if (args.size < '..(#ev.parameters)) + output:write(' if (args.size < ' .. #ev.parameters) for j = 1, #ev.parameters do local kind = ev.parameters[j][1] - if kind ~= "Object" then - if kind == 'HlAttrs' then kind = 'Dictionary' end - output:write('\n || args.items['..(j-1)..'].type != kObjectType'..kind..'') + if kind ~= 'Object' then + if kind == 'HlAttrs' then + kind = 'Dictionary' + end + output:write('\n || args.items[' .. (j - 1) .. '].type != kObjectType' .. kind .. '') end end output:write(') {\n') - output:write(' ELOG("Error handling ui event \''..ev.name..'\'");\n') + output:write(' ELOG("Error handling ui event \'' .. ev.name .. '\'");\n') output:write(' return;\n') output:write(' }\n') end @@ -62,23 +64,29 @@ local function call_ui_event_method(output, ev) for j = 1, #ev.parameters do local param = ev.parameters[j] local kind = param[1] - output:write(' '..kind..' arg_'..j..' = ') + output:write(' ' .. kind .. ' arg_' .. j .. ' = ') if kind == 'HlAttrs' then -- The first HlAttrs argument is rgb_attrs and second is cterm_attrs - output:write('ui_client_dict2hlattrs(args.items['..(j-1)..'].data.dictionary, '..(hlattrs_args_count == 0 and 'true' or 'false')..');\n') + output:write( + 'ui_client_dict2hlattrs(args.items[' + .. (j - 1) + .. '].data.dictionary, ' + .. (hlattrs_args_count == 0 and 'true' or 'false') + .. ');\n' + ) hlattrs_args_count = hlattrs_args_count + 1 elseif kind == 'Object' then - output:write('args.items['..(j-1)..'];\n') + output:write('args.items[' .. (j - 1) .. '];\n') elseif kind == 'Window' then - output:write('(Window)args.items['..(j-1)..'].data.integer;\n') + output:write('(Window)args.items[' .. (j - 1) .. '].data.integer;\n') else - output:write('args.items['..(j-1)..'].data.'..string.lower(kind)..';\n') + output:write('args.items[' .. (j - 1) .. '].data.' .. string.lower(kind) .. ';\n') end end - output:write(' tui_'..ev.name..'(tui') + output:write(' tui_' .. ev.name .. '(tui') for j = 1, #ev.parameters do - output:write(', arg_'..j) + output:write(', arg_' .. j) end output:write(');\n') @@ -90,78 +98,81 @@ for i = 1, #events do assert(ev.return_type == 'void') if ev.since == nil and not ev.noexport then - print("Ui event "..ev.name.." lacks since field.\n") + print('Ui event ' .. ev.name .. ' lacks since field.\n') os.exit(1) end ev.since = tonumber(ev.since) if not ev.remote_only then - if not ev.remote_impl and not ev.noexport then - remote_output:write('void remote_ui_'..ev.name) + remote_output:write('void remote_ui_' .. ev.name) write_signature(remote_output, ev, 'UI *ui') remote_output:write('\n{\n') remote_output:write(' UIData *data = ui->data;\n') remote_output:write(' Array args = data->call_buf;\n') write_arglist(remote_output, ev) - remote_output:write(' push_call(ui, "'..ev.name..'", args);\n') + remote_output:write(' push_call(ui, "' .. ev.name .. '", args);\n') remote_output:write('}\n\n') end end if not (ev.remote_only and ev.remote_impl) then - call_output:write('void ui_call_'..ev.name) + call_output:write('void ui_call_' .. ev.name) write_signature(call_output, ev, '') call_output:write('\n{\n') if ev.remote_only then call_output:write(' Array args = call_buf;\n') write_arglist(call_output, ev) - call_output:write(' ui_call_event("'..ev.name..'", args);\n') + call_output:write(' ui_call_event("' .. ev.name .. '", args);\n') elseif ev.compositor_impl then - call_output:write(' ui_comp_'..ev.name) + call_output:write(' ui_comp_' .. ev.name) write_signature(call_output, ev, '', true) - call_output:write(";\n") + call_output:write(';\n') call_output:write(' UI_CALL') - write_signature(call_output, ev, '!ui->composed, '..ev.name..', ui', true) - call_output:write(";\n") + write_signature(call_output, ev, '!ui->composed, ' .. ev.name .. ', ui', true) + call_output:write(';\n') else call_output:write(' UI_CALL') - write_signature(call_output, ev, 'true, '..ev.name..', ui', true) - call_output:write(";\n") + write_signature(call_output, ev, 'true, ' .. ev.name .. ', ui', true) + call_output:write(';\n') end - call_output:write("}\n\n") + call_output:write('}\n\n') end if ev.compositor_impl then - call_output:write('void ui_composed_call_'..ev.name) + call_output:write('void ui_composed_call_' .. ev.name) write_signature(call_output, ev, '') call_output:write('\n{\n') call_output:write(' UI_CALL') - write_signature(call_output, ev, 'ui->composed, '..ev.name..', ui', true) - call_output:write(";\n") - call_output:write("}\n\n") + write_signature(call_output, ev, 'ui->composed, ' .. ev.name .. ', ui', true) + call_output:write(';\n') + call_output:write('}\n\n') end - if (not ev.remote_only) and (not ev.noexport) and (not ev.client_impl) and (not ev.client_ignore) then + if (not ev.remote_only) and not ev.noexport and not ev.client_impl and not ev.client_ignore then call_ui_event_method(client_output, ev) end end local client_events = {} -for _,ev in ipairs(events) do - if (not ev.noexport) and ((not ev.remote_only) or ev.client_impl) and (not ev.client_ignore) then +for _, ev in ipairs(events) do + if (not ev.noexport) and ((not ev.remote_only) or ev.client_impl) and not ev.client_ignore then client_events[ev.name] = ev end end -local hashorder, hashfun = hashy.hashy_hash("ui_client_handler", vim.tbl_keys(client_events), function (idx) - return "event_handlers["..idx.."].name" -end) +local hashorder, hashfun = hashy.hashy_hash( + 'ui_client_handler', + vim.tbl_keys(client_events), + function(idx) + return 'event_handlers[' .. idx .. '].name' + end +) -client_output:write("static const UIClientHandler event_handlers[] = {\n") +client_output:write('static const UIClientHandler event_handlers[] = {\n') for _, name in ipairs(hashorder) do - client_output:write(' { .name = "'..name..'", .fn = ui_client_event_'..name..'},\n') + client_output:write(' { .name = "' .. name .. '", .fn = ui_client_event_' .. name .. '},\n') end client_output:write('\n};\n\n') @@ -172,25 +183,24 @@ remote_output:close() client_output:close() -- don't expose internal attributes like "impl_name" in public metadata -local exported_attributes = {'name', 'parameters', - 'since', 'deprecated_since'} +local exported_attributes = { 'name', 'parameters', 'since', 'deprecated_since' } local exported_events = {} -for _,ev in ipairs(events) do +for _, ev in ipairs(events) do local ev_exported = {} - for _,attr in ipairs(exported_attributes) do + for _, attr in ipairs(exported_attributes) do ev_exported[attr] = ev[attr] end - for _,p in ipairs(ev_exported.parameters) do + for _, p in ipairs(ev_exported.parameters) do if p[1] == 'HlAttrs' then p[1] = 'Dictionary' end end if not ev.noexport then - exported_events[#exported_events+1] = ev_exported + exported_events[#exported_events + 1] = ev_exported end end local packed = mpack.encode(exported_events) -local dump_bin_array = require("generators.dump_bin_array") +local dump_bin_array = require('generators.dump_bin_array') dump_bin_array(metadata_output, 'ui_events_metadata', packed) metadata_output:close() diff --git a/src/nvim/generators/gen_char_blob.lua b/src/nvim/generators/gen_char_blob.lua index 11f6cbcc13..c40e0d6e82 100644 --- a/src/nvim/generators/gen_char_blob.lua +++ b/src/nvim/generators/gen_char_blob.lua @@ -1,6 +1,6 @@ if arg[1] == '--help' then print('Usage:') - print(' '..arg[0]..' [-c] target source varname [source varname]...') + print(' ' .. arg[0] .. ' [-c] target source varname [source varname]...') print('') print('Generates C file with big uint8_t blob.') print('Blob will be stored in a static const array named varname.') @@ -12,7 +12,7 @@ end local options = {} while true do - local opt = string.match(arg[1], "^-(%w)") + local opt = string.match(arg[1], '^-(%w)') if not opt then break end @@ -36,33 +36,33 @@ for argi = 2, #arg, 2 do local source_file = arg[argi] local modname = arg[argi + 1] if modnames[modname] then - error(string.format("modname %q is already specified for file %q", modname, modnames[modname])) + error(string.format('modname %q is already specified for file %q', modname, modnames[modname])) end modnames[modname] = source_file - local varname = string.gsub(modname,'%.','_dot_').."_module" + local varname = string.gsub(modname, '%.', '_dot_') .. '_module' target:write(('static const uint8_t %s[] = {\n'):format(varname)) local output if options.c then - local luac = os.getenv("LUAC_PRG") - if luac and luac ~= "" then - output = io.popen(luac:format(source_file), "r"):read("*a") + local luac = os.getenv('LUAC_PRG') + if luac and luac ~= '' then + output = io.popen(luac:format(source_file), 'r'):read('*a') elseif warn_on_missing_compiler then - print("LUAC_PRG is missing, embedding raw source") + print('LUAC_PRG is missing, embedding raw source') warn_on_missing_compiler = false end end if not output then - local source = io.open(source_file, "r") - or error(string.format("source_file %q doesn't exist", source_file)) - output = source:read("*a") + local source = io.open(source_file, 'r') + or error(string.format("source_file %q doesn't exist", source_file)) + output = source:read('*a') source:close() end local num_bytes = 0 - local MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line + local MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line target:write(' ') local increase_num_bytes @@ -81,8 +81,11 @@ for argi = 2, #arg, 2 do end target:write(' 0};\n') - if modname ~= "_" then - table.insert(index_items, ' { "'..modname..'", '..varname..', sizeof '..varname..' },\n\n') + if modname ~= '_' then + table.insert( + index_items, + ' { "' .. modname .. '", ' .. varname .. ', sizeof ' .. varname .. ' },\n\n' + ) end end diff --git a/src/nvim/generators/gen_declarations.lua b/src/nvim/generators/gen_declarations.lua index fecca5191e..9fd2750f52 100644 --- a/src/nvim/generators/gen_declarations.lua +++ b/src/nvim/generators/gen_declarations.lua @@ -5,9 +5,9 @@ local preproc_fname = arg[4] local lpeg = vim.lpeg -local fold = function (func, ...) +local fold = function(func, ...) local result = nil - for _, v in ipairs({...}) do + for _, v in ipairs({ ... }) do if result == nil then result = v else @@ -17,144 +17,112 @@ local fold = function (func, ...) return result end -local folder = function (func) - return function (...) +local folder = function(func) + return function(...) return fold(func, ...) end end local lit = lpeg.P local set = function(...) - return lpeg.S(fold(function (a, b) return a .. b end, ...)) + return lpeg.S(fold(function(a, b) + return a .. b + end, ...)) end local any_character = lpeg.P(1) -local rng = function(s, e) return lpeg.R(s .. e) end -local concat = folder(function (a, b) return a * b end) -local branch = folder(function (a, b) return a + b end) -local one_or_more = function(v) return v ^ 1 end -local two_or_more = function(v) return v ^ 2 end -local any_amount = function(v) return v ^ 0 end -local one_or_no = function(v) return v ^ -1 end +local rng = function(s, e) + return lpeg.R(s .. e) +end +local concat = folder(function(a, b) + return a * b +end) +local branch = folder(function(a, b) + return a + b +end) +local one_or_more = function(v) + return v ^ 1 +end +local two_or_more = function(v) + return v ^ 2 +end +local any_amount = function(v) + return v ^ 0 +end +local one_or_no = function(v) + return v ^ -1 +end local look_behind = lpeg.B -local look_ahead = function(v) return #v end -local neg_look_ahead = function(v) return -v end -local neg_look_behind = function(v) return -look_behind(v) end +local look_ahead = function(v) + return #v +end +local neg_look_ahead = function(v) + return -v +end +local neg_look_behind = function(v) + return -look_behind(v) +end -local w = branch( - rng('a', 'z'), - rng('A', 'Z'), - lit('_') -) -local aw = branch( - w, - rng('0', '9') -) +local w = branch(rng('a', 'z'), rng('A', 'Z'), lit('_')) +local aw = branch(w, rng('0', '9')) local s = set(' ', '\n', '\t') local raw_word = concat(w, any_amount(aw)) -local right_word = concat( - raw_word, - neg_look_ahead(aw) -) +local right_word = concat(raw_word, neg_look_ahead(aw)) local word = branch( concat( branch(lit('ArrayOf('), lit('DictionaryOf('), lit('Dict(')), -- typed container macro one_or_more(any_character - lit(')')), lit(')') ), - concat( - neg_look_behind(aw), - right_word - ) -) -local inline_comment = concat( - lit('/*'), - any_amount(concat( - neg_look_ahead(lit('*/')), - any_character - )), - lit('*/') + concat(neg_look_behind(aw), right_word) ) +local inline_comment = + concat(lit('/*'), any_amount(concat(neg_look_ahead(lit('*/')), any_character)), lit('*/')) local spaces = any_amount(branch( s, -- Comments are really handled by preprocessor, so the following is not needed inline_comment, - concat( - lit('//'), - any_amount(concat( - neg_look_ahead(lit('\n')), - any_character - )), - lit('\n') - ), + concat(lit('//'), any_amount(concat(neg_look_ahead(lit('\n')), any_character)), lit('\n')), -- Linemarker inserted by preprocessor - concat( - lit('# '), - any_amount(concat( - neg_look_ahead(lit('\n')), - any_character - )), - lit('\n') - ) + concat(lit('# '), any_amount(concat(neg_look_ahead(lit('\n')), any_character)), lit('\n')) )) -local typ_part = concat( - word, - any_amount(concat( - spaces, - lit('*') - )), - spaces -) +local typ_part = concat(word, any_amount(concat(spaces, lit('*'))), spaces) local typ_id = two_or_more(typ_part) -local arg = typ_id -- argument name is swallowed by typ +local arg = typ_id -- argument name is swallowed by typ local pattern = concat( any_amount(branch(set(' ', '\t'), inline_comment)), - typ_id, -- return type with function name + typ_id, -- return type with function name spaces, lit('('), spaces, - one_or_no(branch( -- function arguments + one_or_no(branch( -- function arguments concat( - arg, -- first argument, does not require comma - any_amount(concat( -- following arguments, start with a comma + arg, -- first argument, does not require comma + any_amount(concat( -- following arguments, start with a comma spaces, lit(','), spaces, arg, - any_amount(concat( - lit('['), - spaces, - any_amount(aw), - spaces, - lit(']') - )) + any_amount(concat(lit('['), spaces, any_amount(aw), spaces, lit(']'))) )), - one_or_no(concat( - spaces, - lit(','), - spaces, - lit('...') - )) + one_or_no(concat(spaces, lit(','), spaces, lit('...'))) ), - lit('void') -- also accepts just void + lit('void') -- also accepts just void )), spaces, lit(')'), - any_amount(concat( -- optional attributes + any_amount(concat( -- optional attributes spaces, lit('FUNC_'), any_amount(aw), - one_or_no(concat( -- attribute argument + one_or_no(concat( -- attribute argument spaces, lit('('), - any_amount(concat( - neg_look_ahead(lit(')')), - any_character - )), + any_amount(concat(neg_look_ahead(lit(')')), any_character)), lit(')') )) )), - look_ahead(concat( -- definition must be followed by "{" + look_ahead(concat( -- definition must be followed by "{" spaces, lit('{') )) @@ -198,10 +166,9 @@ Additionally uses the following environment variables: end local preproc_f = io.open(preproc_fname) -local text = preproc_f:read("*all") +local text = preproc_f:read('*all') preproc_f:close() - local non_static = [[ #define DEFINE_FUNC_ATTRIBUTES #include "nvim/func_attr.h" @@ -289,8 +256,7 @@ while init ~= nil do declaration = declaration .. ';' if os.getenv('NVIM_GEN_DECLARATIONS_LINE_NUMBERS') == '1' then - declaration = declaration .. (' // %s/%s:%u'):format( - curdir, curfile, declline) + declaration = declaration .. (' // %s/%s:%u'):format(curdir, curfile, declline) end declaration = declaration .. '\n' if declaration:sub(1, 6) == 'static' then diff --git a/src/nvim/generators/gen_eval.lua b/src/nvim/generators/gen_eval.lua index 7b272c337e..1ce7f1af9d 100644 --- a/src/nvim/generators/gen_eval.lua +++ b/src/nvim/generators/gen_eval.lua @@ -8,7 +8,7 @@ local funcsfname = autodir .. '/funcs.generated.h' --Will generate funcs.generated.h with definition of functions static const array. -local hashy = require'generators.hashy' +local hashy = require 'generators.hashy' local hashpipe = assert(io.open(funcsfname, 'wb')) @@ -48,18 +48,18 @@ hashpipe:write([[ local funcs = require('eval').funcs for _, func in pairs(funcs) do if func.float_func then - func.func = "float_op_wrapper" - func.data = "{ .float_func = &"..func.float_func.." }" + func.func = 'float_op_wrapper' + func.data = '{ .float_func = &' .. func.float_func .. ' }' end end -local metadata = mpack.decode(io.open(metadata_file, 'rb'):read("*all")) -for _,fun in ipairs(metadata) do +local metadata = mpack.decode(io.open(metadata_file, 'rb'):read('*all')) +for _, fun in ipairs(metadata) do if fun.eval then funcs[fun.name] = { - args=#fun.parameters, - func='api_wrapper', - data='{ .api_handler = &method_handlers['..fun.handler_id..'] }' + args = #fun.parameters, + func = 'api_wrapper', + data = '{ .api_handler = &method_handlers[' .. fun.handler_id .. '] }', } end end @@ -74,28 +74,37 @@ local funcsdata = assert(io.open(funcs_file, 'w')) funcsdata:write(mpack.encode(func_names)) funcsdata:close() -local neworder, hashfun = hashy.hashy_hash("find_internal_func", func_names, function (idx) - return "functions["..idx.."].name" +local neworder, hashfun = hashy.hashy_hash('find_internal_func', func_names, function(idx) + return 'functions[' .. idx .. '].name' end) -hashpipe:write("static const EvalFuncDef functions[] = {\n") +hashpipe:write('static const EvalFuncDef functions[] = {\n') for _, name in ipairs(neworder) do local def = funcs[name] local args = def.args or 0 if type(args) == 'number' then - args = {args, args} + args = { args, args } elseif #args == 1 then args[2] = 'MAX_FUNC_ARGS' end - local base = def.base or "BASE_NONE" + local base = def.base or 'BASE_NONE' local func = def.func or ('f_' .. name) - local data = def.data or "{ .null = NULL }" + local data = def.data or '{ .null = NULL }' local fast = def.fast and 'true' or 'false' - hashpipe:write((' { "%s", %s, %s, %s, %s, &%s, %s },\n') - :format(name, args[1], args[2], base, fast, func, data)) + hashpipe:write( + (' { "%s", %s, %s, %s, %s, &%s, %s },\n'):format( + name, + args[1], + args[2], + base, + fast, + func, + data + ) + ) end hashpipe:write(' { NULL, 0, 0, BASE_NONE, false, NULL, { .null = NULL } },\n') -hashpipe:write("};\n\n") +hashpipe:write('};\n\n') hashpipe:write(hashfun) hashpipe:close() diff --git a/src/nvim/generators/gen_events.lua b/src/nvim/generators/gen_events.lua index 4763a2f463..ee48e918e8 100644 --- a/src/nvim/generators/gen_events.lua +++ b/src/nvim/generators/gen_events.lua @@ -22,7 +22,7 @@ static const struct event_name { for i, event in ipairs(events) do enum_tgt:write(('\n EVENT_%s = %u,'):format(event:upper(), i - 1)) names_tgt:write(('\n {%u, "%s", EVENT_%s},'):format(#event, event, event:upper())) - if i == #events then -- Last item. + if i == #events then -- Last item. enum_tgt:write(('\n NUM_EVENTS = %u,'):format(i)) end end @@ -41,15 +41,15 @@ names_tgt:write('\n};\n') do names_tgt:write('\nstatic AutoCmdVec autocmds[NUM_EVENTS] = {\n ') local line_len = 1 - for _ = 1,((#events) - 1) do - line_len = line_len + #(' KV_INITIAL_VALUE,') + for _ = 1, (#events - 1) do + line_len = line_len + #' KV_INITIAL_VALUE,' if line_len > 80 then names_tgt:write('\n ') - line_len = 1 + #(' KV_INITIAL_VALUE,') + line_len = 1 + #' KV_INITIAL_VALUE,' end names_tgt:write(' KV_INITIAL_VALUE,') end - if line_len + #(' KV_INITIAL_VALUE') > 80 then + if line_len + #' KV_INITIAL_VALUE' > 80 then names_tgt:write('\n KV_INITIAL_VALUE') else names_tgt:write(' KV_INITIAL_VALUE') diff --git a/src/nvim/generators/gen_ex_cmds.lua b/src/nvim/generators/gen_ex_cmds.lua index ae8c952648..e8d1aac182 100644 --- a/src/nvim/generators/gen_ex_cmds.lua +++ b/src/nvim/generators/gen_ex_cmds.lua @@ -21,24 +21,32 @@ local a_to_z = byte_z - byte_a + 1 -- Table giving the index of the first command in cmdnames[] to lookup -- based on the first letter of a command. -local cmdidxs1_out = string.format([[ +local cmdidxs1_out = string.format( + [[ static const uint16_t cmdidxs1[%u] = { -]], a_to_z) +]], + a_to_z +) -- Table giving the index of the first command in cmdnames[] to lookup -- based on the first 2 letters of a command. -- Values in cmdidxs2[c1][c2] are relative to cmdidxs1[c1] so that they -- fit in a byte. -local cmdidxs2_out = string.format([[ +local cmdidxs2_out = string.format( + [[ static const uint8_t cmdidxs2[%u][%u] = { /* a b c d e f g h i j k l m n o p q r s t u v w x y z */ -]], a_to_z, a_to_z) +]], + a_to_z, + a_to_z +) enumfile:write([[ // IWYU pragma: private, include "nvim/ex_cmds_defs.h" typedef enum CMD_index { ]]) -defsfile:write(string.format([[ +defsfile:write(string.format( + [[ #include "nvim/arglist.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" @@ -79,23 +87,34 @@ defsfile:write(string.format([[ static const int command_count = %u; static CommandDefinition cmdnames[%u] = { -]], #defs, #defs)) +]], + #defs, + #defs +)) local cmds, cmdidxs1, cmdidxs2 = {}, {}, {} for _, cmd in ipairs(defs) do if bit.band(cmd.flags, flags.RANGE) == flags.RANGE then - assert(cmd.addr_type ~= 'ADDR_NONE', - string.format('ex_cmds.lua:%s: Using RANGE with ADDR_NONE\n', cmd.command)) + assert( + cmd.addr_type ~= 'ADDR_NONE', + string.format('ex_cmds.lua:%s: Using RANGE with ADDR_NONE\n', cmd.command) + ) else - assert(cmd.addr_type == 'ADDR_NONE', - string.format('ex_cmds.lua:%s: Missing ADDR_NONE\n', cmd.command)) + assert( + cmd.addr_type == 'ADDR_NONE', + string.format('ex_cmds.lua:%s: Missing ADDR_NONE\n', cmd.command) + ) end if bit.band(cmd.flags, flags.DFLALL) == flags.DFLALL then - assert(cmd.addr_type ~= 'ADDR_OTHER' and cmd.addr_type ~= 'ADDR_NONE', - string.format('ex_cmds.lua:%s: Missing misplaced DFLALL\n', cmd.command)) + assert( + cmd.addr_type ~= 'ADDR_OTHER' and cmd.addr_type ~= 'ADDR_NONE', + string.format('ex_cmds.lua:%s: Missing misplaced DFLALL\n', cmd.command) + ) end if bit.band(cmd.flags, flags.PREVIEW) == flags.PREVIEW then - assert(cmd.preview_func ~= nil, - string.format('ex_cmds.lua:%s: Missing preview_func\n', cmd.command)) + assert( + cmd.preview_func ~= nil, + string.format('ex_cmds.lua:%s: Missing preview_func\n', cmd.command) + ) end local enumname = cmd.enum or ('CMD_' .. cmd.command) local byte_cmd = cmd.command:sub(1, 1):byte() @@ -104,12 +123,13 @@ for _, cmd in ipairs(defs) do end local preview_func if cmd.preview_func then - preview_func = string.format("&%s", cmd.preview_func) + preview_func = string.format('&%s', cmd.preview_func) else - preview_func = "NULL" + preview_func = 'NULL' end enumfile:write(' ' .. enumname .. ',\n') - defsfile:write(string.format([[ + defsfile:write(string.format( + [[ [%s] = { .cmd_name = "%s", .cmd_func = (ex_func_T)&%s, @@ -117,7 +137,14 @@ for _, cmd in ipairs(defs) do .cmd_argt = %uL, .cmd_addr_type = %s }, -]], enumname, cmd.command, cmd.func, preview_func, cmd.flags, cmd.addr_type)) +]], + enumname, + cmd.command, + cmd.func, + preview_func, + cmd.flags, + cmd.addr_type + )) end for i = #cmds, 1, -1 do local cmd = cmds[i] @@ -141,10 +168,12 @@ for i = byte_a, byte_z do cmdidxs2_out = cmdidxs2_out .. ' /* ' .. c1 .. ' */ {' for j = byte_a, byte_z do local c2 = string.char(j) - cmdidxs2_out = cmdidxs2_out .. - ((cmdidxs2[c1] and cmdidxs2[c1][c2]) - and string.format('%3d', cmdidxs2[c1][c2] - cmdidxs1[c1]) - or ' 0') .. ',' + cmdidxs2_out = cmdidxs2_out + .. ((cmdidxs2[c1] and cmdidxs2[c1][c2]) and string.format( + '%3d', + cmdidxs2[c1][c2] - cmdidxs1[c1] + ) or ' 0') + .. ',' end cmdidxs2_out = cmdidxs2_out .. ' },\n' end @@ -154,8 +183,12 @@ enumfile:write([[ CMD_USER_BUF = -2 } cmdidx_T; ]]) -defsfile:write(string.format([[ +defsfile:write(string.format( + [[ }; %s}; %s}; -]], cmdidxs1_out, cmdidxs2_out)) +]], + cmdidxs1_out, + cmdidxs2_out +)) diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index 26ade2745d..3a355634f3 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -15,37 +15,37 @@ local options = require('options') local cstr = options.cstr -local type_flags={ - bool='P_BOOL', - number='P_NUM', - string='P_STRING', +local type_flags = { + bool = 'P_BOOL', + number = 'P_NUM', + string = 'P_STRING', } -local redraw_flags={ - ui_option='P_UI_OPTION', - tabline='P_RTABL', - statuslines='P_RSTAT', - current_window='P_RWIN', - current_window_only='P_RWINONLY', - current_buffer='P_RBUF', - all_windows='P_RALL', - curswant='P_CURSWANT', +local redraw_flags = { + ui_option = 'P_UI_OPTION', + tabline = 'P_RTABL', + statuslines = 'P_RSTAT', + current_window = 'P_RWIN', + current_window_only = 'P_RWINONLY', + current_buffer = 'P_RBUF', + all_windows = 'P_RALL', + curswant = 'P_CURSWANT', } -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', +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', } --- @param o vim.option_meta --- @return string local function get_flags(o) --- @type string[] - local ret = {type_flags[o.type]} + local ret = { type_flags[o.type] } local add_flag = function(f) ret[1] = ret[1] .. '|' .. f end @@ -64,19 +64,19 @@ local function get_flags(o) end end for _, flag_desc in ipairs({ - {'alloced'}, - {'nodefault'}, - {'no_mkrc'}, - {'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'}, - {'func'} + { 'alloced' }, + { 'nodefault' }, + { 'no_mkrc' }, + { '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' }, + { 'func' }, }) do local key_name = flag_desc[1] local def_name = flag_desc[2] or ('P_' .. key_name:upper()) @@ -108,20 +108,28 @@ local function get_cond(c, base_string) end local value_dumpers = { - ['function']=function(v) return v() end, - string=cstr, - boolean=function(v) return v and 'true' or 'false' end, - number=function(v) return ('%iL'):format(v) end, - ['nil']=function(_) return '0' end, + ['function'] = function(v) + return v() + end, + string = cstr, + boolean = function(v) + return v and 'true' or 'false' + end, + number = function(v) + return ('%iL'):format(v) + end, + ['nil'] = function(_) + return '0' + end, } local get_value = function(v) return '(void *) ' .. value_dumpers[type(v)](v) end -local get_defaults = function(d,n) +local get_defaults = function(d, n) if d == nil then - error("option '"..n.."' should have a default value") + error("option '" .. n .. "' should have a default value") end return get_value(d) end @@ -153,20 +161,21 @@ local function dump_option(i, o) 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') + 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 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() - ) .. ')' + '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}) + table.insert(defines, { 'PV_' .. varname:sub(3):upper(), pv_name }) w(' .indir=' .. pv_name) end if o.cb then diff --git a/src/nvim/generators/gen_unicode_tables.lua b/src/nvim/generators/gen_unicode_tables.lua index 9ad99c8029..6cedb5db50 100644 --- a/src/nvim/generators/gen_unicode_tables.lua +++ b/src/nvim/generators/gen_unicode_tables.lua @@ -60,12 +60,10 @@ local fp_lines_to_lists = function(fp, n, has_comments) if not line then break end - if (not has_comments - or (line:sub(1, 1) ~= '#' and not line:match('^%s*$'))) then + if not has_comments or (line:sub(1, 1) ~= '#' and not line:match('^%s*$')) then local l = split_on_semicolons(line) if #l ~= n then - io.stderr:write(('Found %s items in line %u, expected %u\n'):format( - #l, i, n)) + io.stderr:write(('Found %s items in line %u, expected %u\n'):format(#l, i, n)) io.stderr:write('Line: ' .. line .. '\n') return nil end @@ -93,15 +91,13 @@ end local make_range = function(start, end_, step, add) if step and add then - return (' {0x%x, 0x%x, %d, %d},\n'):format( - start, end_, step == 0 and -1 or step, add) + return (' {0x%x, 0x%x, %d, %d},\n'):format(start, end_, step == 0 and -1 or step, add) else return (' {0x%04x, 0x%04x},\n'):format(start, end_) end end -local build_convert_table = function(ut_fp, props, cond_func, nl_index, - table_name) +local build_convert_table = function(ut_fp, props, cond_func, nl_index, table_name) ut_fp:write('static const convertStruct ' .. table_name .. '[] = {\n') local start = -1 local end_ = -1 @@ -137,8 +133,7 @@ local build_case_table = function(ut_fp, dataprops, table_name, index) local cond_func = function(p) return p[index] ~= '' end - return build_convert_table(ut_fp, dataprops, cond_func, index, - 'to' .. table_name) + return build_convert_table(ut_fp, dataprops, cond_func, index, 'to' .. table_name) end local build_fold_table = function(ut_fp, foldprops) @@ -154,7 +149,7 @@ local build_combining_table = function(ut_fp, dataprops) local end_ = -1 for _, p in ipairs(dataprops) do -- The 'Mc' property was removed, it does take up space. - if (({Mn=true, Me=true})[p[3]]) then + if ({ Mn = true, Me = true })[p[3]] then local n = tonumber(p[1], 16) if start >= 0 and end_ + 1 == n then -- Continue with the same range. @@ -175,8 +170,7 @@ local build_combining_table = function(ut_fp, dataprops) ut_fp:write('};\n') end -local build_width_table = function(ut_fp, dataprops, widthprops, widths, - table_name) +local build_width_table = function(ut_fp, dataprops, widthprops, widths, table_name) ut_fp:write('static const struct interval ' .. table_name .. '[] = {\n') local start = -1 local end_ = -1 @@ -208,13 +202,13 @@ local build_width_table = function(ut_fp, dataprops, widthprops, widths, -- Only use the char when it’s not a composing char. -- But use all chars from a range. local dp = dataprops[dataidx] - if (n_last > n) or (not (({Mn=true, Mc=true, Me=true})[dp[3]])) then + if (n_last > n) or not ({ Mn = true, Mc = true, Me = true })[dp[3]] then if start >= 0 and end_ + 1 == n then -- luacheck: ignore 542 -- Continue with the same range. else if start >= 0 then ut_fp:write(make_range(start, end_)) - table.insert(ret, {start, end_}) + table.insert(ret, { start, end_ }) end start = n end @@ -224,7 +218,7 @@ local build_width_table = function(ut_fp, dataprops, widthprops, widths, end if start >= 0 then ut_fp:write(make_range(start, end_)) - table.insert(ret, {start, end_}) + table.insert(ret, { start, end_ }) end ut_fp:write('};\n') return ret @@ -316,10 +310,9 @@ local eaw_fp = io.open(eastasianwidth_fname, 'r') local widthprops = parse_width_props(eaw_fp) eaw_fp:close() -local doublewidth = build_width_table(ut_fp, dataprops, widthprops, - {W=true, F=true}, 'doublewidth') -local ambiwidth = build_width_table(ut_fp, dataprops, widthprops, - {A=true}, 'ambiguous') +local doublewidth = + build_width_table(ut_fp, dataprops, widthprops, { W = true, F = true }, 'doublewidth') +local ambiwidth = build_width_table(ut_fp, dataprops, widthprops, { A = true }, 'ambiguous') local emoji_fp = io.open(emoji_fname, 'r') local emojiprops = parse_emoji_props(emoji_fp) diff --git a/src/nvim/generators/gen_vimvim.lua b/src/nvim/generators/gen_vimvim.lua index 29355d3cda..4d1c82a322 100644 --- a/src/nvim/generators/gen_vimvim.lua +++ b/src/nvim/generators/gen_vimvim.lua @@ -41,12 +41,14 @@ end -- Exclude these from the vimCommand keyword list, they are handled specially -- in syntax/vim.vim (vimAugroupKey, vimAutoCmd, vimGlobal, vimSubst). #9327 local function is_special_cased_cmd(cmd) - return (cmd == 'augroup' - or cmd == 'autocmd' - or cmd == 'doautocmd' - or cmd == 'doautoall' - or cmd == 'global' - or cmd == 'substitute') + return ( + cmd == 'augroup' + or cmd == 'autocmd' + or cmd == 'doautocmd' + or cmd == 'doautoall' + or cmd == 'global' + or cmd == 'substitute' + ) end local vimcmd_start = 'syn keyword vimCommand contained ' @@ -133,7 +135,7 @@ end w('\n\nsyn case match') local vimfun_start = 'syn keyword vimFuncName contained ' w('\n\n' .. vimfun_start) -local funcs = mpack.decode(io.open(funcs_file, 'rb'):read("*all")) +local funcs = mpack.decode(io.open(funcs_file, 'rb'):read('*all')) for _, name in ipairs(funcs) do if name then if lld.line_length > 850 then diff --git a/src/nvim/generators/hashy.lua b/src/nvim/generators/hashy.lua index b10bafb9f9..711e695742 100644 --- a/src/nvim/generators/hashy.lua +++ b/src/nvim/generators/hashy.lua @@ -3,7 +3,6 @@ local M = {} _G.d = M - local function setdefault(table, key) local val = table[key] if val == nil then @@ -16,28 +15,30 @@ end function M.build_pos_hash(strings) local len_buckets = {} local maxlen = 0 - for _,s in ipairs(strings) do - table.insert(setdefault(len_buckets, #s),s) - if #s > maxlen then maxlen = #s end + for _, s in ipairs(strings) do + table.insert(setdefault(len_buckets, #s), s) + if #s > maxlen then + maxlen = #s + end end local len_pos_buckets = {} local worst_buck_size = 0 - for len = 1,maxlen do + for len = 1, maxlen do local strs = len_buckets[len] if strs then -- the best position so far generates `best_bucket` -- with `minsize` worst case collisions - local bestpos, minsize, best_bucket = nil, #strs*2, nil - for pos = 1,len do + local bestpos, minsize, best_bucket = nil, #strs * 2, nil + for pos = 1, len do local try_bucket = {} - for _,str in ipairs(strs) do + for _, str in ipairs(strs) do local poschar = string.sub(str, pos, pos) table.insert(setdefault(try_bucket, poschar), str) end local maxsize = 1 - for _,pos_strs in pairs(try_bucket) do + for _, pos_strs in pairs(try_bucket) do maxsize = math.max(maxsize, #pos_strs) end if maxsize < minsize then @@ -46,7 +47,7 @@ function M.build_pos_hash(strings) best_bucket = try_bucket end end - len_pos_buckets[len] = {bestpos, best_bucket} + len_pos_buckets[len] = { bestpos, best_bucket } worst_buck_size = math.max(worst_buck_size, minsize) end end @@ -55,73 +56,79 @@ end function M.switcher(put, tab, maxlen, worst_buck_size) local neworder = {} - put " switch (len) {\n" + put ' switch (len) {\n' local bucky = worst_buck_size > 1 - for len = 1,maxlen do + for len = 1, maxlen do local vals = tab[len] if vals then - put(" case "..len..": ") + put(' case ' .. len .. ': ') local pos, posbuck = unpack(vals) local keys = vim.tbl_keys(posbuck) if #keys > 1 then table.sort(keys) - put("switch (str["..(pos-1).."]) {\n") - for _,c in ipairs(keys) do + put('switch (str[' .. (pos - 1) .. ']) {\n') + for _, c in ipairs(keys) do local buck = posbuck[c] local startidx = #neworder vim.list_extend(neworder, buck) local endidx = #neworder - put(" case '"..c.."': ") - put("low = "..startidx.."; ") - if bucky then put("high = "..endidx.."; ") end - put "break;\n" + put(" case '" .. c .. "': ") + put('low = ' .. startidx .. '; ') + if bucky then + put('high = ' .. endidx .. '; ') + end + put 'break;\n' end - put " default: break;\n" - put " }\n " + put ' default: break;\n' + put ' }\n ' else - local startidx = #neworder - table.insert(neworder, posbuck[keys[1]][1]) - local endidx = #neworder - put("low = "..startidx.."; ") - if bucky then put("high = "..endidx.."; ") end + local startidx = #neworder + table.insert(neworder, posbuck[keys[1]][1]) + local endidx = #neworder + put('low = ' .. startidx .. '; ') + if bucky then + put('high = ' .. endidx .. '; ') + end end - put "break;\n" + put 'break;\n' end end - put " default: break;\n" - put " }\n" + put ' default: break;\n' + put ' }\n' return neworder end function M.hashy_hash(name, strings, access) local stats = {} - local put = function(str) table.insert(stats, str) end + local put = function(str) + table.insert(stats, str) + end local len_pos_buckets, maxlen, worst_buck_size = M.build_pos_hash(strings) - put("int "..name.."_hash(const char *str, size_t len)\n{\n") + put('int ' .. name .. '_hash(const char *str, size_t len)\n{\n') if worst_buck_size > 1 then - put(" int low = 0, high = 0;\n") + put(' int low = 0, high = 0;\n') else - put(" int low = -1;\n") + put(' int low = -1;\n') end local neworder = M.switcher(put, len_pos_buckets, maxlen, worst_buck_size) if worst_buck_size > 1 then - put ([[ + put([[ for (int i = low; i < high; i++) { - if (!memcmp(str, ]]..access("i")..[[, len)) { + if (!memcmp(str, ]] .. access('i') .. [[, len)) { return i; } } return -1; ]]) else - put ([[ - if (low < 0 || memcmp(str, ]]..access("low")..[[, len)) { + put([[ + if (low < 0 || memcmp(str, ]] .. access('low') .. [[, len)) { return -1; } return low; ]]) end - put "}\n\n" + put '}\n\n' return neworder, table.concat(stats) end diff --git a/src/nvim/generators/preload.lua b/src/nvim/generators/preload.lua index 4b7fde2c39..721d2880b8 100644 --- a/src/nvim/generators/preload.lua +++ b/src/nvim/generators/preload.lua @@ -1,7 +1,7 @@ local srcdir = table.remove(arg, 1) local nlualib = table.remove(arg, 1) -package.path = srcdir .. '/src/nvim/?.lua;' ..srcdir .. '/runtime/lua/?.lua;' .. package.path -_G.vim = require'vim.shared' +package.path = srcdir .. '/src/nvim/?.lua;' .. srcdir .. '/runtime/lua/?.lua;' .. package.path +_G.vim = require 'vim.shared' _G.vim.inspect = require 'vim.inspect' package.cpath = package.cpath .. ';' .. nlualib require 'nlua0' -- cgit From 6346987601a28b00564295ee8be0a8b00d9ff911 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Thu, 7 Dec 2023 23:46:57 +0600 Subject: refactor(options): reduce `findoption()` usage Problem: Many places in the code use `findoption()` to access an option using its name, even if the option index is available. This is very slow because it requires looping through the options array over and over. Solution: Use option index instead of name wherever possible. Also introduce an `OptIndex` enum which contains the index for every option as enum constants, this eliminates the need to pass static option names as strings. --- src/nvim/generators/gen_options.lua | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index 3a355634f3..2b17add7ba 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -1,4 +1,5 @@ local options_file = arg[1] +local options_enum_file = arg[2] local opt_fd = assert(io.open(options_file, 'w')) @@ -41,6 +42,12 @@ local list_flags = { flagscomma = 'P_COMMA|P_FLAGLIST', } +--- @param s string +--- @return string +local title_case = function(s) + return s:sub(1, 1):upper() .. s:sub(2):lower() +end + --- @param o vim.option_meta --- @return string local function get_flags(o) @@ -229,4 +236,14 @@ 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 {') +for i, o in ipairs(options.options) do + w((' kOpt%s = %u,'):format(title_case(o.full_name), i - 1)) +end +w('} OptIndex;') + opt_fd:close() -- cgit From bf3bc1cec9f00b9644815001a8732ecedf3ce07f Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Thu, 7 Dec 2023 23:59:30 +0600 Subject: refactor(options): convert `opt_idx` variables to `OptIndex` --- 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 2b17add7ba..7c5fc08129 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -241,6 +241,7 @@ end 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(title_case(o.full_name), i - 1)) end -- cgit From a34cc1a44de75eff4c6b43f983dc983eb283119d Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Fri, 8 Dec 2023 12:36:37 +0600 Subject: refactor(options): define `kOptIndexCount` Add a macro to indicate the option count so that we can iterate through the options[] table more clearly. This also removes the need for having an option with NULL fullname at the end of `options[]`. --- src/nvim/generators/gen_options.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index 7c5fc08129..b7356a7bb1 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -44,8 +44,8 @@ local list_flags = { --- @param s string --- @return string -local title_case = function(s) - return s:sub(1, 1):upper() .. s:sub(2):lower() +local lowercase_to_titlecase = function(s) + return s:sub(1, 1):upper() .. s:sub(2) end --- @param o vim.option_meta @@ -229,7 +229,6 @@ static vimoption_T options[] = {]]) for i, o in ipairs(options.options) do dump_option(i, o) end -w(' [' .. ('%u'):format(#options.options) .. ']={.fullname=NULL}') w('};') w('') @@ -242,9 +241,13 @@ 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(title_case(o.full_name), i - 1)) + 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() -- cgit From 3c2c022e5e299ecac4663c3813e2db5e2b099ffa Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Thu, 7 Dec 2023 01:34:29 +0600 Subject: refactor(options): remove option type macros Problem: We have `P_(BOOL|NUM|STRING)` macros to represent an option's type, which is redundant because `OptValType` can already do that. The current implementation of option type flags is also too limited to allow adding multitype options in the future. Solution: Remove `P_(BOOL|NUM|STRING)` and replace it with a new `type_flags` attribute in `vimoption_T`. Also do some groundwork for adding multitype options in the future. Side-effects: Attempting to set an invalid keycode option (e.g. `set t_foo=123`) no longer gives an error. --- src/nvim/generators/gen_options.lua | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index b7356a7bb1..61d5df3c84 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -16,12 +16,6 @@ local options = require('options') local cstr = options.cstr -local type_flags = { - bool = 'P_BOOL', - number = 'P_NUM', - string = 'P_STRING', -} - local redraw_flags = { ui_option = 'P_UI_OPTION', tabline = 'P_RTABL', @@ -51,11 +45,14 @@ end --- @param o vim.option_meta --- @return string local function get_flags(o) - --- @type string[] - local ret = { type_flags[o.type] } + --- @type string + local flags = '0' + + --- @param f string local add_flag = function(f) - ret[1] = ret[1] .. '|' .. f + flags = flags .. '|' .. f end + if o.list then add_flag(list_flags[o.list]) end @@ -91,7 +88,22 @@ local function get_flags(o) add_flag(def_name) end end - return ret[1] + return flags +end + +--- @param o vim.option_meta +--- @return string +local function get_type_flags(o) + local opt_types = (type(o.type) == 'table') and o.type or { o.type } + local type_flags = '0' + assert(type(opt_types) == 'table') + + 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)) + end + + return type_flags end --- @param c string|string[] @@ -153,6 +165,7 @@ local function dump_option(i, o) w(' .shortname=' .. cstr(o.abbreviation)) end w(' .flags=' .. get_flags(o)) + w(' .type_flags=' .. get_type_flags(o)) if o.enable_if then w(get_cond(o.enable_if)) end -- cgit From 8f08b1efbd096850c04c2e8e2890d993bd4d9f95 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sun, 17 Dec 2023 05:23:33 +0600 Subject: 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'. --- src/nvim/generators/gen_options.lua | 19 +------- src/nvim/generators/gen_options_enum.lua | 76 ++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 18 deletions(-) create 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 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() -- cgit From d82a586a9e39f1d346c1aea78167a85c586ed3f4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 18 Dec 2023 06:18:11 +0800 Subject: refactor: move some anonymous enums back to non-defs headers (#26622) It isn't really useful to put anonymous enums only used as arguments to functions calls in _defs.h headers, as they will only be used by a file that calls those functions, which requires including a non-defs header. Also move os_msg() and os_errmsg() back to message.h, as on Windows they are actual functions instead of macros. Also remove gettext.h and globals.h from private/helpers.h. --- src/nvim/generators/gen_api_dispatch.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index 7cec118243..5928999967 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -236,6 +236,7 @@ local keysets_defs = io.open(keysets_outputf, 'wb') output:write([[ #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" +#include "nvim/globals.h" #include "nvim/log.h" #include "nvim/map_defs.h" #include "nvim/msgpack_rpc/helpers.h" @@ -662,6 +663,7 @@ output:write([[ #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" #include "nvim/func_attr.h" +#include "nvim/globals.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/api/private/dispatch.h" -- cgit From 089b934352437ab310a6dd3b138c7ed9445a3d7b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 22 Dec 2023 12:24:23 +0800 Subject: refactor(options): generate BV_ and WV_ constants (#26705) --- src/nvim/generators/gen_options_enum.lua | 53 ++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_options_enum.lua b/src/nvim/generators/gen_options_enum.lua index c3fe9baae6..9a3953fcbc 100644 --- a/src/nvim/generators/gen_options_enum.lua +++ b/src/nvim/generators/gen_options_enum.lua @@ -1,5 +1,6 @@ -- 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] @@ -16,6 +17,9 @@ 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) @@ -24,6 +28,55 @@ 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 = {} -- cgit From ba0fa4fa197330687b06c74a50b2ccd4800f5881 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 22 Dec 2023 13:32:46 +0800 Subject: refactor(IWYU): add "private" pragma to more generated headers (#26706) "export" only prevents IWYU from adding these headers if the headers that export them are included, while "private" ensures that IWYU never adds these headers. --- src/nvim/generators/gen_api_dispatch.lua | 14 ++++++++------ src/nvim/generators/gen_declarations.lua | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 6 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 5928999967..791edfff96 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -106,7 +106,7 @@ for i = 6, #arg do end headers[#headers + 1] = parts[#parts - 1] .. '/' .. parts[#parts] - local input = io.open(full_path, 'rb') + local input = assert(io.open(full_path, 'rb')) local tmp = c_grammar.grammar:match(input:read('*all')) for j = 1, #tmp do @@ -216,16 +216,16 @@ end -- serialize the API metadata using msgpack and embed into the resulting -- binary for easy querying by clients -local funcs_metadata_output = io.open(funcs_metadata_outputf, 'wb') +local funcs_metadata_output = assert(io.open(funcs_metadata_outputf, 'wb')) local packed = mpack.encode(exported_functions) local dump_bin_array = require('generators.dump_bin_array') dump_bin_array(funcs_metadata_output, 'funcs_metadata', packed) funcs_metadata_output:close() -- start building the dispatch wrapper output -local output = io.open(dispatch_outputf, 'wb') +local output = assert(io.open(dispatch_outputf, 'wb')) -local keysets_defs = io.open(keysets_outputf, 'wb') +local keysets_defs = assert(io.open(keysets_outputf, 'wb')) -- =========================================================================== -- NEW API FILES MUST GO HERE. @@ -257,6 +257,8 @@ output:write([[ ]]) +keysets_defs:write('// IWYU pragma: private, include "nvim/api/private/dispatch.h"\n\n') + for _, k in ipairs(keysets) do local c_name = {} @@ -633,7 +635,7 @@ output:write(hashfun) output:close() functions.keysets = keysets -local mpack_output = io.open(mpack_outputf, 'wb') +local mpack_output = assert(io.open(mpack_outputf, 'wb')) mpack_output:write(mpack.encode(functions)) mpack_output:close() @@ -653,7 +655,7 @@ local function write_shifted_output(_, str) end -- start building lua output -output = io.open(lua_c_bindings_outputf, 'wb') +output = assert(io.open(lua_c_bindings_outputf, 'wb')) output:write([[ #include diff --git a/src/nvim/generators/gen_declarations.lua b/src/nvim/generators/gen_declarations.lua index 9fd2750f52..5d1e586fe6 100644 --- a/src/nvim/generators/gen_declarations.lua +++ b/src/nvim/generators/gen_declarations.lua @@ -207,6 +207,22 @@ if fname:find('.*/src/nvim/.*%.c$') then // IWYU pragma: private, include "%s" ]]):format(header_fname:gsub('.*/src/nvim/', 'nvim/')) .. non_static end +elseif non_static_fname:find('/include/api/private/dispatch_wrappers%.h%.generated%.h$') then + non_static = [[ +// IWYU pragma: private, include "nvim/api/private/dispatch.h" +]] .. non_static +elseif non_static_fname:find('/include/ui_events_call%.h%.generated%.h$') then + non_static = [[ +// IWYU pragma: private, include "nvim/ui.h" +]] .. non_static +elseif non_static_fname:find('/include/ui_events_client%.h%.generated%.h$') then + non_static = [[ +// IWYU pragma: private, include "nvim/ui_client.h" +]] .. non_static +elseif non_static_fname:find('/include/ui_events_remote%.h%.generated%.h$') then + non_static = [[ +// IWYU pragma: private, include "nvim/api/ui.h" +]] .. non_static end local filepattern = '^#%a* (%d+) "([^"]-)/?([^"/]+)"' -- cgit From 2f9ee9b6cfc61a0504fc0bc22bdf481828e2ea91 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 9 Jan 2024 17:36:46 +0000 Subject: fix(doc): improve doc generation of types using lpeg Added a lpeg grammar for LuaCATS and use it in lua2dox.lua --- src/nvim/generators/luacats_grammar.lua | 136 ++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/nvim/generators/luacats_grammar.lua (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/luacats_grammar.lua b/src/nvim/generators/luacats_grammar.lua new file mode 100644 index 0000000000..dcccd028ce --- /dev/null +++ b/src/nvim/generators/luacats_grammar.lua @@ -0,0 +1,136 @@ +--[[! +LPEG grammar for LuaCATS + +Currently only partially supports: +- @param +- @return +]] + +local lpeg = vim.lpeg +local P, R, S = lpeg.P, lpeg.R, lpeg.S +local Ct, Cg = lpeg.Ct, lpeg.Cg + +--- @param x vim.lpeg.Pattern +local function rep(x) + return x ^ 0 +end + +--- @param x vim.lpeg.Pattern +local function rep1(x) + return x ^ 1 +end + +--- @param x vim.lpeg.Pattern +local function opt(x) + return x ^ -1 +end + +local nl = P('\r\n') + P('\n') +local ws = rep1(S(' \t') + nl) +local fill = opt(ws) + +local any = P(1) -- (consume one character) +local letter = R('az', 'AZ') + S('_$') +local num = R('09') +local ident = letter * rep(letter + num + S '-.') +local string_single = P "'" * rep(any - P "'") * P "'" +local string_double = P '"' * rep(any - P '"') * P '"' + +local literal = (string_single + string_double + (opt(P '-') * num) + P 'false' + P 'true') + +local lname = (ident + P '...') * opt(P '?') + +--- @param x string +local function Pf(x) + return fill * P(x) * fill +end + +--- @param x string +local function Sf(x) + return fill * S(x) * fill +end + +--- @param x vim.lpeg.Pattern +local function comma(x) + return x * rep(Pf ',' * x) +end + +--- @param x vim.lpeg.Pattern +local function parenOpt(x) + return (Pf('(') * x ^ -1 * fill * P(')')) + x ^ -1 +end + +--- @type table +local v = setmetatable({}, { + __index = function(_, k) + return lpeg.V(k) + end, +}) + +local desc_delim = Sf '#:' + ws + +--- @class luacats.Param +--- @field kind 'param' +--- @field name string +--- @field type string +--- @field desc? string + +--- @class luacats.Return +--- @field kind 'return' +--- @field [integer] { type: string, name?: string} +--- @field desc? string + +--- @class luacats.Generic +--- @field kind 'generic' +--- @field name string +--- @field type? string + +--- @alias luacats.grammar.result +--- | luacats.Param +--- | luacats.Return +--- | luacats.Generic + +--- @class luacats.grammar +--- @field match fun(self, input: string): luacats.grammar.result? + +local grammar = P { + rep1(P('@') * v.ats), + + ats = (v.at_param + v.at_return + v.at_generic), + + at_param = Ct( + Cg(P('param'), 'kind') + * ws + * Cg(lname, 'name') + * ws + * Cg(v.ltype, 'type') + * opt(desc_delim * Cg(rep(any), 'desc')) + ), + + at_return = Ct( + Cg(P('return'), 'kind') + * ws + * parenOpt(comma(Ct(Cg(v.ltype, 'type') * opt(ws * Cg(ident, 'name'))))) + * opt(desc_delim * Cg(rep(any), 'desc')) + ), + + at_generic = Ct( + Cg(P('generic'), 'kind') * ws * Cg(ident, 'name') * opt(Pf ':' * Cg(v.ltype, 'type')) + ), + + ltype = v.ty_union + Pf '(' * v.ty_union * fill * P ')', + + ty_union = v.ty_opt * rep(Pf '|' * v.ty_opt), + ty = v.ty_fun + ident + v.ty_table + literal, + ty_param = Pf '<' * comma(v.ltype) * fill * P '>', + ty_opt = v.ty * opt(v.ty_param) * opt(P '[]') * opt(P '?'), + + table_key = (Pf '[' * literal * Pf ']') + lname, + table_elem = v.table_key * Pf ':' * v.ltype, + ty_table = Pf '{' * comma(v.table_elem) * Pf '}', + + fun_param = lname * opt(Pf ':' * v.ltype), + ty_fun = Pf 'fun(' * rep(comma(v.fun_param)) * fill * P ')' * opt(Pf ':' * v.ltype), +} + +return grammar --[[@as luacats.grammar]] -- cgit From 646fdf1073433e2bdeec3433f6cbdf8f4be37098 Mon Sep 17 00:00:00 2001 From: glepnir Date: Wed, 17 Jan 2024 20:14:26 +0800 Subject: refactor(api): use hl id directly in nvim_buf_set_extmark --- src/nvim/generators/gen_api_dispatch.lua | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 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 791edfff96..3fb240d70b 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -72,6 +72,7 @@ local keysets = {} local function add_keyset(val) local keys = {} local types = {} + local hlgroups = {} local is_set_name = 'is_set__' .. val.keyset_name .. '_' local has_optional = false for i, field in ipairs(val.fields) do @@ -80,6 +81,7 @@ local function add_keyset(val) end if field.name ~= is_set_name and field.type ~= 'OptionalKeys' then table.insert(keys, field.name) + hlgroups[field.name] = field.name:find('hl_group') and true or false else if i > 1 then error("'is_set__{type}_' must be first if present") @@ -91,10 +93,13 @@ local function add_keyset(val) has_optional = true end end - table.insert( - keysets, - { name = val.keyset_name, keys = keys, types = types, has_optional = has_optional } - ) + table.insert(keysets, { + name = val.keyset_name, + keys = keys, + types = types, + hlgroups = hlgroups, + has_optional = has_optional, + }) end -- read each input file, parse and append to the api metadata @@ -305,10 +310,12 @@ for _, k in ipairs(keysets) do .. typename(k.types[key]) .. ', ' .. ind + .. ', ' + .. (k.hlgroups[key] and 'true' or 'false') .. '},\n' ) end - output:write(' {NULL, 0, kObjectTypeNil, -1},\n') + output:write(' {NULL, 0, kObjectTypeNil, -1, false},\n') output:write('};\n\n') output:write(hashfun) -- cgit From d66ed4ea468d411668713c3777ad3658f18badf3 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 22 Jan 2024 08:49:45 +0100 Subject: refactor(api): give "hl_group" more accurate _meta type These can either be number or string in lua, so we can specify this directly as "number|string". --- src/nvim/generators/gen_api_dispatch.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 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 3fb240d70b..2eee1724c0 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -72,7 +72,6 @@ local keysets = {} local function add_keyset(val) local keys = {} local types = {} - local hlgroups = {} local is_set_name = 'is_set__' .. val.keyset_name .. '_' local has_optional = false for i, field in ipairs(val.fields) do @@ -81,7 +80,6 @@ local function add_keyset(val) end if field.name ~= is_set_name and field.type ~= 'OptionalKeys' then table.insert(keys, field.name) - hlgroups[field.name] = field.name:find('hl_group') and true or false else if i > 1 then error("'is_set__{type}_' must be first if present") @@ -97,7 +95,6 @@ local function add_keyset(val) name = val.keyset_name, keys = keys, types = types, - hlgroups = hlgroups, has_optional = has_optional, }) end @@ -285,7 +282,9 @@ for _, k in ipairs(keysets) do keysets_defs:write('extern KeySetLink ' .. k.name .. '_table[];\n') local function typename(type) - if type ~= nil then + if type == 'HLGroupID' then + return 'kObjectTypeInteger' + elseif type ~= nil then return 'kObjectType' .. type else return 'kObjectTypeNil' @@ -311,7 +310,7 @@ for _, k in ipairs(keysets) do .. ', ' .. ind .. ', ' - .. (k.hlgroups[key] and 'true' or 'false') + .. (k.types[key] == 'HLGroupID' and 'true' or 'false') .. '},\n' ) end -- cgit From c8a27bae3faeaca137e5f67b1b052ce0f0225b36 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 24 Jan 2024 12:27:38 +0800 Subject: fix(options): use a union for def_val (#27169) Problem: APIs get wrong boolean option default values on big-endian platforms. Solution: Use a union for def_val. Cannot use OptVal or OptValData yet as it needs to have the same types as option variables. --- src/nvim/generators/gen_options.lua | 42 +++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 23 deletions(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index 2fd11e4c58..cdb77c4a0c 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -125,31 +125,27 @@ local function get_cond(c, base_string) return cond_string end -local value_dumpers = { - ['function'] = function(v) - return v() - end, - string = cstr, - boolean = function(v) - return v and 'true' or 'false' - end, - number = function(v) - return ('%iL'):format(v) - end, - ['nil'] = function(_) - return '0' - end, -} - -local get_value = function(v) - return '(void *) ' .. value_dumpers[type(v)](v) -end - local get_defaults = function(d, n) if d == nil then error("option '" .. n .. "' should have a default value") end - return get_value(d) + + 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) end --- @type {[1]:string,[2]:string}[] @@ -213,11 +209,11 @@ 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 -- cgit From f9d81c43d2296d212c9cebcbdce401cd76cf0f1f Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 31 Jan 2024 22:02:06 +0100 Subject: refactor(api): use keydict and arena for more api return values Implement api_keydict_to_dict as the complement to api_dict_to_keydict Fix a conversion error when nvim_get_win_config gets called from lua, where Float values "x" and "y" didn't get converted to lua numbers. --- src/nvim/generators/gen_api_dispatch.lua | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 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 2eee1724c0..6d2beee0f8 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -212,6 +212,9 @@ for _, f in ipairs(functions) do end f_exported.parameters[i] = param end + if startswith(f.return_type, 'Dict(') then + f_exported.return_type = 'Dictionary' + end exported_functions[#exported_functions + 1] = f_exported end end @@ -279,7 +282,7 @@ for _, k in ipairs(keysets) do return k.name .. '_table[' .. idx .. '].str' end) - keysets_defs:write('extern KeySetLink ' .. k.name .. '_table[];\n') + keysets_defs:write('extern KeySetLink ' .. k.name .. '_table[' .. (1 + #neworder) .. '];\n') local function typename(type) if type == 'HLGroupID' then @@ -596,7 +599,17 @@ for i = 1, #functions do output:write(');\n') end - if fn.return_type ~= 'void' then + local ret_type = real_type(fn.return_type) + if string.match(ret_type, '^KeyDict_') then + local table = string.sub(ret_type, 9) .. '_table' + output:write( + '\n ret = DICTIONARY_OBJ(api_keydict_to_dict(&rv, ' + .. table + .. ', ARRAY_SIZE(' + .. table + .. '), arena));' + ) + elseif ret_type ~= 'void' then output:write('\n ret = ' .. string.upper(real_type(fn.return_type)) .. '_OBJ(rv);') end output:write('\n\ncleanup:') @@ -869,7 +882,7 @@ local function process_function(fn) output, string.format( [[ - const %s ret = %s(%s); + %s ret = %s(%s); ]], fn.return_type, fn.name, @@ -877,6 +890,7 @@ local function process_function(fn) ) ) + local ret_type = real_type(fn.return_type) if fn.has_lua_imp then -- only push onto the Lua stack if we haven't already write_shifted_output( @@ -890,6 +904,16 @@ local function process_function(fn) return_type ) ) + elseif string.match(ret_type, '^KeyDict_') then + write_shifted_output( + output, + string.format( + [[ + nlua_push_keydict(lstate, &ret, %s_table); + ]], + string.sub(ret_type, 9) + ) + ) else local special = (fn.since ~= nil and fn.since < 11) write_shifted_output( -- cgit From ca2635adf9c9c45ea745b9f750dc4da7063bdd14 Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 1 Feb 2024 12:30:25 +0100 Subject: refactor(generators): style of generating and generated lua dispatch code --- src/nvim/generators/gen_api_dispatch.lua | 199 +++++++++++-------------------- 1 file changed, 70 insertions(+), 129 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 6d2beee0f8..14b4ecb1a3 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -666,11 +666,11 @@ local function include_headers(output_handle, headers_to_include) end end -local function write_shifted_output(_, str) +local function write_shifted_output(str, ...) str = str:gsub('\n ', '\n') str = str:gsub('^ ', '') str = str:gsub(' +$', '') - output:write(str) + output:write(string.format(str, ...)) end -- start building lua output @@ -701,9 +701,7 @@ local lua_c_functions = {} local function process_function(fn) local lua_c_function_name = ('nlua_api_%s'):format(fn.name) write_shifted_output( - output, - string.format( - [[ + [[ static int %s(lua_State *lstate) { @@ -714,11 +712,10 @@ local function process_function(fn) goto exit_0; } ]], - lua_c_function_name, - #fn.parameters, - #fn.parameters, - (#fn.parameters == 1) and '' or 's' - ) + lua_c_function_name, + #fn.parameters, + #fn.parameters, + (#fn.parameters == 1) and '' or 's' ) lua_c_functions[#lua_c_functions + 1] = { binding = lua_c_function_name, @@ -727,38 +724,29 @@ local function process_function(fn) if not fn.fast then write_shifted_output( - output, - string.format( - [[ + [[ if (!nlua_is_deferred_safe()) { return luaL_error(lstate, e_luv_api_disabled, "%s"); } ]], - fn.name - ) + fn.name ) end if fn.textlock then - write_shifted_output( - output, - [[ + write_shifted_output([[ if (text_locked()) { - api_set_error(&err, kErrorTypeException, "%s", get_text_locked_msg()); + api_set_error(&err, kErrorTypeException, "%%s", get_text_locked_msg()); goto exit_0; } - ]] - ) + ]]) elseif fn.textlock_allow_cmdwin then - write_shifted_output( - output, - [[ + write_shifted_output([[ if (textlock != 0 || expr_map_locked()) { - api_set_error(&err, kErrorTypeException, "%s", e_textlock); + api_set_error(&err, kErrorTypeException, "%%s", e_textlock); goto exit_0; } - ]] - ) + ]]) end local cparams = '' @@ -776,44 +764,37 @@ local function process_function(fn) local seterr = '' if string.match(param_type, '^KeyDict_') then write_shifted_output( - output, - string.format( - [[ - %s %s = { 0 }; nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &err);]], - param_type, - cparam, - cparam, - param_type - ) + [[ + %s %s = { 0 }; + nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &err); + ]], + param_type, + cparam, + cparam, + param_type ) cparam = '&' .. cparam errshift = 1 -- free incomplete dict on error else write_shifted_output( - output, - string.format( - [[ - const %s %s = nlua_pop_%s(lstate, %s&err);]], - param[1], - cparam, - param_type, - extra - ) + [[ + const %s %s = nlua_pop_%s(lstate, %s&err);]], + param[1], + cparam, + param_type, + extra ) - seterr = [[ - err_param = "]] .. param[2] .. [[";]] + seterr = '\n err_param = "' .. param[2] .. '";' end - write_shifted_output( - output, - string.format([[ + write_shifted_output([[ if (ERROR_SET(&err)) {]] .. seterr .. [[ + goto exit_%u; } ]], #fn.parameters - j + errshift) - ) free_code[#free_code + 1] = ('api_free_%s(%s);'):format(lc_param_type, cparam) cparams = cparam .. ', ' .. cparams end @@ -822,12 +803,7 @@ local function process_function(fn) end if fn.arena_return then cparams = cparams .. '&arena, ' - write_shifted_output( - output, - [[ - Arena arena = ARENA_EMPTY; - ]] - ) + write_shifted_output(' Arena arena = ARENA_EMPTY;\n') end if fn.has_lua_imp then @@ -844,27 +820,27 @@ local function process_function(fn) local rev_i = #free_code - i + 1 local code = free_code[rev_i] if i == 1 and not string.match(real_type(fn.parameters[1][1]), '^KeyDict_') then - free_at_exit_code = free_at_exit_code .. ('\n %s'):format(code) + free_at_exit_code = free_at_exit_code .. ('\n %s'):format(code) else - free_at_exit_code = free_at_exit_code .. ('\n exit_%u:\n %s'):format(rev_i, code) + free_at_exit_code = free_at_exit_code .. ('\nexit_%u:\n %s'):format(rev_i, code) end end local err_throw_code = [[ - exit_0: - if (ERROR_SET(&err)) { - luaL_where(lstate, 1); - if (err_param) { - lua_pushstring(lstate, "Invalid '"); - lua_pushstring(lstate, err_param); - lua_pushstring(lstate, "': "); - } - lua_pushstring(lstate, err.msg); - api_clear_error(&err); - lua_concat(lstate, err_param ? 5 : 2); - return lua_error(lstate); +exit_0: + if (ERROR_SET(&err)) { + luaL_where(lstate, 1); + if (err_param) { + lua_pushstring(lstate, "Invalid '"); + lua_pushstring(lstate, err_param); + lua_pushstring(lstate, "': "); } - ]] + lua_pushstring(lstate, err.msg); + api_clear_error(&err); + lua_concat(lstate, err_param ? 5 : 2); + return lua_error(lstate); + } +]] local return_type if fn.return_type ~= 'void' then if fn.return_type:match('^ArrayOf') then @@ -874,97 +850,62 @@ local function process_function(fn) end local free_retval if fn.arena_return then - free_retval = 'arena_mem_free(arena_finish(&arena));' + free_retval = ' arena_mem_free(arena_finish(&arena));' else - free_retval = 'api_free_' .. return_type:lower() .. '(ret);' + free_retval = ' api_free_' .. return_type:lower() .. '(ret);' end - write_shifted_output( - output, - string.format( - [[ - %s ret = %s(%s); - ]], - fn.return_type, - fn.name, - cparams - ) - ) + write_shifted_output(' %s ret = %s(%s);\n', fn.return_type, fn.name, cparams) local ret_type = real_type(fn.return_type) if fn.has_lua_imp then -- only push onto the Lua stack if we haven't already - write_shifted_output( - output, - string.format( - [[ + write_shifted_output(string.format( + [[ if (lua_gettop(lstate) == 0) { nlua_push_%s(lstate, ret, true); } ]], - return_type - ) - ) + return_type + )) elseif string.match(ret_type, '^KeyDict_') then write_shifted_output( - output, - string.format( - [[ - nlua_push_keydict(lstate, &ret, %s_table); - ]], - string.sub(ret_type, 9) - ) + ' nlua_push_keydict(lstate, &ret, %s_table);\n', + string.sub(ret_type, 9) ) else local special = (fn.since ~= nil and fn.since < 11) - write_shifted_output( - output, - string.format( - [[ - nlua_push_%s(lstate, ret, %s); - ]], - return_type, - tostring(special) - ) - ) + write_shifted_output(' nlua_push_%s(lstate, ret, %s);\n', return_type, tostring(special)) end write_shifted_output( - output, - string.format( - [[ + + [[ %s %s %s return 1; ]], - free_retval, - free_at_exit_code, - err_throw_code - ) + free_retval, + free_at_exit_code, + err_throw_code ) else write_shifted_output( - output, - string.format( - [[ + [[ %s(%s); %s %s return 0; ]], - fn.name, - cparams, - free_at_exit_code, - err_throw_code - ) + fn.name, + cparams, + free_at_exit_code, + err_throw_code ) end - write_shifted_output( - output, - [[ + write_shifted_output([[ } - ]] - ) + ]]) end for _, fn in ipairs(functions) do -- cgit From af5beac1bd7a68ff0a4e1a944853bacd6a6c0745 Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 8 Feb 2024 13:40:35 +0100 Subject: refactor(api): refactor more api functions to use arena return Currently having two separate memory strategies for API return values is a bit unnecessary, and mostly a consequence of converting the hot spot cases which needed it first. But there is really no downside to using arena everywhere (which implies also directly using strings which are allocated earlier or even statically, without copy). There only restriction is we need to know the size of arrays in advance, but this info can often be passed on from some earlier stage if it is missing. This collects some "small" cases. The more complex stuff will get a PR each. --- src/nvim/generators/gen_api_dispatch.lua | 57 +++++++++++--------------------- 1 file changed, 19 insertions(+), 38 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 14b4ecb1a3..da3010878d 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -535,7 +535,6 @@ for i = 1, #functions do end -- function call - local call_args = table.concat(args, ', ') output:write('\n ') if fn.return_type ~= 'void' then -- has a return value, prefix the call with a declaration @@ -545,58 +544,40 @@ for i = 1, #functions do -- write the function name and the opening parenthesis output:write(fn.name .. '(') + local call_args = {} if fn.receives_channel_id then - -- if the function receives the channel id, pass it as first argument - if #args > 0 or fn.can_fail then - output:write('channel_id, ') - if fn.receives_array_args then - -- if the function receives the array args, pass it the second argument - output:write('args, ') - end - output:write(call_args) - else - output:write('channel_id') - if fn.receives_array_args then - output:write(', args') - end - end - else - if fn.receives_array_args then - if #args > 0 or fn.call_fail then - output:write('args, ' .. call_args) - else - output:write('args') - end - else - output:write(call_args) - end + table.insert(call_args, 'channel_id') + end + + if fn.receives_array_args then + table.insert(call_args, 'args') + end + + for _, a in ipairs(args) do + table.insert(call_args, a) end if fn.arena_return then - output:write(', arena') + table.insert(call_args, 'arena') end if fn.has_lua_imp then - if #args > 0 then - output:write(', NULL') - else - output:write('NULL') - end + table.insert(call_args, 'NULL') end + if fn.can_fail then + table.insert(call_args, 'error') + end + + output:write(table.concat(call_args, ', ')) + output:write(');\n') + if fn.can_fail then -- if the function can fail, also pass a pointer to the local error object - if #args > 0 then - output:write(', error);\n') - else - output:write('error);\n') - end -- and check for the error output:write('\n if (ERROR_SET(error)) {') output:write('\n goto cleanup;') output:write('\n }\n') - else - output:write(');\n') end local ret_type = real_type(fn.return_type) -- cgit From 930d6e38d4eb61adbb4f0d7328f55b31408b7cd1 Mon Sep 17 00:00:00 2001 From: bfredl Date: Sat, 10 Feb 2024 13:13:52 +0100 Subject: refactor(api): use an arena for nvim_buf_get_lines and buffer updates Refactor some earlier "temporary Array" code in buffer_updates.c to use the modern style of MAXSIZE_TEMP_ARRAY and ADD_C --- src/nvim/generators/gen_api_dispatch.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 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 da3010878d..04fe43b712 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -55,15 +55,15 @@ local function add_function(fn) -- for specifying errors fn.parameters[#fn.parameters] = nil end + if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'lstate' then + fn.has_lua_imp = true + fn.parameters[#fn.parameters] = nil + end if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'arena' then -- return value is allocated in an arena fn.arena_return = true fn.parameters[#fn.parameters] = nil end - if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'lstate' then - fn.has_lua_imp = true - fn.parameters[#fn.parameters] = nil - end end end -- cgit From 0353dd3029f9ce31c3894530385443a90f6677ee Mon Sep 17 00:00:00 2001 From: bfredl Date: Sun, 11 Feb 2024 15:46:14 +0100 Subject: refactor(lua): use Arena when converting from lua stack to API args and for return value of nlua_exec/nlua_call_ref, as this uses the same family of functions. NB: the handling of luaref:s is a bit of a mess. add api_luarefs_free_XX functions as a stop-gap as refactoring luarefs is a can of worms for another PR:s. as a minor feature/bug-fix, nvim_buf_call and nvim_win_call now preserves arbitrary return values. --- src/nvim/generators/gen_api_dispatch.lua | 36 +++++++++++++++++++------------- 1 file changed, 22 insertions(+), 14 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 04fe43b712..c16ea29a01 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -333,9 +333,6 @@ KeySetLink *KeyDict_]] .. k.name .. [[_get_field(const char *str, size_t len) } ]]) - keysets_defs:write( - '#define api_free_keydict_' .. k.name .. '(x) api_free_keydict(x, ' .. k.name .. '_table)\n' - ) end local function real_type(type) @@ -687,6 +684,7 @@ local function process_function(fn) static int %s(lua_State *lstate) { Error err = ERROR_INIT; + Arena arena = ARENA_EMPTY; char *err_param = 0; if (lua_gettop(lstate) != %i) { api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s"); @@ -736,18 +734,24 @@ local function process_function(fn) local param = fn.parameters[j] local cparam = string.format('arg%u', j) local param_type = real_type(param[1]) - local lc_param_type = real_type(param[1]):lower() local extra = param_type == 'Dictionary' and 'false, ' or '' - if param[1] == 'Object' or param[1] == 'DictionaryOf(LuaRef)' then + local arg_free_code = '' + if param[1] == 'Object' then + extra = 'true, ' + arg_free_code = 'api_luarefs_free_object(' .. cparam .. ');' + elseif param[1] == 'DictionaryOf(LuaRef)' then extra = 'true, ' + arg_free_code = 'api_luarefs_free_dict(' .. cparam .. ');' + elseif param[1] == 'LuaRef' then + arg_free_code = 'api_free_luaref(' .. cparam .. ');' end local errshift = 0 local seterr = '' if string.match(param_type, '^KeyDict_') then write_shifted_output( [[ - %s %s = { 0 }; - nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &err); + %s %s = KEYDICT_INIT; + nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &arena, &err); ]], param_type, cparam, @@ -756,10 +760,15 @@ local function process_function(fn) ) cparam = '&' .. cparam errshift = 1 -- free incomplete dict on error + arg_free_code = 'api_luarefs_free_keydict(' + .. cparam + .. ', ' + .. string.sub(param_type, 9) + .. '_table);' else write_shifted_output( [[ - const %s %s = nlua_pop_%s(lstate, %s&err);]], + const %s %s = nlua_pop_%s(lstate, %s&arena, &err);]], param[1], cparam, param_type, @@ -776,7 +785,7 @@ local function process_function(fn) } ]], #fn.parameters - j + errshift) - free_code[#free_code + 1] = ('api_free_%s(%s);'):format(lc_param_type, cparam) + free_code[#free_code + 1] = arg_free_code cparams = cparam .. ', ' .. cparams end if fn.receives_channel_id then @@ -784,7 +793,6 @@ local function process_function(fn) end if fn.arena_return then cparams = cparams .. '&arena, ' - write_shifted_output(' Arena arena = ARENA_EMPTY;\n') end if fn.has_lua_imp then @@ -809,6 +817,7 @@ local function process_function(fn) local err_throw_code = [[ exit_0: + arena_mem_free(arena_finish(&arena)); if (ERROR_SET(&err)) { luaL_where(lstate, 1); if (err_param) { @@ -829,10 +838,8 @@ exit_0: else return_type = fn.return_type end - local free_retval - if fn.arena_return then - free_retval = ' arena_mem_free(arena_finish(&arena));' - else + local free_retval = '' + if not fn.arena_return then free_retval = ' api_free_' .. return_type:lower() .. '(ret);' end write_shifted_output(' %s ret = %s(%s);\n', fn.return_type, fn.name, cparams) @@ -858,6 +865,7 @@ exit_0: write_shifted_output(' nlua_push_%s(lstate, ret, %s);\n', return_type, tostring(special)) end + -- NOTE: we currently assume err_throw needs nothing from arena write_shifted_output( [[ -- cgit From d60412b18e4e21f301baa2ac3f3fb7be89655e4b Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 12 Feb 2024 20:40:27 +0100 Subject: refactor(eval): use arena when converting typvals to Object Note: this contains two _temporary_ changes which can be reverted once the Arena vs no-Arena distinction in API wrappers has been removed. Both nlua_push_Object and object_to_vim_take_luaref() has been changed to take the object argument as a pointer. This is not going to be necessary once these are only used with arena (or not at all) allocated Objects. The object_to_vim() variant which leaves luaref untouched might need to stay for a little longer. --- src/nvim/generators/gen_api_dispatch.lua | 13 ++++++++++--- 1 file changed, 10 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 c16ea29a01..90ed90d2bc 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -845,15 +845,17 @@ exit_0: write_shifted_output(' %s ret = %s(%s);\n', fn.return_type, fn.name, cparams) local ret_type = real_type(fn.return_type) + local ret_mode = (ret_type == 'Object') and '&' or '' if fn.has_lua_imp then -- only push onto the Lua stack if we haven't already write_shifted_output(string.format( [[ if (lua_gettop(lstate) == 0) { - nlua_push_%s(lstate, ret, true); + nlua_push_%s(lstate, %sret, true); } ]], - return_type + return_type, + ret_mode )) elseif string.match(ret_type, '^KeyDict_') then write_shifted_output( @@ -862,7 +864,12 @@ exit_0: ) else local special = (fn.since ~= nil and fn.since < 11) - write_shifted_output(' nlua_push_%s(lstate, ret, %s);\n', return_type, tostring(special)) + write_shifted_output( + ' nlua_push_%s(lstate, %sret, %s);\n', + return_type, + ret_mode, + tostring(special) + ) end -- NOTE: we currently assume err_throw needs nothing from arena -- cgit From 51ea753747c7df12a2d06ad45100db7797c11e1b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 16 Feb 2024 13:27:42 +0800 Subject: fix(genvimvim): generate prefixed boolean options properly (#27487) --- src/nvim/generators/gen_vimvim.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_vimvim.lua b/src/nvim/generators/gen_vimvim.lua index 4d1c82a322..fcdc5bddc2 100644 --- a/src/nvim/generators/gen_vimvim.lua +++ b/src/nvim/generators/gen_vimvim.lua @@ -83,7 +83,7 @@ local vimopt_start = 'syn keyword vimOption contained ' w('\n\n' .. vimopt_start) for _, opt_desc in ipairs(options.options) do - if not opt_desc.varname or opt_desc.varname:sub(1, 7) ~= 'p_force' then + if not opt_desc.immutable then if lld.line_length > 850 then w('\n' .. vimopt_start) end @@ -91,7 +91,7 @@ for _, opt_desc in ipairs(options.options) do if opt_desc.abbreviation then w(' ' .. opt_desc.abbreviation) end - if opt_desc.type == 'bool' then + if opt_desc.type == 'boolean' then w(' inv' .. opt_desc.full_name) w(' no' .. opt_desc.full_name) if opt_desc.abbreviation then -- cgit From eb8a3e0575d36ebfee1e401db0a064763cf684cd Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 18 Feb 2024 17:20:49 +0800 Subject: vim-patch:9.1.0114: Setting some options may change curswant (#27514) Problem: Setting some options changes curswant unnecessarily. Solution: Add a P_HLONLY flag that prevents changing curswant. (zeertzjq) closes: vim/vim#14044 https://github.com/vim/vim/commit/fcaed6a70faf73bff3e5405ada556d726024f866 --- src/nvim/generators/gen_options.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index cdb77c4a0c..749844e658 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -20,10 +20,10 @@ local redraw_flags = { tabline = 'P_RTABL', statuslines = 'P_RSTAT', current_window = 'P_RWIN', - current_window_only = 'P_RWINONLY', current_buffer = 'P_RBUF', all_windows = 'P_RALL', curswant = 'P_CURSWANT', + highlight_only = 'P_HLONLY', } local list_flags = { -- cgit From 3cc54586be7760652e8bad88cae82ce74ef9432e Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 20 Feb 2024 13:44:50 +0100 Subject: refactor(api): make freeing of return-value opt-in instead of opt out As only a few API functions make use of explicit freeing of the return value, make it opt-in instead. The arena is always present under the hood, so `Arena *arena` arg now doesn't mean anything other than getting access to this arena. Also it is in principle possible to return an allocated value while still using the arena as scratch space for other stuff (unlikely, but there no reason to not allow it). --- src/nvim/generators/c_grammar.lua | 1 + src/nvim/generators/gen_api_dispatch.lua | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/c_grammar.lua b/src/nvim/generators/c_grammar.lua index 1720b32919..8a3e70990a 100644 --- a/src/nvim/generators/c_grammar.lua +++ b/src/nvim/generators/c_grammar.lua @@ -47,6 +47,7 @@ local c_proto = Ct( * (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) * (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(num ^ 1)) * P(')'), 'deprecated_since') ^ -1) * (fill * Cg((P('FUNC_API_FAST') * Cc(true)), 'fast') ^ -1) + * (fill * Cg((P('FUNC_API_RET_ALLOC') * Cc(true)), 'ret_alloc') ^ -1) * (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) * (fill * Cg((P('FUNC_API_REMOTE_ONLY') * Cc(true)), 'remote_only') ^ -1) * (fill * Cg((P('FUNC_API_LUA_ONLY') * Cc(true)), 'lua_only') ^ -1) diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index 90ed90d2bc..c3fc5aa0a3 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -60,8 +60,7 @@ local function add_function(fn) fn.parameters[#fn.parameters] = nil end if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'arena' then - -- return value is allocated in an arena - fn.arena_return = true + fn.receives_arena = true fn.parameters[#fn.parameters] = nil end end @@ -554,7 +553,7 @@ for i = 1, #functions do table.insert(call_args, a) end - if fn.arena_return then + if fn.receives_arena then table.insert(call_args, 'arena') end @@ -621,8 +620,8 @@ for n, name in ipairs(hashorder) do .. (fn.impl_name or fn.name) .. ', .fast = ' .. tostring(fn.fast) - .. ', .arena_return = ' - .. tostring(not not fn.arena_return) + .. ', .ret_alloc = ' + .. tostring(not not fn.ret_alloc) .. '},\n' ) end @@ -791,7 +790,7 @@ local function process_function(fn) if fn.receives_channel_id then cparams = 'LUA_INTERNAL_CALL, ' .. cparams end - if fn.arena_return then + if fn.receives_arena then cparams = cparams .. '&arena, ' end @@ -839,7 +838,7 @@ exit_0: return_type = fn.return_type end local free_retval = '' - if not fn.arena_return then + if fn.ret_alloc then free_retval = ' api_free_' .. return_type:lower() .. '(ret);' end write_shifted_output(' %s ret = %s(%s);\n', fn.return_type, fn.name, cparams) -- cgit From 9beb40a4db5613601fc1a4b828a44e5977eca046 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 15 Feb 2024 17:16:04 +0000 Subject: feat(docs): replace lua2dox.lua Problem: The documentation flow (`gen_vimdoc.py`) has several issues: - it's not very versatile - depends on doxygen - doesn't work well with Lua code as it requires an awkward filter script to convert it into pseudo-C. - The intermediate XML files and filters makes it too much like a rube goldberg machine. Solution: Re-implement the flow using Lua, LPEG and treesitter. - `gen_vimdoc.py` is now replaced with `gen_vimdoc.lua` and replicates a portion of the logic. - `lua2dox.lua` is gone! - No more XML files. - Doxygen is now longer used and instead we now use: - LPEG for comment parsing (see `scripts/luacats_grammar.lua` and `scripts/cdoc_grammar.lua`). - LPEG for C parsing (see `scripts/cdoc_parser.lua`) - Lua patterns for Lua parsing (see `scripts/luacats_parser.lua`). - Treesitter for Markdown parsing (see `scripts/text_utils.lua`). - The generated `runtime/doc/*.mpack` files have been removed. - `scripts/gen_eval_files.lua` now instead uses `scripts/cdoc_parser.lua` directly. - Text wrapping is implemented in `scripts/text_utils.lua` and appears to produce more consistent results (the main contributer to the diff of this change). --- src/nvim/generators/c_grammar.lua | 70 ++++++++++----- src/nvim/generators/gen_api_dispatch.lua | 14 +-- src/nvim/generators/gen_api_ui_events.lua | 4 + src/nvim/generators/luacats_grammar.lua | 136 ------------------------------ 4 files changed, 61 insertions(+), 163 deletions(-) delete mode 100644 src/nvim/generators/luacats_grammar.lua (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/c_grammar.lua b/src/nvim/generators/c_grammar.lua index 8a3e70990a..9ce9f3d7a6 100644 --- a/src/nvim/generators/c_grammar.lua +++ b/src/nvim/generators/c_grammar.lua @@ -6,46 +6,74 @@ local lpeg = vim.lpeg local P, R, S = lpeg.P, lpeg.R, lpeg.S local C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg +--- @param pat vim.lpeg.Pattern +local function rep(pat) + return pat ^ 0 +end + +--- @param pat vim.lpeg.Pattern +local function rep1(pat) + return pat ^ 1 +end + +--- @param pat vim.lpeg.Pattern +local function opt(pat) + return pat ^ -1 +end + local any = P(1) -- (consume one character) local letter = R('az', 'AZ') + S('_$') local num = R('09') local alpha = letter + num local nl = P('\r\n') + P('\n') local not_nl = any - nl -local ws = S(' \t') + nl -local fill = ws ^ 0 -local c_comment = P('//') * (not_nl ^ 0) -local c_preproc = P('#') * (not_nl ^ 0) -local dllexport = P('DLLEXPORT') * (ws ^ 1) -local typed_container = (P('ArrayOf(') + P('DictionaryOf(') + P('Dict(')) - * ((any - P(')')) ^ 1) +local space = S(' \t') +local ws = space + nl +local fill = rep(ws) +local c_comment = P('//') * rep(not_nl) +local cdoc_comment = P('///') * opt(Ct(Cg(rep(space) * rep(not_nl), 'comment'))) +local c_preproc = P('#') * rep(not_nl) +local dllexport = P('DLLEXPORT') * rep1(ws) + +local typed_container = ( + (P('ArrayOf(') + P('DictionaryOf(') + P('Dict(')) + * rep1(any - P(')')) * P(')') -local c_id = (typed_container + (letter * (alpha ^ 0))) +) + +local c_id = (typed_container + (letter * rep(alpha))) local c_void = P('void') + local c_param_type = ( ((P('Error') * fill * P('*') * fill) * Cc('error')) + ((P('Arena') * fill * P('*') * fill) * Cc('arena')) + ((P('lua_State') * fill * P('*') * fill) * Cc('lstate')) - + C((P('const ') ^ -1) * c_id * (ws ^ 1) * P('*')) - + (C(c_id) * (ws ^ 1)) + + C(opt(P('const ')) * c_id * rep1(ws) * rep1(P('*'))) + + (C(c_id) * rep1(ws)) ) + local c_type = (C(c_void) * (ws ^ 1)) + c_param_type local c_param = Ct(c_param_type * C(c_id)) local c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) local c_params = Ct(c_void + c_param_list) + +local impl_line = (any - P('}')) * opt(rep(not_nl)) * nl + +local ignore_line = rep1(not_nl) * nl + +local empty_line = Ct(Cc('empty') * nl * nl) + local c_proto = Ct( - (dllexport ^ -1) + Cc('proto') + * opt(dllexport) + * opt(Cg(P('static') * fill * Cc(true), 'static')) * Cg(c_type, 'return_type') * Cg(c_id, 'name') * fill - * P('(') - * fill - * Cg(c_params, 'parameters') - * fill - * P(')') + * (P('(') * fill * Cg(c_params, 'parameters') * fill * P(')')) * Cg(Cc(false), 'fast') - * (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) - * (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(num ^ 1)) * P(')'), 'deprecated_since') ^ -1) + * (fill * Cg((P('FUNC_API_SINCE(') * C(rep1(num))) * P(')'), 'since') ^ -1) + * (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(rep1(num))) * P(')'), 'deprecated_since') ^ -1) * (fill * Cg((P('FUNC_API_FAST') * Cc(true)), 'fast') ^ -1) * (fill * Cg((P('FUNC_API_RET_ALLOC') * Cc(true)), 'ret_alloc') ^ -1) * (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) @@ -60,7 +88,7 @@ local c_proto = Ct( * (fill * Cg((P('FUNC_API_CLIENT_IMPL') * Cc(true)), 'client_impl') ^ -1) * (fill * Cg((P('FUNC_API_CLIENT_IGNORE') * Cc(true)), 'client_ignore') ^ -1) * fill - * P(';') + * (P(';') + (P('{') * nl + (impl_line ^ 0) * P('}'))) ) local c_field = Ct(Cg(c_id, 'type') * ws * Cg(c_id, 'name') * fill * P(';') * fill) @@ -83,5 +111,7 @@ local c_keyset = Ct( * P(';') ) -local grammar = Ct((c_proto + c_comment + c_preproc + ws + c_keyset) ^ 1) +local grammar = Ct( + rep1(empty_line + c_proto + cdoc_comment + c_comment + c_preproc + ws + c_keyset + ignore_line) +) return { grammar = grammar, typed_container = typed_container } diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index c3fc5aa0a3..56331e4162 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -23,9 +23,7 @@ local function_names = {} local c_grammar = require('generators.c_grammar') -local function startswith(String, Start) - return string.sub(String, 1, string.len(Start)) == Start -end +local startswith = vim.startswith local function add_function(fn) local public = startswith(fn.name, 'nvim_') or fn.deprecated_since @@ -112,10 +110,12 @@ for i = 6, #arg do local tmp = c_grammar.grammar:match(input:read('*all')) for j = 1, #tmp do local val = tmp[j] - if val.keyset_name then - add_keyset(val) - else - add_function(val) + if val[1] ~= 'empty' then + if val.keyset_name then + add_keyset(val) + else + add_function(val) + end end end input:close() diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua index 89f8c654f4..697626b793 100644 --- a/src/nvim/generators/gen_api_ui_events.lua +++ b/src/nvim/generators/gen_api_ui_events.lua @@ -93,6 +93,10 @@ local function call_ui_event_method(output, ev) output:write('}\n\n') end +events = vim.tbl_filter(function(ev) + return ev[1] ~= 'empty' +end, events) + for i = 1, #events do local ev = events[i] assert(ev.return_type == 'void') diff --git a/src/nvim/generators/luacats_grammar.lua b/src/nvim/generators/luacats_grammar.lua deleted file mode 100644 index dcccd028ce..0000000000 --- a/src/nvim/generators/luacats_grammar.lua +++ /dev/null @@ -1,136 +0,0 @@ ---[[! -LPEG grammar for LuaCATS - -Currently only partially supports: -- @param -- @return -]] - -local lpeg = vim.lpeg -local P, R, S = lpeg.P, lpeg.R, lpeg.S -local Ct, Cg = lpeg.Ct, lpeg.Cg - ---- @param x vim.lpeg.Pattern -local function rep(x) - return x ^ 0 -end - ---- @param x vim.lpeg.Pattern -local function rep1(x) - return x ^ 1 -end - ---- @param x vim.lpeg.Pattern -local function opt(x) - return x ^ -1 -end - -local nl = P('\r\n') + P('\n') -local ws = rep1(S(' \t') + nl) -local fill = opt(ws) - -local any = P(1) -- (consume one character) -local letter = R('az', 'AZ') + S('_$') -local num = R('09') -local ident = letter * rep(letter + num + S '-.') -local string_single = P "'" * rep(any - P "'") * P "'" -local string_double = P '"' * rep(any - P '"') * P '"' - -local literal = (string_single + string_double + (opt(P '-') * num) + P 'false' + P 'true') - -local lname = (ident + P '...') * opt(P '?') - ---- @param x string -local function Pf(x) - return fill * P(x) * fill -end - ---- @param x string -local function Sf(x) - return fill * S(x) * fill -end - ---- @param x vim.lpeg.Pattern -local function comma(x) - return x * rep(Pf ',' * x) -end - ---- @param x vim.lpeg.Pattern -local function parenOpt(x) - return (Pf('(') * x ^ -1 * fill * P(')')) + x ^ -1 -end - ---- @type table -local v = setmetatable({}, { - __index = function(_, k) - return lpeg.V(k) - end, -}) - -local desc_delim = Sf '#:' + ws - ---- @class luacats.Param ---- @field kind 'param' ---- @field name string ---- @field type string ---- @field desc? string - ---- @class luacats.Return ---- @field kind 'return' ---- @field [integer] { type: string, name?: string} ---- @field desc? string - ---- @class luacats.Generic ---- @field kind 'generic' ---- @field name string ---- @field type? string - ---- @alias luacats.grammar.result ---- | luacats.Param ---- | luacats.Return ---- | luacats.Generic - ---- @class luacats.grammar ---- @field match fun(self, input: string): luacats.grammar.result? - -local grammar = P { - rep1(P('@') * v.ats), - - ats = (v.at_param + v.at_return + v.at_generic), - - at_param = Ct( - Cg(P('param'), 'kind') - * ws - * Cg(lname, 'name') - * ws - * Cg(v.ltype, 'type') - * opt(desc_delim * Cg(rep(any), 'desc')) - ), - - at_return = Ct( - Cg(P('return'), 'kind') - * ws - * parenOpt(comma(Ct(Cg(v.ltype, 'type') * opt(ws * Cg(ident, 'name'))))) - * opt(desc_delim * Cg(rep(any), 'desc')) - ), - - at_generic = Ct( - Cg(P('generic'), 'kind') * ws * Cg(ident, 'name') * opt(Pf ':' * Cg(v.ltype, 'type')) - ), - - ltype = v.ty_union + Pf '(' * v.ty_union * fill * P ')', - - ty_union = v.ty_opt * rep(Pf '|' * v.ty_opt), - ty = v.ty_fun + ident + v.ty_table + literal, - ty_param = Pf '<' * comma(v.ltype) * fill * P '>', - ty_opt = v.ty * opt(v.ty_param) * opt(P '[]') * opt(P '?'), - - table_key = (Pf '[' * literal * Pf ']') + lname, - table_elem = v.table_key * Pf ':' * v.ltype, - ty_table = Pf '{' * comma(v.table_elem) * Pf '}', - - fun_param = lname * opt(Pf ':' * v.ltype), - ty_fun = Pf 'fun(' * rep(comma(v.fun_param)) * fill * P ')' * opt(Pf ':' * v.ltype), -} - -return grammar --[[@as luacats.grammar]] -- cgit From de5cf09cf98e20d8d3296ad6933ff2741acf83f7 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 26 Feb 2024 18:00:46 +0100 Subject: refactor(metadata): generate all metadata in lua Then we can just load metadata in C as a single msgpack blob. Which also can be used directly as binarly data, instead of first unpacking all the functions and ui_events metadata to immediately pack it again, which was a bit of a silly walk (and one extra usecase of `msgpack_rpc_from_object` which will get yak shaved in the next PR) --- src/nvim/generators/gen_api_dispatch.lua | 94 ++++++++++++++++++++++++++----- src/nvim/generators/gen_api_ui_events.lua | 4 +- src/nvim/generators/nvim_version.lua.in | 9 +++ src/nvim/generators/preload.lua | 3 + 4 files changed, 92 insertions(+), 18 deletions(-) create mode 100644 src/nvim/generators/nvim_version.lua.in (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index 56331e4162..78a83445af 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -2,15 +2,18 @@ local mpack = vim.mpack local hashy = require 'generators.hashy' -assert(#arg >= 5) +local pre_args = 7 +assert(#arg >= pre_args) -- output h file with generated dispatch functions (dispatch_wrappers.generated.h) local dispatch_outputf = arg[1] --- output h file with packed metadata (funcs_metadata.generated.h) -local funcs_metadata_outputf = arg[2] +-- output h file with packed metadata (api_metadata.generated.h) +local api_metadata_outputf = arg[2] -- output metadata mpack file, for use by other build scripts (api_metadata.mpack) local mpack_outputf = arg[3] local lua_c_bindings_outputf = arg[4] -- lua_api_c_bindings.generated.c local keysets_outputf = arg[5] -- keysets_defs.generated.h +local ui_metadata_inputf = arg[6] -- ui events metadata +local git_version_inputf = arg[7] -- git version header local functions = {} @@ -96,8 +99,10 @@ local function add_keyset(val) }) end +local ui_options_text = nil + -- read each input file, parse and append to the api metadata -for i = 6, #arg do +for i = pre_args + 1, #arg do local full_path = arg[i] local parts = {} for part in string.gmatch(full_path, '[^/]+') do @@ -107,17 +112,18 @@ for i = 6, #arg do local input = assert(io.open(full_path, 'rb')) - local tmp = c_grammar.grammar:match(input:read('*all')) + local text = input:read('*all') + local tmp = c_grammar.grammar:match(text) for j = 1, #tmp do local val = tmp[j] - if val[1] ~= 'empty' then - if val.keyset_name then - add_keyset(val) - else - add_function(val) - end + if val.keyset_name then + add_keyset(val) + elseif val.name then + add_function(val) end end + + ui_options_text = ui_options_text or string.match(text, 'ui_ext_names%[][^{]+{([^}]+)}') input:close() end @@ -218,13 +224,71 @@ for _, f in ipairs(functions) do end end +local ui_options = { 'rgb' } +for x in string.gmatch(ui_options_text, '"([a-z][a-z_]+)"') do + table.insert(ui_options, x) +end + +local version = require 'nvim_version' +local git_version = io.open(git_version_inputf):read '*a' +local version_build = string.match(git_version, '#define NVIM_VERSION_BUILD "([^"]+)"') or vim.NIL + -- serialize the API metadata using msgpack and embed into the resulting -- binary for easy querying by clients -local funcs_metadata_output = assert(io.open(funcs_metadata_outputf, 'wb')) -local packed = mpack.encode(exported_functions) +local api_metadata_output = assert(io.open(api_metadata_outputf, 'wb')) +local pieces = {} + +-- Naively using mpack.encode({foo=x, bar=y}) will make the build +-- "non-reproducible". Emit maps directly as FIXDICT(2) "foo" x "bar" y instead +local function fixdict(num) + if num > 15 then + error 'implement more dict codes' + end + table.insert(pieces, string.char(128 + num)) +end +local function put(item, item2) + table.insert(pieces, mpack.encode(item)) + if item2 ~= nil then + table.insert(pieces, mpack.encode(item2)) + end +end + +fixdict(6) + +put('version') +fixdict(1 + #version) +for _, item in ipairs(version) do + -- NB: all items are mandatory. But any error will be less confusing + -- with placholder vim.NIL (than invalid mpack data) + put(item[1], item[2] or vim.NIL) +end +put('build', version_build) + +put('functions', exported_functions) +put('ui_events') +table.insert(pieces, io.open(ui_metadata_inputf, 'rb'):read('*all')) +put('ui_options', ui_options) + +put('error_types') +fixdict(2) +put('Exception', { id = 0 }) +put('Validation', { id = 1 }) + +put('types') +local types = + { { 'Buffer', 'nvim_buf_' }, { 'Window', 'nvim_win_' }, { 'Tabpage', 'nvim_tabpage_' } } +fixdict(#types) +for i, item in ipairs(types) do + put(item[1]) + fixdict(2) + put('id', i - 1) + put('prefix', item[2]) +end + +local packed = table.concat(pieces) local dump_bin_array = require('generators.dump_bin_array') -dump_bin_array(funcs_metadata_output, 'funcs_metadata', packed) -funcs_metadata_output:close() +dump_bin_array(api_metadata_output, 'packed_api_metadata', packed) +api_metadata_output:close() -- start building the dispatch wrapper output local output = assert(io.open(dispatch_outputf, 'wb')) diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua index 697626b793..a4f59c7209 100644 --- a/src/nvim/generators/gen_api_ui_events.lua +++ b/src/nvim/generators/gen_api_ui_events.lua @@ -204,7 +204,5 @@ for _, ev in ipairs(events) do end end -local packed = mpack.encode(exported_events) -local dump_bin_array = require('generators.dump_bin_array') -dump_bin_array(metadata_output, 'ui_events_metadata', packed) +metadata_output:write(mpack.encode(exported_events)) metadata_output:close() diff --git a/src/nvim/generators/nvim_version.lua.in b/src/nvim/generators/nvim_version.lua.in new file mode 100644 index 0000000000..d0dbf77922 --- /dev/null +++ b/src/nvim/generators/nvim_version.lua.in @@ -0,0 +1,9 @@ +return { + {"major", ${NVIM_VERSION_MAJOR}}, + {"minor", ${NVIM_VERSION_MINOR}}, + {"patch", ${NVIM_VERSION_PATCH}}, + {"prerelease", "$NVIM_VERSION_PRERELEASE" ~= ""}, + {"api_level", ${NVIM_API_LEVEL}}, + {"api_compatible", ${NVIM_API_LEVEL_COMPAT}}, + {"api_prerelease", ${NVIM_API_PRERELEASE}}, +} diff --git a/src/nvim/generators/preload.lua b/src/nvim/generators/preload.lua index 721d2880b8..e14671074c 100644 --- a/src/nvim/generators/preload.lua +++ b/src/nvim/generators/preload.lua @@ -1,10 +1,13 @@ local srcdir = table.remove(arg, 1) local nlualib = table.remove(arg, 1) +local gendir = table.remove(arg, 1) package.path = srcdir .. '/src/nvim/?.lua;' .. srcdir .. '/runtime/lua/?.lua;' .. package.path +package.path = gendir .. '/?.lua;' .. package.path _G.vim = require 'vim.shared' _G.vim.inspect = require 'vim.inspect' package.cpath = package.cpath .. ';' .. nlualib require 'nlua0' +vim.NIL = vim.mpack.NIL -- WOW BOB WOW arg[0] = table.remove(arg, 1) return loadfile(arg[0])() -- cgit From dc37c1550bed46fffbb677d343cdc5bc94056219 Mon Sep 17 00:00:00 2001 From: bfredl Date: Sun, 25 Feb 2024 15:02:48 +0100 Subject: refactor(msgpack): allow flushing buffer while packing msgpack Before, we needed to always pack an entire msgpack_rpc Object to a continous memory buffer before sending it out to a channel. But this is generally wasteful. it is better to just flush whatever is in the buffer and then continue packing to a new buffer. This is also done for the UI event packer where there are some extra logic to "finish" of an existing batch of nevents/ncalls. This doesn't really stop us from flushing the buffer, just that we need to update the state machine accordingly so the next call to prepare_call() always will start with a new event (even though the buffer might contain overflow data from a large event). --- src/nvim/generators/gen_api_dispatch.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index 78a83445af..04b4363e42 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -307,7 +307,6 @@ output:write([[ #include "nvim/globals.h" #include "nvim/log.h" #include "nvim/map_defs.h" -#include "nvim/msgpack_rpc/helpers.h" #include "nvim/api/autocmd.h" #include "nvim/api/buffer.h" -- cgit From e534ec47db4bf5e110c828ca3d875f5685dcfdde Mon Sep 17 00:00:00 2001 From: bfredl Date: Fri, 8 Mar 2024 09:15:21 +0100 Subject: refactor(ui): remove outdated UI vs UIData distinction Just some basic spring cleaning. In the distant past, not all UI:s where remote UI:s. They still aren't, but both of the "UI" and "UIData" structs are now only for remote UI:s. Thus join them as "RemoteUI". --- src/nvim/generators/gen_api_ui_events.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/nvim/generators') diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua index a4f59c7209..0808f71daa 100644 --- a/src/nvim/generators/gen_api_ui_events.lua +++ b/src/nvim/generators/gen_api_ui_events.lua @@ -110,10 +110,9 @@ for i = 1, #events do if not ev.remote_only then if not ev.remote_impl and not ev.noexport then remote_output:write('void remote_ui_' .. ev.name) - write_signature(remote_output, ev, 'UI *ui') + write_signature(remote_output, ev, 'RemoteUI *ui') remote_output:write('\n{\n') - remote_output:write(' UIData *data = ui->data;\n') - remote_output:write(' Array args = data->call_buf;\n') + remote_output:write(' Array args = ui->call_buf;\n') write_arglist(remote_output, ev) remote_output:write(' push_call(ui, "' .. ev.name .. '", args);\n') remote_output:write('}\n\n') -- cgit