mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
feat(lua): low-level interpreter mode (nvim -ll)
This commit is contained in:
@@ -239,6 +239,14 @@ argument.
|
|||||||
Disables |shada| unless |-i| was given.
|
Disables |shada| unless |-i| was given.
|
||||||
Disables swapfile (like |-n|).
|
Disables swapfile (like |-n|).
|
||||||
|
|
||||||
|
*-ll*
|
||||||
|
-ll {script} [args]
|
||||||
|
Execute a lua script, similarly to |-l|, but the editor is not
|
||||||
|
initialized. This gives a lua enviroment similar to a worker
|
||||||
|
thread. See |lua-loop-threading|.
|
||||||
|
|
||||||
|
Unlike `-l` no prior arguments are allowed.
|
||||||
|
|
||||||
*-b*
|
*-b*
|
||||||
-b Binary mode. File I/O will only recognize <NL> to separate
|
-b Binary mode. File I/O will only recognize <NL> to separate
|
||||||
lines. The 'expandtab' option will be reset. The 'textwidth'
|
lines. The 'expandtab' option will be reset. The 'textwidth'
|
||||||
|
@@ -42,8 +42,11 @@ function vim._load_package(name)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- TODO(bfredl): dedicated state for this?
|
||||||
|
if vim.api then
|
||||||
-- Insert vim._load_package after the preloader at position 2
|
-- Insert vim._load_package after the preloader at position 2
|
||||||
table.insert(package.loaders, 2, vim._load_package)
|
table.insert(package.loaders, 2, vim._load_package)
|
||||||
|
end
|
||||||
|
|
||||||
-- builtin functions which always should be available
|
-- builtin functions which always should be available
|
||||||
require('vim.shared')
|
require('vim.shared')
|
||||||
@@ -78,6 +81,6 @@ function vim.empty_dict()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- only on main thread: functions for interacting with editor state
|
-- only on main thread: functions for interacting with editor state
|
||||||
if not vim.is_thread() then
|
if vim.api and not vim.is_thread() then
|
||||||
require('vim._editor')
|
require('vim._editor')
|
||||||
end
|
end
|
||||||
|
@@ -64,6 +64,7 @@
|
|||||||
#include "nvim/window.h"
|
#include "nvim/window.h"
|
||||||
|
|
||||||
static int in_fast_callback = 0;
|
static int in_fast_callback = 0;
|
||||||
|
static bool in_script = false;
|
||||||
|
|
||||||
// Initialized in nlua_init().
|
// Initialized in nlua_init().
|
||||||
static lua_State *global_lstate = NULL;
|
static lua_State *global_lstate = NULL;
|
||||||
@@ -133,8 +134,13 @@ static void nlua_error(lua_State *const lstate, const char *const msg)
|
|||||||
str = lua_tolstring(lstate, -1, &len);
|
str = lua_tolstring(lstate, -1, &len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (in_script) {
|
||||||
|
os_errmsg(str);
|
||||||
|
os_errmsg("\n");
|
||||||
|
} else {
|
||||||
msg_ext_set_kind("lua_error");
|
msg_ext_set_kind("lua_error");
|
||||||
semsg_multiline(msg, (int)len, str);
|
semsg_multiline(msg, (int)len, str);
|
||||||
|
}
|
||||||
|
|
||||||
lua_pop(lstate, 1);
|
lua_pop(lstate, 1);
|
||||||
}
|
}
|
||||||
@@ -534,7 +540,7 @@ int nlua_get_global_ref_count(void)
|
|||||||
return nlua_global_refs->ref_count;
|
return nlua_global_refs->ref_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nlua_common_vim_init(lua_State *lstate, bool is_thread)
|
static void nlua_common_vim_init(lua_State *lstate, bool is_thread, bool is_standalone)
|
||||||
FUNC_ATTR_NONNULL_ARG(1)
|
FUNC_ATTR_NONNULL_ARG(1)
|
||||||
{
|
{
|
||||||
nlua_ref_state_t *ref_state = nlua_new_ref_state(lstate, is_thread);
|
nlua_ref_state_t *ref_state = nlua_new_ref_state(lstate, is_thread);
|
||||||
@@ -567,7 +573,9 @@ static void nlua_common_vim_init(lua_State *lstate, bool is_thread)
|
|||||||
lua_setfield(lstate, -2, "_empty_dict_mt");
|
lua_setfield(lstate, -2, "_empty_dict_mt");
|
||||||
|
|
||||||
// vim.loop
|
// vim.loop
|
||||||
if (is_thread) {
|
if (is_standalone) {
|
||||||
|
// do nothing, use libluv like in a standalone interpreter
|
||||||
|
} else if (is_thread) {
|
||||||
luv_set_callback(lstate, nlua_luv_thread_cb_cfpcall);
|
luv_set_callback(lstate, nlua_luv_thread_cb_cfpcall);
|
||||||
luv_set_thread(lstate, nlua_luv_thread_cfpcall);
|
luv_set_thread(lstate, nlua_luv_thread_cfpcall);
|
||||||
luv_set_cthread(lstate, nlua_luv_thread_cfcpcall);
|
luv_set_cthread(lstate, nlua_luv_thread_cfcpcall);
|
||||||
@@ -606,7 +614,7 @@ static int nlua_module_preloader(lua_State *lstate)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool nlua_init_packages(lua_State *lstate)
|
static bool nlua_init_packages(lua_State *lstate, bool is_standalone)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
// put builtin packages in preload
|
// put builtin packages in preload
|
||||||
@@ -618,7 +626,7 @@ static bool nlua_init_packages(lua_State *lstate)
|
|||||||
lua_pushcclosure(lstate, nlua_module_preloader, 1); // [package, preload, cclosure]
|
lua_pushcclosure(lstate, nlua_module_preloader, 1); // [package, preload, cclosure]
|
||||||
lua_setfield(lstate, -2, def.name); // [package, preload]
|
lua_setfield(lstate, -2, def.name); // [package, preload]
|
||||||
|
|
||||||
if (nlua_disable_preload && strequal(def.name, "vim.inspect")) {
|
if ((nlua_disable_preload && !is_standalone) && strequal(def.name, "vim.inspect")) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -769,7 +777,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
|||||||
lua_pushcfunction(lstate, &nlua_ui_detach);
|
lua_pushcfunction(lstate, &nlua_ui_detach);
|
||||||
lua_setfield(lstate, -2, "ui_detach");
|
lua_setfield(lstate, -2, "ui_detach");
|
||||||
|
|
||||||
nlua_common_vim_init(lstate, false);
|
nlua_common_vim_init(lstate, false, false);
|
||||||
|
|
||||||
// patch require() (only for --startuptime)
|
// patch require() (only for --startuptime)
|
||||||
if (time_fd != NULL) {
|
if (time_fd != NULL) {
|
||||||
@@ -788,7 +796,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
|||||||
|
|
||||||
lua_setglobal(lstate, "vim");
|
lua_setglobal(lstate, "vim");
|
||||||
|
|
||||||
if (!nlua_init_packages(lstate)) {
|
if (!nlua_init_packages(lstate, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -823,10 +831,29 @@ void nlua_init(char **argv, int argc, int lua_arg0)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static lua_State *nlua_thread_acquire_vm(void)
|
static lua_State *nlua_thread_acquire_vm(void)
|
||||||
|
{
|
||||||
|
return nlua_init_state(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nlua_run_script(char **argv, int argc, int lua_arg0)
|
||||||
|
FUNC_ATTR_NORETURN
|
||||||
|
{
|
||||||
|
in_script = true;
|
||||||
|
global_lstate = nlua_init_state(false);
|
||||||
|
luv_set_thread_cb(nlua_thread_acquire_vm, nlua_common_free_all_mem);
|
||||||
|
nlua_init_argv(global_lstate, argv, argc, lua_arg0);
|
||||||
|
bool lua_ok = nlua_exec_file(argv[lua_arg0 - 1]);
|
||||||
|
#ifdef EXITFREE
|
||||||
|
nlua_free_all_mem();
|
||||||
|
#endif
|
||||||
|
exit(lua_ok ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_State *nlua_init_state(bool thread)
|
||||||
{
|
{
|
||||||
// If it is called from the main thread, it will attempt to rebuild the cache.
|
// If it is called from the main thread, it will attempt to rebuild the cache.
|
||||||
const uv_thread_t self = uv_thread_self();
|
const uv_thread_t self = uv_thread_self();
|
||||||
if (uv_thread_equal(&main_thread, &self)) {
|
if (!in_script && uv_thread_equal(&main_thread, &self)) {
|
||||||
runtime_search_path_validate();
|
runtime_search_path_validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -835,9 +862,11 @@ static lua_State *nlua_thread_acquire_vm(void)
|
|||||||
// Add in the lua standard libraries
|
// Add in the lua standard libraries
|
||||||
luaL_openlibs(lstate);
|
luaL_openlibs(lstate);
|
||||||
|
|
||||||
|
if (!in_script) {
|
||||||
// print
|
// print
|
||||||
lua_pushcfunction(lstate, &nlua_print);
|
lua_pushcfunction(lstate, &nlua_print);
|
||||||
lua_setglobal(lstate, "print");
|
lua_setglobal(lstate, "print");
|
||||||
|
}
|
||||||
|
|
||||||
lua_pushinteger(lstate, 0);
|
lua_pushinteger(lstate, 0);
|
||||||
lua_setfield(lstate, LUA_REGISTRYINDEX, "nlua.refcount");
|
lua_setfield(lstate, LUA_REGISTRYINDEX, "nlua.refcount");
|
||||||
@@ -845,18 +874,20 @@ static lua_State *nlua_thread_acquire_vm(void)
|
|||||||
// vim
|
// vim
|
||||||
lua_newtable(lstate);
|
lua_newtable(lstate);
|
||||||
|
|
||||||
nlua_common_vim_init(lstate, true);
|
nlua_common_vim_init(lstate, thread, in_script);
|
||||||
|
|
||||||
nlua_state_add_stdlib(lstate, true);
|
nlua_state_add_stdlib(lstate, true);
|
||||||
|
|
||||||
|
if (!in_script) {
|
||||||
lua_createtable(lstate, 0, 0);
|
lua_createtable(lstate, 0, 0);
|
||||||
lua_pushcfunction(lstate, nlua_thr_api_nvim__get_runtime);
|
lua_pushcfunction(lstate, nlua_thr_api_nvim__get_runtime);
|
||||||
lua_setfield(lstate, -2, "nvim__get_runtime");
|
lua_setfield(lstate, -2, "nvim__get_runtime");
|
||||||
lua_setfield(lstate, -2, "api");
|
lua_setfield(lstate, -2, "api");
|
||||||
|
}
|
||||||
|
|
||||||
lua_setglobal(lstate, "vim");
|
lua_setglobal(lstate, "vim");
|
||||||
|
|
||||||
nlua_init_packages(lstate);
|
nlua_init_packages(lstate, in_script);
|
||||||
|
|
||||||
lua_getglobal(lstate, "package");
|
lua_getglobal(lstate, "package");
|
||||||
lua_getfield(lstate, -1, "loaded");
|
lua_getfield(lstate, -1, "loaded");
|
||||||
|
@@ -239,6 +239,14 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
argv0 = argv[0];
|
argv0 = argv[0];
|
||||||
|
|
||||||
|
if (argc > 1 && STRICMP(argv[1], "-ll") == 0) {
|
||||||
|
if (argc == 2) {
|
||||||
|
print_mainerr(err_arg_missing, argv[1]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
nlua_run_script(argv, argc, 3);
|
||||||
|
}
|
||||||
|
|
||||||
char *fname = NULL; // file name from command line
|
char *fname = NULL; // file name from command line
|
||||||
mparm_T params; // various parameters passed between
|
mparm_T params; // various parameters passed between
|
||||||
// main() and other functions.
|
// main() and other functions.
|
||||||
@@ -2110,6 +2118,12 @@ static int execute_env(char *env)
|
|||||||
/// @param str string to append to the primary error message, or NULL
|
/// @param str string to append to the primary error message, or NULL
|
||||||
static void mainerr(const char *errstr, const char *str)
|
static void mainerr(const char *errstr, const char *str)
|
||||||
FUNC_ATTR_NORETURN
|
FUNC_ATTR_NORETURN
|
||||||
|
{
|
||||||
|
print_mainerr(errstr, str);
|
||||||
|
os_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_mainerr(const char *errstr, const char *str)
|
||||||
{
|
{
|
||||||
char *prgname = path_tail(argv0);
|
char *prgname = path_tail(argv0);
|
||||||
|
|
||||||
@@ -2126,8 +2140,6 @@ static void mainerr(const char *errstr, const char *str)
|
|||||||
os_errmsg(_("\nMore info with \""));
|
os_errmsg(_("\nMore info with \""));
|
||||||
os_errmsg(prgname);
|
os_errmsg(prgname);
|
||||||
os_errmsg(" -h\"\n");
|
os_errmsg(" -h\"\n");
|
||||||
|
|
||||||
os_exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prints version information for "nvim -v" or "nvim --version".
|
/// Prints version information for "nvim -v" or "nvim --version".
|
||||||
|
Reference in New Issue
Block a user