Skip to content
Permalink
Browse files

eval: wait(): always spin up dummy-timer #10990

This avoids getting "stuck".  If user actually _wants_ to get stuck
forever, they could use `:sleep` or specify a really big `interval`.
  • Loading branch information...
justinmk committed Sep 11, 2019
1 parent c8223e1 commit 7652904f79f6e434568e0b8e5946cfcafc9aa767
Showing with 32 additions and 44 deletions.
  1. +14 −17 runtime/doc/eval.txt
  2. +16 −25 src/nvim/eval.c
  3. +2 −2 test/functional/eval/wait_spec.lua
@@ -8920,23 +8920,20 @@ visualmode([expr]) *visualmode()*
the old value is returned. See |non-zero-arg|.

wait({timeout}, {condition}[, {interval}]) *wait()*
Wait until {condition} is satisfied, where {condition} is a
|Funcref| or a |string| containing an expression.

{timeout} is the maximum number of milliseconds to wait,
-1 means forever.

By default, the condition is evaluated on user and internal
events. If {interval} is given, the condition is evaluated
every {interval} milliseconds in addition. This can be useful
to guarantee that the function returns when the condition is
satisfied even if the editor is idle.

Returns one of the following:
* 0 if the condition was satisfied before the timeout
* -1 if the timeout was exceeded
* -2 if the function was interrupted
* -3 if an error occurred
Waits until {condition} evaluates to |TRUE|, where {condition}
is a |Funcref| or |string| containing an expression.

{timeout} is the maximum waiting time in milliseconds, -1
means forever.

Condition is evaluated on user events, internal events, and
every {interval} milliseconds (default: 200).

Returns a status integer:
0 if the condition was satisfied before timeout
-1 if the timeout was exceeded
-2 if the function was interrupted (by |CTRL-C|)
-3 if an error occurred

wildmenumode() *wildmenumode()*
Returns |TRUE| when the wildmenu is active and |FALSE|
@@ -10910,31 +10910,24 @@ static void f_wait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
EMSG2(_(e_invargval), "1");
return;
}
if ((argvars[2].v_type != VAR_NUMBER && argvars[2].v_type != VAR_UNKNOWN)
|| (argvars[2].v_type == VAR_NUMBER && argvars[2].vval.v_number <= 0)) {
EMSG2(_(e_invargval), "3");
return;
}

int timeout = argvars[0].vval.v_number;
typval_T expr = argvars[1];
int interval = argvars[2].v_type == VAR_NUMBER
? argvars[2].vval.v_number
: 200; // Default.
TimeWatcher *tw = xmalloc(sizeof(TimeWatcher));

int interval = -1;
typval_T *tv_interval = &argvars[2];

TimeWatcher *tw = NULL;

if (tv_interval->v_type == VAR_NUMBER) {
interval = tv_interval->vval.v_number;
if (interval <= 0) {
EMSG2(_(e_invargval), "3");
return;
}
// Start dummy timer
tw = xmalloc(sizeof(TimeWatcher));
time_watcher_init(&main_loop, tw, NULL);
tw->events = main_loop.events;
tw->blockable = true;
time_watcher_start(tw, dummy_timer_due_cb, interval, interval);
} else if (tv_interval->v_type != VAR_UNKNOWN) {
EMSG2(_(e_invargval), "3");
return;
}
// 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, interval, interval);

typval_T argv = TV_INITIAL_VALUE;
typval_T exprval = TV_INITIAL_VALUE;
@@ -10960,10 +10953,8 @@ static void f_wait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
called_emsg = save_called_emsg;

// Stop dummy timer
if (tw) {
time_watcher_stop(tw);
time_watcher_close(tw, dummy_timer_close_cb);
}
time_watcher_stop(tw);
time_watcher_close(tw, dummy_timer_close_cb);
}

// "win_screenpos()" function
@@ -59,10 +59,10 @@ describe('wait()', function()
]])

nvim('set_var', 'counter', 0)
eq(-1, call('wait', 20, 'Count() >= 5'))
eq(-1, call('wait', 20, 'Count() >= 5', 99999))

nvim('set_var', 'counter', 0)
eq(0, call('wait', 1000, 'Count() >= 5', 5))
eq(0, call('wait', 10000, 'Count() >= 5', 5))
eq(5, nvim('get_var', 'counter'))
end)

0 comments on commit 7652904

Please sign in to comment.
You can’t perform that action at this time.