diff options
-rw-r--r-- | src/nvim/eval.c | 13 | ||||
-rw-r--r-- | test/functional/eval/timer_spec.lua | 15 |
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 |