mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
lua: vim.wait initial outline
This commit is contained in:
parent
7d8dc4c331
commit
504d6878da
@ -28,6 +28,8 @@
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/change.h"
|
||||
#include "nvim/eval/userfunc.h"
|
||||
#include "nvim/event/time.h"
|
||||
#include "nvim/event/loop.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include "nvim/os/os.h"
|
||||
@ -255,6 +257,91 @@ static struct luaL_Reg regex_meta[] = {
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
// 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)
|
||||
{
|
||||
xfree(tw);
|
||||
}
|
||||
|
||||
static bool nlua_wait_condition(lua_State *lstate, int *status,
|
||||
bool *callback_result)
|
||||
{
|
||||
lua_pushvalue(lstate, 2);
|
||||
*status = lua_pcall(lstate, 0, 1, 0);
|
||||
if (*status) {
|
||||
return true; // break on error, but keep error on stack
|
||||
}
|
||||
*callback_result = lua_toboolean(lstate, -1);
|
||||
lua_pop(lstate, 1);
|
||||
return *callback_result; // break if true
|
||||
}
|
||||
|
||||
/// "vim.wait(timeout, condition[, interval])" function
|
||||
static int nlua_wait(lua_State *lstate)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
intptr_t timeout = luaL_checkinteger(lstate, 1);
|
||||
if (timeout < 0) {
|
||||
return luaL_error(lstate, "timeout must be > 0");
|
||||
}
|
||||
if (lua_type(lstate, 2) != LUA_TFUNCTION) {
|
||||
lua_pushliteral(lstate, "vim.wait: condition must be a function");
|
||||
return lua_error(lstate);
|
||||
}
|
||||
|
||||
intptr_t interval = 200;
|
||||
if (lua_gettop(lstate) >= 3) {
|
||||
interval = luaL_checkinteger(lstate, 3);
|
||||
if (interval < 0) {
|
||||
return luaL_error(lstate, "interval must be > 0");
|
||||
}
|
||||
}
|
||||
|
||||
TimeWatcher *tw = xmalloc(sizeof(TimeWatcher));
|
||||
|
||||
// Start dummy timer.
|
||||
time_watcher_init(&main_loop, tw, NULL);
|
||||
tw->events = main_loop.events;
|
||||
tw->blockable = true;
|
||||
time_watcher_start(tw, dummy_timer_due_cb,
|
||||
(uint64_t)interval, (uint64_t)interval);
|
||||
|
||||
int pcall_status = 0;
|
||||
bool callback_result = false;
|
||||
|
||||
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, main_loop.events, (int)timeout,
|
||||
nlua_wait_condition(lstate, &pcall_status,
|
||||
&callback_result)
|
||||
|| got_int);
|
||||
|
||||
if (pcall_status) {
|
||||
// TODO: add prefix to error?
|
||||
// handled after stopped time_watcher
|
||||
} else if (got_int) {
|
||||
got_int = false;
|
||||
vgetc();
|
||||
lua_pushinteger(lstate, -2);
|
||||
} else if (callback_result) {
|
||||
lua_pushinteger(lstate, 0);
|
||||
} else {
|
||||
lua_pushinteger(lstate, -1);
|
||||
}
|
||||
|
||||
// Stop dummy timer
|
||||
time_watcher_stop(tw);
|
||||
time_watcher_close(tw, dummy_timer_close_cb);
|
||||
|
||||
if (pcall_status) {
|
||||
return lua_error(lstate);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// Initialize lua interpreter state
|
||||
///
|
||||
/// Called by lua interpreter itself to initialize state.
|
||||
@ -305,7 +392,6 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
// regex
|
||||
lua_pushcfunction(lstate, &nlua_regex);
|
||||
lua_setfield(lstate, -2, "regex");
|
||||
|
||||
luaL_newmetatable(lstate, "nvim_regex");
|
||||
luaL_register(lstate, NULL, regex_meta);
|
||||
lua_pushvalue(lstate, -1); // [meta, meta]
|
||||
@ -320,6 +406,10 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
lua_pushcfunction(lstate, &nlua_rpcnotify);
|
||||
lua_setfield(lstate, -2, "rpcnotify");
|
||||
|
||||
// wait
|
||||
lua_pushcfunction(lstate, &nlua_wait);
|
||||
lua_setfield(lstate, -2, "wait");
|
||||
|
||||
// vim.loop
|
||||
luv_set_loop(lstate, &main_loop.uv);
|
||||
luv_set_callback(lstate, nlua_luv_cfpcall);
|
||||
|
Loading…
Reference in New Issue
Block a user