mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:7.4.2180
Problem: There is no easy way to stop all timers. There is no way to
temporary pause a timer.
Solution: Add timer_stopall() and timer_pause().
b73598e2f0
This commit is contained in:
parent
8924e75f34
commit
5b8ce2feed
@ -2298,9 +2298,11 @@ tanh({expr}) Float hyperbolic tangent of {expr}
|
||||
tempname() String name for a temporary file
|
||||
test_garbagecollect_now() none free memory right now for testing
|
||||
timer_info([{id}]) List information about timers
|
||||
timer_pause({id}, {pause}) none pause or unpause a timer
|
||||
timer_start({time}, {callback} [, {options}])
|
||||
Number create a timer
|
||||
timer_stop({timer}) none stop a timer
|
||||
timer_stopall() none stop all timers
|
||||
tolower({expr}) String the String {expr} switched to lowercase
|
||||
toupper({expr}) String the String {expr} switched to uppercase
|
||||
tr({src}, {fromstr}, {tostr}) String translate chars of {src} in {fromstr}
|
||||
@ -7534,6 +7536,19 @@ timer_info([{id}])
|
||||
-1 means forever
|
||||
"callback" the callback
|
||||
|
||||
timer_pause({timer}, {paused}) *timer_pause()*
|
||||
Pause or unpause a timer. A paused timer does not invoke its
|
||||
callback, while the time it would is not changed. Unpausing a
|
||||
timer may cause the callback to be invoked almost immediately
|
||||
if enough time has passed.
|
||||
|
||||
Pausing a timer is useful to avoid the callback to be called
|
||||
for a short time.
|
||||
|
||||
If {paused} evaluates to a non-zero Number or a non-empty
|
||||
String, then the timer is paused, otherwise it is unpaused.
|
||||
See |non-zero-arg|.
|
||||
|
||||
*timer_start()*
|
||||
timer_start({time}, {callback} [, {options}])
|
||||
Create a timer and return the timer ID.
|
||||
@ -7565,6 +7580,11 @@ timer_stop({timer}) *timer_stop()*
|
||||
{timer} is an ID returned by timer_start(), thus it must be a
|
||||
Number. If {timer} does not exist there is no error.
|
||||
|
||||
timer_stopall() *timer_stopall()*
|
||||
Stop all timers. The timer callbacks will no longer be
|
||||
invoked. Useful if some timers is misbehaving. If there are
|
||||
no timers there is no error.
|
||||
|
||||
tolower({expr}) *tolower()*
|
||||
The result is a copy of the String given, with all uppercase
|
||||
characters turned into lowercase (just like applying |gu| to
|
||||
|
@ -446,6 +446,7 @@ typedef struct {
|
||||
int refcount;
|
||||
long timeout;
|
||||
bool stopped;
|
||||
bool paused;
|
||||
Callback callback;
|
||||
} timer_T;
|
||||
|
||||
@ -17939,6 +17940,7 @@ static void add_timer_info(typval_T *rettv, timer_T *timer)
|
||||
list_append_dict(list, dict);
|
||||
dict_add_nr_str(dict, "id", (long)timer->timer_id, NULL);
|
||||
dict_add_nr_str(dict, "time", timer->timeout, NULL);
|
||||
dict_add_nr_str(dict, "paused", (long)timer->paused, NULL);
|
||||
|
||||
dict_add_nr_str(dict, "repeat",
|
||||
(long)(timer->repeat_count < 0 ? -1 : timer->repeat_count),
|
||||
@ -17965,7 +17967,9 @@ static void add_timer_info_all(typval_T *rettv)
|
||||
{
|
||||
timer_T *timer;
|
||||
map_foreach_value(timers, timer, {
|
||||
if (!timer->stopped) {
|
||||
add_timer_info(rettv, timer);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -17978,7 +17982,7 @@ static void f_timer_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
EMSG(_(e_number_exp));
|
||||
} else {
|
||||
timer_T *timer = pmap_get(uint64_t)(timers, get_tv_number(&argvars[0]));
|
||||
if (timer != NULL) {
|
||||
if (timer != NULL && !timer->stopped) {
|
||||
add_timer_info(rettv, timer);
|
||||
}
|
||||
}
|
||||
@ -17987,6 +17991,20 @@ static void f_timer_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// "timer_pause(timer, paused)" function
|
||||
static void f_timer_pause(typval_T *argvars, typval_T *unused, FunPtr fptr)
|
||||
{
|
||||
if (argvars[0].v_type != VAR_NUMBER) {
|
||||
EMSG(_(e_number_exp));
|
||||
} else {
|
||||
int paused = (bool)get_tv_number(&argvars[1]);
|
||||
timer_T *timer = pmap_get(uint64_t)(timers, get_tv_number(&argvars[0]));
|
||||
if (timer != NULL) {
|
||||
timer->paused = paused;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// "timer_start(timeout, callback, opts)" function
|
||||
static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
@ -18019,6 +18037,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
timer = xmalloc(sizeof *timer);
|
||||
timer->refcount = 1;
|
||||
timer->stopped = false;
|
||||
timer->paused = false;
|
||||
timer->repeat_count = repeat;
|
||||
timer->timeout = timeout;
|
||||
timer->timer_id = last_timer_id++;
|
||||
@ -18028,8 +18047,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
timer->tw.events = multiqueue_new_child(main_loop.events);
|
||||
// if main loop is blocked, don't queue up multiple events
|
||||
timer->tw.blockable = true;
|
||||
time_watcher_start(&timer->tw, timer_due_cb, timeout,
|
||||
timeout * (repeat != 1));
|
||||
time_watcher_start(&timer->tw, timer_due_cb, timeout, timeout);
|
||||
|
||||
pmap_put(uint64_t)(timers, timer->timer_id, timer);
|
||||
rettv->vval.v_number = timer->timer_id;
|
||||
@ -18053,13 +18071,19 @@ static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
timer_stop(timer);
|
||||
}
|
||||
|
||||
static void f_timer_stopall(typval_T *argvars, typval_T *unused, FunPtr fptr)
|
||||
{
|
||||
timer_teardown();
|
||||
}
|
||||
|
||||
// invoked on the main loop
|
||||
static void timer_due_cb(TimeWatcher *tw, void *data)
|
||||
{
|
||||
timer_T *timer = (timer_T *)data;
|
||||
if (timer->stopped) {
|
||||
if (timer->stopped || timer->paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
timer->refcount++;
|
||||
// if repeat was negative repeat forever
|
||||
if (timer->repeat_count >= 0 && --timer->repeat_count == 0) {
|
||||
|
@ -307,8 +307,10 @@ return {
|
||||
termopen={args={1, 2}},
|
||||
test_garbagecollect_now={},
|
||||
timer_info={args={0,1}},
|
||||
timer_pause={args=2},
|
||||
timer_start={args={2,3}},
|
||||
timer_stop={args=1},
|
||||
timer_stopall={args=0},
|
||||
tolower={args=1},
|
||||
toupper={args=1},
|
||||
tr={args=3},
|
||||
|
17
src/nvim/testdir/shared.vim
Normal file
17
src/nvim/testdir/shared.vim
Normal file
@ -0,0 +1,17 @@
|
||||
" Functions shared by several tests.
|
||||
|
||||
" Wait for up to a second for "expr" to become true.
|
||||
" Return time slept in milliseconds.
|
||||
func WaitFor(expr)
|
||||
let slept = 0
|
||||
for i in range(100)
|
||||
try
|
||||
if eval(a:expr)
|
||||
return slept
|
||||
endif
|
||||
catch
|
||||
endtry
|
||||
let slept += 10
|
||||
sleep 10m
|
||||
endfor
|
||||
endfunc
|
@ -4,8 +4,10 @@ if !has('timers')
|
||||
finish
|
||||
endif
|
||||
|
||||
source shared.vim
|
||||
|
||||
func MyHandler(timer)
|
||||
let s:val += 1
|
||||
let g:val += 1
|
||||
endfunc
|
||||
|
||||
func MyHandlerWithLists(lists, timer)
|
||||
@ -13,44 +15,98 @@ func MyHandlerWithLists(lists, timer)
|
||||
endfunc
|
||||
|
||||
func Test_oneshot()
|
||||
let s:val = 0
|
||||
let g:val = 0
|
||||
let timer = timer_start(50, 'MyHandler')
|
||||
sleep 200m
|
||||
call assert_equal(1, s:val)
|
||||
let slept = WaitFor('g:val == 1')
|
||||
call assert_equal(1, g:val)
|
||||
call assert_inrange(30, 100, slept)
|
||||
endfunc
|
||||
|
||||
func Test_repeat_three()
|
||||
let s:val = 0
|
||||
let g:val = 0
|
||||
let timer = timer_start(50, 'MyHandler', {'repeat': 3})
|
||||
sleep 500m
|
||||
call assert_equal(3, s:val)
|
||||
let slept = WaitFor('g:val == 3')
|
||||
call assert_equal(3, g:val)
|
||||
call assert_inrange(100, 250, slept)
|
||||
endfunc
|
||||
|
||||
func Test_repeat_many()
|
||||
let s:val = 0
|
||||
let g:val = 0
|
||||
let timer = timer_start(50, 'MyHandler', {'repeat': -1})
|
||||
sleep 200m
|
||||
call timer_stop(timer)
|
||||
call assert_true(s:val > 1)
|
||||
call assert_true(s:val < 5)
|
||||
call assert_inrange(2, 4, g:val)
|
||||
endfunc
|
||||
|
||||
func Test_with_partial_callback()
|
||||
let s:val = 0
|
||||
let g:val = 0
|
||||
let s:meow = {}
|
||||
function s:meow.bite(...)
|
||||
let s:val += 1
|
||||
let g:val += 1
|
||||
endfunction
|
||||
|
||||
call timer_start(50, s:meow.bite)
|
||||
sleep 200m
|
||||
call assert_equal(1, s:val)
|
||||
let slept = WaitFor('g:val == 1')
|
||||
call assert_equal(1, g:val)
|
||||
call assert_inrange(30, 100, slept)
|
||||
endfunc
|
||||
|
||||
func Test_retain_partial()
|
||||
call timer_start(100, function('MyHandlerWithLists', [['a']]))
|
||||
call timer_start(50, function('MyHandlerWithLists', [['a']]))
|
||||
call garbagecollect()
|
||||
sleep 100m
|
||||
endfunc
|
||||
|
||||
func Test_info()
|
||||
let id = timer_start(1000, 'MyHandler')
|
||||
let info = timer_info(id)
|
||||
call assert_equal(id, info[0]['id'])
|
||||
call assert_equal(1000, info[0]['time'])
|
||||
call assert_equal("function('MyHandler')", string(info[0]['callback']))
|
||||
|
||||
let found = 0
|
||||
for info in timer_info()
|
||||
if info['id'] == id
|
||||
let found += 1
|
||||
endif
|
||||
endfor
|
||||
call assert_equal(1, found)
|
||||
|
||||
call timer_stop(id)
|
||||
call assert_equal([], timer_info(id))
|
||||
endfunc
|
||||
|
||||
func Test_stopall()
|
||||
let id1 = timer_start(1000, 'MyHandler')
|
||||
let id2 = timer_start(2000, 'MyHandler')
|
||||
let info = timer_info()
|
||||
call assert_equal(2, len(info))
|
||||
|
||||
call timer_stopall()
|
||||
let info = timer_info()
|
||||
call assert_equal(0, len(info))
|
||||
endfunc
|
||||
|
||||
func Test_paused()
|
||||
let g:val = 0
|
||||
|
||||
let id = timer_start(50, 'MyHandler')
|
||||
let info = timer_info(id)
|
||||
call assert_equal(0, info[0]['paused'])
|
||||
|
||||
call timer_pause(id, 1)
|
||||
let info = timer_info(id)
|
||||
call assert_equal(1, info[0]['paused'])
|
||||
sleep 200m
|
||||
call assert_equal(0, g:val)
|
||||
|
||||
call timer_pause(id, 0)
|
||||
let info = timer_info(id)
|
||||
call assert_equal(0, info[0]['paused'])
|
||||
|
||||
let slept = WaitFor('g:val == 1')
|
||||
call assert_equal(1, g:val)
|
||||
call assert_inrange(0, 10, slept)
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -261,7 +261,7 @@ static int included_patches[] = {
|
||||
2183,
|
||||
// 2182 NA
|
||||
// 2181,
|
||||
// 2180,
|
||||
2180,
|
||||
// 2179,
|
||||
// 2178,
|
||||
// 2177,
|
||||
|
Loading…
Reference in New Issue
Block a user