Merge remote-tracking branch 'vim/master'

This commit is contained in:
Kazuki Sakamoto
2016-03-15 20:29:23 -07:00
33 changed files with 743 additions and 145 deletions
+48 -11
View File
@@ -1,4 +1,4 @@
*eval.txt* For Vim version 7.4. Last change: 2016 Mar 14
*eval.txt* For Vim version 7.4. Last change: 2016 Mar 15
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -350,10 +350,6 @@ This works like: >
: let index = index + 1
:endwhile
Note that all items in the list should be of the same type, otherwise this
results in error |E706|. To avoid this |:unlet| the variable at the end of
the loop.
If all you want to do is modify each item in the list then the |map()|
function will be a simpler method than a for loop.
@@ -2133,9 +2129,12 @@ tabpagewinnr( {tabarg}[, {arg}])
Number number of current window in tab page
taglist( {expr}) List list of tags matching {expr}
tagfiles() List tags files used
tempname() String name for a temporary file
tan( {expr}) Float tangent of {expr}
tanh( {expr}) Float hyperbolic tangent of {expr}
tempname() String name for a temporary file
timer_start( {time}, {callback} [, {options}])
Number create a timer
timer_stop( {timer}) none stop a timer
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}
@@ -3572,8 +3571,15 @@ foreground() Move the Vim window to the foreground. Useful when sent from
*function()* *E700* *E922* *E923*
function({name} [, {arglist}] [, {dict}])
Return a |Funcref| variable that refers to function {name}.
{name} can be a user defined function or an internal function.
{name} can be the name of a user defined function or an
internal function.
{name} can also be a Funcref, also a partial. When it is a
partial the dict stored in it will be used and the {dict}
argument is not allowed. E.g.: >
let FuncWithArg = function(dict.Func, [arg])
let Broken = function(dict.Func, [arg], dict)
<
When {arglist} or {dict} is present this creates a partial.
That mans the argument list and/or the dictionary is stored in
the Funcref and will be used when the Funcref is called.
@@ -3598,6 +3604,10 @@ function({name} [, {arglist}] [, {dict}])
let Func = function('Callback', context)
...
call Func() " will echo: called for example
< The use of function() is not needed when there are no extra
arguments, these two are equivalent: >
let Func = function('Callback', context)
let Func = context.Callback
< The argument list and the Dictionary can be combined: >
function Callback(arg1, count) dict
@@ -4523,13 +4533,13 @@ job_info({job}) *job_info()*
"status" what |job_status()| returns
"channel" what |job_getchannel()| returns
"exitval" only valid when "status" is "dead"
"exit-cb" function to be called on exit
"exit_cb" function to be called on exit
"stoponexit" |job-stoponexit|
job_setoptions({job}, {options}) *job_setoptions()*
Change options for {job}. Supported are:
"stoponexit" |job-stoponexit|
"exit-cb" |job-exit-cb|
"exit_cb" |job-exit_cb|
job_start({command} [, {options}]) *job_start()*
Start a job and return a Job object. Unlike |system()| and
@@ -6897,8 +6907,7 @@ systemlist({expr} [, {input}]) *systemlist()*
is the same as |readfile()| will output with {binary} argument
set to "b".
Returns an empty string on error, so be careful not to run
into |E706|.
Returns an empty string on error.
tabpagebuflist([{arg}]) *tabpagebuflist()*
@@ -7014,6 +7023,33 @@ tanh({expr}) *tanh()*
{only available when compiled with the |+float| feature}
*timer_start()*
timer_start({time}, {callback} [, {options}])
Create a timer and return the timer ID.
{time} is the waiting time in milliseconds. This is the
minimum time before invoking the callback. When the system is
busy or Vim is not waiting for input the time will be longer.
{callback} is the function to call. It can be the name of a
function or a Funcref. It is called with one argument, which
is the timer ID. The callback is only invoked when Vim is
waiting for input.
{options} is a dictionary. Supported entries:
"repeat" Number of times to repeat calling the
callback. -1 means forever.
Example: >
func MyHandler(timer)
echo 'Handler called'
endfunc
let timer = timer_start(500, 'MyHandler',
\ {'repeat': 3})
< This will invoke MyHandler() three times at 500 msec
intervals.
{only available when compiled with the |+timers| feature}
tolower({expr}) *tolower()*
The result is a copy of the String given, with all uppercase
characters turned into lowercase (just like applying |gu| to
@@ -7573,6 +7609,7 @@ termresponse Compiled with support for |t_RV| and |v:termresponse|.
textobjects Compiled with support for |text-objects|.
tgetent Compiled with tgetent support, able to use a termcap
or terminfo file.
timers Compiled with |timer_start()| support.
title Compiled with window title support |'title'|.
toolbar Compiled with support for |gui-toolbar|.
transparency Compiled with 'transparency' support.
+3 -1
View File
@@ -6669,7 +6669,9 @@ A jump table for the options with a short description can be found at |Q_op|.
c don't give |ins-completion-menu| messages. For example,
"-- XXX completion (YYY)", "match 1 of 2", "The only match",
"Pattern not found", "Back at original", etc.
q use "recording" instead of "recording @a"
q use "recording" instead of "recording @a"
F don't give the file info when editing a file, like `:silent`
was used for the command
This gives you the opportunity to avoid that a change between buffers
requires you to hit <Enter>, but still gives as useful a message as
+5
View File
@@ -139,14 +139,19 @@ open_buffer(
#endif
)
{
int old_msg_silent = msg_silent;
#ifdef FEAT_NETBEANS_INTG
int oldFire = netbeansFireChanges;
netbeansFireChanges = 0;
#endif
if (shortmess(SHM_FILEINFO))
msg_silent = 1;
retval = readfile(curbuf->b_ffname, curbuf->b_fname,
(linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap,
flags | READ_NEW);
msg_silent = old_msg_silent;
#ifdef FEAT_NETBEANS_INTG
netbeansFireChanges = oldFire;
#endif
+1 -35
View File
@@ -1304,19 +1304,7 @@ invoke_callback(channel_T *channel, char_u *callback, partial_T *partial,
&rettv, 2, argv, 0L, 0L, &dummy, TRUE, partial, NULL);
clear_tv(&rettv);
/* If an echo command was used the cursor needs to be put back where
* it belongs. If highlighting was changed a redraw is needed. */
update_screen(0);
setcursor();
cursor_on();
out_flush();
#ifdef FEAT_GUI
if (gui.in_use)
{
gui_update_cursor(TRUE, FALSE);
gui_mch_flush();
}
#endif
redraw_after_callback();
}
/*
@@ -3043,28 +3031,6 @@ channel_get_timeout(channel_T *channel, int part)
return channel->ch_part[part].ch_timeout;
}
/*
* Get a callback from "arg". It can be a Funcref or a function name.
* When "arg" is zero return an empty string.
* Return NULL for an invalid argument.
*/
static char_u *
get_callback(typval_T *arg, partial_T **pp)
{
if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL)
{
*pp = arg->vval.v_partial;
return (*pp)->pt_name;
}
*pp = NULL;
if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
return arg->vval.v_string;
if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
return (char_u *)"";
EMSG(_("E921: Invalid callback argument"));
return NULL;
}
static int
handle_mode(typval_T *item, jobopt_T *opt, ch_mode_T *modep, int jo)
{
+174 -26
View File
@@ -110,6 +110,7 @@ static char *e_illvar = N_("E461: Illegal variable name: %s");
#ifdef FEAT_FLOAT
static char *e_float_as_string = N_("E806: using Float as a String");
#endif
static char *e_dict_both = N_("E924: can't have both a \"self\" dict and a partial: %s");
#define NAMESPACE_CHAR (char_u *)"abglstvw"
@@ -793,6 +794,10 @@ static void f_test(typval_T *argvars, typval_T *rettv);
static void f_tan(typval_T *argvars, typval_T *rettv);
static void f_tanh(typval_T *argvars, typval_T *rettv);
#endif
#ifdef FEAT_TIMERS
static void f_timer_start(typval_T *argvars, typval_T *rettv);
static void f_timer_stop(typval_T *argvars, typval_T *rettv);
#endif
static void f_tolower(typval_T *argvars, typval_T *rettv);
static void f_toupper(typval_T *argvars, typval_T *rettv);
static void f_tr(typval_T *argvars, typval_T *rettv);
@@ -8403,6 +8408,10 @@ static struct fst
#endif
{"tempname", 0, 0, f_tempname},
{"test", 1, 1, f_test},
#ifdef FEAT_TIMERS
{"timer_start", 2, 3, f_timer_start},
{"timer_stop", 1, 1, f_timer_stop},
#endif
{"tolower", 1, 1, f_tolower},
{"toupper", 1, 1, f_toupper},
{"tr", 3, 3, f_tr},
@@ -8759,8 +8768,6 @@ call_func(
}
if (error == ERROR_NONE && partial->pt_argc > 0)
{
int i;
for (argv_clear = 0; argv_clear < partial->pt_argc; ++argv_clear)
copy_tv(&partial->pt_argv[argv_clear], &argv[argv_clear]);
for (i = 0; i < argcount_in; ++i)
@@ -8914,8 +8921,7 @@ call_func(
name);
break;
case ERROR_BOTH:
emsg_funcname(N_("E924: can't have both a \"self\" dict and a partial: %s"),
name);
emsg_funcname(e_dict_both, name);
break;
}
}
@@ -9240,6 +9246,12 @@ ga_concat_esc(garray_T *gap, char_u *str)
char_u *p;
char_u buf[NUMBUFLEN];
if (str == NULL)
{
ga_concat(gap, (char_u *)"NULL");
return;
}
for (p = str; *p != NUL; ++p)
switch (*p)
{
@@ -9382,7 +9394,8 @@ f_assert_fails(typval_T *argvars, typval_T *rettv UNUSED)
char_u buf[NUMBUFLEN];
char *error = (char *)get_tv_string_buf_chk(&argvars[1], buf);
if (strstr((char *)vimvars[VV_ERRMSG].vv_str, error) == NULL)
if (error == NULL
|| strstr((char *)vimvars[VV_ERRMSG].vv_str, error) == NULL)
{
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
@@ -11777,15 +11790,36 @@ f_function(typval_T *argvars, typval_T *rettv)
{
char_u *s;
char_u *name;
int use_string = FALSE;
s = get_tv_string(&argvars[0]);
if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
if (argvars[0].v_type == VAR_FUNC)
{
/* function(MyFunc, [arg], dict) */
s = argvars[0].vval.v_string;
}
else if (argvars[0].v_type == VAR_PARTIAL
&& argvars[0].vval.v_partial != NULL)
/* function(dict.MyFunc, [arg]) */
s = argvars[0].vval.v_partial->pt_name;
else
{
/* function('MyFunc', [arg], dict) */
s = get_tv_string(&argvars[0]);
use_string = TRUE;
}
if (s == NULL || *s == NUL || (use_string && VIM_ISDIGIT(*s)))
EMSG2(_(e_invarg2), s);
/* Don't check an autoload name for existence here. */
else if (vim_strchr(s, AUTOLOAD_CHAR) == NULL && !function_exists(s))
else if (use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL
&& !function_exists(s))
EMSG2(_("E700: Unknown function: %s"), s);
else
{
int dict_idx = 0;
int arg_idx = 0;
list_T *list = NULL;
if (STRNCMP(s, "s:", 2) == 0 || STRNCMP(s, "<SID>", 5) == 0)
{
char sid_buf[25];
@@ -11808,10 +11842,6 @@ f_function(typval_T *argvars, typval_T *rettv)
if (argvars[1].v_type != VAR_UNKNOWN)
{
partial_T *pt;
int dict_idx = 0;
int arg_idx = 0;
if (argvars[2].v_type != VAR_UNKNOWN)
{
/* function(name, [args], dict) */
@@ -11824,27 +11854,44 @@ f_function(typval_T *argvars, typval_T *rettv)
else
/* function(name, [args]) */
arg_idx = 1;
if (dict_idx > 0 && (argvars[dict_idx].v_type != VAR_DICT
|| argvars[dict_idx].vval.v_dict == NULL))
if (dict_idx > 0)
{
EMSG(_("E922: expected a dict"));
vim_free(name);
return;
if (argvars[dict_idx].v_type != VAR_DICT)
{
EMSG(_("E922: expected a dict"));
vim_free(name);
return;
}
if (argvars[0].v_type == VAR_PARTIAL)
{
EMSG2(_(e_dict_both), name);
vim_free(name);
return;
}
if (argvars[dict_idx].vval.v_dict == NULL)
dict_idx = 0;
}
if (arg_idx > 0 && (argvars[arg_idx].v_type != VAR_LIST
|| argvars[arg_idx].vval.v_list == NULL))
if (arg_idx > 0)
{
EMSG(_("E923: Second argument of function() must be a list or a dict"));
vim_free(name);
return;
if (argvars[arg_idx].v_type != VAR_LIST)
{
EMSG(_("E923: Second argument of function() must be a list or a dict"));
vim_free(name);
return;
}
list = argvars[arg_idx].vval.v_list;
if (list == NULL || list->lv_len == 0)
arg_idx = 0;
}
}
if (dict_idx > 0 || arg_idx > 0)
{
partial_T *pt = (partial_T *)alloc_clear(sizeof(partial_T));
pt = (partial_T *)alloc_clear(sizeof(partial_T));
if (pt != NULL)
{
if (arg_idx > 0)
{
list_T *list = argvars[arg_idx].vval.v_list;
listitem_T *li;
int i = 0;
@@ -11864,7 +11911,12 @@ f_function(typval_T *argvars, typval_T *rettv)
}
}
if (dict_idx > 0)
if (argvars[0].v_type == VAR_PARTIAL)
{
pt->pt_dict = argvars[0].vval.v_partial->pt_dict;
++pt->pt_dict->dv_refcount;
}
else if (dict_idx > 0)
{
pt->pt_dict = argvars[dict_idx].vval.v_dict;
++pt->pt_dict->dv_refcount;
@@ -13620,6 +13672,9 @@ f_has(typval_T *argvars, typval_T *rettv)
#ifdef HAVE_TGETENT
"tgetent",
#endif
#ifdef FEAT_TIMERS
"timers",
#endif
#ifdef FEAT_TITLE
"title",
#endif
@@ -20060,6 +20115,82 @@ f_tanh(typval_T *argvars, typval_T *rettv)
}
#endif
#if defined(FEAT_JOB_CHANNEL) || defined(FEAT_TIMERS) || defined(PROTO)
/*
* Get a callback from "arg". It can be a Funcref or a function name.
* When "arg" is zero return an empty string.
* Return NULL for an invalid argument.
*/
char_u *
get_callback(typval_T *arg, partial_T **pp)
{
if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL)
{
*pp = arg->vval.v_partial;
return (*pp)->pt_name;
}
*pp = NULL;
if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
return arg->vval.v_string;
if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
return (char_u *)"";
EMSG(_("E921: Invalid callback argument"));
return NULL;
}
#endif
#ifdef FEAT_TIMERS
/*
* "timer_start(time, callback [, options])" function
*/
static void
f_timer_start(typval_T *argvars, typval_T *rettv)
{
long msec = get_tv_number(&argvars[0]);
timer_T *timer;
int repeat = 0;
char_u *callback;
dict_T *dict;
if (argvars[2].v_type != VAR_UNKNOWN)
{
if (argvars[2].v_type != VAR_DICT
|| (dict = argvars[2].vval.v_dict) == NULL)
{
EMSG2(_(e_invarg2), get_tv_string(&argvars[2]));
return;
}
if (dict_find(dict, (char_u *)"repeat", -1) != NULL)
repeat = get_dict_number(dict, (char_u *)"repeat");
}
timer = create_timer(msec, repeat);
callback = get_callback(&argvars[1], &timer->tr_partial);
if (callback == NULL)
{
stop_timer(timer);
rettv->vval.v_number = -1;
}
else
{
timer->tr_callback = vim_strsave(callback);
rettv->vval.v_number = timer->tr_id;
}
}
/*
* "timer_stop(timer)" function
*/
static void
f_timer_stop(typval_T *argvars, typval_T *rettv UNUSED)
{
timer_T *timer = find_timer(get_tv_number(&argvars[0]));
if (timer != NULL)
stop_timer(timer);
}
#endif
/*
* "tolower(string)" function
*/
@@ -21544,7 +21675,7 @@ handle_subscript(
rettv->v_type = VAR_UNKNOWN;
/* Invoke the function. Recursive! */
if (rettv->v_type == VAR_PARTIAL)
if (functv.v_type == VAR_PARTIAL)
{
pt = functv.vval.v_partial;
s = pt->pt_name;
@@ -21593,6 +21724,23 @@ handle_subscript(
}
}
}
if (rettv->v_type == VAR_FUNC && selfdict != NULL)
{
partial_T *pt = (partial_T *)alloc_clear(sizeof(partial_T));
/* Turn "dict.Func" into a partial for "Func" with "dict". */
if (pt != NULL)
{
pt->pt_dict = selfdict;
selfdict = NULL;
pt->pt_name = rettv->vval.v_string;
func_ref(pt->pt_name);
rettv->v_type = VAR_PARTIAL;
rettv->vval.v_partial = pt;
}
}
dict_unref(selfdict);
return ret;
}
+23 -12
View File
@@ -2065,26 +2065,30 @@ write_viminfo(char_u *file, int forceit)
viminfo_errcnt = 0;
do_viminfo(fp_in, fp_out, forceit ? 0 : (VIF_WANT_INFO | VIF_WANT_MARKS));
fclose(fp_out); /* errors are ignored !? */
if (fclose(fp_out) == EOF)
++viminfo_errcnt;
if (fp_in != NULL)
{
fclose(fp_in);
/* In case of an error keep the original viminfo file. Otherwise
* rename the newly written file. Give an error if that fails. */
if (viminfo_errcnt == 0 && vim_rename(tempname, fname) == -1)
if (viminfo_errcnt == 0)
{
++viminfo_errcnt;
EMSG2(_("E886: Can't rename viminfo file to %s!"), fname);
if (vim_rename(tempname, fname) == -1)
{
++viminfo_errcnt;
EMSG2(_("E886: Can't rename viminfo file to %s!"), fname);
}
# ifdef WIN3264
/* If the viminfo file was hidden then also hide the new file. */
else if (hidden)
mch_hide(fname);
# endif
}
if (viminfo_errcnt > 0)
mch_remove(tempname);
#ifdef WIN3264
/* If the viminfo file was hidden then also hide the new file. */
if (hidden)
mch_hide(fname);
#endif
}
end:
@@ -2605,7 +2609,8 @@ ex_file(exarg_T *eap)
return;
}
/* print full file name if :cd used */
fileinfo(FALSE, FALSE, eap->forceit);
if (!shortmess(SHM_FILEINFO))
fileinfo(FALSE, FALSE, eap->forceit);
}
/*
@@ -3884,7 +3889,8 @@ do_ecmd(
msg_scroll = msg_scroll_save;
msg_scrolled_ign = TRUE;
fileinfo(FALSE, TRUE, FALSE);
if (!shortmess(SHM_FILEINFO))
fileinfo(FALSE, TRUE, FALSE);
msg_scrolled_ign = FALSE;
}
@@ -6114,6 +6120,11 @@ find_help_tags(
|| (arg[0] == '\\' && arg[1] == '{'))
*d++ = '\\';
/*
* If tag starts with "('", skip the "(". Fixes CTRL-] on ('option'.
*/
if (*arg == '(' && arg[1] == '\'')
arg++;
for (s = arg; *s; ++s)
{
/*
+168
View File
@@ -1088,6 +1088,174 @@ profile_zero(proftime_T *tm)
# endif /* FEAT_PROFILE || FEAT_RELTIME */
# if defined(FEAT_TIMERS) || defined(PROTO)
static timer_T *first_timer = NULL;
static int last_timer_id = 0;
/*
* Insert a timer in the list of timers.
*/
static void
insert_timer(timer_T *timer)
{
timer->tr_next = first_timer;
timer->tr_prev = NULL;
if (first_timer != NULL)
first_timer->tr_prev = timer;
first_timer = timer;
}
/*
* Take a timer out of the list of timers.
*/
static void
remove_timer(timer_T *timer)
{
if (timer->tr_prev == NULL)
first_timer = timer->tr_next;
else
timer->tr_prev->tr_next = timer->tr_next;
if (timer->tr_next != NULL)
timer->tr_next->tr_prev = timer->tr_prev;
}
static void
free_timer(timer_T *timer)
{
vim_free(timer->tr_callback);
partial_unref(timer->tr_partial);
vim_free(timer);
}
/*
* Create a timer and return it. NULL if out of memory.
* Caller should set the callback.
*/
timer_T *
create_timer(long msec, int repeat)
{
timer_T *timer = (timer_T *)alloc_clear(sizeof(timer_T));
if (timer == NULL)
return NULL;
timer->tr_id = ++last_timer_id;
insert_timer(timer);
if (repeat != 0)
{
timer->tr_repeat = repeat - 1;
timer->tr_interval = msec;
}
profile_setlimit(msec, &timer->tr_due);
return timer;
}
/*
* Invoke the callback of "timer".
*/
static void
timer_callback(timer_T *timer)
{
typval_T rettv;
int dummy;
typval_T argv[2];
argv[0].v_type = VAR_NUMBER;
argv[0].vval.v_number = timer->tr_id;
argv[1].v_type = VAR_UNKNOWN;
call_func(timer->tr_callback, (int)STRLEN(timer->tr_callback),
&rettv, 1, argv, 0L, 0L, &dummy, TRUE,
timer->tr_partial, NULL);
clear_tv(&rettv);
}
/*
* Call timers that are due.
* Return the time in msec until the next timer is due.
*/
long
check_due_timer()
{
timer_T *timer;
long this_due;
long next_due;
proftime_T now;
int did_one = FALSE;
# ifdef WIN3264
LARGE_INTEGER fr;
QueryPerformanceFrequency(&fr);
# endif
while (!got_int)
{
profile_start(&now);
next_due = -1;
for (timer = first_timer; timer != NULL; timer = timer->tr_next)
{
# ifdef WIN3264
this_due = (long)(((double)(timer->tr_due.QuadPart - now.QuadPart)
/ (double)fr.QuadPart) * 1000);
# else
this_due = (timer->tr_due.tv_sec - now.tv_sec) * 1000
+ (timer->tr_due.tv_usec - now.tv_usec) / 1000;
# endif
if (this_due <= 1)
{
remove_timer(timer);
timer_callback(timer);
did_one = TRUE;
if (timer->tr_repeat != 0)
{
profile_setlimit(timer->tr_interval, &timer->tr_due);
if (timer->tr_repeat > 0)
--timer->tr_repeat;
insert_timer(timer);
}
else
free_timer(timer);
/* the callback may do anything, start all over */
break;
}
if (next_due == -1 || next_due > this_due)
next_due = this_due;
}
if (timer == NULL)
break;
}
if (did_one)
redraw_after_callback();
return next_due;
}
/*
* Find a timer by ID. Returns NULL if not found;
*/
timer_T *
find_timer(int id)
{
timer_T *timer;
for (timer = first_timer; timer != NULL; timer = timer->tr_next)
if (timer->tr_id == id)
break;
return timer;
}
/*
* Stop a timer and delete it.
*/
void
stop_timer(timer_T *timer)
{
remove_timer(timer);
free_timer(timer);
}
# endif
#if defined(FEAT_SYN_HL) && defined(FEAT_RELTIME) && defined(FEAT_FLOAT)
# if defined(HAVE_MATH_H)
# include <math.h>
+12 -2
View File
@@ -8913,12 +8913,22 @@ ex_sleep(exarg_T *eap)
do_sleep(long msec)
{
long done;
long wait_now;
cursor_on();
out_flush();
for (done = 0; !got_int && done < msec; done += 1000L)
for (done = 0; !got_int && done < msec; done += wait_now)
{
ui_delay(msec - done > 1000L ? 1000L : msec - done, TRUE);
wait_now = msec - done > 1000L ? 1000L : msec - done;
#ifdef FEAT_TIMERS
{
long due_time = check_due_timer();
if (due_time > 0 && due_time < wait_now)
wait_now = due_time;
}
#endif
ui_delay(wait_now, TRUE);
ui_breakcheck();
#ifdef MESSAGE_QUEUE
/* Process the netbeans and clientserver messages that may have been
+7
View File
@@ -399,6 +399,13 @@
# define FEAT_RELTIME
#endif
/*
* +timers timer_start()
*/
#if defined(FEAT_RELTIME) && (defined(UNIX) || defined(WIN32))
# define FEAT_TIMERS
#endif
/*
* +textobjects Text objects: "vaw", "das", etc.
*/
+32 -3
View File
@@ -2892,6 +2892,35 @@ gui_insert_lines(int row, int count)
}
}
static int
gui_wait_for_chars_or_timer(long wtime)
{
#ifdef FEAT_TIMERS
int due_time;
long remaining = wtime;
/* When waiting very briefly don't trigger timers. */
if (wtime >= 0 && wtime < 10L)
return gui_mch_wait_for_chars(wtime);
while (wtime < 0 || remaining > 0)
{
/* Trigger timers and then get the time in wtime until the next one is
* due. Wait up to that time. */
due_time = check_due_timer();
if (due_time <= 0 || (wtime > 0 && due_time > remaining))
due_time = remaining;
if (gui_mch_wait_for_chars(due_time))
return TRUE;
if (wtime > 0)
remaining -= due_time;
}
return FALSE;
#else
return gui_mch_wait_for_chars(wtime);
#endif
}
/*
* The main GUI input routine. Waits for a character from the keyboard.
* wtime == -1 Wait forever.
@@ -2928,7 +2957,7 @@ gui_wait_for_chars(long wtime)
/* Blink when waiting for a character. Probably only does something
* for showmatch() */
gui_mch_start_blink();
retval = gui_mch_wait_for_chars(wtime);
retval = gui_wait_for_chars_or_timer(wtime);
gui_mch_stop_blink();
return retval;
}
@@ -2944,7 +2973,7 @@ gui_wait_for_chars(long wtime)
* 'updatetime' and if nothing is typed within that time put the
* K_CURSORHOLD key in the input buffer.
*/
if (gui_mch_wait_for_chars(p_ut) == OK)
if (gui_wait_for_chars_or_timer(p_ut) == OK)
retval = OK;
#ifdef FEAT_AUTOCMD
else if (trigger_cursorhold())
@@ -2965,7 +2994,7 @@ gui_wait_for_chars(long wtime)
{
/* Blocking wait. */
before_blocking();
retval = gui_mch_wait_for_chars(-1L);
retval = gui_wait_for_chars_or_timer(-1L);
}
gui_mch_stop_blink();
+2 -3
View File
@@ -3682,10 +3682,9 @@ gui_mch_browseW(
filterp = convert_filterW(filter);
vim_memset(&fileStruct, 0, sizeof(OPENFILENAMEW));
#ifdef OPENFILENAME_SIZE_VERSION_400
#ifdef OPENFILENAME_SIZE_VERSION_400W
/* be compatible with Windows NT 4.0 */
/* TODO: what to use for OPENFILENAMEW??? */
fileStruct.lStructSize = OPENFILENAME_SIZE_VERSION_400;
fileStruct.lStructSize = OPENFILENAME_SIZE_VERSION_400W;
#else
fileStruct.lStructSize = sizeof(fileStruct);
#endif
+2 -1
View File
@@ -214,7 +214,8 @@
#define SHM_INTRO 'I' /* intro messages */
#define SHM_COMPLETIONMENU 'c' /* completion menu messages */
#define SHM_RECORDING 'q' /* short recording message */
#define SHM_ALL "rmfixlnwaWtToOsAIcq" /* all possible flags for 'shm' */
#define SHM_FILEINFO 'F' /* no file info messages */
#define SHM_ALL "rmfixlnwaWtToOsAIcqF" /* all possible flags for 'shm' */
/* characters for p_go: */
#define GO_ASEL 'a' /* autoselect */
+1
View File
@@ -91,6 +91,7 @@ void partial_unref(partial_T *pt);
void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
float_T vim_round(float_T f);
long do_searchpair(char_u *spat, char_u *mpat, char_u *epat, int dir, char_u *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, long time_limit);
char_u *get_callback(typval_T *arg, partial_T **pp);
void set_vim_var_nr(int idx, long val);
long get_vim_var_nr(int idx);
char_u *get_vim_var_str(int idx);
+6 -2
View File
@@ -18,6 +18,10 @@ float_T profile_float(proftime_T *tm);
void profile_setlimit(long msec, proftime_T *tm);
int profile_passed_limit(proftime_T *tm);
void profile_zero(proftime_T *tm);
timer_T *create_timer(long msec, int repeats);
long check_due_timer(void);
timer_T *find_timer(int id);
void stop_timer(timer_T *timer);
void profile_divide(proftime_T *tm, int count, proftime_T *tm2);
void profile_add(proftime_T *tm, proftime_T *tm2);
void profile_self(proftime_T *self, proftime_T *total, proftime_T *children);
@@ -60,9 +64,9 @@ void ex_argdelete(exarg_T *eap);
void ex_listdo(exarg_T *eap);
void ex_compiler(exarg_T *eap);
void ex_runtime(exarg_T *eap);
int source_runtime(char_u *name, int all);
int source_runtime(char_u *name, int flags);
int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
int do_in_runtimepath(char_u *name, int all, void (*callback)(char_u *fname, void *ck), void *cookie);
int do_in_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
void ex_packloadall(exarg_T *eap);
void ex_packadd(exarg_T *eap);
void ex_options(exarg_T *eap);
+1
View File
@@ -6,6 +6,7 @@ void redraw_all_later(int type);
void redraw_curbuf_later(int type);
void redraw_buf_later(buf_T *buf, int type);
int redraw_asap(int type);
void redraw_after_callback(void);
void redrawWinline(linenr_T lnum, int invalid);
void update_curbuf(int type);
void update_screen(int type);
+21
View File
@@ -410,6 +410,27 @@ redraw_asap(int type)
return ret;
}
/*
* Invoked after an asynchronous callback is called.
* If an echo command was used the cursor needs to be put back where
* it belongs. If highlighting was changed a redraw is needed.
*/
void
redraw_after_callback()
{
update_screen(0);
setcursor();
cursor_on();
out_flush();
#ifdef FEAT_GUI
if (gui.in_use)
{
gui_update_cursor(TRUE, FALSE);
gui_mch_flush();
}
#endif
}
/*
* Changed something in the current window, at buffer line "lnum", that
* requires that line and possibly other lines to be redrawn.
+15
View File
@@ -2972,3 +2972,18 @@ struct js_reader
void *js_cookie; /* can be used by js_fill */
};
typedef struct js_reader js_read_T;
typedef struct timer_S timer_T;
struct timer_S
{
int tr_id;
#ifdef FEAT_TIMERS
timer_T *tr_next;
timer_T *tr_prev;
proftime_T tr_due; /* when the callback is to be invoked */
int tr_repeat; /* number of times to repeat, -1 forever */
long tr_interval; /* only set when it repeats */
char_u *tr_callback; /* allocated */
partial_T *tr_partial;
#endif
};
+1 -2
View File
@@ -87,7 +87,6 @@ SCRIPTS_ALL = \
test103.out \
test104.out \
test105.out \
test106.out \
test107.out \
test108.out \
test_autocmd_option.out \
@@ -110,7 +109,6 @@ SCRIPTS_ALL = \
test_match_conceal.out \
test_nested_function.out \
test_options.out \
test_qf_title.out \
test_ruby.out \
test_search_mbyte.out \
test_signs.out \
@@ -172,6 +170,7 @@ SCRIPTS_GUI = test16.out
# Keep test_alot.res as the last one, sort the others.
NEW_TESTS = test_arglist.res \
test_assert.res \
test_backspace_opt.res \
test_cdo.res \
test_channel.res \
test_hardcopy.res \
-16
View File
@@ -1,16 +0,0 @@
Tests for errorformat. vim: set ft=vim ts=8 :
STARTTEST
:so small.vim
:if !has('quickfix') | e! test.ok | wq! test.out | endif
:set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#
:cgetexpr ['WWWW', 'EEEE', 'CCCC']
:$put =strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
:cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']
:$put =strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
:cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']
:$put =strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
:/^Results/,$wq! test.out
ENDTEST
Results of test106:
-4
View File
@@ -1,4 +0,0 @@
Results of test106:
[['W', 1], ['E^@CCCC', 1]]
[['W', 1], ['E^@CCCC', 1]]
[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]
+3 -1
View File
@@ -2,13 +2,14 @@
" This makes testing go faster, since Vim doesn't need to restart.
source test_assign.vim
source test_backspace_opt.vim
source test_cursor_func.vim
source test_delete.vim
source test_ex_undo.vim
source test_expand.vim
source test_feedkeys.vim
source test_file_perm.vim
source test_glob2regpat.vim
source test_help_tagjump.vim
source test_join.vim
source test_lispwords.vim
source test_menu.vim
@@ -18,5 +19,6 @@ source test_searchpos.vim
source test_set.vim
source test_sort.vim
source test_syn_attr.vim
source test_timers.vim
source test_undolevels.vim
source test_unlet.vim
+21
View File
@@ -48,6 +48,27 @@ func Test_wrong_error_type()
call assert_equal(type([]), type(verrors))
endfunc
func Test_compare_fail()
let s:v = {}
let s:x = {"a": s:v}
let s:v["b"] = s:x
let s:w = {"c": s:x, "d": ''}
try
call assert_equal(s:w, '')
catch
call assert_exception('E724:')
call assert_true(v:errors[0] =~ "Expected NULL but got ''")
call remove(v:errors, 0)
endtry
endfunc
func Test_assert_fail_fails()
call assert_fails('xxx', {})
call assert_true(v:errors[0] =~ "Expected {} but got 'E731:")
call remove(v:errors, 0)
endfunc
func Test_user_is_happy()
smile
sleep 300m
+1
View File
@@ -53,6 +53,7 @@ func Test_backspace_option()
" Cleared when 'compatible' is set
set compatible
call assert_equal('', &backspace)
set nocompatible
endfunc
" vim: tabstop=2 shiftwidth=0 expandtab
+19
View File
@@ -0,0 +1,19 @@
" Tests for :undo
func Test_ex_undo()
new ex-undo
setlocal ul=10
exe "normal ione\n\<Esc>"
setlocal ul=10
exe "normal itwo\n\<Esc>"
setlocal ul=10
exe "normal ithree\n\<Esc>"
call assert_equal(4, line('$'))
undo
call assert_equal(3, line('$'))
undo 1
call assert_equal(2, line('$'))
undo 0
call assert_equal(1, line('$'))
quit!
endfunc
+18
View File
@@ -0,0 +1,18 @@
" Tests for :help! {subject}
func Test_help_tagjump()
help
call assert_equal("help", &filetype)
call assert_true(getline('.') =~ '\*help.txt\*')
helpclose
exec "help! ('textwidth'"
call assert_equal("help", &filetype)
call assert_true(getline('.') =~ "\\*'textwidth'\\*")
helpclose
exec "help! ('buflisted'),"
call assert_equal("help", &filetype)
call assert_true(getline('.') =~ "\\*'buflisted'\\*")
helpclose
endfunc
+30 -3
View File
@@ -9,9 +9,9 @@ func MySort(up, one, two)
return 0
endif
if a:up
return a:one > a:two
return a:one > a:two ? 1 : -1
endif
return a:one < a:two
return a:one < a:two ? 1 : -1
endfunc
func Test_partial_args()
@@ -19,6 +19,9 @@ func Test_partial_args()
call assert_equal("foo/bar/xxx", Cb("xxx"))
call assert_equal("foo/bar/yyy", call(Cb, ["yyy"]))
let Cb = function('MyFunc', [])
call assert_equal("a/b/c", Cb("a", "b", "c"))
let Sort = function('MySort', [1])
call assert_equal([1, 2, 3], sort([3, 1, 2], Sort))
let Sort = function('MySort', [0])
@@ -34,10 +37,34 @@ func Test_partial_dict()
let Cb = function('MyDictFunc', ["foo", "bar"], dict)
call assert_equal("hello/foo/bar", Cb())
call assert_fails('Cb("xxx")', 'E492:')
let Cb = function('MyDictFunc', ["foo"], dict)
call assert_equal("hello/foo/xxx", Cb("xxx"))
call assert_fails('Cb()', 'E492:')
let Cb = function('MyDictFunc', [], dict)
call assert_equal("hello/ttt/xxx", Cb("ttt", "xxx"))
call assert_fails('Cb("yyy")', 'E492:')
let Cb = function('MyDictFunc', dict)
call assert_equal("hello/xxx/yyy", Cb("xxx", "yyy"))
call assert_fails('Cb()', 'E492:')
call assert_fails('Cb("fff")', 'E492:')
endfunc
func Test_partial_implicit()
let dict = {'name': 'foo'}
func dict.MyFunc(arg) dict
return self.name . '/' . a:arg
endfunc
call assert_equal('foo/bar', dict.MyFunc('bar'))
call assert_fails('let func = dict.MyFunc', 'E704:')
let Func = dict.MyFunc
call assert_equal('foo/aaa', Func('aaa'))
let Func = function(dict.MyFunc, ['bbb'])
call assert_equal('foo/bbb', Func())
call assert_fails('call function(dict.MyFunc, ["bbb"], dict)', 'E924:')
endfunc
-18
View File
@@ -1,18 +0,0 @@
Tests for quickfix window's title vim: set ft=vim :
STARTTEST
:so small.vim
:if !has('quickfix') | e! test.ok | wq! test.out | endif
:set efm=%E%f:%l:%c:%m
:cgetexpr ['file:1:1:message']
:let qflist=getqflist()
:call setqflist(qflist, 'r')
:copen
:let g:quickfix_title=w:quickfix_title
:wincmd p
:$put =g:quickfix_title
:/^Results/,$w test.out
:qa!
ENDTEST
Results of test_qf_title:
-2
View File
@@ -1,2 +0,0 @@
Results of test_qf_title:
:setqflist()
+50
View File
@@ -316,3 +316,53 @@ func Test_errortitle()
augroup END
augroup! QfBufWinEnter
endfunc
function XqfTitleTests(cchar)
let Xgetexpr = a:cchar . 'getexpr'
if a:cchar == 'c'
let Xgetlist = 'getqflist()'
else
let Xgetlist = 'getloclist(0)'
endif
let Xopen = a:cchar . 'open'
let Xclose = a:cchar . 'close'
exe Xgetexpr . " ['file:1:1:message']"
exe 'let l = ' . Xgetlist
if a:cchar == 'c'
call setqflist(l, 'r')
else
call setloclist(0, l, 'r')
endif
exe Xopen
if a:cchar == 'c'
let title = ':setqflist()'
else
let title = ':setloclist()'
endif
call assert_equal(title, w:quickfix_title)
exe Xclose
endfunction
" Tests for quickfix window's title
function Test_qf_title()
call XqfTitleTests('c')
call XqfTitleTests('l')
endfunction
" Tests for 'errorformat'
function Test_efm()
let save_efm = &efm
set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#
cgetexpr ['WWWW', 'EEEE', 'CCCC']
let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']
let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l)
cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY']
let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l)
let &efm = save_efm
endfunction
+32
View File
@@ -0,0 +1,32 @@
" Test for timers
if !has('timers')
finish
endif
func MyHandler(timer)
let s:val += 1
endfunc
func Test_oneshot()
let s:val = 0
let timer = timer_start(50, 'MyHandler')
sleep 200m
call assert_equal(1, s:val)
endfunc
func Test_repeat_three()
let s:val = 0
let timer = timer_start(50, 'MyHandler', {'repeat': 3})
sleep 500m
call assert_equal(3, s:val)
endfunc
func Test_repeat_many()
let s: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)
endfunc
-2
View File
@@ -1,7 +1,5 @@
" Tests for 'undolevels'
set nocompatible viminfo+=nviminfo
func FillBuffer()
for i in range(1,13)
put=i
+8 -1
View File
@@ -2286,7 +2286,14 @@ undo_time(
* Init "closest" to a value we can't reach. */
if (absolute)
{
target = step;
if (step == 0)
{
/* target 0 does not exist, got to 1 and above it. */
target = 1;
above = TRUE;
}
else
target = step;
closest = -1;
}
else
+39
View File
@@ -636,6 +636,11 @@ static char *(features[]) =
#else
"-textobjects",
#endif
#ifdef FEAT_TIMERS
"+timers",
#else
"-timers",
#endif
#ifdef FEAT_TITLE
"+title",
#else
@@ -758,6 +763,40 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1579,
/**/
1578,
/**/
1577,
/**/
1576,
/**/
1575,
/**/
1574,
/**/
1573,
/**/
1572,
/**/
1571,
/**/
1570,
/**/
1569,
/**/
1568,
/**/
1567,
/**/
1566,
/**/
1565,
/**/
1564,
/**/
1563,
/**/
1562,
/**/