mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
lua: docs and tests for vim.schedule
This commit is contained in:
parent
81e1dbca99
commit
b684bd05b5
@ -203,6 +203,8 @@ User reloads the buffer with ":edit", emits: >
|
|||||||
In-process lua plugins can also recieve buffer updates, in the form of lua
|
In-process lua plugins can also recieve buffer updates, in the form of lua
|
||||||
callbacks. These callbacks are called frequently in various contexts, buffer
|
callbacks. These callbacks are called frequently in various contexts, buffer
|
||||||
contents or window layout should not be changed inside these |textlock|.
|
contents or window layout should not be changed inside these |textlock|.
|
||||||
|
|lua-vim.schedule| can be used to defer these operations to the main loop,
|
||||||
|
where they are allowed.
|
||||||
|
|
||||||
|nvim_buf_attach| will take keyword args for the callbacks. "on_lines" will
|
|nvim_buf_attach| will take keyword args for the callbacks. "on_lines" will
|
||||||
receive parameters ("lines", {buf}, {changedtick}, {firstline}, {lastline}, {new_lastline}).
|
receive parameters ("lines", {buf}, {changedtick}, {firstline}, {lastline}, {new_lastline}).
|
||||||
|
@ -379,6 +379,12 @@ vim.stricmp(a, b) *lua-vim.stricmp*
|
|||||||
string arguments and returns 0, 1 or -1 if strings are equal, a is
|
string arguments and returns 0, 1 or -1 if strings are equal, a is
|
||||||
greater then b or a is lesser then b respectively.
|
greater then b or a is lesser then b respectively.
|
||||||
|
|
||||||
|
vim.schedule(callback) *lua-vim.schedule*
|
||||||
|
Schedule `callback` to be called soon by the main event loop. This is
|
||||||
|
useful in contexts where some functionality is blocked, like an
|
||||||
|
autocommand or callback running with |textlock|. Then the scheduled
|
||||||
|
callback could invoke this functionality later when it is allowed.
|
||||||
|
|
||||||
vim.type_idx *lua-vim.type_idx*
|
vim.type_idx *lua-vim.type_idx*
|
||||||
Type index for use in |lua-special-tbl|. Specifying one of the
|
Type index for use in |lua-special-tbl|. Specifying one of the
|
||||||
values from |lua-vim.types| allows typing the empty table (it is
|
values from |lua-vim.types| allows typing the empty table (it is
|
||||||
|
@ -36,12 +36,6 @@ typedef struct {
|
|||||||
String lua_err_str;
|
String lua_err_str;
|
||||||
} LuaError;
|
} LuaError;
|
||||||
|
|
||||||
/// We use this to store Lua callbacks
|
|
||||||
typedef struct {
|
|
||||||
// TODO: store more info for debugging, traceback?
|
|
||||||
int cb;
|
|
||||||
} nlua_ctx;
|
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "lua/vim_module.generated.h"
|
# include "lua/vim_module.generated.h"
|
||||||
# include "lua/executor.c.generated.h"
|
# include "lua/executor.c.generated.h"
|
||||||
@ -114,33 +108,32 @@ static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nlua_schedule_cb(void **argv)
|
static void nlua_schedule_event(void **argv)
|
||||||
{
|
{
|
||||||
nlua_ctx *ctx = argv[0];
|
LuaRef cb = (LuaRef)(ptrdiff_t)argv[0];
|
||||||
lua_State *const lstate = nlua_enter();
|
lua_State *const lstate = nlua_enter();
|
||||||
lua_rawgeti(lstate, LUA_REGISTRYINDEX, ctx->cb);
|
nlua_pushref(lstate, cb);
|
||||||
luaL_unref(lstate, LUA_REGISTRYINDEX, ctx->cb);
|
nlua_unref(lstate, cb);
|
||||||
lua_pcall(lstate, 0, 0, 0);
|
if (lua_pcall(lstate, 0, 0, 0)) {
|
||||||
free(ctx);
|
nlua_error(lstate, _("Error executing vim.schedule lua callback: %.*s"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Schedule Lua callback on main loop's event queue
|
/// Schedule Lua callback on main loop's event queue
|
||||||
///
|
///
|
||||||
/// This is used to make sure nvim API is called at the right moment.
|
|
||||||
///
|
|
||||||
/// @param lstate Lua interpreter state.
|
/// @param lstate Lua interpreter state.
|
||||||
/// @param[in] msg Message base, must contain one `%s`.
|
|
||||||
static int nlua_schedule(lua_State *const lstate)
|
static int nlua_schedule(lua_State *const lstate)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
// TODO: report error using nlua_error instead
|
if (lua_type(lstate, 1) != LUA_TFUNCTION) {
|
||||||
luaL_checktype(lstate, 1, LUA_TFUNCTION);
|
lua_pushliteral(lstate, "vim.schedule: expected function");
|
||||||
|
return lua_error(lstate);
|
||||||
|
}
|
||||||
|
|
||||||
nlua_ctx* ctx = (nlua_ctx*)malloc(sizeof(nlua_ctx));
|
LuaRef cb = nlua_ref(lstate, 1);
|
||||||
lua_pushvalue(lstate, 1);
|
|
||||||
ctx->cb = luaL_ref(lstate, LUA_REGISTRYINDEX);
|
|
||||||
|
|
||||||
multiqueue_put(main_loop.events, nlua_schedule_cb, 1, ctx);
|
multiqueue_put(main_loop.events, nlua_schedule_event,
|
||||||
|
1, (void *)(ptrdiff_t)cb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,10 +5,13 @@ local funcs = helpers.funcs
|
|||||||
local meths = helpers.meths
|
local meths = helpers.meths
|
||||||
local clear = helpers.clear
|
local clear = helpers.clear
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
|
local eval = helpers.eval
|
||||||
|
local feed = helpers.feed
|
||||||
|
local meth_pcall = helpers.meth_pcall
|
||||||
|
|
||||||
before_each(clear)
|
before_each(clear)
|
||||||
|
|
||||||
describe('vim.stricmp', function()
|
describe('lua function', function()
|
||||||
-- İ: `tolower("İ")` is `i` which has length 1 while `İ` itself has
|
-- İ: `tolower("İ")` is `i` which has length 1 while `İ` itself has
|
||||||
-- length 2 (in bytes).
|
-- length 2 (in bytes).
|
||||||
-- Ⱥ: `tolower("Ⱥ")` is `ⱥ` which has length 2 while `Ⱥ` itself has
|
-- Ⱥ: `tolower("Ⱥ")` is `ⱥ` which has length 2 while `Ⱥ` itself has
|
||||||
@ -17,7 +20,7 @@ describe('vim.stricmp', function()
|
|||||||
-- Note: 'i' !=? 'İ' and 'ⱥ' !=? 'Ⱥ' on some systems.
|
-- Note: 'i' !=? 'İ' and 'ⱥ' !=? 'Ⱥ' on some systems.
|
||||||
-- Note: Built-in Nvim comparison (on systems lacking `strcasecmp`) works
|
-- Note: Built-in Nvim comparison (on systems lacking `strcasecmp`) works
|
||||||
-- only on ASCII characters.
|
-- only on ASCII characters.
|
||||||
it('works', function()
|
it('vim.stricmp', function()
|
||||||
eq(0, funcs.luaeval('vim.stricmp("a", "A")'))
|
eq(0, funcs.luaeval('vim.stricmp("a", "A")'))
|
||||||
eq(0, funcs.luaeval('vim.stricmp("A", "a")'))
|
eq(0, funcs.luaeval('vim.stricmp("A", "a")'))
|
||||||
eq(0, funcs.luaeval('vim.stricmp("a", "a")'))
|
eq(0, funcs.luaeval('vim.stricmp("a", "a")'))
|
||||||
@ -106,10 +109,35 @@ describe('vim.stricmp', function()
|
|||||||
eq(1, funcs.luaeval('vim.stricmp("\\0c\\0", "\\0b\\0")'))
|
eq(1, funcs.luaeval('vim.stricmp("\\0c\\0", "\\0b\\0")'))
|
||||||
eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")'))
|
eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")'))
|
||||||
end)
|
end)
|
||||||
end)
|
|
||||||
|
|
||||||
describe("vim.split", function()
|
it("vim.schedule", function()
|
||||||
it("works", function()
|
meths.execute_lua([[
|
||||||
|
test_table = {}
|
||||||
|
vim.schedule(function()
|
||||||
|
table.insert(test_table, "xx")
|
||||||
|
end)
|
||||||
|
table.insert(test_table, "yy")
|
||||||
|
]], {})
|
||||||
|
eq({"yy","xx"}, meths.execute_lua("return test_table", {}))
|
||||||
|
|
||||||
|
-- type checked args
|
||||||
|
eq({false, 'Error executing lua: vim.schedule: expected function'},
|
||||||
|
meth_pcall(meths.execute_lua, "vim.schedule('stringly')", {}))
|
||||||
|
|
||||||
|
eq({false, 'Error executing lua: vim.schedule: expected function'},
|
||||||
|
meth_pcall(meths.execute_lua, "vim.schedule()", {}))
|
||||||
|
|
||||||
|
meths.execute_lua([[
|
||||||
|
vim.schedule(function()
|
||||||
|
error("big failure\nvery async")
|
||||||
|
end)
|
||||||
|
]], {})
|
||||||
|
|
||||||
|
feed("<cr>")
|
||||||
|
eq('Error executing vim.schedule lua callback: [string "<nvim>"]:2: big failure\nvery async', eval("v:errmsg"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("vim.split", function()
|
||||||
local split = function(str, sep)
|
local split = function(str, sep)
|
||||||
return meths.execute_lua('return vim.split(...)', {str, sep})
|
return meths.execute_lua('return vim.split(...)', {str, sep})
|
||||||
end
|
end
|
||||||
@ -141,10 +169,8 @@ describe("vim.split", function()
|
|||||||
assert(string.match(err, "Infinite loop detected"))
|
assert(string.match(err, "Infinite loop detected"))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end)
|
|
||||||
|
|
||||||
describe("vim.trim", function()
|
it('vim.trim', function()
|
||||||
it('works', function()
|
|
||||||
local trim = function(s)
|
local trim = function(s)
|
||||||
return meths.execute_lua('return vim.trim(...)', { s })
|
return meths.execute_lua('return vim.trim(...)', { s })
|
||||||
end
|
end
|
||||||
@ -164,10 +190,8 @@ describe("vim.trim", function()
|
|||||||
eq(false, status)
|
eq(false, status)
|
||||||
assert(string.match(err, "Only strings can be trimmed"))
|
assert(string.match(err, "Only strings can be trimmed"))
|
||||||
end)
|
end)
|
||||||
end)
|
|
||||||
|
|
||||||
describe("vim.inspect", function()
|
it('vim.inspect', function()
|
||||||
it('works', function()
|
|
||||||
-- just make sure it basically works, it has its own test suite
|
-- just make sure it basically works, it has its own test suite
|
||||||
local inspect = function(t, opts)
|
local inspect = function(t, opts)
|
||||||
return meths.execute_lua('return vim.inspect(...)', { t, opts })
|
return meths.execute_lua('return vim.inspect(...)', { t, opts })
|
||||||
@ -187,10 +211,8 @@ describe("vim.inspect", function()
|
|||||||
end})
|
end})
|
||||||
]], {}))
|
]], {}))
|
||||||
end)
|
end)
|
||||||
end)
|
|
||||||
|
|
||||||
describe("vim.deepcopy", function()
|
it("vim.deepcopy", function()
|
||||||
it("works", function()
|
|
||||||
local is_dc = meths.execute_lua([[
|
local is_dc = meths.execute_lua([[
|
||||||
local a = { x = { 1, 2 }, y = 5}
|
local a = { x = { 1, 2 }, y = 5}
|
||||||
local b = vim.deepcopy(a)
|
local b = vim.deepcopy(a)
|
||||||
|
Loading…
Reference in New Issue
Block a user