forked from aniani/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().
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
*eval.txt* For Vim version 7.4. Last change: 2016 Aug 06
|
*eval.txt* For Vim version 7.4. Last change: 2016 Aug 07
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@@ -1969,7 +1969,7 @@ assert_exception({error} [, {msg}]) none assert {error} is in v:exception
|
|||||||
assert_fails({cmd} [, {error}]) none assert {cmd} fails
|
assert_fails({cmd} [, {error}]) none assert {cmd} fails
|
||||||
assert_false({actual} [, {msg}]) none assert {actual} is false
|
assert_false({actual} [, {msg}]) none assert {actual} is false
|
||||||
assert_inrange({lower}, {upper}, {actual} [, {msg}])
|
assert_inrange({lower}, {upper}, {actual} [, {msg}])
|
||||||
none assert {actual} is inside the range
|
none assert {actual} is inside the range
|
||||||
assert_match({pat}, {text} [, {msg}]) none assert {pat} matches {text}
|
assert_match({pat}, {text} [, {msg}]) none assert {pat} matches {text}
|
||||||
assert_notequal({exp}, {act} [, {msg}]) none assert {exp} is not equal {act}
|
assert_notequal({exp}, {act} [, {msg}]) none assert {exp} is not equal {act}
|
||||||
assert_notmatch({pat}, {text} [, {msg}]) none assert {pat} not matches {text}
|
assert_notmatch({pat}, {text} [, {msg}]) none assert {pat} not matches {text}
|
||||||
@@ -2340,9 +2340,11 @@ test_null_partial() Funcref null value for testing
|
|||||||
test_null_string() String null value for testing
|
test_null_string() String null value for testing
|
||||||
test_settime({expr}) none set current time for testing
|
test_settime({expr}) none set current time for testing
|
||||||
timer_info([{id}]) List information about timers
|
timer_info([{id}]) List information about timers
|
||||||
|
timer_pause({id}, {pause}) none pause or unpause a timer
|
||||||
timer_start({time}, {callback} [, {options}])
|
timer_start({time}, {callback} [, {options}])
|
||||||
Number create a timer
|
Number create a timer
|
||||||
timer_stop({timer}) none stop a timer
|
timer_stop({timer}) none stop a timer
|
||||||
|
timer_stopall() none stop all timers
|
||||||
tolower({expr}) String the String {expr} switched to lowercase
|
tolower({expr}) String the String {expr} switched to lowercase
|
||||||
toupper({expr}) String the String {expr} switched to uppercase
|
toupper({expr}) String the String {expr} switched to uppercase
|
||||||
tr({src}, {fromstr}, {tostr}) String translate chars of {src} in {fromstr}
|
tr({src}, {fromstr}, {tostr}) String translate chars of {src} in {fromstr}
|
||||||
@@ -7555,8 +7557,26 @@ timer_info([{id}])
|
|||||||
"time" time the timer was started with
|
"time" time the timer was started with
|
||||||
"remaining" time until the timer fires
|
"remaining" time until the timer fires
|
||||||
"repeat" number of times the timer will still fire;
|
"repeat" number of times the timer will still fire;
|
||||||
-1 means forever
|
-1 means forever
|
||||||
"callback" the callback
|
"callback" the callback
|
||||||
|
"paused" 1 if the timer is paused, 0 otherwise
|
||||||
|
|
||||||
|
{only available when compiled with the |+timers| feature}
|
||||||
|
|
||||||
|
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|.
|
||||||
|
|
||||||
|
{only available when compiled with the |+timers| feature}
|
||||||
|
|
||||||
*timer_start()*
|
*timer_start()*
|
||||||
timer_start({time}, {callback} [, {options}])
|
timer_start({time}, {callback} [, {options}])
|
||||||
@@ -7583,6 +7603,7 @@ timer_start({time}, {callback} [, {options}])
|
|||||||
\ {'repeat': 3})
|
\ {'repeat': 3})
|
||||||
< This will invoke MyHandler() three times at 500 msec
|
< This will invoke MyHandler() three times at 500 msec
|
||||||
intervals.
|
intervals.
|
||||||
|
|
||||||
{only available when compiled with the |+timers| feature}
|
{only available when compiled with the |+timers| feature}
|
||||||
|
|
||||||
timer_stop({timer}) *timer_stop()*
|
timer_stop({timer}) *timer_stop()*
|
||||||
@@ -7590,6 +7611,15 @@ timer_stop({timer}) *timer_stop()*
|
|||||||
{timer} is an ID returned by timer_start(), thus it must be a
|
{timer} is an ID returned by timer_start(), thus it must be a
|
||||||
Number. If {timer} does not exist there is no error.
|
Number. If {timer} does not exist there is no error.
|
||||||
|
|
||||||
|
{only available when compiled with the |+timers| feature}
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
{only available when compiled with the |+timers| feature}
|
||||||
|
|
||||||
tolower({expr}) *tolower()*
|
tolower({expr}) *tolower()*
|
||||||
The result is a copy of the String given, with all uppercase
|
The result is a copy of the String given, with all uppercase
|
||||||
characters turned into lowercase (just like applying |gu| to
|
characters turned into lowercase (just like applying |gu| to
|
||||||
|
@@ -397,8 +397,10 @@ static void f_tanh(typval_T *argvars, typval_T *rettv);
|
|||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_TIMERS
|
#ifdef FEAT_TIMERS
|
||||||
static void f_timer_info(typval_T *argvars, typval_T *rettv);
|
static void f_timer_info(typval_T *argvars, typval_T *rettv);
|
||||||
|
static void f_timer_pause(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_timer_start(typval_T *argvars, typval_T *rettv);
|
static void f_timer_start(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_timer_stop(typval_T *argvars, typval_T *rettv);
|
static void f_timer_stop(typval_T *argvars, typval_T *rettv);
|
||||||
|
static void f_timer_stopall(typval_T *argvars, typval_T *rettv);
|
||||||
#endif
|
#endif
|
||||||
static void f_tolower(typval_T *argvars, typval_T *rettv);
|
static void f_tolower(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_toupper(typval_T *argvars, typval_T *rettv);
|
static void f_toupper(typval_T *argvars, typval_T *rettv);
|
||||||
@@ -817,8 +819,10 @@ static struct fst
|
|||||||
{"test_settime", 1, 1, f_test_settime},
|
{"test_settime", 1, 1, f_test_settime},
|
||||||
#ifdef FEAT_TIMERS
|
#ifdef FEAT_TIMERS
|
||||||
{"timer_info", 0, 1, f_timer_info},
|
{"timer_info", 0, 1, f_timer_info},
|
||||||
|
{"timer_pause", 2, 2, f_timer_pause},
|
||||||
{"timer_start", 2, 3, f_timer_start},
|
{"timer_start", 2, 3, f_timer_start},
|
||||||
{"timer_stop", 1, 1, f_timer_stop},
|
{"timer_stop", 1, 1, f_timer_stop},
|
||||||
|
{"timer_stopall", 0, 0, f_timer_stopall},
|
||||||
#endif
|
#endif
|
||||||
{"tolower", 1, 1, f_tolower},
|
{"tolower", 1, 1, f_tolower},
|
||||||
{"toupper", 1, 1, f_toupper},
|
{"toupper", 1, 1, f_toupper},
|
||||||
@@ -11987,6 +11991,25 @@ f_timer_info(typval_T *argvars, typval_T *rettv)
|
|||||||
add_timer_info_all(rettv);
|
add_timer_info_all(rettv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "timer_pause(timer, paused)" function
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
f_timer_pause(typval_T *argvars, typval_T *rettv UNUSED)
|
||||||
|
{
|
||||||
|
timer_T *timer = NULL;
|
||||||
|
int paused = (int)get_tv_number(&argvars[1]);
|
||||||
|
|
||||||
|
if (argvars[0].v_type != VAR_NUMBER)
|
||||||
|
EMSG(_(e_number_exp));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timer = find_timer((int)get_tv_number(&argvars[0]));
|
||||||
|
if (timer != NULL)
|
||||||
|
timer->tr_paused = paused;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "timer_start(time, callback [, options])" function
|
* "timer_start(time, callback [, options])" function
|
||||||
*/
|
*/
|
||||||
@@ -12048,6 +12071,15 @@ f_timer_stop(typval_T *argvars, typval_T *rettv UNUSED)
|
|||||||
if (timer != NULL)
|
if (timer != NULL)
|
||||||
stop_timer(timer);
|
stop_timer(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "timer_stopall()" function
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
f_timer_stopall(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
|
||||||
|
{
|
||||||
|
stop_all_timers();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1189,6 +1189,8 @@ check_due_timer(void)
|
|||||||
next_due = -1;
|
next_due = -1;
|
||||||
for (timer = first_timer; timer != NULL; timer = timer->tr_next)
|
for (timer = first_timer; timer != NULL; timer = timer->tr_next)
|
||||||
{
|
{
|
||||||
|
if (timer->tr_paused)
|
||||||
|
continue;
|
||||||
# ifdef WIN3264
|
# ifdef WIN3264
|
||||||
this_due = (long)(((double)(timer->tr_due.QuadPart - now.QuadPart)
|
this_due = (long)(((double)(timer->tr_due.QuadPart - now.QuadPart)
|
||||||
/ (double)fr.QuadPart) * 1000);
|
/ (double)fr.QuadPart) * 1000);
|
||||||
@@ -1251,6 +1253,15 @@ stop_timer(timer_T *timer)
|
|||||||
free_timer(timer);
|
free_timer(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
stop_all_timers(void)
|
||||||
|
{
|
||||||
|
timer_T *timer;
|
||||||
|
|
||||||
|
while (first_timer != NULL)
|
||||||
|
stop_timer(first_timer);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
add_timer_info(typval_T *rettv, timer_T *timer)
|
add_timer_info(typval_T *rettv, timer_T *timer)
|
||||||
{
|
{
|
||||||
@@ -1283,6 +1294,7 @@ add_timer_info(typval_T *rettv, timer_T *timer)
|
|||||||
|
|
||||||
dict_add_nr_str(dict, "repeat",
|
dict_add_nr_str(dict, "repeat",
|
||||||
(long)(timer->tr_repeat < 0 ? -1 : timer->tr_repeat + 1), NULL);
|
(long)(timer->tr_repeat < 0 ? -1 : timer->tr_repeat + 1), NULL);
|
||||||
|
dict_add_nr_str(dict, "paused", (long)(timer->tr_paused), NULL);
|
||||||
|
|
||||||
di = dictitem_alloc((char_u *)"callback");
|
di = dictitem_alloc((char_u *)"callback");
|
||||||
if (di != NULL)
|
if (di != NULL)
|
||||||
|
@@ -22,6 +22,7 @@ timer_T *create_timer(long msec, int repeat);
|
|||||||
long check_due_timer(void);
|
long check_due_timer(void);
|
||||||
timer_T *find_timer(int id);
|
timer_T *find_timer(int id);
|
||||||
void stop_timer(timer_T *timer);
|
void stop_timer(timer_T *timer);
|
||||||
|
void stop_all_timers(void);
|
||||||
void add_timer_info(typval_T *rettv, timer_T *timer);
|
void add_timer_info(typval_T *rettv, timer_T *timer);
|
||||||
void add_timer_info_all(typval_T *rettv);
|
void add_timer_info_all(typval_T *rettv);
|
||||||
int set_ref_in_timer(int copyID);
|
int set_ref_in_timer(int copyID);
|
||||||
|
@@ -3159,6 +3159,7 @@ struct timer_S
|
|||||||
timer_T *tr_next;
|
timer_T *tr_next;
|
||||||
timer_T *tr_prev;
|
timer_T *tr_prev;
|
||||||
proftime_T tr_due; /* when the callback is to be invoked */
|
proftime_T tr_due; /* when the callback is to be invoked */
|
||||||
|
int tr_paused; /* when TRUE callback is not invoked */
|
||||||
int tr_repeat; /* number of times to repeat, -1 forever */
|
int tr_repeat; /* number of times to repeat, -1 forever */
|
||||||
long tr_interval; /* msec */
|
long tr_interval; /* msec */
|
||||||
char_u *tr_callback; /* allocated */
|
char_u *tr_callback; /* allocated */
|
||||||
|
@@ -109,14 +109,17 @@ func s:kill_server(cmd)
|
|||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Wait for up to a second for "expr" to become true.
|
" Wait for up to a second for "expr" to become true.
|
||||||
|
" Return time slept in milliseconds.
|
||||||
func WaitFor(expr)
|
func WaitFor(expr)
|
||||||
|
let slept = 0
|
||||||
for i in range(100)
|
for i in range(100)
|
||||||
try
|
try
|
||||||
if eval(a:expr)
|
if eval(a:expr)
|
||||||
return
|
return slept
|
||||||
endif
|
endif
|
||||||
catch
|
catch
|
||||||
endtry
|
endtry
|
||||||
|
let slept += 10
|
||||||
sleep 10m
|
sleep 10m
|
||||||
endfor
|
endfor
|
||||||
endfunc
|
endfunc
|
||||||
|
@@ -1,11 +1,13 @@
|
|||||||
" Test for timers
|
" Test for timers
|
||||||
|
|
||||||
|
source shared.vim
|
||||||
|
|
||||||
if !has('timers')
|
if !has('timers')
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
|
|
||||||
func MyHandler(timer)
|
func MyHandler(timer)
|
||||||
let s:val += 1
|
let g:val += 1
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func MyHandlerWithLists(lists, timer)
|
func MyHandlerWithLists(lists, timer)
|
||||||
@@ -13,43 +15,101 @@ func MyHandlerWithLists(lists, timer)
|
|||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_oneshot()
|
func Test_oneshot()
|
||||||
let s:val = 0
|
let g:val = 0
|
||||||
let timer = timer_start(50, 'MyHandler')
|
let timer = timer_start(50, 'MyHandler')
|
||||||
sleep 200m
|
let slept = WaitFor('g:val == 1')
|
||||||
call assert_equal(1, s:val)
|
call assert_equal(1, g:val)
|
||||||
|
call assert_inrange(30, 100, slept)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_repeat_three()
|
func Test_repeat_three()
|
||||||
let s:val = 0
|
let g:val = 0
|
||||||
let timer = timer_start(50, 'MyHandler', {'repeat': 3})
|
let timer = timer_start(50, 'MyHandler', {'repeat': 3})
|
||||||
sleep 500m
|
let slept = WaitFor('g:val == 3')
|
||||||
call assert_equal(3, s:val)
|
call assert_equal(3, g:val)
|
||||||
|
call assert_inrange(100, 250, slept)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_repeat_many()
|
func Test_repeat_many()
|
||||||
let s:val = 0
|
let g:val = 0
|
||||||
let timer = timer_start(50, 'MyHandler', {'repeat': -1})
|
let timer = timer_start(50, 'MyHandler', {'repeat': -1})
|
||||||
sleep 200m
|
sleep 200m
|
||||||
call timer_stop(timer)
|
call timer_stop(timer)
|
||||||
call assert_true(s:val > 1)
|
call assert_inrange(2, 4, g:val)
|
||||||
call assert_true(s:val < 5)
|
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_with_partial_callback()
|
func Test_with_partial_callback()
|
||||||
let s:val = 0
|
let g:val = 0
|
||||||
let s:meow = {}
|
let s:meow = {}
|
||||||
function s:meow.bite(...)
|
function s:meow.bite(...)
|
||||||
let s:val += 1
|
let g:val += 1
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
call timer_start(50, s:meow.bite)
|
call timer_start(50, s:meow.bite)
|
||||||
sleep 200m
|
let slept = WaitFor('g:val == 1')
|
||||||
call assert_equal(1, s:val)
|
call assert_equal(1, g:val)
|
||||||
|
call assert_inrange(30, 100, slept)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_retain_partial()
|
func Test_retain_partial()
|
||||||
call timer_start(100, function('MyHandlerWithLists', [['a']]))
|
call timer_start(50, function('MyHandlerWithLists', [['a']]))
|
||||||
call test_garbagecollect_now()
|
call test_garbagecollect_now()
|
||||||
sleep 200m
|
sleep 100m
|
||||||
endfunc
|
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_true(info[0]['remaining'] > 500)
|
||||||
|
call assert_true(info[0]['remaining'] <= 1000)
|
||||||
|
call assert_equal(1, info[0]['repeat'])
|
||||||
|
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 100m
|
||||||
|
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: ts=2 sw=0 et
|
" vim: ts=2 sw=0 et
|
||||||
|
@@ -763,6 +763,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2180,
|
||||||
/**/
|
/**/
|
||||||
2179,
|
2179,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user