aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/lua
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
commit1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (patch)
treecd08258054db80bb9a11b1061bb091c70b76926a /src/nvim/lua
parenteaa89c11d0f8aefbb512de769c6c82f61a8baca3 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-aucmd_textputpost.tar.gz
rneovim-aucmd_textputpost.tar.bz2
rneovim-aucmd_textputpost.zip
Merge remote-tracking branch 'upstream/master' into aucmd_textputpostaucmd_textputpost
Diffstat (limited to 'src/nvim/lua')
-rw-r--r--src/nvim/lua/base64.c70
-rw-r--r--src/nvim/lua/base64.h7
-rw-r--r--src/nvim/lua/converter.c149
-rw-r--r--src/nvim/lua/converter.h17
-rw-r--r--src/nvim/lua/executor.c285
-rw-r--r--src/nvim/lua/executor.h21
-rw-r--r--src/nvim/lua/secure.c119
-rw-r--r--src/nvim/lua/secure.h7
-rw-r--r--src/nvim/lua/spell.c23
-rw-r--r--src/nvim/lua/spell.h9
-rw-r--r--src/nvim/lua/stdlib.c134
-rw-r--r--src/nvim/lua/stdlib.h7
-rw-r--r--src/nvim/lua/treesitter.c517
-rw-r--r--src/nvim/lua/treesitter.h11
-rw-r--r--src/nvim/lua/xdiff.c76
-rw-r--r--src/nvim/lua/xdiff.h9
16 files changed, 1007 insertions, 454 deletions
diff --git a/src/nvim/lua/base64.c b/src/nvim/lua/base64.c
new file mode 100644
index 0000000000..c1f43a37d7
--- /dev/null
+++ b/src/nvim/lua/base64.c
@@ -0,0 +1,70 @@
+#include <assert.h>
+#include <lauxlib.h>
+#include <lua.h>
+#include <stddef.h>
+
+#include "nvim/base64.h"
+#include "nvim/lua/base64.h"
+#include "nvim/memory.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "lua/base64.c.generated.h"
+#endif
+
+static int nlua_base64_encode(lua_State *L)
+{
+ if (lua_gettop(L) < 1) {
+ return luaL_error(L, "Expected 1 argument");
+ }
+
+ if (lua_type(L, 1) != LUA_TSTRING) {
+ luaL_argerror(L, 1, "expected string");
+ }
+
+ size_t src_len = 0;
+ const char *src = lua_tolstring(L, 1, &src_len);
+
+ const char *ret = base64_encode(src, src_len);
+ assert(ret != NULL);
+ lua_pushstring(L, ret);
+ xfree((void *)ret);
+
+ return 1;
+}
+
+static int nlua_base64_decode(lua_State *L)
+{
+ if (lua_gettop(L) < 1) {
+ return luaL_error(L, "Expected 1 argument");
+ }
+
+ if (lua_type(L, 1) != LUA_TSTRING) {
+ luaL_argerror(L, 1, "expected string");
+ }
+
+ size_t src_len = 0;
+ const char *src = lua_tolstring(L, 1, &src_len);
+
+ const char *ret = base64_decode(src, src_len);
+ if (ret == NULL) {
+ return luaL_error(L, "Invalid input");
+ }
+
+ lua_pushstring(L, ret);
+ xfree((void *)ret);
+
+ return 1;
+}
+
+static const luaL_Reg base64_functions[] = {
+ { "encode", nlua_base64_encode },
+ { "decode", nlua_base64_decode },
+ { NULL, NULL },
+};
+
+int luaopen_base64(lua_State *L)
+{
+ lua_newtable(L);
+ luaL_register(L, NULL, base64_functions);
+ return 1;
+}
diff --git a/src/nvim/lua/base64.h b/src/nvim/lua/base64.h
new file mode 100644
index 0000000000..3c95968cda
--- /dev/null
+++ b/src/nvim/lua/base64.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <lua.h> // IWYU pragma: keep
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "lua/base64.h.generated.h"
+#endif
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index 6160b84485..4598d48c4a 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -1,6 +1,3 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
#include <assert.h>
#include <lauxlib.h>
#include <lua.h>
@@ -10,26 +7,24 @@
#include <stdlib.h>
#include <string.h>
+#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/memory.h"
-// FIXME: vim.h is not actually needed, but otherwise it states MAXPATHL is
-// redefined
-#include "klib/kvec.h"
-#include "nvim/ascii.h"
+#include "nvim/ascii_defs.h"
#include "nvim/eval/decode.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/eval/typval_encode.h"
#include "nvim/eval/userfunc.h"
-#include "nvim/garray.h"
+#include "nvim/func_attr.h"
#include "nvim/gettext.h"
#include "nvim/lua/converter.h"
#include "nvim/lua/executor.h"
-#include "nvim/macros.h"
+#include "nvim/macros_defs.h"
+#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/types.h"
-#include "nvim/vim.h"
+#include "nvim/types_defs.h"
+#include "nvim/vim_defs.h"
/// Determine, which keys lua table contains
typedef struct {
@@ -183,7 +178,7 @@ typedef struct {
int idx; ///< Container index (used to detect self-referencing structures).
} TVPopStackItem;
-/// Convert lua object to VimL typval_T
+/// Convert lua object to Vimscript typval_T
///
/// Should pop exactly one value from lua stack.
///
@@ -459,7 +454,7 @@ static bool typval_conv_special = false;
TYPVAL_ENCODE_CONV_NUMBER(tv, flt)
#define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \
- lua_pushlstring(lstate, (const char *)(str), (len))
+ lua_pushlstring(lstate, (str), (len))
#define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING
@@ -469,9 +464,7 @@ static bool typval_conv_special = false;
#define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \
do { \
const blob_T *const blob_ = (blob); \
- lua_pushlstring(lstate, \
- blob_ != NULL ? (const char *)blob_->bv_ga.ga_data : "", \
- (size_t)(len)); \
+ lua_pushlstring(lstate, blob_ != NULL ? blob_->bv_ga.ga_data : "", (size_t)(len)); \
} while (0)
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
@@ -603,7 +596,7 @@ static bool typval_conv_special = false;
#undef TYPVAL_ENCODE_CONV_RECURSE
#undef TYPVAL_ENCODE_ALLOW_SPECIALS
-/// Convert VimL typval_T to lua value
+/// Convert Vimscript typval_T to lua value
///
/// Should leave single value in lua stack. May only fail if lua failed to grow
/// stack.
@@ -630,8 +623,7 @@ bool nlua_push_typval(lua_State *lstate, typval_T *const tv, bool special)
/// Push value which is a type index
///
-/// Used for all “typed” tables: i.e. for all tables which represent VimL
-/// values.
+/// Used for all “typed” tables: i.e. for all tables which represent Vimscript values.
static inline void nlua_push_type_idx(lua_State *lstate)
FUNC_ATTR_NONNULL_ALL
{
@@ -659,7 +651,7 @@ static inline void nlua_push_type(lua_State *lstate, ObjectType type)
lua_pushnumber(lstate, (lua_Number)type);
}
-/// Create lua table which has an entry that determines its VimL type
+/// Create Lua table which has an entry that determines its Vimscript type
///
/// @param[out] lstate Lua state.
/// @param[in] narr Number of “array” entries to be populated later.
@@ -816,7 +808,7 @@ String nlua_pop_String(lua_State *lstate, Error *err)
{
if (lua_type(lstate, -1) != LUA_TSTRING) {
lua_pop(lstate, 1);
- api_set_error(err, kErrorTypeValidation, "Expected lua string");
+ api_set_error(err, kErrorTypeValidation, "Expected Lua string");
return (String) { .size = 0, .data = NULL };
}
String ret;
@@ -837,7 +829,7 @@ Integer nlua_pop_Integer(lua_State *lstate, Error *err)
{
if (lua_type(lstate, -1) != LUA_TNUMBER) {
lua_pop(lstate, 1);
- api_set_error(err, kErrorTypeValidation, "Expected lua number");
+ api_set_error(err, kErrorTypeValidation, "Expected Lua number");
return 0;
}
const lua_Number n = lua_tonumber(lstate, -1);
@@ -852,6 +844,9 @@ Integer nlua_pop_Integer(lua_State *lstate, Error *err)
/// Convert lua value to boolean
///
+/// Despite the name of the function, this uses lua semantics for booleans.
+/// thus `err` is never set as any lua value can be co-erced into a lua bool
+///
/// Always pops one value from the stack.
Boolean nlua_pop_Boolean(lua_State *lstate, Error *err)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
@@ -861,6 +856,36 @@ Boolean nlua_pop_Boolean(lua_State *lstate, Error *err)
return ret;
}
+/// Convert lua value to boolean
+///
+/// This follows API conventions for a Boolean value, compare api_object_to_bool
+///
+/// Always pops one value from the stack.
+Boolean nlua_pop_Boolean_strict(lua_State *lstate, Error *err)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ Boolean ret = false;
+ switch (lua_type(lstate, -1)) {
+ case LUA_TBOOLEAN:
+ ret = lua_toboolean(lstate, -1);
+ break;
+
+ case LUA_TNUMBER:
+ ret = (lua_tonumber(lstate, -1) != 0);
+ break;
+
+ case LUA_TNIL:
+ ret = false;
+ break;
+
+ default:
+ api_set_error(err, kErrorTypeValidation, "not a boolean");
+ }
+
+ lua_pop(lstate, 1);
+ return ret;
+}
+
/// Check whether typed table on top of the stack has given type
///
/// @param[in] lstate Lua state.
@@ -874,7 +899,8 @@ static inline LuaTableProps nlua_check_type(lua_State *const lstate, Error *cons
{
if (lua_type(lstate, -1) != LUA_TTABLE) {
if (err) {
- api_set_error(err, kErrorTypeValidation, "Expected lua table");
+ api_set_error(err, kErrorTypeValidation, "Expected Lua %s",
+ (type == kObjectTypeFloat) ? "number" : "table");
}
return (LuaTableProps) { .type = kObjectTypeNil };
}
@@ -887,7 +913,7 @@ static inline LuaTableProps nlua_check_type(lua_State *const lstate, Error *cons
if (table_props.type != type) {
if (err) {
- api_set_error(err, kErrorTypeValidation, "Unexpected type");
+ api_set_error(err, kErrorTypeValidation, "Expected %s-like Lua table", api_typename(type));
}
}
@@ -1171,7 +1197,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
break;
case kObjectTypeNil:
api_set_error(err, kErrorTypeValidation,
- "Cannot convert given lua table");
+ "Cannot convert given Lua table");
break;
default:
abort();
@@ -1227,26 +1253,19 @@ LuaRef nlua_pop_LuaRef(lua_State *const lstate, Error *err)
return rv;
}
-#define GENERATE_INDEX_FUNCTION(type) \
- type nlua_pop_##type(lua_State *lstate, Error *err) \
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \
- { \
- type ret; \
- if (lua_type(lstate, -1) != LUA_TNUMBER) { \
- api_set_error(err, kErrorTypeValidation, "Expected Lua number"); \
- ret = (type) - 1; \
- } else { \
- ret = (type)lua_tonumber(lstate, -1); \
- } \
- lua_pop(lstate, 1); \
- return ret; \
+handle_T nlua_pop_handle(lua_State *lstate, Error *err)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ handle_T ret;
+ if (lua_type(lstate, -1) != LUA_TNUMBER) {
+ api_set_error(err, kErrorTypeValidation, "Expected Lua number");
+ ret = (handle_T) - 1;
+ } else {
+ ret = (handle_T)lua_tonumber(lstate, -1);
}
-
-GENERATE_INDEX_FUNCTION(Buffer)
-GENERATE_INDEX_FUNCTION(Window)
-GENERATE_INDEX_FUNCTION(Tabpage)
-
-#undef GENERATE_INDEX_FUNCTION
+ lua_pop(lstate, 1);
+ return ret;
+}
/// Record some auxiliary values in vim module
///
@@ -1295,10 +1314,11 @@ void nlua_init_types(lua_State *const lstate)
lua_rawset(lstate, -3);
}
-void nlua_pop_keydict(lua_State *L, void *retval, field_hash hashy, Error *err)
+// lua specific variant of api_dict_to_keydict
+void nlua_pop_keydict(lua_State *L, void *retval, FieldHashfn hashy, char **err_opt, Error *err)
{
if (!lua_istable(L, -1)) {
- api_set_error(err, kErrorTypeValidation, "Expected lua table");
+ api_set_error(err, kErrorTypeValidation, "Expected Lua table");
lua_pop(L, -1);
return;
}
@@ -1308,14 +1328,45 @@ void nlua_pop_keydict(lua_State *L, void *retval, field_hash hashy, Error *err)
// [dict, key, value]
size_t len;
const char *s = lua_tolstring(L, -2, &len);
- Object *field = hashy(retval, s, len);
+ KeySetLink *field = hashy(s, len);
if (!field) {
api_set_error(err, kErrorTypeValidation, "invalid key: %.*s", (int)len, s);
lua_pop(L, 3); // []
return;
}
- *field = nlua_pop_Object(L, true, err);
+ if (field->opt_index >= 0) {
+ OptKeySet *ks = (OptKeySet *)retval;
+ ks->is_set_ |= (1ULL << field->opt_index);
+ }
+ char *mem = ((char *)retval + field->ptr_off);
+
+ if (field->type == kObjectTypeNil) {
+ *(Object *)mem = nlua_pop_Object(L, true, err);
+ } else if (field->type == kObjectTypeInteger) {
+ *(Integer *)mem = nlua_pop_Integer(L, err);
+ } else if (field->type == kObjectTypeBoolean) {
+ *(Boolean *)mem = nlua_pop_Boolean_strict(L, err);
+ } else if (field->type == kObjectTypeString) {
+ *(String *)mem = nlua_pop_String(L, err);
+ } else if (field->type == kObjectTypeFloat) {
+ *(Float *)mem = nlua_pop_Float(L, err);
+ } else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow
+ || field->type == kObjectTypeTabpage) {
+ *(handle_T *)mem = nlua_pop_handle(L, err);
+ } else if (field->type == kObjectTypeArray) {
+ *(Array *)mem = nlua_pop_Array(L, err);
+ } else if (field->type == kObjectTypeDictionary) {
+ *(Dictionary *)mem = nlua_pop_Dictionary(L, false, err);
+ } else if (field->type == kObjectTypeLuaRef) {
+ *(LuaRef *)mem = nlua_pop_LuaRef(L, err);
+ } else {
+ abort();
+ }
+ if (ERROR_SET(err)) {
+ *err_opt = field->str;
+ break;
+ }
}
// [dict]
lua_pop(L, 1);
diff --git a/src/nvim/lua/converter.h b/src/nvim/lua/converter.h
index ddc0acfbfa..a502df80d9 100644
--- a/src/nvim/lua/converter.h
+++ b/src/nvim/lua/converter.h
@@ -1,15 +1,14 @@
-#ifndef NVIM_LUA_CONVERTER_H
-#define NVIM_LUA_CONVERTER_H
+#pragma once
-#include <lua.h>
-#include <stdbool.h>
-#include <stdint.h>
+#include <lua.h> // IWYU pragma: keep
-#include "nvim/api/private/defs.h"
-#include "nvim/eval/typval.h"
-#include "nvim/func_attr.h"
+#include "nvim/api/private/defs.h" // IWYU pragma: keep
+#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
+
+#define nlua_pop_Buffer nlua_pop_handle
+#define nlua_pop_Window nlua_pop_handle
+#define nlua_pop_Tabpage nlua_pop_handle
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "lua/converter.h.generated.h"
#endif
-#endif // NVIM_LUA_CONVERTER_H
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 1415ceeaed..06d16efb05 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -1,12 +1,11 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
#include <assert.h>
#include <inttypes.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <tree_sitter/api.h>
#include <uv.h>
@@ -16,9 +15,9 @@
#include "nvim/api/extmark.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/ascii.h"
-#include "nvim/buffer_defs.h"
+#include "nvim/ascii_defs.h"
#include "nvim/change.h"
+#include "nvim/cmdexpand_defs.h"
#include "nvim/cursor.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
@@ -42,25 +41,24 @@
#include "nvim/lua/executor.h"
#include "nvim/lua/stdlib.h"
#include "nvim/lua/treesitter.h"
-#include "nvim/macros.h"
+#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/msgpack_rpc/channel.h"
-#include "nvim/option_defs.h"
+#include "nvim/option_vars.h"
#include "nvim/os/fileio.h"
#include "nvim/os/os.h"
#include "nvim/path.h"
-#include "nvim/pos.h"
+#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/runtime.h"
#include "nvim/strings.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/usercmd.h"
-#include "nvim/version.h"
-#include "nvim/vim.h"
+#include "nvim/vim_defs.h"
#include "nvim/window.h"
static int in_fast_callback = 0;
@@ -109,11 +107,16 @@ typedef enum luv_err_type {
kThreadCallback,
} luv_err_t;
+lua_State *get_global_lstate(void)
+{
+ return global_lstate;
+}
+
/// Convert lua error into a Vim error message
///
/// @param lstate Lua interpreter state.
-/// @param[in] msg Message base, must contain one `%s`.
-static void nlua_error(lua_State *const lstate, const char *const msg)
+/// @param[in] msg Message base, must contain one `%*s`.
+void nlua_error(lua_State *const lstate, const char *const msg)
FUNC_ATTR_NONNULL_ALL
{
size_t len;
@@ -135,8 +138,8 @@ static void nlua_error(lua_State *const lstate, const char *const msg)
}
if (in_script) {
- os_errmsg(str);
- os_errmsg("\n");
+ fprintf(stderr, msg, (int)len, str);
+ fprintf(stderr, "\n");
} else {
msg_ext_set_kind("lua_error");
semsg_multiline(msg, (int)len, str);
@@ -150,7 +153,7 @@ static void nlua_error(lua_State *const lstate, const char *const msg)
/// @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)
+int nlua_pcall(lua_State *lstate, int nargs, int nresults)
{
lua_getglobal(lstate, "debug");
lua_getfield(lstate, -1, "traceback");
@@ -165,17 +168,6 @@ static int nlua_pcall(lua_State *lstate, int nargs, int nresults)
return status;
}
-/// Gets the version of the current Nvim build.
-///
-/// @param lstate Lua interpreter state.
-static int nlua_nvim_version(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
-{
- Dictionary version = version_dict();
- nlua_push_Dictionary(lstate, version, true);
- api_free_dictionary(version);
- return 1;
-}
-
static void nlua_luv_error_event(void **argv)
{
char *error = (char *)argv[0];
@@ -211,9 +203,7 @@ static int nlua_luv_cfpcall(lua_State *lstate, int nargs, int nresult, int flags
if (status) {
if (status == LUA_ERRMEM && !(flags & LUVF_CALLBACK_NOEXIT)) {
// consider out of memory errors unrecoverable, just like xmalloc()
- os_errmsg(e_outofmem);
- os_errmsg("\n");
- preserve_exit();
+ preserve_exit(e_outofmem);
}
const char *error = lua_tostring(lstate, -1);
@@ -349,7 +339,7 @@ static int nlua_init_argv(lua_State *const L, char **argv, int argc, int lua_arg
lua_pushstring(L, argv[lua_arg0 - 1]);
lua_rawseti(L, -2, 0); // _G.arg[0] = "foo.lua"
- for (; lua_arg0 >= 0 && i + lua_arg0 < argc; i++) {
+ for (; i + lua_arg0 < argc; i++) {
lua_pushstring(L, argv[i + lua_arg0]);
lua_rawseti(L, -2, i + 1); // _G.arg[i+1] = "--foo"
}
@@ -381,6 +371,12 @@ static int nlua_schedule(lua_State *const lstate)
return lua_error(lstate);
}
+ // If main_loop is closing don't schedule tasks to run in the future,
+ // otherwise any refs allocated here will not be cleaned up.
+ if (main_loop.closing) {
+ return 0;
+ }
+
LuaRef cb = nlua_ref_global(lstate, 1);
multiqueue_put(main_loop.events, nlua_schedule_event,
@@ -390,7 +386,8 @@ static int nlua_schedule(lua_State *const lstate)
// Dummy timer callback. Used by f_wait().
static void dummy_timer_due_cb(TimeWatcher *tw, void *data)
-{}
+{
+}
// Dummy timer close callback. Used by f_wait().
static void dummy_timer_close_cb(TimeWatcher *tw, void *data)
@@ -414,6 +411,10 @@ static bool nlua_wait_condition(lua_State *lstate, int *status, bool *callback_r
static int nlua_wait(lua_State *lstate)
FUNC_ATTR_NONNULL_ALL
{
+ if (in_fast_callback) {
+ return luaL_error(lstate, e_luv_api_disabled, "vim.wait");
+ }
+
intptr_t timeout = luaL_checkinteger(lstate, 1);
if (timeout < 0) {
return luaL_error(lstate, "timeout must be >= 0");
@@ -452,8 +453,7 @@ static int nlua_wait(lua_State *lstate)
fast_only = lua_toboolean(lstate, 4);
}
- MultiQueue *loop_events = fast_only || in_fast_callback > 0
- ? main_loop.fast_events : main_loop.events;
+ MultiQueue *loop_events = fast_only ? main_loop.fast_events : main_loop.events;
TimeWatcher *tw = xmalloc(sizeof(TimeWatcher));
@@ -469,12 +469,16 @@ static int nlua_wait(lua_State *lstate)
int pcall_status = 0;
bool callback_result = false;
+ // Flush screen updates before blocking.
+ ui_flush();
+
LOOP_PROCESS_EVENTS_UNTIL(&main_loop,
loop_events,
(int)timeout,
got_int || (is_function ? nlua_wait_condition(lstate,
&pcall_status,
- &callback_result) : false));
+ &callback_result)
+ : false));
// Stop dummy timer
time_watcher_stop(tw);
@@ -572,7 +576,7 @@ static void nlua_common_vim_init(lua_State *lstate, bool is_thread, bool is_stan
lua_setfield(lstate, LUA_REGISTRYINDEX, "mpack.empty_dict");
lua_setfield(lstate, -2, "_empty_dict_mt");
- // vim.loop
+ // vim.uv
if (is_standalone) {
// do nothing, use libluv like in a standalone interpreter
} else if (is_thread) {
@@ -585,9 +589,12 @@ static void nlua_common_vim_init(lua_State *lstate, bool is_thread, bool is_stan
}
luaopen_luv(lstate);
lua_pushvalue(lstate, -1);
- lua_setfield(lstate, -3, "loop");
+ lua_setfield(lstate, -3, "uv");
+
+ lua_pushvalue(lstate, -1);
+ lua_setfield(lstate, -3, "loop"); // deprecated
- // package.loaded.luv = vim.loop
+ // package.loaded.luv = vim.uv
// otherwise luv will be reinitialized when require'luv'
lua_getglobal(lstate, "package");
lua_getfield(lstate, -1, "loaded");
@@ -622,7 +629,7 @@ static bool nlua_init_packages(lua_State *lstate, bool is_standalone)
lua_getfield(lstate, -1, "preload"); // [package, preload]
for (size_t i = 0; i < ARRAY_SIZE(builtin_modules); i++) {
ModuleDef def = builtin_modules[i];
- lua_pushinteger(lstate, (long)i); // [package, preload, i]
+ lua_pushinteger(lstate, (lua_Integer)i); // [package, preload, i]
lua_pushcclosure(lstate, nlua_module_preloader, 1); // [package, preload, cclosure]
lua_setfield(lstate, -2, def.name); // [package, preload]
@@ -636,7 +643,7 @@ static bool nlua_init_packages(lua_State *lstate, bool is_standalone)
lua_getglobal(lstate, "require");
lua_pushstring(lstate, "vim._init_packages");
if (nlua_pcall(lstate, 1, 0)) {
- os_errmsg((char *)lua_tostring(lstate, -1));
+ os_errmsg(lua_tostring(lstate, -1));
os_errmsg("\n");
return false;
}
@@ -741,10 +748,6 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
// vim.types, vim.type_idx, vim.val_idx
nlua_init_types(lstate);
- // neovim version
- lua_pushcfunction(lstate, &nlua_nvim_version);
- lua_setfield(lstate, -2, "version");
-
// schedule
lua_pushcfunction(lstate, &nlua_schedule);
lua_setfield(lstate, -2, "schedule");
@@ -852,7 +855,7 @@ void nlua_run_script(char **argv, int argc, int lua_arg0)
exit(lua_ok ? 0 : 1);
}
-lua_State *nlua_init_state(bool thread)
+static lua_State *nlua_init_state(bool thread)
{
// If it is called from the main thread, it will attempt to rebuild the cache.
const uv_thread_t self = uv_thread_self();
@@ -926,12 +929,13 @@ static void nlua_common_free_all_mem(lua_State *lstate)
if (nlua_track_refs) {
// in case there are leaked luarefs, leak the associated memory
// to get LeakSanitizer stacktraces on exit
- pmap_destroy(handle_T)(&ref_state->ref_markers);
+ map_destroy(int, &ref_state->ref_markers);
}
#endif
lua_close(lstate);
}
+
static void nlua_print_event(void **argv)
{
char *str = argv[0];
@@ -960,10 +964,13 @@ static void nlua_print_event(void **argv)
}
break;
}
- msg(str + start);
+ msg(str + start, 0);
+ if (msg_silent == 0) {
+ msg_didout = true; // Make blank lines work properly
+ }
}
if (len && str[len - 1] == NUL) { // Last was newline
- msg("");
+ msg("", 0);
}
xfree(str);
}
@@ -1110,7 +1117,7 @@ static int nlua_debug(lua_State *lstate)
.v_type = VAR_UNKNOWN,
},
};
- for (;;) {
+ while (true) {
lua_settop(lstate, 0);
typval_T input;
get_user_input(input_args, &input, false, false);
@@ -1122,7 +1129,7 @@ static int nlua_debug(lua_State *lstate)
tv_clear(&input);
return 0;
}
- if (luaL_loadbuffer(lstate, (const char *)input.vval.v_string,
+ if (luaL_loadbuffer(lstate, input.vval.v_string,
strlen(input.vval.v_string), "=(debug command)")) {
nlua_error(lstate, _("E5115: Error while loading debug string: %.*s"));
} else if (nlua_pcall(lstate, 0, 0)) {
@@ -1145,7 +1152,7 @@ static bool viml_func_is_fast(const char *name)
if (fdef) {
return fdef->fast;
}
- // Not a vimL function
+ // Not a Vimscript function
return false;
}
@@ -1155,7 +1162,7 @@ int nlua_call(lua_State *lstate)
size_t name_len;
const char *name = luaL_checklstring(lstate, 1, &name_len);
if (!nlua_is_deferred_safe() && !viml_func_is_fast(name)) {
- return luaL_error(lstate, e_luv_api_disabled, "vimL function");
+ return luaL_error(lstate, e_luv_api_disabled, "Vimscript function");
}
int nargs = lua_gettop(lstate) - 1;
@@ -1174,28 +1181,29 @@ int nlua_call(lua_State *lstate)
}
}
- TRY_WRAP({
- // TODO(bfredl): this should be simplified in error handling refactor
- force_abort = false;
- suppress_errthrow = false;
- did_throw = false;
- did_emsg = false;
+ // TODO(bfredl): this should be simplified in error handling refactor
+ force_abort = false;
+ suppress_errthrow = false;
+ did_throw = false;
+ did_emsg = false;
- try_start();
- typval_T rettv;
- funcexe_T funcexe = FUNCEXE_INIT;
- funcexe.fe_firstline = curwin->w_cursor.lnum;
- funcexe.fe_lastline = curwin->w_cursor.lnum;
- funcexe.fe_evaluate = true;
+ typval_T rettv;
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.fe_firstline = curwin->w_cursor.lnum;
+ funcexe.fe_lastline = curwin->w_cursor.lnum;
+ funcexe.fe_evaluate = true;
+
+ TRY_WRAP(&err, {
// 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);
- if (!try_end(&err)) {
- nlua_push_typval(lstate, &rettv, false);
- }
- tv_clear(&rettv);
+ (void)call_func(name, (int)name_len, &rettv, nargs, vim_args, &funcexe);
});
+ if (!ERROR_SET(&err)) {
+ nlua_push_typval(lstate, &rettv, false);
+ }
+ tv_clear(&rettv);
+
free_vim_args:
while (i > 0) {
tv_clear(&vim_args[--i]);
@@ -1300,13 +1308,16 @@ LuaRef nlua_ref(lua_State *lstate, nlua_ref_state_t *ref_state, int index)
#ifdef NLUA_TRACK_REFS
if (nlua_track_refs) {
// dummy allocation to make LeakSanitizer track our luarefs
- pmap_put(handle_T)(&ref_state->ref_markers, ref, xmalloc(3));
+ pmap_put(int)(&ref_state->ref_markers, ref, xmalloc(3));
}
#endif
}
return ref;
}
+// TODO(lewis6991): Currently cannot be run in __gc metamethods as they are
+// invoked in lua_close() which can be invoked after the ref_markers map is
+// destroyed in nlua_common_free_all_mem.
LuaRef nlua_ref_global(lua_State *lstate, int index)
{
return nlua_ref(lstate, nlua_global_refs, index);
@@ -1320,7 +1331,7 @@ void nlua_unref(lua_State *lstate, nlua_ref_state_t *ref_state, LuaRef ref)
#ifdef NLUA_TRACK_REFS
// NB: don't remove entry from map to track double-unref
if (nlua_track_refs) {
- xfree(pmap_get(handle_T)(&ref_state->ref_markers, ref));
+ xfree(pmap_get(int)(&ref_state->ref_markers, ref));
}
#endif
luaL_unref(lstate, LUA_REGISTRYINDEX, ref);
@@ -1493,7 +1504,7 @@ int nlua_source_using_linegetter(LineGetter fgetline, void *cookie, char *name)
/// Call a LuaCallable given some typvals
///
-/// Used to call any lua callable passed from Lua into VimL
+/// Used to call any Lua callable passed from Lua into Vimscript.
///
/// @param[in] lstate Lua State
/// @param[in] lua_cb Lua Callable
@@ -1628,24 +1639,25 @@ bool nlua_is_deferred_safe(void)
///
/// Used for :lua.
///
-/// @param eap VimL command being run.
+/// @param eap Vimscript command being run.
void ex_lua(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL
{
size_t len;
char *code = script_get(eap, &len);
- if (eap->skip) {
+ if (eap->skip || code == NULL) {
xfree(code);
return;
}
- // When =expr is used transform it to print(vim.inspect(expr))
- if (code[0] == '=') {
- len += sizeof("vim.pretty_print()") - sizeof("=");
+ // When =expr is used transform it to vim.print(expr)
+ if (eap->cmdidx == CMD_equal || code[0] == '=') {
+ size_t off = (eap->cmdidx == CMD_equal) ? 0 : 1;
+ len += sizeof("vim.print()") - 1 - off;
// code_buf needs to be 1 char larger then len for null byte in the end.
// lua nlua_typval_exec doesn't expect null terminated string so len
// needs to end before null byte.
char *code_buf = xmallocz(len);
- vim_snprintf(code_buf, len + 1, "vim.pretty_print(%s)", code + 1);
+ vim_snprintf(code_buf, len + 1, "vim.print(%s)", code + off);
xfree(code);
code = code_buf;
}
@@ -1659,7 +1671,7 @@ void ex_lua(exarg_T *const eap)
///
/// Used for :luado.
///
-/// @param eap VimL command being run.
+/// @param eap Vimscript command being run.
void ex_luado(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL
{
@@ -1667,7 +1679,7 @@ void ex_luado(exarg_T *const eap)
emsg(_("cannot save undo information"));
return;
}
- const char *const cmd = (const char *)eap->arg;
+ const char *const cmd = eap->arg;
const size_t cmd_len = strlen(cmd);
lua_State *const lstate = global_lstate;
@@ -1708,7 +1720,9 @@ void ex_luado(exarg_T *const eap)
break;
}
lua_pushvalue(lstate, -1);
- const char *old_line = (const char *)ml_get_buf(curbuf, l, false);
+ const char *const old_line = ml_get_buf(curbuf, l);
+ // Get length of old_line here as calling Lua code may free it.
+ const size_t old_line_len = strlen(old_line);
lua_pushstring(lstate, old_line);
lua_pushnumber(lstate, (lua_Number)l);
if (nlua_pcall(lstate, 2, 1)) {
@@ -1716,8 +1730,6 @@ void ex_luado(exarg_T *const eap)
break;
}
if (lua_isstring(lstate, -1)) {
- 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);
char *const new_line_transformed = xmemdupz(new_line, new_line_len);
@@ -1740,11 +1752,11 @@ void ex_luado(exarg_T *const eap)
///
/// Used for :luafile.
///
-/// @param eap VimL command being run.
+/// @param eap Vimscript command being run.
void ex_luafile(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL
{
- nlua_exec_file((const char *)eap->arg);
+ nlua_exec_file(eap->arg);
}
/// Executes Lua code from a file or "-" (stdin).
@@ -1768,13 +1780,12 @@ bool nlua_exec_file(const char *path)
StringBuilder sb = KV_INITIAL_VALUE;
kv_resize(sb, 64);
- ptrdiff_t read_size = -1;
// Read all input from stdin, unless interrupted (ctrl-c).
while (true) {
if (got_int) { // User canceled.
return false;
}
- read_size = file_read(stdin_dup, IObuff, 64);
+ ptrdiff_t read_size = file_read(stdin_dup, IObuff, 64);
if (read_size < 0) {