aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/eval.c13
-rw-r--r--test/functional/eval/timer_spec.lua15
2 files changed, 28 insertions, 0 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index ac0daa226a..9a86c5765c 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -435,6 +435,7 @@ typedef struct {
TimeWatcher tw;
int timer_id;
int repeat_count;
+ long timeout;
bool stopped;
ufunc_T *callback;
} timer_T;
@@ -16639,6 +16640,9 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv)
}
if (dict_find(dict, (char_u *)"repeat", -1) != NULL) {
repeat = get_dict_number(dict, (char_u *)"repeat");
+ if (repeat == 0) {
+ repeat = 1;
+ }
}
}
@@ -16656,6 +16660,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv)
timer = xmalloc(sizeof *timer);
timer->stopped = false;
timer->repeat_count = repeat;
+ timer->timeout = timeout;
timer->timer_id = last_timer_id++;
timer->callback = func;
@@ -16710,6 +16715,14 @@ static void timer_due_cb(TimeWatcher *tw, void *data)
call_user_func(timer->callback, ARRAY_SIZE(argv), argv, &rettv,
curwin->w_cursor.lnum, curwin->w_cursor.lnum, NULL);
clear_tv(&rettv);
+
+ if (!timer->stopped && timer->timeout == 0) {
+ // special case: timeout=0 means the callback will be
+ // invoked again on the next event loop tick.
+ // we don't use uv_idle_t to not spin the event loop
+ // when the main loop is blocked.
+ time_watcher_start(&timer->tw, timer_due_cb, 0, 0);
+ }
}
static void timer_stop(timer_T *timer)
diff --git a/test/functional/eval/timer_spec.lua b/test/functional/eval/timer_spec.lua
index a31e942cdf..2f83edb9e4 100644
--- a/test/functional/eval/timer_spec.lua
+++ b/test/functional/eval/timer_spec.lua
@@ -22,6 +22,14 @@ describe('timers', function()
eq(1,eval("g:val"))
end)
+ it('works one-shot when repeat=0', function()
+ execute("call timer_start(50, 'MyHandler', {'repeat': 0})")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 200)
+ eq(1,eval("g:val"))
+ end)
+
+
it('works with repeat two', function()
execute("call timer_start(50, 'MyHandler', {'repeat': 2})")
eq(0,eval("g:val"))
@@ -37,6 +45,13 @@ describe('timers', function()
eq(2,eval("g:val"))
end)
+ it('works with zero timeout', function()
+ -- timer_start does still not invoke the callback immediately
+ eq(0,eval("[timer_start(0, 'MyHandler', {'repeat': 1000}), g:val][1]"))
+ run(nil, nil, nil, 300)
+ eq(1000,eval("g:val"))
+ end)
+
it('can be started during sleep', function()
nvim_async("command", "sleep 10")
-- this also tests that remote requests works during sleep