diff options
Diffstat (limited to 'src/nvim/lua/executor.c')
-rw-r--r-- | src/nvim/lua/executor.c | 501 |
1 files changed, 66 insertions, 435 deletions
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 59ebafd9c8..b27b1ae7a8 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -5,9 +5,7 @@ #include <lua.h> #include <lualib.h> -#include "cjson/lua_cjson.h" #include "luv/luv.h" -#include "mpack/lmpack.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" @@ -27,8 +25,8 @@ #include "nvim/getchar.h" #include "nvim/lua/converter.h" #include "nvim/lua/executor.h" +#include "nvim/lua/stdlib.h" #include "nvim/lua/treesitter.h" -#include "nvim/lua/xdiff.h" #include "nvim/macros.h" #include "nvim/map.h" #include "nvim/memline.h" @@ -36,7 +34,6 @@ #include "nvim/misc1.h" #include "nvim/msgpack_rpc/channel.h" #include "nvim/os/os.h" -#include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/undo.h" #include "nvim/version.h" @@ -83,11 +80,32 @@ static void nlua_error(lua_State *const lstate, const char *const msg) const char *const str = lua_tolstring(lstate, -1, &len); msg_ext_set_kind("lua_error"); - emsgf_multiline(msg, (int)len, str); + semsg_multiline(msg, (int)len, str); lua_pop(lstate, 1); } +/// Like lua_pcall, but use debug.traceback as errfunc. +/// +/// @param lstate Lua interpreter state +/// @param[in] nargs Number of arguments expected by the function being called. +/// @param[in] nresults Number of results the function returns. +static int nlua_pcall(lua_State *lstate, int nargs, int nresults) +{ + lua_getglobal(lstate, "debug"); + lua_getfield(lstate, -1, "traceback"); + lua_remove(lstate, -2); + lua_insert(lstate, -2 - nargs); + int status = lua_pcall(lstate, nargs, nresults, -2 - nargs); + if (status) { + lua_remove(lstate, -2); + } else { + lua_remove(lstate, -1 - nresults); + } + return status; +} + + /// Gets the version of the current Nvim build. /// /// @param lstate Lua interpreter state. @@ -99,118 +117,12 @@ static int nlua_nvim_version(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL return 1; } -/// Compare two strings, ignoring case -/// -/// Expects two values on the stack: compared strings. Returns one of the -/// following numbers: 0, -1 or 1. -/// -/// Does no error handling: never call it with non-string or with some arguments -/// omitted. -static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL -{ - size_t s1_len; - size_t s2_len; - const char *s1 = luaL_checklstring(lstate, 1, &s1_len); - const char *s2 = luaL_checklstring(lstate, 2, &s2_len); - char *nul1; - char *nul2; - int ret = 0; - assert(s1[s1_len] == NUL); - assert(s2[s2_len] == NUL); - do { - nul1 = memchr(s1, NUL, s1_len); - nul2 = memchr(s2, NUL, s2_len); - ret = STRICMP(s1, s2); - if (ret == 0) { - // Compare "a\0" greater then "a". - if ((nul1 == NULL) != (nul2 == NULL)) { - ret = ((nul1 != NULL) - (nul2 != NULL)); - break; - } - if (nul1 != NULL) { - assert(nul2 != NULL); - // Can't shift both strings by the same amount of bytes: lowercase - // letter may have different byte-length than uppercase. - s1_len -= (size_t)(nul1 - s1) + 1; - s2_len -= (size_t)(nul2 - s2) + 1; - s1 = nul1 + 1; - s2 = nul2 + 1; - } else { - break; - } - } else { - break; - } - } while (true); - lua_pop(lstate, 2); - lua_pushnumber(lstate, (lua_Number)((ret > 0) - (ret < 0))); - return 1; -} - -/// convert byte index to UTF-32 and UTF-16 indices -/// -/// Expects a string and an optional index. If no index is supplied, the length -/// of the string is returned. -/// -/// Returns two values: the UTF-32 and UTF-16 indices. -static int nlua_str_utfindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL -{ - size_t s1_len; - const char *s1 = luaL_checklstring(lstate, 1, &s1_len); - intptr_t idx; - if (lua_gettop(lstate) >= 2) { - idx = luaL_checkinteger(lstate, 2); - if (idx < 0 || idx > (intptr_t)s1_len) { - return luaL_error(lstate, "index out of range"); - } - } else { - idx = (intptr_t)s1_len; - } - - size_t codepoints = 0, codeunits = 0; - mb_utflen((const char_u *)s1, (size_t)idx, &codepoints, &codeunits); - - lua_pushinteger(lstate, (long)codepoints); - lua_pushinteger(lstate, (long)codeunits); - - return 2; -} - -/// convert UTF-32 or UTF-16 indices to byte index. -/// -/// Expects up to three args: string, index and use_utf16. -/// If use_utf16 is not supplied it defaults to false (use UTF-32) -/// -/// Returns the byte index. -static int nlua_str_byteindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL -{ - size_t s1_len; - const char *s1 = luaL_checklstring(lstate, 1, &s1_len); - intptr_t idx = luaL_checkinteger(lstate, 2); - if (idx < 0) { - return luaL_error(lstate, "index out of range"); - } - bool use_utf16 = false; - if (lua_gettop(lstate) >= 3) { - use_utf16 = lua_toboolean(lstate, 3); - } - - ssize_t byteidx = mb_utf_index_to_bytes((const char_u *)s1, s1_len, - (size_t)idx, use_utf16); - if (byteidx == -1) { - return luaL_error(lstate, "index out of range"); - } - - lua_pushinteger(lstate, (long)byteidx); - - return 1; -} static void nlua_luv_error_event(void **argv) { char *error = (char *)argv[0]; msg_ext_set_kind("lua_error"); - emsgf_multiline("Error executing luv callback:\n%s", error); + semsg_multiline("Error executing luv callback:\n%s", error); xfree(error); } @@ -224,7 +136,7 @@ static int nlua_luv_cfpcall(lua_State *lstate, int nargs, int nresult, int flags in_fast_callback++; int top = lua_gettop(lstate); - int status = lua_pcall(lstate, nargs, nresult, 0); + int status = nlua_pcall(lstate, nargs, nresult); if (status) { if (status == LUA_ERRMEM && !(flags & LUVF_CALLBACK_NOEXIT)) { // consider out of memory errors unrecoverable, just like xmalloc() @@ -255,7 +167,7 @@ static void nlua_schedule_event(void **argv) lua_State *const lstate = global_lstate; nlua_pushref(lstate, cb); nlua_unref(lstate, cb); - if (lua_pcall(lstate, 0, 0, 0)) { + if (nlua_pcall(lstate, 0, 0)) { nlua_error(lstate, _("Error executing vim.schedule lua callback: %.*s")); } } @@ -278,14 +190,6 @@ static int nlua_schedule(lua_State *const lstate) return 0; } -static struct luaL_Reg regex_meta[] = { - { "__gc", regex_gc }, - { "__tostring", regex_tostring }, - { "match_str", regex_match_str }, - { "match_line", regex_match_line }, - { NULL, NULL } -}; - // Dummy timer callback. Used by f_wait(). static void dummy_timer_due_cb(TimeWatcher *tw, void *data) { @@ -300,7 +204,7 @@ static void dummy_timer_close_cb(TimeWatcher *tw, void *data) static bool nlua_wait_condition(lua_State *lstate, int *status, bool *callback_result) { lua_pushvalue(lstate, 2); - *status = lua_pcall(lstate, 0, 1, 0); + *status = nlua_pcall(lstate, 0, 1); if (*status) { return true; // break on error, but keep error on stack } @@ -422,39 +326,28 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL // vim lua_newtable(lstate); + // vim.api nlua_add_api_functions(lstate); + // vim.types, vim.type_idx, vim.val_idx nlua_init_types(lstate); - // stricmp - lua_pushcfunction(lstate, &nlua_stricmp); - lua_setfield(lstate, -2, "stricmp"); - // str_utfindex - lua_pushcfunction(lstate, &nlua_str_utfindex); - lua_setfield(lstate, -2, "str_utfindex"); - // str_byteindex - lua_pushcfunction(lstate, &nlua_str_byteindex); - lua_setfield(lstate, -2, "str_byteindex"); + // neovim version lua_pushcfunction(lstate, &nlua_nvim_version); lua_setfield(lstate, -2, "version"); + // schedule lua_pushcfunction(lstate, &nlua_schedule); lua_setfield(lstate, -2, "schedule"); + // in_fast_event lua_pushcfunction(lstate, &nlua_in_fast_event); lua_setfield(lstate, -2, "in_fast_event"); + // call lua_pushcfunction(lstate, &nlua_call); lua_setfield(lstate, -2, "call"); - // regex - lua_pushcfunction(lstate, &nlua_regex); - lua_setfield(lstate, -2, "regex"); - luaL_newmetatable(lstate, "nvim_regex"); - luaL_register(lstate, NULL, regex_meta); - lua_pushvalue(lstate, -1); // [meta, meta] - lua_setfield(lstate, -2, "__index"); // [meta] - lua_pop(lstate, 1); // don't use metatable now // rpcrequest lua_pushcfunction(lstate, &nlua_rpcrequest); @@ -468,30 +361,6 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_pushcfunction(lstate, &nlua_wait); lua_setfield(lstate, -2, "wait"); - // _getvar - lua_pushcfunction(lstate, &nlua_getvar); - lua_setfield(lstate, -2, "_getvar"); - - // _setvar - lua_pushcfunction(lstate, &nlua_setvar); - lua_setfield(lstate, -2, "_setvar"); - - - // vim.loop - luv_set_loop(lstate, &main_loop.uv); - luv_set_callback(lstate, nlua_luv_cfpcall); - luaopen_luv(lstate); - lua_pushvalue(lstate, -1); - lua_setfield(lstate, -3, "loop"); - - // package.loaded.luv = vim.loop - // otherwise luv will be reinitialized when require'luv' - lua_getglobal(lstate, "package"); - lua_getfield(lstate, -1, "loaded"); - lua_pushvalue(lstate, -3); - lua_setfield(lstate, -2, "luv"); - lua_pop(lstate, 3); - // vim.NIL lua_newuserdata(lstate, 0); lua_createtable(lstate, 0, 0); @@ -512,35 +381,32 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_setfield(lstate, LUA_REGISTRYINDEX, "mpack.empty_dict"); lua_setfield(lstate, -2, "_empty_dict_mt"); - // vim.mpack - luaopen_mpack(lstate); + // internal vim._treesitter... API + nlua_add_treesitter(lstate); + + // vim.loop + luv_set_loop(lstate, &main_loop.uv); + luv_set_callback(lstate, nlua_luv_cfpcall); + luaopen_luv(lstate); lua_pushvalue(lstate, -1); - lua_setfield(lstate, -3, "mpack"); + lua_setfield(lstate, -3, "loop"); - // package.loaded.mpack = vim.mpack - // otherwise luv will be reinitialized when require'mpack' + // package.loaded.luv = vim.loop + // otherwise luv will be reinitialized when require'luv' lua_getglobal(lstate, "package"); lua_getfield(lstate, -1, "loaded"); lua_pushvalue(lstate, -3); - lua_setfield(lstate, -2, "mpack"); + lua_setfield(lstate, -2, "luv"); lua_pop(lstate, 3); - // internal vim._treesitter... API - nlua_add_treesitter(lstate); - - // vim.diff - lua_pushcfunction(lstate, &nlua_xdl_diff); - lua_setfield(lstate, -2, "diff"); - - lua_cjson_new(lstate); - lua_setfield(lstate, -2, "json"); + nlua_state_add_stdlib(lstate); lua_setglobal(lstate, "vim"); { const char *code = (char *)&shared_module[0]; if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/shared.lua") - || lua_pcall(lstate, 0, 0, 0)) { + || nlua_pcall(lstate, 0, 0)) { nlua_error(lstate, _("E5106: Error while creating shared module: %.*s")); return 1; } @@ -552,7 +418,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL const char *code = (char *)&inspect_module[0]; if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/inspect.lua") - || lua_pcall(lstate, 0, 1, 0)) { + || nlua_pcall(lstate, 0, 1)) { nlua_error(lstate, _("E5106: Error while creating inspect module: %.*s")); return 1; } @@ -561,7 +427,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL code = (char *)&lua_F_module[0]; if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/F.lua") - || lua_pcall(lstate, 0, 1, 0)) { + || nlua_pcall(lstate, 0, 1)) { nlua_error(lstate, _("E5106: Error while creating vim.F module: %.*s")); return 1; } @@ -574,7 +440,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL { const char *code = (char *)&vim_module[0]; if (luaL_loadbuffer(lstate, code, strlen(code), "@vim.lua") - || lua_pcall(lstate, 0, 0, 0)) { + || nlua_pcall(lstate, 0, 0)) { nlua_error(lstate, _("E5106: Error while creating vim module: %.*s")); return 1; } @@ -586,7 +452,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL const char *code = (char *)&lua_meta_module[0]; if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/_meta.lua") - || lua_pcall(lstate, 0, 1, 0)) { + || nlua_pcall(lstate, 0, 1)) { nlua_error(lstate, _("E5106: Error while creating vim._meta module: %.*s")); return 1; } @@ -613,7 +479,7 @@ void nlua_init(void) lua_State *lstate = luaL_newstate(); if (lstate == NULL) { - EMSG(_("E970: Failed to initialize lua interpreter")); + emsg(_("E970: Failed to initialize lua interpreter")); preserve_exit(); } luaL_openlibs(lstate); @@ -674,10 +540,10 @@ static void nlua_print_event(void **argv) } break; } - msg((char_u *)str + start); + msg(str + start); } if (len && str[len - 1] == NUL) { // Last was newline - msg((char_u *)""); + msg(""); } xfree(str); } @@ -704,6 +570,7 @@ static int nlua_print(lua_State *const lstate) for (; curargidx <= nargs; curargidx++) { lua_pushvalue(lstate, -1); // tostring lua_pushvalue(lstate, curargidx); // arg + // Do not use nlua_pcall here to avoid duplicate stack trace information if (lua_pcall(lstate, 1, 1, 0)) { errmsg = lua_tolstring(lstate, -1, &errmsg_len); goto nlua_print_error; @@ -743,7 +610,7 @@ nlua_print_error: /// debug.debug: interaction with user while debugging. /// /// @param lstate Lua interpreter state. -int nlua_debug(lua_State *lstate) +static int nlua_debug(lua_State *lstate) FUNC_ATTR_NONNULL_ALL { const typval_T input_args[] = { @@ -771,7 +638,7 @@ int nlua_debug(lua_State *lstate) if (luaL_loadbuffer(lstate, (const char *)input.vval.v_string, STRLEN(input.vval.v_string), "=(debug command)")) { nlua_error(lstate, _("E5115: Error while loading debug string: %.*s")); - } else if (lua_pcall(lstate, 0, 0, 0)) { + } else if (nlua_pcall(lstate, 0, 0)) { nlua_error(lstate, _("E5116: Error while calling debug string: %.*s")); } tv_clear(&input); @@ -898,109 +765,6 @@ check_err: return request ? 1 : 0; } -static dict_T *nlua_get_var_scope(lua_State *lstate) { - const char *scope = luaL_checkstring(lstate, 1); - handle_T handle = (handle_T)luaL_checkinteger(lstate, 2); - dict_T *dict = NULL; - Error err = ERROR_INIT; - if (strequal(scope, "g")) { - dict = &globvardict; - } else if (strequal(scope, "v")) { - dict = &vimvardict; - } else if (strequal(scope, "b")) { - buf_T *buf = find_buffer_by_handle(handle, &err); - if (buf) { - dict = buf->b_vars; - } - } else if (strequal(scope, "w")) { - win_T *win = find_window_by_handle(handle, &err); - if (win) { - dict = win->w_vars; - } - } else if (strequal(scope, "t")) { - tabpage_T *tabpage = find_tab_by_handle(handle, &err); - if (tabpage) { - dict = tabpage->tp_vars; - } - } else { - luaL_error(lstate, "invalid scope", err.msg); - return NULL; - } - - if (ERROR_SET(&err)) { - luaL_error(lstate, "FAIL: %s", err.msg); - return NULL; - } - return dict; -} - - -static int nlua_getvar(lua_State *lstate) -{ - // non-local return if not found - dict_T *dict = nlua_get_var_scope(lstate); - size_t len; - const char *name = luaL_checklstring(lstate, 3, &len); - - dictitem_T *di = tv_dict_find(dict, name, (ptrdiff_t)len); - if (di == NULL) { - return 0; // nil - } - nlua_push_typval(lstate, &di->di_tv, false); - return 1; -} - -static int nlua_setvar(lua_State *lstate) -{ - // non-local return if not found - dict_T *dict = nlua_get_var_scope(lstate); - String key; - key.data = (char *)luaL_checklstring(lstate, 3, &key.size); - - bool del = (lua_gettop(lstate) < 4) || lua_isnil(lstate, 4); - - Error err = ERROR_INIT; - dictitem_T *di = dict_check_writable(dict, key, del, &err); - if (ERROR_SET(&err)) { - return 0; - } - - if (del) { - // Delete the key - if (di == NULL) { - // Doesn't exist, nothing to do - return 0; - } else { - // Delete the entry - tv_dict_item_remove(dict, di); - } - } else { - // Update the key - typval_T tv; - - // Convert the lua value to a vimscript type in the temporary variable - lua_pushvalue(lstate, 4); - if (!nlua_pop_typval(lstate, &tv)) { - return luaL_error(lstate, "Couldn't convert lua value"); - } - - if (di == NULL) { - // Need to create an entry - di = tv_dict_item_alloc_len(key.data, key.size); - tv_dict_add(dict, di); - } else { - // Clear the old value - tv_clear(&di->di_tv); - } - - // Update the value - tv_copy(&tv, &di->di_tv); - // Clear the temporary variable - tv_clear(&tv); - } - return 0; -} - static int nlua_nil_tostring(lua_State *lstate) { lua_pushstring(lstate, "vim.NIL"); @@ -1167,7 +931,7 @@ static void nlua_typval_exec(const char *lcmd, size_t lcmd_len, const char *name PUSH_ALL_TYPVALS(lstate, args, argcount, special); - if (lua_pcall(lstate, argcount, ret_tv ? 1 : 0, 0)) { + if (nlua_pcall(lstate, argcount, ret_tv ? 1 : 0)) { nlua_error(lstate, _("E5108: Error executing lua %.*s")); return; } @@ -1222,7 +986,7 @@ int typval_exec_lua_callable(lua_State *lstate, LuaCallable lua_cb, int argcount PUSH_ALL_TYPVALS(lstate, argvars, argcount, false); - if (lua_pcall(lstate, argcount, 1, 0)) { + if (nlua_pcall(lstate, argcount, 1)) { nlua_print(lstate); return ERROR_OTHER; } @@ -1257,7 +1021,7 @@ Object nlua_exec(const String str, const Array args, Error *err) nlua_push_Object(lstate, args.items[i], false); } - if (lua_pcall(lstate, (int)args.size, 1, 0)) { + if (nlua_pcall(lstate, (int)args.size, 1)) { size_t len; const char *errstr = lua_tolstring(lstate, -1, &len); api_set_error(err, kErrorTypeException, @@ -1290,7 +1054,7 @@ Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Erro nlua_push_Object(lstate, args.items[i], false); } - if (lua_pcall(lstate, nargs, retval ? 1 : 0, 0)) { + if (nlua_pcall(lstate, nargs, retval ? 1 : 0)) { // if err is passed, the caller will deal with the error. if (err) { size_t len; @@ -1349,7 +1113,7 @@ void ex_luado(exarg_T *const eap) FUNC_ATTR_NONNULL_ALL { if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) { - EMSG(_("cannot save undo information")); + emsg(_("cannot save undo information")); return; } const char *const cmd = (const char *)eap->arg; @@ -1384,7 +1148,7 @@ void ex_luado(exarg_T *const eap) if (lcmd_len >= IOSIZE) { xfree(lcmd); } - if (lua_pcall(lstate, 0, 1, 0)) { + if (nlua_pcall(lstate, 0, 1)) { nlua_error(lstate, _("E5110: Error executing lua: %.*s")); return; } @@ -1396,7 +1160,7 @@ void ex_luado(exarg_T *const eap) const char *old_line = (const char *)ml_get_buf(curbuf, l, false); lua_pushstring(lstate, old_line); lua_pushnumber(lstate, (lua_Number)l); - if (lua_pcall(lstate, 2, 1, 0)) { + if (nlua_pcall(lstate, 2, 1)) { nlua_error(lstate, _("E5111: Error calling lua: %.*s")); break; } @@ -1447,7 +1211,7 @@ bool nlua_exec_file(const char *path) return false; } - if (lua_pcall(lstate, 0, 0, 0)) { + if (nlua_pcall(lstate, 0, 0)) { nlua_error(lstate, _("E5113: Error while calling lua chunk: %.*s")); return false; } @@ -1499,7 +1263,7 @@ int nlua_expand_pat(expand_T *xp, char_u *pat, int *num_results, char_u ***resul // [ vim, vim._on_key, buf ] lua_pushlstring(lstate, (const char *)pat, STRLEN(pat)); - if (lua_pcall(lstate, 1, 2, 0) != 0) { + if (nlua_pcall(lstate, 1, 2) != 0) { nlua_error(lstate, _("Error executing vim._expand_pat: %.*s")); return FAIL; @@ -1553,139 +1317,6 @@ cleanup: return ret; } -static int nlua_regex(lua_State *lstate) -{ - Error err = ERROR_INIT; - const char *text = luaL_checkstring(lstate, 1); - regprog_T *prog = NULL; - - TRY_WRAP({ - try_start(); - prog = vim_regcomp((char_u *)text, RE_AUTO | RE_MAGIC | RE_STRICT); - try_end(&err); - }); - - if (ERROR_SET(&err)) { - return luaL_error(lstate, "couldn't parse regex: %s", err.msg); - } - assert(prog); - - regprog_T **p = lua_newuserdata(lstate, sizeof(regprog_T *)); - *p = prog; - - lua_getfield(lstate, LUA_REGISTRYINDEX, "nvim_regex"); // [udata, meta] - lua_setmetatable(lstate, -2); // [udata] - return 1; -} - -static regprog_T **regex_check(lua_State *L) -{ - return luaL_checkudata(L, 1, "nvim_regex"); -} - - -static int regex_gc(lua_State *lstate) -{ - regprog_T **prog = regex_check(lstate); - vim_regfree(*prog); - return 0; -} - -static int regex_tostring(lua_State *lstate) -{ - lua_pushstring(lstate, "<regex>"); - return 1; -} - -static int regex_match(lua_State *lstate, regprog_T **prog, char_u *str) -{ - regmatch_T rm; - rm.regprog = *prog; - rm.rm_ic = false; - bool match = vim_regexec(&rm, str, 0); - *prog = rm.regprog; - - if (match) { - lua_pushinteger(lstate, (lua_Integer)(rm.startp[0]-str)); - lua_pushinteger(lstate, (lua_Integer)(rm.endp[0]-str)); - return 2; - } - return 0; -} - -static int regex_match_str(lua_State *lstate) -{ - regprog_T **prog = regex_check(lstate); - const char *str = luaL_checkstring(lstate, 2); - int nret = regex_match(lstate, prog, (char_u *)str); - - if (!*prog) { - return luaL_error(lstate, "regex: internal error"); - } - - return nret; -} - -static int regex_match_line(lua_State *lstate) -{ - regprog_T **prog = regex_check(lstate); - - int narg = lua_gettop(lstate); - if (narg < 3) { - return luaL_error(lstate, "not enough args"); - } - - long bufnr = luaL_checkinteger(lstate, 2); - long rownr = luaL_checkinteger(lstate, 3); - long start = 0, end = -1; - if (narg >= 4) { - start = luaL_checkinteger(lstate, 4); - } - if (narg >= 5) { - end = luaL_checkinteger(lstate, 5); - if (end < 0) { - return luaL_error(lstate, "invalid end"); - } - } - - buf_T *buf = bufnr ? handle_get_buffer((int)bufnr) : curbuf; - if (!buf || buf->b_ml.ml_mfp == NULL) { - return luaL_error(lstate, "invalid buffer"); - } - - if (rownr >= buf->b_ml.ml_line_count) { - return luaL_error(lstate, "invalid row"); - } - - char_u *line = ml_get_buf(buf, rownr+1, false); - size_t len = STRLEN(line); - - if (start < 0 || (size_t)start > len) { - return luaL_error(lstate, "invalid start"); - } - - char_u save = NUL; - if (end >= 0) { - if ((size_t)end > len || end < start) { - return luaL_error(lstate, "invalid end"); - } - save = line[end]; - line[end] = NUL; - } - - int nret = regex_match(lstate, prog, line+start); - - if (end >= 0) { - line[end] = save; - } - - if (!*prog) { - return luaL_error(lstate, "regex: internal error"); - } - - return nret; -} - // Required functions for lua c functions as VimL callbacks int nlua_CFunction_func_call(int argcount, typval_T *argvars, typval_T *rettv, void *state) @@ -1785,7 +1416,7 @@ void nlua_execute_on_key(int c) // [ vim, vim._on_key, buf ] lua_pushlstring(lstate, (const char *)buf, buf_len); - if (lua_pcall(lstate, 1, 0, 0)) { + if (nlua_pcall(lstate, 1, 0)) { nlua_error(lstate, _("Error executing vim.on_key Lua callback: %.*s")); } |