mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
feat(lua): allow some viml functions to run in fast
This change adds the necessary plumbing to annotate functions in funcs.c as being allowed in run in luv fast events.
This commit is contained in:
parent
6613f58ceb
commit
5c41165c8e
@ -1038,6 +1038,8 @@ vim.fn.{func}({...}) *vim.fn*
|
|||||||
Note: vim.fn keys are generated lazily, thus `pairs(vim.fn)` only
|
Note: vim.fn keys are generated lazily, thus `pairs(vim.fn)` only
|
||||||
enumerates functions that were called at least once.
|
enumerates functions that were called at least once.
|
||||||
|
|
||||||
|
Note: The majority of functions cannot run in |api-fast| callbacks with some
|
||||||
|
undocumented exceptions which are allowed.
|
||||||
|
|
||||||
*lua-vim-variables*
|
*lua-vim-variables*
|
||||||
The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed
|
The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
-- Defaults to BASE_NONE (function cannot be used as a method).
|
-- Defaults to BASE_NONE (function cannot be used as a method).
|
||||||
-- func Name of the C function which implements the VimL function. Defaults to
|
-- func Name of the C function which implements the VimL function. Defaults to
|
||||||
-- `f_{funcname}`.
|
-- `f_{funcname}`.
|
||||||
|
-- fast Function can run in |api-fast| events. Defaults to false.
|
||||||
|
|
||||||
local varargs = function(nr)
|
local varargs = function(nr)
|
||||||
return {nr}
|
return {nr}
|
||||||
@ -205,7 +206,7 @@ return {
|
|||||||
hlID={args=1, base=1},
|
hlID={args=1, base=1},
|
||||||
hlexists={args=1, base=1},
|
hlexists={args=1, base=1},
|
||||||
hostname={},
|
hostname={},
|
||||||
iconv={args=3, base=1},
|
iconv={args=3, base=1, fast=true},
|
||||||
indent={args=1, base=1},
|
indent={args=1, base=1},
|
||||||
index={args={2, 4}, base=1},
|
index={args={2, 4}, base=1},
|
||||||
input={args={1, 3}, base=1},
|
input={args={1, 3}, base=1},
|
||||||
|
@ -19,6 +19,7 @@ typedef struct {
|
|||||||
uint8_t min_argc; ///< Minimal number of arguments.
|
uint8_t min_argc; ///< Minimal number of arguments.
|
||||||
uint8_t max_argc; ///< Maximal number of arguments.
|
uint8_t max_argc; ///< Maximal number of arguments.
|
||||||
uint8_t base_arg; ///< Method base arg # (1-indexed), BASE_NONE or BASE_LAST.
|
uint8_t base_arg; ///< Method base arg # (1-indexed), BASE_NONE or BASE_LAST.
|
||||||
|
bool fast; ///< Can be run in |api-fast| events
|
||||||
VimLFunc func; ///< Function implementation.
|
VimLFunc func; ///< Function implementation.
|
||||||
FunPtr data; ///< Userdata for function implementation.
|
FunPtr data; ///< Userdata for function implementation.
|
||||||
} EvalFuncDef;
|
} EvalFuncDef;
|
||||||
|
@ -61,10 +61,11 @@ for _, name in ipairs(neworder) do
|
|||||||
local base = def.base or "BASE_NONE"
|
local base = def.base or "BASE_NONE"
|
||||||
local func = def.func or ('f_' .. name)
|
local func = def.func or ('f_' .. name)
|
||||||
local data = def.data or "NULL"
|
local data = def.data or "NULL"
|
||||||
hashpipe:write((' { "%s", %s, %s, %s, &%s, (FunPtr)%s },\n')
|
local fast = def.fast and 'true' or 'false'
|
||||||
:format(name, args[1], args[2], base, func, data))
|
hashpipe:write((' { "%s", %s, %s, %s, %s, &%s, (FunPtr)%s },\n')
|
||||||
|
:format(name, args[1], args[2], base, fast, func, data))
|
||||||
end
|
end
|
||||||
hashpipe:write(' { NULL, 0, 0, BASE_NONE, NULL, NULL },\n')
|
hashpipe:write(' { NULL, 0, 0, BASE_NONE, false, NULL, NULL },\n')
|
||||||
hashpipe:write("};\n\n")
|
hashpipe:write("};\n\n")
|
||||||
hashpipe:write(hashfun)
|
hashpipe:write(hashfun)
|
||||||
hashpipe:close()
|
hashpipe:close()
|
||||||
|
@ -916,12 +916,22 @@ int nlua_in_fast_event(lua_State *lstate)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool viml_func_is_fast(const char *name)
|
||||||
|
{
|
||||||
|
const EvalFuncDef *const fdef = find_internal_func((const char *)name);
|
||||||
|
if (fdef) {
|
||||||
|
return fdef->fast;
|
||||||
|
}
|
||||||
|
// Not a vimL function
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int nlua_call(lua_State *lstate)
|
int nlua_call(lua_State *lstate)
|
||||||
{
|
{
|
||||||
Error err = ERROR_INIT;
|
Error err = ERROR_INIT;
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
const char *name = luaL_checklstring(lstate, 1, &name_len);
|
const char *name = luaL_checklstring(lstate, 1, &name_len);
|
||||||
if (!nlua_is_deferred_safe()) {
|
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, "vimL function");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,6 +794,20 @@ describe('lua stdlib', function()
|
|||||||
pcall_err(exec_lua, "vim.fn.nvim_get_current_line()"))
|
pcall_err(exec_lua, "vim.fn.nvim_get_current_line()"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('vim.fn can be called in fast events (if function is allowed)', function()
|
||||||
|
exec_lua([[
|
||||||
|
local timer = vim.loop.new_timer()
|
||||||
|
timer:start(0, 0, function()
|
||||||
|
timer:close()
|
||||||
|
assert(vim.in_fast_event())
|
||||||
|
vim.g.fnres = vim.fn.iconv('hello', 'utf-8', 'utf-8')
|
||||||
|
end)
|
||||||
|
]])
|
||||||
|
|
||||||
|
helpers.poke_eventloop()
|
||||||
|
eq('hello', exec_lua[[return vim.g.fnres]])
|
||||||
|
end)
|
||||||
|
|
||||||
it('vim.rpcrequest and vim.rpcnotify', function()
|
it('vim.rpcrequest and vim.rpcnotify', function()
|
||||||
exec_lua([[
|
exec_lua([[
|
||||||
chan = vim.fn.jobstart({'cat'}, {rpc=true})
|
chan = vim.fn.jobstart({'cat'}, {rpc=true})
|
||||||
|
Loading…
Reference in New Issue
Block a user