diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2023-01-05 13:06:21 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-05 13:06:21 -0500 |
commit | 08ebf8d3a80c65b01d493ca84ad2ab7304a669f9 (patch) | |
tree | 77f73c6e88134d702ca275e43b45f5316ba5b47e /src/nvim/lua/executor.c | |
parent | 39d70fcafd6efa9d01b88bb90cab81c393040453 (diff) | |
parent | 628b717022815a431ea0b980444d6115c644f8c8 (diff) | |
download | rneovim-08ebf8d3a80c65b01d493ca84ad2ab7304a669f9.tar.gz rneovim-08ebf8d3a80c65b01d493ca84ad2ab7304a669f9.tar.bz2 rneovim-08ebf8d3a80c65b01d493ca84ad2ab7304a669f9.zip |
Merge #18706 execute Lua with "nvim -l"
Diffstat (limited to 'src/nvim/lua/executor.c')
-rw-r--r-- | src/nvim/lua/executor.c | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 34b572f884..307b34a55c 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -323,6 +323,30 @@ static int nlua_thr_api_nvim__get_runtime(lua_State *lstate) return 1; } +/// Copies args starting at `lua_arg0` into the Lua `arg` global. +/// +/// Example (`lua_arg0` points to "--arg1"): +/// nvim -l foo.lua --arg1 --arg2 +/// +/// @note Lua CLI sets arguments upto "-e" as _negative_ `_G.arg` indices, but we currently don't +/// follow that convention. +/// +/// @see https://www.lua.org/pil/1.4.html +/// @see https://github.com/premake/premake-core/blob/1c1304637f4f5e50ba8c57aae8d1d80ec3b7aaf2/src/host/premake.c#L563-L594 +/// +/// @returns number of args +static int nlua_init_argv(lua_State *const L, char **argv, int argc, int lua_arg0) +{ + lua_newtable(L); // _G.arg + int i = 0; + for (; lua_arg0 >= 0 && i + lua_arg0 < argc; i++) { + lua_pushstring(L, argv[i + lua_arg0]); + lua_rawseti(L, -2, i + 1); // _G.arg[i+1] = "arg1" + } + lua_setglobal(L, "arg"); + return i; +} + static void nlua_schedule_event(void **argv) { LuaRef cb = (LuaRef)(ptrdiff_t)argv[0]; @@ -765,10 +789,8 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL return true; } -/// Initialize global lua interpreter -/// -/// Crashes Nvim if initialization fails. -void nlua_init(void) +/// Initializes global Lua interpreter, or exits Nvim on failure. +void nlua_init(char **argv, int argc, int lua_arg0) { #ifdef NLUA_TRACK_REFS const char *env = os_getenv("NVIM_LUA_NOTRACK"); @@ -789,10 +811,9 @@ void nlua_init(void) } luv_set_thread_cb(nlua_thread_acquire_vm, nlua_common_free_all_mem); - global_lstate = lstate; - main_thread = uv_thread_self(); + nlua_init_argv(lstate, argv, argc, lua_arg0); } static lua_State *nlua_thread_acquire_vm(void) @@ -1686,21 +1707,49 @@ void ex_luafile(exarg_T *const eap) nlua_exec_file((const char *)eap->arg); } -/// execute lua code from a file. +/// Executes Lua code from a file or "-" (stdin). /// -/// Note: we call the lua global loadfile as opposed to calling luaL_loadfile -/// in case loadfile has been overridden in the users environment. +/// Calls the Lua `loadfile` global as opposed to `luaL_loadfile` in case `loadfile` was overridden +/// in the user environment. /// -/// @param path path of the file +/// @param path Path to the file, may be "-" (stdin) during startup. /// -/// @return true if everything ok, false if there was an error (echoed) +/// @return true on success, false on error (echoed) or user canceled (CTRL-c) while reading "-" +/// (stdin). bool nlua_exec_file(const char *path) FUNC_ATTR_NONNULL_ALL { lua_State *const lstate = global_lstate; + if (!strequal(path, "-")) { + lua_getglobal(lstate, "loadfile"); + lua_pushstring(lstate, path); + } else { + FileDescriptor *stdin_dup = file_open_stdin(); + + 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); + if (read_size < 0) { // Error. + return false; + } + kv_concat_len(sb, IObuff, (size_t)read_size); + if (read_size < 64) { // EOF. + break; + } + } + kv_push(sb, NUL); + file_free(stdin_dup, false); - lua_getglobal(lstate, "loadfile"); - lua_pushstring(lstate, path); + lua_getglobal(lstate, "loadstring"); + lua_pushstring(lstate, sb.items); + kv_destroy(sb); + } if (nlua_pcall(lstate, 1, 2)) { nlua_error(lstate, _("E5111: Error calling lua: %.*s")); |