# HG changeset patch # User Christian Brabandt # Date 1470514505 -7200 # Node ID 34cc6a1013400b56919f1a2f9a3ad90b46222e48 # Parent b864a0dabc7466d01be83b38c4f7f6c408aceb6d commit https://github.com/vim/vim/commit/8e97bd74b5377753597e3d98e7123d8985c7fffd Author: Bram Moolenaar Date: Sat Aug 6 22:05:07 2016 +0200 patch 7.4.2170 Problem: Cannot get information about timers. Solution: Add timer_info(). diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.4. Last change: 2016 Aug 02 +*eval.txt* For Vim version 7.4. Last change: 2016 Aug 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2339,6 +2339,7 @@ test_null_list() List null value for te test_null_partial() Funcref null value for testing test_null_string() String null value for testing test_settime({expr}) none set current time for testing +timer_info([{id}]) List information about timers timer_start({time}, {callback} [, {options}]) Number create a timer timer_stop({timer}) none stop a timer @@ -3392,9 +3393,13 @@ exepath({expr}) *exepath()* an empty string is returned. *exists()* -exists({expr}) The result is a Number, which is |TRUE| if {expr} is - defined, zero otherwise. The {expr} argument is a string, - which contains one of these: +exists({expr}) The result is a Number, which is |TRUE| if {expr} is defined, + zero otherwise. + + For checking for a supported feature use |has()|. + For checking if a file exists use |filereadable()|. + + The {expr} argument is a string, which contains one of these: &option-name Vim option (only checks if it exists, not if it really works) +option-name Vim option that works. @@ -3442,7 +3447,6 @@ exists({expr}) The result is a Number, w event and pattern. ##event autocommand for this event is supported. - For checking for a supported feature use |has()|. Examples: > exists("&shortname") @@ -5476,7 +5480,8 @@ matchadd({group}, {pattern}[, {priority} available from |getmatches()|. All matches can be deleted in one operation by |clearmatches()|. -matchaddpos({group}, {pos}[, {priority}[, {id}[, {dict}]]]) *matchaddpos()* + *matchaddpos()* +matchaddpos({group}, {pos}[, {priority}[, {id}[, {dict}]]]) Same as |matchadd()|, but requires a list of positions {pos} instead of a pattern. This command is faster than |matchadd()| because it does not require to handle regular expressions and @@ -7536,6 +7541,23 @@ test_settime({expr}) *test_settime() {expr} must evaluate to a number. When the value is zero the normal behavior is restored. + *timer_info()* +timer_info([{id}]) + Return a list with information about timers. + When {id} is given only information about this timer is + returned. When timer {id} does not exist an empty list is + returned. + When {id} is omitted information about all timers is returned. + + For each timer the information is stored in a Dictionary with + these items: + "id" the timer ID + "time" time the timer was started with + "remaining" time until the timer fires + "repeat" number of times the timer will still fire; + -1 means forever + "callback" the callback + *timer_start()* timer_start({time}, {callback} [, {options}]) Create a timer and return the timer ID. @@ -7566,7 +7588,7 @@ timer_start({time}, {callback} [, {optio timer_stop({timer}) *timer_stop()* Stop a timer. The timer callback will no longer be invoked. {timer} is an ID returned by timer_start(), thus it must be a - Number. + Number. If {timer} does not exist there is no error. tolower({expr}) *tolower()* The result is a copy of the String given, with all uppercase diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -396,6 +396,7 @@ static void f_tan(typval_T *argvars, typ static void f_tanh(typval_T *argvars, typval_T *rettv); #endif #ifdef FEAT_TIMERS +static void f_timer_info(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); #endif @@ -815,6 +816,7 @@ static struct fst {"test_null_string", 0, 0, f_test_null_string}, {"test_settime", 1, 1, f_test_settime}, #ifdef FEAT_TIMERS + {"timer_info", 0, 1, f_timer_info}, {"timer_start", 2, 3, f_timer_start}, {"timer_stop", 1, 1, f_timer_stop}, #endif @@ -11961,6 +11963,31 @@ free_callback(char_u *callback, partial_ #ifdef FEAT_TIMERS /* + * "timer_info([timer])" function + */ + static void +f_timer_info(typval_T *argvars, typval_T *rettv) +{ + timer_T *timer = NULL; + + if (rettv_list_alloc(rettv) != OK) + return; + if (argvars[0].v_type != VAR_UNKNOWN) + { + if (argvars[0].v_type != VAR_NUMBER) + EMSG(_(e_number_exp)); + else + { + timer = find_timer((int)get_tv_number(&argvars[0])); + if (timer != NULL) + add_timer_info(rettv, timer); + } + } + else + add_timer_info_all(rettv); +} + +/* * "timer_start(time, callback [, options])" function */ static void diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -1139,10 +1139,8 @@ create_timer(long msec, int repeat) timer->tr_id = ++last_timer_id; insert_timer(timer); if (repeat != 0) - { timer->tr_repeat = repeat - 1; - timer->tr_interval = msec; - } + timer->tr_interval = msec; profile_setlimit(msec, &timer->tr_due); return timer; @@ -1253,6 +1251,64 @@ stop_timer(timer_T *timer) free_timer(timer); } + void +add_timer_info(typval_T *rettv, timer_T *timer) +{ + list_T *list = rettv->vval.v_list; + dict_T *dict = dict_alloc(); + dictitem_T *di; + long remaining; + proftime_T now; + + if (dict == NULL) + return; + list_append_dict(list, dict); + + dict_add_nr_str(dict, "id", (long)timer->tr_id, NULL); + dict_add_nr_str(dict, "time", (long)timer->tr_interval, NULL); + + profile_start(&now); +# ifdef WIN3264 + remaining = (long)(((double)(timer->tr_due.QuadPart - now.QuadPart) + / (double)fr.QuadPart) * 1000); +# else + remaining = (timer->tr_due.tv_sec - now.tv_sec) * 1000 + + (timer->tr_due.tv_usec - now.tv_usec) / 1000; +# endif + dict_add_nr_str(dict, "remaining", (long)remaining, NULL); + + dict_add_nr_str(dict, "repeat", + (long)(timer->tr_repeat < 0 ? -1 : timer->tr_repeat + 1), NULL); + + di = dictitem_alloc((char_u *)"callback"); + if (di != NULL) + { + if (dict_add(dict, di) == FAIL) + vim_free(di); + else if (timer->tr_partial != NULL) + { + di->di_tv.v_type = VAR_PARTIAL; + di->di_tv.vval.v_partial = timer->tr_partial; + ++timer->tr_partial->pt_refcount; + } + else + { + di->di_tv.v_type = VAR_FUNC; + di->di_tv.vval.v_string = vim_strsave(timer->tr_callback); + } + di->di_tv.v_lock = 0; + } +} + + void +add_timer_info_all(typval_T *rettv) +{ + timer_T *timer; + + for (timer = first_timer; timer != NULL; timer = timer->tr_next) + add_timer_info(rettv, timer); +} + /* * Mark references in partials of timers. */ diff --git a/src/proto/ex_cmds2.pro b/src/proto/ex_cmds2.pro --- a/src/proto/ex_cmds2.pro +++ b/src/proto/ex_cmds2.pro @@ -22,6 +22,8 @@ timer_T *create_timer(long msec, int rep long check_due_timer(void); timer_T *find_timer(int id); void stop_timer(timer_T *timer); +void add_timer_info(typval_T *rettv, timer_T *timer); +void add_timer_info_all(typval_T *rettv); int set_ref_in_timer(int copyID); void timer_free_all(void); void profile_divide(proftime_T *tm, int count, proftime_T *tm2); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2170, +/**/ 2169, /**/ 2168,