From 813476bf7291dfaf9fc0ef77c9f53a07258a3801 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Tue, 30 Aug 2022 23:13:52 +0100 Subject: fix(exceptions): restore `did_throw` (#20000) `!did_throw` doesn't exactly imply `!current_exception`, as `did_throw = false` is sometimes used to defer exception handling for later (without forgetting the exception). E.g: uncaught exception handling in `do_cmdline()` may be deferred to a different call (e.g: when `try_level > 0`). In #7881, `current_exception = NULL` in `do_cmdline()` is used as an analogue of `did_throw = false`, but also causes the pending exception to be lost, which also leaks as `discard_exception()` wasn't used. It may be possible to fix this by saving/restoring `current_exception`, but handling all of `did_throw`'s edge cases seems messier. Maybe not worth diverging over. This fix also uncovers a `man_spec.lua` bug on Windows: exceptions are thrown due to Windows missing `man`, but they're lost; skip these tests if `man` isn't executable. --- src/nvim/lua/executor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 39585ac182..42aa13cfc1 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1027,7 +1027,7 @@ int nlua_call(lua_State *lstate) // TODO(bfredl): this should be simplified in error handling refactor force_abort = false; suppress_errthrow = false; - current_exception = NULL; + did_throw = false; did_emsg = false; try_start(); -- cgit From f31db30975479cb6b57247f124a65f4362f80bfe Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 30 Jun 2022 13:26:31 +0600 Subject: feat(lua): vim.ui_attach to get ui events from lua Co-authored-by: Famiu Haque --- src/nvim/lua/executor.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 4 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 42aa13cfc1..f144e47c3a 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -7,6 +7,7 @@ #include #include "luv/luv.h" +#include "nvim/api/extmark.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" @@ -40,6 +41,9 @@ #include "nvim/os/os.h" #include "nvim/profile.h" #include "nvim/runtime.h" +#include "nvim/screen.h" +#include "nvim/ui.h" +#include "nvim/ui_compositor.h" #include "nvim/undo.h" #include "nvim/usercmd.h" #include "nvim/version.h" @@ -589,6 +593,71 @@ static bool nlua_init_packages(lua_State *lstate) return true; } +/// "vim.ui_attach(ns_id, {ext_foo=true}, cb)" function +static int nlua_ui_attach(lua_State *lstate) + FUNC_ATTR_NONNULL_ALL +{ + uint32_t ns_id = (uint32_t)luaL_checkinteger(lstate, 1); + + if (!ns_initialized(ns_id)) { + return luaL_error(lstate, "invalid ns_id"); + } + if (!lua_istable(lstate, 2)) { + return luaL_error(lstate, "ext_widgets must be a table"); + } + if (!lua_isfunction(lstate, 3)) { + return luaL_error(lstate, "callback must be a Lua function"); + } + + bool ext_widgets[kUIGlobalCount] = { false }; + bool tbl_has_true_val = false; + + lua_pushvalue(lstate, 2); + lua_pushnil(lstate); + while (lua_next(lstate, -2)) { + // [dict, key, val] + size_t len; + const char *s = lua_tolstring(lstate, -2, &len); + bool val = lua_toboolean(lstate, -1); + + for (size_t i = 0; i < kUIGlobalCount; i++) { + if (strequal(s, ui_ext_names[i])) { + if (val) { + tbl_has_true_val = true; + } + ext_widgets[i] = val; + goto ok; + } + } + + return luaL_error(lstate, "Unexpected key: %s", s); +ok: + lua_pop(lstate, 1); + } + + if (!tbl_has_true_val) { + return luaL_error(lstate, "ext_widgets table must contain at least one 'true' value"); + } + + LuaRef ui_event_cb = nlua_ref_global(lstate, 3); + ui_comp_add_cb(ns_id, ui_event_cb, ext_widgets); + return 0; +} + +/// "vim.ui_detach(ns_id)" function +static int nlua_ui_detach(lua_State *lstate) + FUNC_ATTR_NONNULL_ALL +{ + uint32_t ns_id = (uint32_t)luaL_checkinteger(lstate, 1); + + if (!ns_initialized(ns_id)) { + return luaL_error(lstate, "invalid ns_id"); + } + + ui_comp_remove_cb(ns_id); + return 0; +} + /// Initialize lua interpreter state /// /// Called by lua interpreter itself to initialize state. @@ -649,6 +718,14 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_pushcfunction(lstate, &nlua_wait); lua_setfield(lstate, -2, "wait"); + // ui_attach + lua_pushcfunction(lstate, &nlua_ui_attach); + lua_setfield(lstate, -2, "ui_attach"); + + // ui_detach + lua_pushcfunction(lstate, &nlua_ui_detach); + lua_setfield(lstate, -2, "ui_detach"); + nlua_common_vim_init(lstate, false); // patch require() (only for --startuptime) @@ -1422,9 +1499,10 @@ bool nlua_ref_is_function(LuaRef ref) /// @param name if non-NULL, sent to callback as first arg /// if NULL, only args are used /// @param retval if true, convert return value to Object -/// if false, discard return value +/// if false, only check if return value is truthy /// @param err Error details, if any (if NULL, errors are echoed) -/// @return Return value of function, if retval was set. Otherwise NIL. +/// @return Return value of function, if retval was set. Otherwise +/// BOOLEAN_OBJ(true) or NIL. Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Error *err) { lua_State *const lstate = global_lstate; @@ -1438,7 +1516,7 @@ Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Erro nlua_push_Object(lstate, args.items[i], false); } - if (nlua_pcall(lstate, nargs, retval ? 1 : 0)) { + if (nlua_pcall(lstate, nargs, 1)) { // if err is passed, the caller will deal with the error. if (err) { size_t len; @@ -1458,7 +1536,10 @@ Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Erro } return nlua_pop_Object(lstate, false, err); } else { - return NIL; + bool value = lua_toboolean(lstate, -1); + lua_pop(lstate, 1); + + return value ? BOOLEAN_OBJ(true) : NIL; } } -- cgit From 689f5d604e59eba1ddab6f91b458a8163dc6629d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 1 Sep 2022 20:32:59 +0800 Subject: feat(api): add support for :horizontal modifier --- src/nvim/lua/executor.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index f144e47c3a..2315ecd874 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -2103,6 +2103,8 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview) lua_pushboolean(lstate, cmdmod.cmod_split & WSP_VERT); lua_setfield(lstate, -2, "vertical"); + lua_pushboolean(lstate, cmdmod.cmod_split & WSP_HOR); + lua_setfield(lstate, -2, "horizontal"); lua_pushboolean(lstate, cmdmod.cmod_flags & CMOD_SILENT); lua_setfield(lstate, -2, "silent"); lua_pushboolean(lstate, cmdmod.cmod_flags & CMOD_ERRSILENT); -- cgit From 1ef7720567b08caec0c077605fb2a01a9d6eafbc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 1 Sep 2022 18:46:34 +0800 Subject: fix(api)!: correctly deal with number before :tab Now nvim_parse_cmd and nvim_create_user_command use a "tab" value which is the same as the number passed before :tab modifier instead of the number plus 1, and "tab" value is -1 if :tab modifier is not used. --- src/nvim/lua/executor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 2315ecd874..1013cf76f9 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -2082,7 +2082,7 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview) lua_newtable(lstate); // smods table - lua_pushinteger(lstate, cmdmod.cmod_tab); + lua_pushinteger(lstate, cmdmod.cmod_tab - 1); lua_setfield(lstate, -2, "tab"); lua_pushinteger(lstate, cmdmod.cmod_verbose - 1); -- cgit From db9b8b08e74ae8cfb08960eca0a7273538ebcdf1 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 6 Sep 2022 22:23:54 +0200 Subject: refactor(typval): change FC_CFUNC abstraction into FC_LUAREF "cfuncs" was only ever used to wrap luarefs. As vim8script is finished and will not be developed further, support for "cfuncs" for other usecases are not planned. This abstraction was immediately broken anyway in order to get luarefs out of userfuncs again. Even if a new kind of userfunc needs to be invented in the future, likely just extending the FC_... flag union directy, instead of invoking unnecessary heap object and c function pointer indirection, will be a more straightforward design pattern. --- src/nvim/lua/executor.c | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 1013cf76f9..857e2111d6 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1425,12 +1425,11 @@ int nlua_source_using_linegetter(LineGetter fgetline, void *cookie, char *name) /// @param[in] argcount Count of typval arguments /// @param[in] argvars Typval Arguments /// @param[out] rettv The return value from the called function. -int typval_exec_lua_callable(lua_State *lstate, LuaCallable lua_cb, int argcount, typval_T *argvars, - typval_T *rettv) +int typval_exec_lua_callable(LuaRef lua_cb, int argcount, typval_T *argvars, typval_T *rettv) { - LuaRef cb = lua_cb.func_ref; + lua_State *lstate = global_lstate; - nlua_pushref(lstate, cb); + nlua_pushref(lstate, lua_cb); PUSH_ALL_TYPVALS(lstate, argvars, argcount, false); @@ -1833,26 +1832,6 @@ static int nlua_is_thread(lua_State *lstate) return 1; } -// Required functions for lua c functions as VimL callbacks - -int nlua_CFunction_func_call(int argcount, typval_T *argvars, typval_T *rettv, void *state) -{ - lua_State *const lstate = global_lstate; - LuaCFunctionState *funcstate = (LuaCFunctionState *)state; - - return typval_exec_lua_callable(lstate, funcstate->lua_callable, - argcount, argvars, rettv); -} - -void nlua_CFunction_func_free(void *state) -{ - lua_State *const lstate = global_lstate; - LuaCFunctionState *funcstate = (LuaCFunctionState *)state; - - nlua_unref_global(lstate, funcstate->lua_callable.func_ref); - xfree(funcstate); -} - bool nlua_is_table_from_lua(typval_T *const arg) { if (arg->v_type == VAR_DICT) { @@ -1898,11 +1877,9 @@ char_u *nlua_register_table_as_callable(typval_T *const arg) } lua_pop(lstate, 2); // [table] - LuaCFunctionState *state = xmalloc(sizeof(LuaCFunctionState)); - state->lua_callable.func_ref = nlua_ref_global(lstate, -1); + LuaRef func = nlua_ref_global(lstate, -1); - char_u *name = register_cfunc(&nlua_CFunction_func_call, - &nlua_CFunction_func_free, state); + char_u *name = register_luafunc(func); lua_pop(lstate, 1); // [] assert(top == lua_gettop(lstate)); -- cgit From c5322e752e9e568de907f7a1ef733bbfe342140c Mon Sep 17 00:00:00 2001 From: Dundar Göc Date: Fri, 26 Aug 2022 23:11:25 +0200 Subject: refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/lua/executor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 857e2111d6..78ac051308 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1044,7 +1044,7 @@ static int nlua_debug(lua_State *lstate) if (input.v_type != VAR_STRING || input.vval.v_string == NULL || *input.vval.v_string == NUL - || STRCMP(input.vval.v_string, "cont") == 0) { + || strcmp(input.vval.v_string, "cont") == 0) { tv_clear(&input); return 0; } -- cgit From 3ff46544c9872b4161fd098569c30b55fe3abd36 Mon Sep 17 00:00:00 2001 From: Dundar Göc Date: Fri, 26 Aug 2022 23:11:25 +0200 Subject: refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/lua/executor.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 78ac051308..128f133b23 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1049,7 +1049,7 @@ static int nlua_debug(lua_State *lstate) return 0; } if (luaL_loadbuffer(lstate, (const char *)input.vval.v_string, - STRLEN(input.vval.v_string), "=(debug command)")) { + strlen(input.vval.v_string), "=(debug command)")) { nlua_error(lstate, _("E5115: Error while loading debug string: %.*s")); } else if (nlua_pcall(lstate, 0, 0)) { nlua_error(lstate, _("E5116: Error while calling debug string: %.*s")); @@ -1641,7 +1641,7 @@ void ex_luado(exarg_T *const eap) break; } if (lua_isstring(lstate, -1)) { - size_t old_line_len = STRLEN(old_line); + size_t old_line_len = strlen(old_line); size_t new_line_len; const char *const new_line = lua_tolstring(lstate, -1, &new_line_len); @@ -2001,7 +2001,7 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview) // Split args by unescaped whitespace || (nargs dependent) if (cmd->uc_argt & EX_NOSPC) { - if ((cmd->uc_argt & EX_NEEDARG) || STRLEN(eap->arg)) { + if ((cmd->uc_argt & EX_NEEDARG) || strlen(eap->arg)) { // For commands where nargs is 1 or "?" and argument is passed, fargs = { args } lua_rawseti(lstate, -2, 1); } else { @@ -2011,7 +2011,7 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview) } else if (eap->args == NULL) { // For commands with more than one possible argument, split if argument list isn't available. lua_pop(lstate, 1); // Pop the reference of opts.args - size_t length = STRLEN(eap->arg); + size_t length = strlen(eap->arg); size_t end = 0; size_t len = 0; int i = 1; -- cgit From b98de0e0e5df96cadbac9222ddb1caa463cea2f0 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 16 Sep 2022 16:37:37 +0800 Subject: vim-patch:8.2.0067: ERROR_UNKNOWN clashes on some systems (#20212) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: ERROR_UNKNOWN clashes on some systems. Solution: Rename ERROR_ to FCERR_. (Ola Söder, closes vim/vim#5415) https://github.com/vim/vim/commit/ef140544f6703a7a4c0f6a15f610508ed6b09e89 Remove ERROR_BOTH which was removed from Vim in patch 7.4.1582. --- src/nvim/lua/executor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 128f133b23..94947c2fbc 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1435,12 +1435,12 @@ int typval_exec_lua_callable(LuaRef lua_cb, int argcount, typval_T *argvars, typ if (nlua_pcall(lstate, argcount, 1)) { nlua_print(lstate); - return ERROR_OTHER; + return FCERR_OTHER; } nlua_pop_typval(lstate, rettv); - return ERROR_NONE; + return FCERR_NONE; } /// Execute Lua string -- cgit From 3dda52d860eb4937127693d4660db18305069370 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 16 Sep 2022 17:31:42 +0800 Subject: vim-patch:8.2.3796: the funcexe_T struct members are not named consistently (#20214) Problem: The funcexe_T struct members are not named consistently. Solution: Prefix "fe_" to all the members. https://github.com/vim/vim/commit/851f86b951cdd67ad9cf3149e46169d1375c8d82 Omit fe_check_type: always NULL in legacy Vim script. --- src/nvim/lua/executor.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 94947c2fbc..d56b3642aa 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1110,9 +1110,9 @@ int nlua_call(lua_State *lstate) try_start(); typval_T rettv; funcexe_T funcexe = FUNCEXE_INIT; - funcexe.firstline = curwin->w_cursor.lnum; - funcexe.lastline = curwin->w_cursor.lnum; - funcexe.evaluate = true; + funcexe.fe_firstline = curwin->w_cursor.lnum; + funcexe.fe_lastline = curwin->w_cursor.lnum; + funcexe.fe_evaluate = true; // call_func() retval is deceptive, ignore it. Instead we set `msg_list` // (TRY_WRAP) to capture abort-causing non-exception errors. (void)call_func((char *)name, (int)name_len, &rettv, nargs, vim_args, &funcexe); -- cgit From 6d557e324fd4223fff3279a0112f40431c540163 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 18 Sep 2022 03:17:15 +0200 Subject: vim-patch:8.1.0941: macros for MS-Windows are inconsistent (#20215) Problem: Macros for MS-Windows are inconsistent, using "32", "3264 and others. Solution: Use MSWIN for all MS-Windows builds. Use FEAT_GUI_MSWIN for the GUI build. (Hirohito Higashi, closes vim/vim#3932) https://github.com/vim/vim/commit/4f97475d326c2773a78561fb874e4f23c25cbcd9 --- src/nvim/lua/executor.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index d56b3642aa..09f8c688d8 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -248,7 +248,7 @@ static int nlua_luv_thread_common_cfpcall(lua_State *lstate, int nargs, int nres mch_errmsg(e_outofmem); mch_errmsg("\n"); lua_close(lstate); -#ifdef WIN32 +#ifdef MSWIN ExitThread(0); #else pthread_exit(0); @@ -673,7 +673,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_setfield(lstate, -2, "debug"); lua_pop(lstate, 1); -#ifdef WIN32 +#ifdef MSWIN // os.getenv lua_getglobal(lstate, "os"); lua_pushcfunction(lstate, &nlua_getenv); @@ -1201,7 +1201,7 @@ static int nlua_empty_dict_tostring(lua_State *lstate) return 1; } -#ifdef WIN32 +#ifdef MSWIN /// os.getenv: override os.getenv to maintain coherency. #9681 /// /// uv_os_setenv uses SetEnvironmentVariableW which does not update _environ. -- cgit From 00cfc1dcebd1c81dd0d8c111740782e86cf2e385 Mon Sep 17 00:00:00 2001 From: bfredl Date: Fri, 16 Sep 2022 19:21:32 +0200 Subject: fix(redraw): avoid unnecessary redraws and glitches with floats+messages fixes #20106 fixes #20229 --- src/nvim/lua/executor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 09f8c688d8..6063414a02 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1658,7 +1658,7 @@ void ex_luado(exarg_T *const eap) } lua_pop(lstate, 1); check_cursor(); - update_screen(UPD_NOT_VALID); + redraw_curbuf_later(UPD_NOT_VALID); } /// Run lua file -- cgit From 35e2c4a2edd28f72c48c70530c5486365c2502a4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 28 Sep 2022 18:27:59 +0800 Subject: fix(lua): fix architecture-dependent behavior in usercmd "reg" (#20384) I don't think using an integer as a NUL-terminated string can work on big-endian systems, at least. This is also not tested. Add a test. Also fix a mistake in the docs of nvim_parse_cmd. --- src/nvim/lua/executor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 6063414a02..f3821f149a 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -2036,7 +2036,8 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview) } lua_setfield(lstate, -2, "fargs"); - lua_pushstring(lstate, (const char *)&eap->regname); + char reg[2] = { (char)eap->regname, NUL }; + lua_pushstring(lstate, reg); lua_setfield(lstate, -2, "reg"); lua_pushinteger(lstate, eap->addr_count); -- cgit