Compare commits

...

11 Commits

Author SHA1 Message Date
Bram Moolenaar
5409f5d8c9 patch 8.2.1047: Vim9: script cannot use line continuation like :def function
Problem:    Vim9: script cannot use line continuation like in a :def function.
Solution:   Pass the getline function pointer to the eval() functions.  Use it
            for addition and multiplication operators.
2020-06-24 18:37:35 +02:00
Bram Moolenaar
b7e2483655 patch 8.2.1046: insufficient tests for src/buffer.c
Problem:    Insufficient tests for src/buffer.c.
Solution:   Add more tests.  Move comments related tests to a separate file.
            (Yegappan Lakshmanan, closes #6325)
2020-06-24 13:37:35 +02:00
Bram Moolenaar
67fbdfefd2 patch 8.2.1045: Vim9: line break before operator does not work
Problem:    Vim9: line break before operator does not work.
Solution:   Peek the next line for an operator.
2020-06-23 22:26:05 +02:00
Bram Moolenaar
ef6d86c173 patch 8.2.1044: not all systemd file types are recognized
Problem:    Not all systemd file types are recognized.
Solution:   Match several more files. (Guido Cella, closes #6319)
2020-06-23 21:01:38 +02:00
Bram Moolenaar
4014e2ceb0 patch 8.2.1043: %a item in 'statusline' not tested
Problem:    %a item in 'statusline' not tested.
Solution:   Add a test. (Dominique Pellé, closes #6318)
2020-06-23 20:00:50 +02:00
Bram Moolenaar
df069eec3b patch 8.2.1042: Vim9: cannot put an operator on the next line
Problem:    Vim9: cannot put an operator on the next line.
Solution:   Require a colon before a range to see if that causes problems.
2020-06-22 23:02:51 +02:00
Bram Moolenaar
7eaafe65ee patch 8.2.1041: test summary is missing executed count
Problem:    Test summary is missing executed count.
Solution:   Adjust pattern used for counting.
2020-06-22 22:10:06 +02:00
Bram Moolenaar
bdd2c290d3 patch 8.2.1040: not enough testing for movement commands
Problem:    Not enough testing for movement commands.
Solution:   Add more tests. (Yegappan Lakshmanan, closes #6313)
2020-06-22 21:34:30 +02:00
Bram Moolenaar
25fd267287 patch 8.2.1039: cannot put NUL byte on clipboard
Problem:    Cannot put NUL byte on clipboard.
Solution:   Use the text length. (Christian Brabandt, closes #6312,
            closes #6149)
2020-06-22 20:30:27 +02:00
Bram Moolenaar
b2b218d89b patch 8.2.1038: popupwin test fails
Problem:    Popupwin test fails.
Solution:   Fix WaitForAssert() argument.
2020-06-22 20:22:19 +02:00
Bram Moolenaar
acd4c5e914 patch 8.2.1037: Vim9: crash when using line continuation inside :def
Problem:    Vim9: crash when using line continuation inside :def.
Solution:   Check for no more lines available.
2020-06-22 19:39:03 +02:00
38 changed files with 1281 additions and 493 deletions

View File

@@ -1,4 +1,4 @@
*vim9.txt* For Vim version 8.2. Last change: 2020 Jun 21
*vim9.txt* For Vim version 8.2. Last change: 2020 Jun 22
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -257,27 +257,32 @@ Function call: >
arg2
)
For binary operators iin expressions not in [], {} or () a line break is
possible AFTER the operators. For example: >
let text = lead ..
middle ..
end
For binary operators in expressions not in [], {} or () a line break is
possible just before or after the operator. For example: >
let text = lead
.. middle
.. end
let total = start +
end -
correction
let result = positive ?
PosFunc(arg) :
NegFunc(arg)
let result = positive
? PosFunc(arg)
: NegFunc(arg)
A special case is "->" for function call chains, it can appear in the next
line: >
let result = GetBuilder()
->BuilderSetWidth(333)
->BuilderSetHeight(777)
->BuilderBuild()
Note that "enddef" cannot be used at the start of a continuation line, it ends
the current function.
< *E1050*
To make it possible for the operator at the start of the line to be
recognized, it is required to put a colon before a range. This will adde
"start" and print: >
let result = start
+ print
This will assign "start" and print a line: >
let result = start
:+ print
It is also possible to split a function header over multiple lines, in between
arguments: >
@@ -286,6 +291,9 @@ arguments: >
separator = '-'
): string
Note that "enddef" cannot be used at the start of a continuation line, it ends
the current function.
No curly braces expansion ~

View File

@@ -1655,8 +1655,9 @@ au BufNewFile,BufRead *.sil setf sil
au BufNewFile,BufRead */etc/sysctl.conf,*/etc/sysctl.d/*.conf setf sysctl
" Systemd unit files
au BufNewFile,BufRead */systemd/*.{automount,mount,path,service,socket,swap,target,timer} setf systemd
au BufNewFile,BufRead */systemd/*.{automount,dnssd,link,mount,netdev,network,nspawn,path,service,slice,socket,swap,target,timer} setf systemd
" Systemd overrides
au BufNewFile,BufRead */etc/systemd/*.conf.d/*.conf setf systemd
au BufNewFile,BufRead */etc/systemd/system/*.d/*.conf setf systemd
au BufNewFile,BufRead */.config/systemd/user/*.d/*.conf setf systemd
" Systemd temp files

View File

@@ -788,12 +788,14 @@ get_literal_key(char_u **arg, typval_T *tv)
/*
* Allocate a variable for a Dictionary and fill it from "*arg".
* "literal" is TRUE for #{key: val}
* "flags" can have EVAL_EVALUATE and other EVAL_ flags.
* Return OK or FAIL. Returns NOTDONE for {expr}.
*/
int
eval_dict(char_u **arg, typval_T *rettv, int flags, int literal)
{
int evaluate = flags & EVAL_EVALUATE;
evalarg_T evalarg;
dict_T *d = NULL;
typval_T tvkey;
typval_T tv;
@@ -803,6 +805,9 @@ eval_dict(char_u **arg, typval_T *rettv, int flags, int literal)
char_u buf[NUMBUFLEN];
int vim9script = current_sctx.sc_version == SCRIPT_VERSION_VIM9;
CLEAR_FIELD(evalarg);
evalarg.eval_flags = flags;
/*
* First check if it's not a curly-braces thing: {expr}.
* Must do this without evaluating, otherwise a function may be called
@@ -812,7 +817,7 @@ eval_dict(char_u **arg, typval_T *rettv, int flags, int literal)
*/
if (!vim9script && *start != '}')
{
if (eval1(&start, &tv, 0) == FAIL) // recursive!
if (eval1(&start, &tv, NULL) == FAIL) // recursive!
return FAIL;
if (*start == '}')
return NOTDONE;
@@ -832,7 +837,7 @@ eval_dict(char_u **arg, typval_T *rettv, int flags, int literal)
{
if ((literal
? get_literal_key(arg, &tvkey)
: eval1(arg, &tvkey, flags)) == FAIL) // recursive!
: eval1(arg, &tvkey, &evalarg)) == FAIL) // recursive!
goto failret;
if (**arg != ':')
@@ -854,7 +859,7 @@ eval_dict(char_u **arg, typval_T *rettv, int flags, int literal)
}
*arg = skipwhite(*arg + 1);
if (eval1(arg, &tv, flags) == FAIL) // recursive!
if (eval1(arg, &tv, &evalarg) == FAIL) // recursive!
{
if (evaluate)
clear_tv(&tvkey);

View File

@@ -45,12 +45,12 @@ typedef struct
} forinfo_T;
static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op);
static int eval2(char_u **arg, typval_T *rettv, int flags);
static int eval3(char_u **arg, typval_T *rettv, int flags);
static int eval4(char_u **arg, typval_T *rettv, int flags);
static int eval5(char_u **arg, typval_T *rettv, int flags);
static int eval6(char_u **arg, typval_T *rettv, int flags, int want_string);
static int eval7(char_u **arg, typval_T *rettv, int flags, int want_string);
static int eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
static int eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
static int eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
static int eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
static int eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
static int eval7(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
static int eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp);
static int free_unref_items(int copyID);
@@ -169,7 +169,7 @@ eval_to_bool(
if (skip)
++emsg_skip;
if (eval0(arg, &tv, nextcmd, skip ? 0 : EVAL_EVALUATE) == FAIL)
if (eval0(arg, &tv, nextcmd, skip ? NULL : &EVALARG_EVALUATE) == FAIL)
*error = TRUE;
else
{
@@ -197,7 +197,7 @@ eval1_emsg(char_u **arg, typval_T *rettv, int evaluate)
int did_emsg_before = did_emsg;
int called_emsg_before = called_emsg;
ret = eval1(arg, rettv, evaluate ? EVAL_EVALUATE : 0);
ret = eval1(arg, rettv, evaluate ? &EVALARG_EVALUATE : NULL);
if (ret == FAIL)
{
// Report the invalid expression unless the expression evaluation has
@@ -325,7 +325,8 @@ eval_to_string_skip(
if (skip)
++emsg_skip;
if (eval0(arg, &tv, nextcmd, skip ? 0 : EVAL_EVALUATE) == FAIL || skip)
if (eval0(arg, &tv, nextcmd, skip ? NULL : &EVALARG_EVALUATE)
== FAIL || skip)
retval = NULL;
else
{
@@ -348,7 +349,7 @@ skip_expr(char_u **pp)
typval_T rettv;
*pp = skipwhite(*pp);
return eval1(pp, &rettv, 0);
return eval1(pp, &rettv, NULL);
}
/*
@@ -370,7 +371,7 @@ eval_to_string(
char_u numbuf[NUMBUFLEN];
#endif
if (eval0(arg, &tv, nextcmd, EVAL_EVALUATE) == FAIL)
if (eval0(arg, &tv, nextcmd, &EVALARG_EVALUATE) == FAIL)
retval = NULL;
else
{
@@ -440,7 +441,7 @@ eval_to_number(char_u *expr)
++emsg_off;
if (eval1(&p, &rettv, EVAL_EVALUATE) == FAIL)
if (eval1(&p, &rettv, &EVALARG_EVALUATE) == FAIL)
retval = -1;
else
{
@@ -463,7 +464,7 @@ eval_expr(char_u *arg, char_u **nextcmd)
typval_T *tv;
tv = ALLOC_ONE(typval_T);
if (tv != NULL && eval0(arg, tv, nextcmd, EVAL_EVALUATE) == FAIL)
if (tv != NULL && eval0(arg, tv, nextcmd, &EVALARG_EVALUATE) == FAIL)
VIM_CLEAR(tv);
return tv;
@@ -588,7 +589,7 @@ eval_foldexpr(char_u *arg, int *cp)
++sandbox;
++textwinlock;
*cp = NUL;
if (eval0(arg, &tv, NULL, EVAL_EVALUATE) == FAIL)
if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL)
retval = 0;
else
{
@@ -776,7 +777,7 @@ get_lval(
else
{
empty1 = FALSE;
if (eval1(&p, &var1, EVAL_EVALUATE) == FAIL) // recursive!
if (eval1(&p, &var1, &EVALARG_EVALUATE) == FAIL) // recursive!
return NULL;
if (tv_get_string_chk(&var1) == NULL)
{
@@ -814,7 +815,7 @@ get_lval(
{
lp->ll_empty2 = FALSE;
// recursive!
if (eval1(&p, &var2, EVAL_EVALUATE) == FAIL)
if (eval1(&p, &var2, &EVALARG_EVALUATE) == FAIL)
{
clear_tv(&var1);
return NULL;
@@ -1424,7 +1425,10 @@ eval_for_line(
char_u *expr;
typval_T tv;
list_T *l;
evalarg_T evalarg;
CLEAR_FIELD(evalarg);
evalarg.eval_flags = skip ? 0 : EVAL_EVALUATE;
*errp = TRUE; // default: there is an error
fi = ALLOC_CLEAR_ONE(forinfo_T);
@@ -1444,8 +1448,7 @@ eval_for_line(
if (skip)
++emsg_skip;
if (eval0(skipwhite(expr + 2), &tv, nextcmdp, skip ? 0 : EVAL_EVALUATE)
== OK)
if (eval0(skipwhite(expr + 2), &tv, nextcmdp, &evalarg) == OK)
{
*errp = FALSE;
if (!skip)
@@ -1763,6 +1766,35 @@ eval_func(
return ret;
}
/*
* If inside Vim9 script, "arg" points to the end of a line (ignoring comments)
* and there is a next line, return the next line (skipping blanks) and set
* "getnext".
* Otherwise just return "arg" unmodified and set "getnext" to FALSE.
* "arg" must point somewhere inside a line, not at the start.
*/
static char_u *
eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
{
*getnext = FALSE;
if (current_sctx.sc_version == SCRIPT_VERSION_VIM9
&& evalarg != NULL
&& evalarg->eval_cookie != NULL
&& (*arg == NUL || (VIM_ISWHITE(arg[-1])
&& (*arg == '"' || *arg == '#')))
&& source_nextline(evalarg->eval_cookie) != NULL)
{
char_u *p = source_nextline(evalarg->eval_cookie);
if (p != NULL)
{
*getnext = TRUE;
return skipwhite(p);
}
}
return arg;
}
/*
* The "evaluate" argument: When FALSE, the argument is only parsed but not
* executed. The function may return OK, but the rettv will be of type
@@ -1774,7 +1806,7 @@ eval_func(
* This calls eval1() and handles error message and nextcmd.
* Put the result in "rettv" when returning OK and "evaluate" is TRUE.
* Note: "rettv.v_lock" is not set.
* "flags" has EVAL_EVALUATE and similar flags.
* "evalarg" can be NULL, EVALARG_EVALUATE or a pointer.
* Return OK or FAIL.
*/
int
@@ -1782,15 +1814,16 @@ eval0(
char_u *arg,
typval_T *rettv,
char_u **nextcmd,
int flags)
evalarg_T *evalarg)
{
int ret;
char_u *p;
int did_emsg_before = did_emsg;
int called_emsg_before = called_emsg;
int flags = evalarg == NULL ? 0 : evalarg->eval_flags;
p = skipwhite(arg);
ret = eval1(&p, rettv, flags);
ret = eval1(&p, rettv, evalarg);
if (ret == FAIL || !ends_excmd2(arg, p))
{
if (ret != FAIL)
@@ -1826,23 +1859,36 @@ eval0(
* Return OK or FAIL.
*/
int
eval1(char_u **arg, typval_T *rettv, int flags)
eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
{
int result;
typval_T var2;
/*
* Get the first variable.
*/
if (eval2(arg, rettv, flags) == FAIL)
if (eval2(arg, rettv, evalarg) == FAIL)
return FAIL;
if ((*arg)[0] == '?')
{
int evaluate = flags & EVAL_EVALUATE;
int result;
typval_T var2;
evalarg_T nested_evalarg;
int orig_flags;
if (evalarg == NULL)
{
CLEAR_FIELD(nested_evalarg);
orig_flags = 0;
}
else
{
nested_evalarg = *evalarg;
orig_flags = evalarg->eval_flags;
}
int evaluate = nested_evalarg.eval_flags & EVAL_EVALUATE;
result = FALSE;
if (flags & EVAL_EVALUATE)
if (evaluate)
{
int error = FALSE;
@@ -1857,7 +1903,9 @@ eval1(char_u **arg, typval_T *rettv, int flags)
* Get the second variable. Recursive!
*/
*arg = skipwhite(*arg + 1);
if (eval1(arg, rettv, result ? flags : flags & ~EVAL_EVALUATE) == FAIL)
nested_evalarg.eval_flags = result ? orig_flags
: orig_flags & ~EVAL_EVALUATE;
if (eval1(arg, rettv, &nested_evalarg) == FAIL)
return FAIL;
/*
@@ -1875,7 +1923,9 @@ eval1(char_u **arg, typval_T *rettv, int flags)
* Get the third variable. Recursive!
*/
*arg = skipwhite(*arg + 1);
if (eval1(arg, &var2, !result ? flags : flags & ~EVAL_EVALUATE) == FAIL)
nested_evalarg.eval_flags = !result ? orig_flags
: orig_flags & ~EVAL_EVALUATE;
if (eval1(arg, &var2, &nested_evalarg) == FAIL)
{
if (evaluate && result)
clear_tv(rettv);
@@ -1898,7 +1948,7 @@ eval1(char_u **arg, typval_T *rettv, int flags)
* Return OK or FAIL.
*/
static int
eval2(char_u **arg, typval_T *rettv, int flags)
eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
{
typval_T var2;
long result;
@@ -1908,7 +1958,7 @@ eval2(char_u **arg, typval_T *rettv, int flags)
/*
* Get the first variable.
*/
if (eval3(arg, rettv, flags) == FAIL)
if (eval3(arg, rettv, evalarg) == FAIL)
return FAIL;
/*
@@ -1918,7 +1968,22 @@ eval2(char_u **arg, typval_T *rettv, int flags)
result = FALSE;
while ((*arg)[0] == '|' && (*arg)[1] == '|')
{
int evaluate = flags & EVAL_EVALUATE;
evalarg_T nested_evalarg;
int evaluate;
int orig_flags;
if (evalarg == NULL)
{
CLEAR_FIELD(nested_evalarg);
orig_flags = 0;
evaluate = FALSE;
}
else
{
nested_evalarg = *evalarg;
orig_flags = evalarg->eval_flags;
evaluate = orig_flags & EVAL_EVALUATE;
}
if (evaluate && first)
{
@@ -1934,8 +1999,9 @@ eval2(char_u **arg, typval_T *rettv, int flags)
* Get the second variable.
*/
*arg = skipwhite(*arg + 2);
if (eval3(arg, &var2, !result ? flags : flags & ~EVAL_EVALUATE)
== FAIL)
nested_evalarg.eval_flags = !result ? orig_flags
: orig_flags & ~EVAL_EVALUATE;
if (eval3(arg, &var2, &nested_evalarg) == FAIL)
return FAIL;
/*
@@ -1969,7 +2035,7 @@ eval2(char_u **arg, typval_T *rettv, int flags)
* Return OK or FAIL.
*/
static int
eval3(char_u **arg, typval_T *rettv, int flags)
eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
{
typval_T var2;
long result;
@@ -1979,7 +2045,7 @@ eval3(char_u **arg, typval_T *rettv, int flags)
/*
* Get the first variable.
*/
if (eval4(arg, rettv, flags) == FAIL)
if (eval4(arg, rettv, evalarg) == FAIL)
return FAIL;
/*
@@ -1989,8 +2055,22 @@ eval3(char_u **arg, typval_T *rettv, int flags)
result = TRUE;
while ((*arg)[0] == '&' && (*arg)[1] == '&')
{
int evaluate = flags & EVAL_EVALUATE;
evalarg_T nested_evalarg;
int orig_flags;
int evaluate;
if (evalarg == NULL)
{
CLEAR_FIELD(nested_evalarg);
orig_flags = 0;
evaluate = FALSE;
}
else
{
nested_evalarg = *evalarg;
orig_flags = evalarg->eval_flags;
evaluate = orig_flags & EVAL_EVALUATE;
}
if (evaluate && first)
{
if (tv_get_number_chk(rettv, &error) == 0)
@@ -2005,7 +2085,9 @@ eval3(char_u **arg, typval_T *rettv, int flags)
* Get the second variable.
*/
*arg = skipwhite(*arg + 2);
if (eval4(arg, &var2, result ? flags : flags & ~EVAL_EVALUATE) == FAIL)
nested_evalarg.eval_flags = result ? orig_flags
: orig_flags & ~EVAL_EVALUATE;
if (eval4(arg, &var2, &nested_evalarg) == FAIL)
return FAIL;
/*
@@ -2048,7 +2130,7 @@ eval3(char_u **arg, typval_T *rettv, int flags)
* Return OK or FAIL.
*/
static int
eval4(char_u **arg, typval_T *rettv, int flags)
eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
{
typval_T var2;
char_u *p;
@@ -2060,7 +2142,7 @@ eval4(char_u **arg, typval_T *rettv, int flags)
/*
* Get the first variable.
*/
if (eval5(arg, rettv, flags) == FAIL)
if (eval5(arg, rettv, evalarg) == FAIL)
return FAIL;
p = *arg;
@@ -2128,12 +2210,12 @@ eval4(char_u **arg, typval_T *rettv, int flags)
* Get the second variable.
*/
*arg = skipwhite(p + len);
if (eval5(arg, &var2, flags) == FAIL)
if (eval5(arg, &var2, evalarg) == FAIL)
{
clear_tv(rettv);
return FAIL;
}
if (flags & EVAL_EVALUATE)
if (evalarg != NULL && (evalarg->eval_flags & EVAL_EVALUATE))
{
int ret = typval_compare(rettv, &var2, type, ic);
@@ -2195,23 +2277,14 @@ eval_addlist(typval_T *tv1, typval_T *tv2)
* Return OK or FAIL.
*/
static int
eval5(char_u **arg, typval_T *rettv, int flags)
eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
{
typval_T var2;
int op;
varnumber_T n1, n2;
#ifdef FEAT_FLOAT
float_T f1 = 0, f2 = 0;
#endif
char_u *s1, *s2;
char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
char_u *p;
int concat;
int evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
/*
* Get the first variable.
*/
if (eval6(arg, rettv, flags, FALSE) == FAIL)
if (eval6(arg, rettv, evalarg, FALSE) == FAIL)
return FAIL;
/*
@@ -2219,12 +2292,20 @@ eval5(char_u **arg, typval_T *rettv, int flags)
*/
for (;;)
{
int getnext;
char_u *p;
int op;
int concat;
typval_T var2;
// "." is only string concatenation when scriptversion is 1
op = **arg;
concat = op == '.'
&& (*(*arg + 1) == '.' || current_sctx.sc_version < 2);
p = eval_next_non_blank(*arg, evalarg, &getnext);
op = *p;
concat = op == '.' && (*(p + 1) == '.' || current_sctx.sc_version < 2);
if (op != '+' && op != '-' && !concat)
break;
if (getnext)
*arg = skipwhite(getsourceline(0, evalarg->eval_cookie, 0, TRUE));
if ((op != '+' || (rettv->v_type != VAR_LIST
&& rettv->v_type != VAR_BLOB))
@@ -2240,7 +2321,7 @@ eval5(char_u **arg, typval_T *rettv, int flags)
// we know that the first operand needs to be a string or number
// without evaluating the 2nd operand. So check before to avoid
// side effects after an error.
if ((flags & EVAL_EVALUATE) && tv_get_string_chk(rettv) == NULL)
if (evaluate && tv_get_string_chk(rettv) == NULL)
{
clear_tv(rettv);
return FAIL;
@@ -2253,21 +2334,23 @@ eval5(char_u **arg, typval_T *rettv, int flags)
if (op == '.' && *(*arg + 1) == '.') // .. string concatenation
++*arg;
*arg = skipwhite(*arg + 1);
if (eval6(arg, &var2, flags, op == '.') == FAIL)
if (eval6(arg, &var2, evalarg, op == '.') == FAIL)
{
clear_tv(rettv);
return FAIL;
}
if (flags & EVAL_EVALUATE)
if (evaluate)
{
/*
* Compute the result.
*/
if (op == '.')
{
s1 = tv_get_string_buf(rettv, buf1); // already checked
s2 = tv_get_string_buf_chk(&var2, buf2);
char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
char_u *s1 = tv_get_string_buf(rettv, buf1);
char_u *s2 = tv_get_string_buf_chk(&var2, buf2);
if (s2 == NULL) // type error ?
{
clear_tv(rettv);
@@ -2290,9 +2373,11 @@ eval5(char_u **arg, typval_T *rettv, int flags)
}
else
{
int error = FALSE;
int error = FALSE;
varnumber_T n1, n2;
#ifdef FEAT_FLOAT
float_T f1 = 0, f2 = 0;
if (rettv->v_type == VAR_FLOAT)
{
f1 = rettv->vval.v_float;
@@ -2381,7 +2466,7 @@ eval5(char_u **arg, typval_T *rettv, int flags)
eval6(
char_u **arg,
typval_T *rettv,
int flags,
evalarg_T *evalarg,
int want_string) // after "." operator
{
typval_T var2;
@@ -2396,7 +2481,7 @@ eval6(
/*
* Get the first variable.
*/
if (eval7(arg, rettv, flags, want_string) == FAIL)
if (eval7(arg, rettv, evalarg, want_string) == FAIL)
return FAIL;
/*
@@ -2404,11 +2489,17 @@ eval6(
*/
for (;;)
{
op = **arg;
int evaluate = evalarg == NULL ? 0
: (evalarg->eval_flags & EVAL_EVALUATE);
int getnext;
op = *eval_next_non_blank(*arg, evalarg, &getnext);
if (op != '*' && op != '/' && op != '%')
break;
if (getnext)
*arg = skipwhite(getsourceline(0, evalarg->eval_cookie, 0, TRUE));
if (flags & EVAL_EVALUATE)
if (evaluate)
{
#ifdef FEAT_FLOAT
if (rettv->v_type == VAR_FLOAT)
@@ -2431,10 +2522,10 @@ eval6(
* Get the second variable.
*/
*arg = skipwhite(*arg + 1);
if (eval7(arg, &var2, flags, FALSE) == FAIL)
if (eval7(arg, &var2, evalarg, FALSE) == FAIL)
return FAIL;
if (flags & EVAL_EVALUATE)
if (evaluate)
{
#ifdef FEAT_FLOAT
if (var2.v_type == VAR_FLOAT)
@@ -2551,10 +2642,12 @@ eval6(
eval7(
char_u **arg,
typval_T *rettv,
int flags,
evalarg_T *evalarg,
int want_string) // after "." operator
{
int evaluate = flags & EVAL_EVALUATE;
int flags = evalarg == NULL ? 0 : evalarg->eval_flags;
int evaluate = evalarg != NULL
&& (evalarg->eval_flags & EVAL_EVALUATE);
int len;
char_u *s;
char_u *start_leader, *end_leader;
@@ -2672,15 +2765,17 @@ eval7(
/*
* nested expression: (expression).
*/
case '(': *arg = skipwhite(*arg + 1);
ret = eval1(arg, rettv, flags); // recursive!
if (**arg == ')')
++*arg;
else if (ret == OK)
{
emsg(_(e_missing_close));
clear_tv(rettv);
ret = FAIL;
case '(': {
*arg = skipwhite(*arg + 1);
ret = eval1(arg, rettv, evalarg); // recursive!
if (**arg == ')')
++*arg;
else if (ret == OK)
{
emsg(_(e_missing_close));
clear_tv(rettv);
ret = FAIL;
}
}
break;
@@ -3030,6 +3125,11 @@ eval_index(
}
else
{
evalarg_T evalarg;
CLEAR_FIELD(evalarg);
evalarg.eval_flags = flags;
/*
* something[idx]
*
@@ -3038,7 +3138,7 @@ eval_index(
*arg = skipwhite(*arg + 1);
if (**arg == ':')
empty1 = TRUE;
else if (eval1(arg, &var1, flags) == FAIL) // recursive!
else if (eval1(arg, &var1, &evalarg) == FAIL) // recursive!
return FAIL;
else if (evaluate && tv_get_string_chk(&var1) == NULL)
{
@@ -3056,7 +3156,7 @@ eval_index(
*arg = skipwhite(*arg + 1);
if (**arg == ']')
empty2 = TRUE;
else if (eval1(arg, &var2, flags) == FAIL) // recursive!
else if (eval1(arg, &var2, &evalarg) == FAIL) // recursive!
{
if (!empty1)
clear_tv(&var1);
@@ -4947,6 +5047,10 @@ ex_echo(exarg_T *eap)
int atstart = TRUE;
int did_emsg_before = did_emsg;
int called_emsg_before = called_emsg;
evalarg_T evalarg;
CLEAR_FIELD(evalarg);
evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
if (eap->skip)
++emsg_skip;
@@ -4957,7 +5061,7 @@ ex_echo(exarg_T *eap)
need_clr_eos = needclr;
p = arg;
if (eval1(&arg, &rettv, eap->skip ? 0 : EVAL_EVALUATE) == FAIL)
if (eval1(&arg, &rettv, &evalarg) == FAIL)
{
/*
* Report the invalid expression unless the expression evaluation

View File

@@ -2084,7 +2084,7 @@ f_eval(typval_T *argvars, typval_T *rettv)
s = skipwhite(s);
p = s;
if (s == NULL || eval1(&s, rettv, EVAL_EVALUATE) == FAIL)
if (s == NULL || eval1(&s, rettv, &EVALARG_EVALUATE) == FAIL)
{
if (p != NULL && !aborting())
semsg(_(e_invexpr2), p);

View File

@@ -435,7 +435,7 @@ eval_spell_expr(char_u *badword, char_u *expr)
if (p_verbose == 0)
++emsg_off;
if (eval1(&p, &rettv, EVAL_EVALUATE) == OK)
if (eval1(&p, &rettv, &EVALARG_EVALUATE) == OK)
{
if (rettv.v_type != VAR_LIST)
clear_tv(&rettv);
@@ -774,7 +774,7 @@ ex_let(exarg_T *eap)
}
else
{
int eval_flags;
evalarg_T evalarg;
rettv.v_type = VAR_UNKNOWN;
i = FAIL;
@@ -797,14 +797,17 @@ ex_let(exarg_T *eap)
if (eap->skip)
++emsg_skip;
eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
i = eval0(expr, &rettv, &eap->nextcmd, eval_flags);
evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
evalarg.eval_cookie = eap->getline == getsourceline
? eap->cookie : NULL;
i = eval0(expr, &rettv, &eap->nextcmd, &evalarg);
if (eap->skip)
--emsg_skip;
}
if (eap->skip)
{
if (i != FAIL)
clear_tv(&rettv);
--emsg_skip;
}
else if (i != FAIL)
{

View File

@@ -1729,7 +1729,14 @@ do_one_cmd(
#ifdef FEAT_EVAL
if (current_sctx.sc_version == SCRIPT_VERSION_VIM9 && !starts_with_colon)
{
if (ea.cmd > cmd)
{
emsg(_(e_colon_required));
goto doend;
}
p = find_ex_command(&ea, NULL, lookup_scriptvar, NULL);
}
else
#endif
p = find_ex_command(&ea, NULL, NULL, NULL);
@@ -3446,7 +3453,7 @@ excmd_get_argt(cmdidx_T idx)
* Backslashed delimiters after / or ? will be skipped, and commands will
* not be expanded between /'s and ?'s or after "'".
*
* Also skip white space and ":" characters.
* Also skip white space and ":" characters after the range.
* Returns the "cmd" pointer advanced to beyond the range.
*/
char_u *

View File

@@ -895,9 +895,12 @@ report_discard_pending(int pending, void *value)
ex_eval(exarg_T *eap)
{
typval_T tv;
evalarg_T evalarg;
if (eval0(eap->arg, &tv, &eap->nextcmd, eap->skip ? 0 : EVAL_EVALUATE)
== OK)
evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
evalarg.eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL;
if (eval0(eap->arg, &tv, &eap->nextcmd, &evalarg) == OK)
clear_tv(&tv);
}

View File

@@ -1790,6 +1790,7 @@ EXTERN char e_const_req_value[] INIT(= N_("E1021: const requires a value"));
EXTERN char e_type_req[] INIT(= N_("E1022: type or initialization required"));
EXTERN char e_declare_var[] INIT(= N_("E1016: Cannot declare a %s variable: %s"));
EXTERN char e_declare_env_var[] INIT(= N_("E1016: Cannot declare an environment variable: %s"));
EXTERN char e_colon_required[] INIT(= N_("E1050: Colon required before a range"));
#endif
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
EXTERN char e_alloc_color[] INIT(= N_("E254: Cannot allocate color %s"));
@@ -1879,6 +1880,9 @@ EXTERN char windowsVersion[20] INIT(= {0});
// Used for lv_first in a non-materialized range() list.
EXTERN listitem_T range_list_item;
// Passed to an eval() function to enable evaluation.
EXTERN evalarg_T EVALARG_EVALUATE INIT2(EVAL_EVALUATE, NULL);
#endif
#ifdef MSWIN

View File

@@ -1165,6 +1165,10 @@ get_list_tv(char_u **arg, typval_T *rettv, int flags, int do_error)
list_T *l = NULL;
typval_T tv;
listitem_T *item;
evalarg_T evalarg;
CLEAR_FIELD(evalarg);
evalarg.eval_flags = flags;
if (evaluate)
{
@@ -1176,7 +1180,7 @@ get_list_tv(char_u **arg, typval_T *rettv, int flags, int do_error)
*arg = skipwhite(*arg + 1);
while (**arg != ']' && **arg != NUL)
{
if (eval1(arg, &tv, flags) == FAIL) // recursive!
if (eval1(arg, &tv, &evalarg) == FAIL) // recursive!
goto failret;
if (evaluate)
{

View File

@@ -26,8 +26,8 @@ int next_for_item(void *fi_void, char_u *arg);
void free_for_info(void *fi_void);
void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx);
int pattern_match(char_u *pat, char_u *text, int ic);
int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int flags);
int eval1(char_u **arg, typval_T *rettv, int flags);
int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, evalarg_T *evalarg);
int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg_in);
void eval_addblob(typval_T *tv1, typval_T *tv2);
int eval_addlist(typval_T *tv1, typval_T *tv2);
char_u *partial_name(partial_T *pt);

View File

@@ -22,6 +22,7 @@ void ex_options(exarg_T *eap);
linenr_T *source_breakpoint(void *cookie);
int *source_dbg_tick(void *cookie);
int source_level(void *cookie);
char_u *source_nextline(void *cookie);
int do_source(char_u *fname, int check_other, int is_vimrc, int *ret_sid);
void ex_scriptnames(exarg_T *eap);
void scriptnames_slash_adjust(void);

View File

@@ -1050,6 +1050,15 @@ source_level(void *cookie)
{
return ((struct source_cookie *)cookie)->level;
}
/*
* Return the readahead line.
*/
char_u *
source_nextline(void *cookie)
{
return ((struct source_cookie *)cookie)->nextline;
}
#endif
#if (defined(MSWIN) && defined(FEAT_CSCOPE)) || defined(HAVE_FD_CLOEXEC)

View File

@@ -1746,6 +1746,19 @@ typedef struct
# endif
} scriptitem_T;
// Struct passed through eval() functions.
// See EVALARG_EVALUATE for a fixed value with eval_flags set to EVAL_EVALUATE.
typedef struct {
int eval_flags; // EVAL_ flag values below
// copied from exarg_T when "getline" is "getsourceline". Can be NULL.
void *eval_cookie; // argument for getline()
} evalarg_T;
// Flags for expression evaluation.
#define EVAL_EVALUATE 1 // when missing don't actually evaluate
#define EVAL_CONSTANT 2 // when not a constant return FAIL
# ifdef FEAT_PROFILE
/*
* Struct used in sn_prl_ga for every line of a script.

View File

@@ -90,6 +90,7 @@ NEW_TESTS = \
test_close_count \
test_cmdline \
test_command_count \
test_comments \
test_comparators \
test_compiler \
test_conceal \
@@ -341,6 +342,7 @@ NEW_TESTS_RES = \
test_close_count.res \
test_cmdline.res \
test_command_count.res \
test_comments.res \
test_comparators.res \
test_conceal.res \
test_const.res \

View File

@@ -28,7 +28,7 @@ if 1
" This uses the :s command to just fetch and process the output of the
" tests, it doesn't actually replace anything.
" And it uses "silent" to avoid reporting the number of matches.
silent %s/^Executed\s\+\zs\d\+\ze\s\+tests\?/\=Count(submatch(0),'executed')/egn
silent %s/Executed\s\+\zs\d\+\ze\s\+tests\?/\=Count(submatch(0),'executed')/egn
silent %s/^SKIPPED \zs.*/\=Count(submatch(0), 'skipped')/egn
silent %s/^\(\d\+\)\s\+FAILED:/\=Count(submatch(1), 'failed')/egn

View File

@@ -1,5 +1,7 @@
" Tests for Vim buffer
source check.vim
" Test for the :bunload command with an offset
func Test_bunload_with_offset()
%bwipe!
@@ -152,6 +154,24 @@ func Test_bdelete_cmd()
set nobuflisted
enew
call assert_fails('bdelete ' .. bnr, 'E516:')
" Deleting more than one buffer
new Xbuf1
new Xbuf2
exe 'bdel ' .. bufnr('Xbuf2') .. ' ' .. bufnr('Xbuf1')
call assert_equal(1, winnr('$'))
call assert_equal(0, getbufinfo('Xbuf1')[0].loaded)
call assert_equal(0, getbufinfo('Xbuf2')[0].loaded)
" Deleting more than one buffer and an invalid buffer
new Xbuf1
new Xbuf2
let cmd = "exe 'bdel ' .. bufnr('Xbuf2') .. ' xxx ' .. bufnr('Xbuf1')"
call assert_fails(cmd, 'E94:')
call assert_equal(2, winnr('$'))
call assert_equal(1, getbufinfo('Xbuf1')[0].loaded)
call assert_equal(0, getbufinfo('Xbuf2')[0].loaded)
%bwipe!
endfunc
@@ -166,4 +186,188 @@ func Test_buffer_error()
%bwipe
endfunc
" Test for the status messages displayed when unloading, deleting or wiping
" out buffers
func Test_buffer_statusmsg()
CheckEnglish
set report=1
new Xbuf1
new Xbuf2
let bnr = bufnr()
exe "normal 2\<C-G>"
call assert_match('buf ' .. bnr .. ':', v:statusmsg)
bunload Xbuf1 Xbuf2
call assert_equal('2 buffers unloaded', v:statusmsg)
bdel Xbuf1 Xbuf2
call assert_equal('2 buffers deleted', v:statusmsg)
bwipe Xbuf1 Xbuf2
call assert_equal('2 buffers wiped out', v:statusmsg)
set report&
endfunc
" Test for quitting the 'swapfile exists' dialog with the split buffer
" command.
func Test_buffer_sbuf_cleanup()
call writefile([], 'Xfile')
" first open the file in a buffer
new Xfile
let bnr = bufnr()
close
" create the swap file
call writefile([], '.Xfile.swp')
" Remove the catch-all that runtest.vim adds
au! SwapExists
augroup BufTest
au!
autocmd SwapExists Xfile let v:swapchoice='q'
augroup END
exe 'sbuf ' . bnr
call assert_equal(1, winnr('$'))
call assert_equal(0, getbufinfo('Xfile')[0].loaded)
" test for :sball
sball
call assert_equal(1, winnr('$'))
call assert_equal(0, getbufinfo('Xfile')[0].loaded)
%bw!
set shortmess+=F
let v:statusmsg = ''
edit Xfile
call assert_equal('', v:statusmsg)
call assert_equal(1, winnr('$'))
call assert_equal(0, getbufinfo('Xfile')[0].loaded)
set shortmess&
call delete('Xfile')
call delete('.Xfile.swp')
augroup BufTest
au!
augroup END
augroup! BufTest
endfunc
" Test for deleting a modified buffer with :confirm
func Test_bdel_with_confirm()
CheckUnix
CheckNotGui
CheckFeature dialog_con
new
call setline(1, 'test')
call assert_fails('bdel', 'E89:')
call feedkeys('c', 'L')
confirm bdel
call assert_equal(2, winnr('$'))
call assert_equal(1, &modified)
call feedkeys('n', 'L')
confirm bdel
call assert_equal(1, winnr('$'))
endfunc
" Test for editing another buffer from a modified buffer with :confirm
func Test_goto_buf_with_confirm()
CheckUnix
CheckNotGui
CheckFeature dialog_con
new Xfile
enew
call setline(1, 'test')
call assert_fails('b Xfile', 'E37:')
call feedkeys('c', 'L')
call assert_fails('confirm b Xfile', 'E37:')
call assert_equal(1, &modified)
call assert_equal('', @%)
call feedkeys('y', 'L')
call assert_fails('confirm b Xfile', 'E37:')
call assert_equal(1, &modified)
call assert_equal('', @%)
call feedkeys('n', 'L')
confirm b Xfile
call assert_equal('Xfile', @%)
close!
endfunc
" Test for splitting buffer with 'switchbuf'
func Test_buffer_switchbuf()
new Xfile
wincmd w
set switchbuf=useopen
sbuf Xfile
call assert_equal(1, winnr())
call assert_equal(2, winnr('$'))
set switchbuf=usetab
tabnew
sbuf Xfile
call assert_equal(1, tabpagenr())
call assert_equal(2, tabpagenr('$'))
set switchbuf&
%bw
endfunc
" Test for BufAdd autocommand wiping out the buffer
func Test_bufadd_autocmd_bwipe()
%bw!
augroup BufAdd_Wipe
au!
autocmd BufAdd Xfile %bw!
augroup END
edit Xfile
call assert_equal('', @%)
call assert_equal(0, bufexists('Xfile'))
augroup BufAdd_Wipe
au!
augroup END
augroup! BufAdd_Wipe
endfunc
" Test for trying to load a buffer with text locked
" <C-\>e in the command line is used to lock the text
func Test_load_buf_with_text_locked()
new Xfile1
edit Xfile2
let cmd = ":\<C-\>eexecute(\"normal \<C-O>\")\<CR>\<C-C>"
call assert_fails("call feedkeys(cmd, 'xt')", 'E565:')
%bw!
endfunc
" Test for using CTRL-^ to edit the alternative file keeping the cursor
" position with 'nostartofline'. Also test using the 'buf' command.
func Test_buffer_edit_altfile()
call writefile(repeat(['one two'], 50), 'Xfile1')
call writefile(repeat(['five six'], 50), 'Xfile2')
set nosol
edit Xfile1
call cursor(25, 5)
edit Xfile2
call cursor(30, 4)
exe "normal \<C-^>"
call assert_equal([0, 25, 5, 0], getpos('.'))
exe "normal \<C-^>"
call assert_equal([0, 30, 4, 0], getpos('.'))
buf Xfile1
call assert_equal([0, 25, 5, 0], getpos('.'))
buf Xfile2
call assert_equal([0, 30, 4, 0], getpos('.'))
set sol&
call delete('Xfile1')
call delete('Xfile2')
endfunc
" Test for running the :sball command with a maximum window count and a
" modified buffer
func Test_sball_with_count()
%bw!
edit Xfile1
call setline(1, ['abc'])
new Xfile2
new Xfile3
new Xfile4
2sball
call assert_equal(bufnr('Xfile4'), winbufnr(1))
call assert_equal(bufnr('Xfile1'), winbufnr(2))
call assert_equal(0, getbufinfo('Xfile2')[0].loaded)
call assert_equal(0, getbufinfo('Xfile3')[0].loaded)
%bw!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -392,6 +392,7 @@ func Test_getcompletion()
call delete('Xtags')
set tags&
call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E871:')
call assert_fails('call getcompletion("", "burp")', 'E475:')
call assert_fails('call getcompletion("abc", [])', 'E475:')
endfunc

View File

@@ -0,0 +1,277 @@
" Tests for the various flags in the 'comments' option
" Test for the 'n' flag in 'comments'
func Test_comment_nested()
new
setlocal comments=n:> fo+=ro
exe "normal i> B\nD\<C-C>ggOA\<C-C>joC\<C-C>Go\<BS>>>> F\nH"
exe "normal 5GOE\<C-C>6GoG"
let expected =<< trim END
> A
> B
> C
> D
>>>> E
>>>> F
>>>> G
>>>> H
END
call assert_equal(expected, getline(1, '$'))
close!
endfunc
" Test for the 'b' flag in 'comments'
func Test_comment_blank()
new
setlocal comments=b:* fo+=ro
exe "normal i* E\nF\n\<BS>G\nH\<C-C>ggOC\<C-C>O\<BS>B\<C-C>OA\<C-C>2joD"
let expected =<< trim END
A
*B
* C
* D
* E
* F
*G
H
END
call assert_equal(expected, getline(1, '$'))
close!
endfunc
" Test for the 'f' flag in 'comments' (only the first line has a comment
" string)
func Test_comment_firstline()
new
setlocal comments=f:- fo+=ro
exe "normal i- B\nD\<C-C>ggoC\<C-C>ggOA\<C-C>"
call assert_equal(['A', '- B', ' C', ' D'], getline(1, '$'))
%d
setlocal comments=:-
exe "normal i- B\nD\<C-C>ggoC\<C-C>ggOA\<C-C>"
call assert_equal(['- A', '- B', '- C', '- D'], getline(1, '$'))
close!
endfunc
" Test for the 's', 'm' and 'e' flags in 'comments'
" Test for automatically adding comment leaders in insert mode
func Test_comment_threepiece()
new
setlocal expandtab
call setline(1, ["\t/*"])
setlocal formatoptions=croql
call cursor(1, 3)
call feedkeys("A\<cr>\<cr>/", 'tnix')
call assert_equal(["\t/*", " *", " */"], getline(1, '$'))
" If a comment ends in a single line, then don't add it in the next line
%d
call setline(1, '/* line1 */')
call feedkeys("A\<CR>next line", 'xt')
call assert_equal(['/* line1 */', 'next line'], getline(1, '$'))
%d
" Copy the trailing indentation from the leader comment to a new line
setlocal autoindent noexpandtab
call feedkeys("a\t/*\tone\ntwo\n/", 'xt')
call assert_equal(["\t/*\tone", "\t *\ttwo", "\t */"], getline(1, '$'))
close!
endfunc
" Test for the 'r' flag in 'comments' (right align comment)
func Test_comment_rightalign()
new
setlocal comments=sr:/***,m:**,ex-2:******/ fo+=ro
exe "normal i=\<C-C>o\t /***\nD\n/"
exe "normal 2GOA\<C-C>joB\<C-C>jOC\<C-C>joE\<C-C>GOF\<C-C>joG"
let expected =<< trim END
=
A
/***
** B
** C
** D
** E
** F
******/
G
END
call assert_equal(expected, getline(1, '$'))
close!
endfunc
" Test for the 'O' flag in 'comments'
func Test_comment_O()
new
setlocal comments=Ob:* fo+=ro
exe "normal i* B\nD\<C-C>kOA\<C-C>joC"
let expected =<< trim END
A
* B
* C
* D
END
call assert_equal(expected, getline(1, '$'))
close!
endfunc
" Test for using a multibyte character as a comment leader
func Test_comment_multibyte_leader()
new
let t =<< trim END
{
a
a
a
}
END
call setline(1, t)
call cursor(2, 1)
set tw=2 fo=cqm comments=n:
exe "normal gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgq"
let t =<< trim END
a
a
a
END
exe "normal o\n" . join(t, "\n")
let expected =<< trim END
{
a
a
a
a
a
a
}
END
call assert_equal(expected, getline(1, '$'))
set tw& fo& comments&
close!
endfunc
" Test for a space character in 'comments' setting
func Test_comment_space()
new
setlocal comments=b:\ > fo+=ro
exe "normal i> B\nD\<C-C>ggOA\<C-C>joC"
exe "normal Go > F\nH\<C-C>kOE\<C-C>joG"
let expected =<< trim END
A
> B
C
D
> E
> F
> G
> H
END
call assert_equal(expected, getline(1, '$'))
close!
endfunc
" Test for formatting lines with and without comments
func Test_comment_format_lines()
new
call setline(1, ['one', '/* two */', 'three'])
normal gggqG
call assert_equal(['one', '/* two */', 'three'], getline(1, '$'))
close!
endfunc
" Test for using 'a' in 'formatoptions' with comments
func Test_comment_autoformat()
new
setlocal formatoptions+=a
call feedkeys("a- one\n- two\n", 'xt')
call assert_equal(['- one', '- two', ''], getline(1, '$'))
%d
call feedkeys("a\none\n", 'xt')
call assert_equal(['', 'one', ''], getline(1, '$'))
setlocal formatoptions+=aw
%d
call feedkeys("aone \ntwo\n", 'xt')
call assert_equal(['one two', ''], getline(1, '$'))
%d
call feedkeys("aone\ntwo\n", 'xt')
call assert_equal(['one', 'two', ''], getline(1, '$'))
close!
endfunc
" Test for joining lines with comments ('j' flag in 'formatoptions')
func Test_comment_join_lines_fo_j()
new
setlocal fo+=j comments=://
call setline(1, ['i++; // comment1', ' // comment2'])
normal J
call assert_equal('i++; // comment1 comment2', getline(1))
setlocal fo-=j
call setline(1, ['i++; // comment1', ' // comment2'])
normal J
call assert_equal('i++; // comment1 // comment2', getline(1))
" Test with nested comments
setlocal fo+=j comments=n:>,n:)
call setline(1, ['i++; > ) > ) comment1', ' > ) comment2'])
normal J
call assert_equal('i++; > ) > ) comment1 comment2', getline(1))
close!
endfunc
" Test for formatting lines where only the first line has a comment.
func Test_comment_format_firstline_comment()
new
setlocal formatoptions=tcq
call setline(1, ['- one two', 'three'])
normal gggqG
call assert_equal(['- one two three'], getline(1, '$'))
%d
call setline(1, ['- one', '- two'])
normal gggqG
call assert_equal(['- one', '- two'], getline(1, '$'))
close!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -99,6 +99,7 @@ func Test_screenpos()
\ 'curscol': wincol + 9,
\ 'endcol': wincol + 9}, screenpos(winid, 2, 22))
close
call assert_equal({}, screenpos(999, 1, 1))
bwipe!
endfunc

View File

@@ -440,7 +440,7 @@ let s:filename_checks = {
\ 'swiftgyb': ['file.swift.gyb'],
\ 'sil': ['file.sil'],
\ 'sysctl': ['/etc/sysctl.conf', '/etc/sysctl.d/file.conf'],
\ 'systemd': ['any/systemd/file.automount', 'any/systemd/file.mount', 'any/systemd/file.path', 'any/systemd/file.service', 'any/systemd/file.socket', 'any/systemd/file.swap', 'any/systemd/file.target', 'any/systemd/file.timer', '/etc/systemd/system/some.d/file.conf', '/etc/systemd/system/some.d/.#file', '/etc/systemd/system/.#otherfile', '/home/user/.config/systemd/user/some.d/mine.conf', '/home/user/.config/systemd/user/some.d/.#file', '/home/user/.config/systemd/user/.#otherfile'],
\ 'systemd': ['any/systemd/file.automount', 'any/systemd/file.dnssd', 'any/systemd/file.link', 'any/systemd/file.mount', 'any/systemd/file.netdev', 'any/systemd/file.network', 'any/systemd/file.nspawn', 'any/systemd/file.path', 'any/systemd/file.service', 'any/systemd/file.slice', 'any/systemd/file.socket', 'any/systemd/file.swap', 'any/systemd/file.target', 'any/systemd/file.timer', '/etc/systemd/some.conf.d/file.conf', '/etc/systemd/system/some.d/file.conf', '/etc/systemd/system/some.d/.#file', '/etc/systemd/system/.#otherfile', '/home/user/.config/systemd/user/some.d/mine.conf', '/home/user/.config/systemd/user/some.d/.#file', '/home/user/.config/systemd/user/.#otherfile'],
\ 'systemverilog': ['file.sv', 'file.svh'],
\ 'tags': ['tags'],
\ 'tak': ['file.tak'],

View File

@@ -475,6 +475,11 @@ func Test_simplify()
call assert_equal('./file', simplify('./dir/../file'))
call assert_equal('../dir/file', simplify('dir/../../dir/file'))
call assert_equal('./file', simplify('dir/.././file'))
call assert_equal('../dir', simplify('./../dir'))
call assert_equal('..', simplify('../testdir/..'))
call mkdir('Xdir')
call assert_equal('.', simplify('Xdir/../.'))
call delete('Xdir', 'd')
call assert_fails('call simplify({->0})', 'E729:')
call assert_fails('call simplify([])', 'E730:')

View File

@@ -1,3 +1,4 @@
" Test for the gf and gF (goto file) commands
" This is a test if a URL is recognized by "gf", with the cursor before and
" after the "://". Also test ":\\".
@@ -38,6 +39,13 @@ func Test_gf_url()
call search("URL")
call assert_equal("URL://machine.name:1234?q=vim", expand("<cfile>"))
%d
call setline(1, "demo://remote_file")
wincmd f
call assert_equal('demo://remote_file', @%)
call assert_equal(2, winnr('$'))
close!
set isf&vim
enew!
endfunc
@@ -118,6 +126,11 @@ func Test_gf_visual()
norm! ttvtXgf
call assert_equal('Xtest_gf_visual', bufname('%'))
" if multiple lines are selected, then gf should fail
call setline(1, ["one", "two"])
normal VGgf
call assert_equal('Xtest_gf_visual', @%)
bwipe!
call delete('Xtest_gf_visual')
set hidden&
@@ -146,4 +159,21 @@ func Test_gf_error()
bwipe!
endfunc
" If a file is not found by 'gf', then 'includeexpr' should be used to locate
" the file.
func Test_gf_includeexpr()
new
let g:Inc_fname = ''
func IncFunc()
let g:Inc_fname = v:fname
return v:fname
endfunc
setlocal includeexpr=IncFunc()
call setline(1, 'somefile.java')
call assert_fails('normal gf', 'E447:')
call assert_equal('somefile.java', g:Inc_fname)
close!
delfunc IncFunc
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -754,8 +754,9 @@ func Test_normal17_z_scroll_hor2()
bw!
endfunc
" Test for H, M and L commands with folds
func Test_scroll_cmds()
" Test for commands that scroll the window horizontally. Test with folds.
" H, M, L, CTRL-E, CTRL-Y, CTRL-U, CTRL-D, PageUp, PageDown commands
func Test_vert_scroll_cmds()
15new
call setline(1, range(1, 100))
exe "normal! 30ggz\<CR>"
@@ -764,6 +765,8 @@ func Test_scroll_cmds()
40,43fold
46,49fold
let h = winheight(0)
" Test for H, M and L commands
" Top of the screen = 30
" Folded lines = 9
" Bottom of the screen = 30 + h + 9 - 1
@@ -771,10 +774,104 @@ func Test_scroll_cmds()
call assert_equal(35 + h, line('.'))
normal! 4H
call assert_equal(33, line('.'))
" Test for the CTRL-E and CTRL-Y commands with folds
%d
call setline(1, range(1, 10))
3,5fold
exe "normal 6G3\<C-E>"
call assert_equal(6, line('w0'))
exe "normal 2\<C-Y>"
call assert_equal(2, line('w0'))
" Test for CTRL-Y on a folded line
%d
call setline(1, range(1, 100))
exe (h + 2) .. "," .. (h + 4) .. "fold"
exe h + 5
normal z-
exe "normal \<C-Y>\<C-Y>"
call assert_equal(h + 1, line('w$'))
" Using <PageUp> and <PageDown> in an empty buffer should beep
%d
call assert_beeps('exe "normal \<PageUp>"')
call assert_beeps('exe "normal \<C-B>"')
call assert_beeps('exe "normal \<PageDown>"')
call assert_beeps('exe "normal \<C-F>"')
" Test for <C-U> and <C-D> with fold
%d
call setline(1, range(1, 100))
10,35fold
set scroll=10
exe "normal \<C-D>"
call assert_equal(36, line('.'))
exe "normal \<C-D>"
call assert_equal(46, line('.'))
exe "normal \<C-U>"
call assert_equal(36, line('.'))
exe "normal \<C-U>"
call assert_equal(10, line('.'))
exe "normal \<C-U>"
call assert_equal(1, line('.'))
set scroll&
" Test for scrolling to the top of the file with <C-U> and a fold
10
normal ztL
exe "normal \<C-U>\<C-U>"
call assert_equal(1, line('w0'))
" Test for CTRL-D on a folded line
%d
call setline(1, range(1, 100))
50,100fold
75
normal z-
exe "normal \<C-D>"
call assert_equal(50, line('.'))
call assert_equal(100, line('w$'))
normal z.
let lnum = winline()
exe "normal \<C-D>"
call assert_equal(lnum, winline())
call assert_equal(50, line('.'))
normal zt
exe "normal \<C-D>"
call assert_equal(50, line('w0'))
set foldenable&
close!
endfunc
" Test for the 'sidescroll' option
func Test_sidescroll_opt()
new
20vnew
" scroll by 2 characters horizontally
set sidescroll=2 nowrap
call setline(1, repeat('a', 40))
normal g$l
call assert_equal(19, screenpos(0, 1, 21).col)
normal l
call assert_equal(20, screenpos(0, 1, 22).col)
normal g0h
call assert_equal(2, screenpos(0, 1, 2).col)
call assert_equal(20, screenpos(0, 1, 20).col)
" when 'sidescroll' is 0, cursor positioned at the center
set sidescroll=0
normal g$l
call assert_equal(11, screenpos(0, 1, 21).col)
normal g0h
call assert_equal(10, screenpos(0, 1, 10).col)
%bw!
set wrap& sidescroll&
endfunc
" basic tests for foldopen/folddelete
func Test_normal18_z_fold()
CheckFeature folding
@@ -1170,6 +1267,7 @@ func Test_normal21_nv_hat()
edit Xfoo | %bw
call assert_fails(':buffer #', 'E86')
call assert_fails(':execute "normal! \<C-^>"', 'E23')
call assert_fails("normal i\<C-R>#", 'E23:')
" Test for the expected behavior when switching between two named buffers.
edit Xfoo | edit Xbar
@@ -2962,4 +3060,40 @@ func Test_normal_word_move()
close!
endfunc
" Test for 'scrolloff' with a long line that doesn't fit in the screen
func Test_normal_scroloff()
10new
80vnew
call setline(1, repeat('a', 1000))
set scrolloff=10
normal gg10gj
call assert_equal(8, winline())
normal 10gj
call assert_equal(10, winline())
normal 10gk
call assert_equal(3, winline())
set scrolloff&
close!
endfunc
" Test for vertical scrolling with CTRL-F and CTRL-B with a long line
func Test_normal_vert_scroll_longline()
10new
80vnew
call setline(1, range(1, 10))
call append(5, repeat('a', 1000))
exe "normal gg\<C-F>"
call assert_equal(6, line('.'))
exe "normal \<C-F>\<C-F>"
call assert_equal(11, line('.'))
call assert_equal(1, winline())
exe "normal \<C-B>"
call assert_equal(10, line('.'))
call assert_equal(3, winline())
exe "normal \<C-B>\<C-B>"
call assert_equal(5, line('.'))
call assert_equal(5, winline())
close!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -513,6 +513,7 @@ func Test_set_one_column()
endfunc
func Test_set_values()
" opt_test.vim is generated from ../optiondefs.h using gen_opt_test.vim
if filereadable('opt_test.vim')
source opt_test.vim
else
@@ -921,4 +922,35 @@ func Test_opt_boolean()
set number&
endfunc
" Test for the 'window' option
func Test_window_opt()
" Needs only one open widow
%bw!
call setline(1, range(1, 8))
set window=5
exe "normal \<C-F>"
call assert_equal(4, line('w0'))
exe "normal \<C-F>"
call assert_equal(7, line('w0'))
exe "normal \<C-F>"
call assert_equal(8, line('w0'))
exe "normal \<C-B>"
call assert_equal(5, line('w0'))
exe "normal \<C-B>"
call assert_equal(2, line('w0'))
exe "normal \<C-B>"
call assert_equal(1, line('w0'))
set window=1
exe "normal gg\<C-F>"
call assert_equal(2, line('w0'))
exe "normal \<C-F>"
call assert_equal(3, line('w0'))
exe "normal \<C-B>"
call assert_equal(2, line('w0'))
exe "normal \<C-B>"
call assert_equal(1, line('w0'))
enew!
set window&
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -2454,10 +2454,9 @@ func Test_popupwin_terminal_buffer()
call term_sendkeys(termbuf2, "exit\<CR>")
" Exiting shell closes popup window
let pupwin = win_getid()
call feedkeys("exit\<CR>", 'xt')
" Wait for shell to exit
call WaitForAssert({-> assert_notequal(pupwin, win_getid())})
call WaitForAssert({-> assert_equal("dead", job_status(term_getjob(termbuf)))})
call feedkeys(":quit\<CR>", 'xt')
call assert_equal(origwin, win_getid())

View File

@@ -488,10 +488,10 @@ func Xtest_browse(cchar)
call assert_fails('Xprev', 'E553')
call assert_fails('Xpfile', 'E553')
Xnfile
call assert_equal('Xqftestfile2', bufname('%'))
call assert_equal('Xqftestfile2', @%)
call assert_equal(10, line('.'))
Xpfile
call assert_equal('Xqftestfile1', bufname('%'))
call assert_equal('Xqftestfile1', @%)
call assert_equal(6, line('.'))
5Xcc
call assert_equal(5, g:Xgetlist({'idx':0}).idx)
@@ -507,7 +507,7 @@ func Xtest_browse(cchar)
call assert_equal(6, g:Xgetlist({'idx':0}).idx)
Xlast
Xprev
call assert_equal('Xqftestfile2', bufname('%'))
call assert_equal('Xqftestfile2', @%)
call assert_equal(11, line('.'))
call assert_fails('Xnext', 'E553')
call assert_fails('Xnfile', 'E553')
@@ -520,14 +520,14 @@ func Xtest_browse(cchar)
endif
call assert_equal(6, g:Xgetlist({'idx':0}).idx)
Xrewind
call assert_equal('Xqftestfile1', bufname('%'))
call assert_equal('Xqftestfile1', @%)
call assert_equal(5, line('.'))
10Xnext
call assert_equal('Xqftestfile2', bufname('%'))
call assert_equal('Xqftestfile2', @%)
call assert_equal(11, line('.'))
10Xprev
call assert_equal('Xqftestfile1', bufname('%'))
call assert_equal('Xqftestfile1', @%)
call assert_equal(5, line('.'))
" Jumping to an error from the error window using cc command
@@ -538,7 +538,7 @@ func Xtest_browse(cchar)
Xopen
10Xcc
call assert_equal(11, line('.'))
call assert_equal('Xqftestfile2', bufname('%'))
call assert_equal('Xqftestfile2', @%)
Xopen
call cursor(2, 1)
if a:cchar == 'c'
@@ -547,14 +547,14 @@ func Xtest_browse(cchar)
.ll
endif
call assert_equal(6, line('.'))
call assert_equal('Xqftestfile1', bufname('%'))
call assert_equal('Xqftestfile1', @%)
" Jumping to an error from the error window (when only the error window is
" present)
Xopen | only
Xlast 1
call assert_equal(5, line('.'))
call assert_equal('Xqftestfile1', bufname('%'))
call assert_equal('Xqftestfile1', @%)
Xexpr ""
call assert_fails('Xnext', 'E42:')
@@ -1859,7 +1859,7 @@ func Test_switchbuf()
copen | only
cfirst
call assert_equal(1, tabpagenr())
call assert_equal('Xqftestfile1', bufname(''))
call assert_equal('Xqftestfile1', @%)
" If opening a file changes 'switchbuf', then the new value should be
" retained.
@@ -2679,7 +2679,7 @@ func Test_cwindow_jump()
wincmd b
cfirst
call assert_equal(2, winnr())
call assert_equal('F1', bufname(''))
call assert_equal('F1', @%)
enew | only
exe 'sb' bnum
exe 'botright sb' bnum
@@ -2768,7 +2768,7 @@ func XvimgrepTests(cchar)
edit +3 Xtestfile2
Xvimgrep +\cemacs+j Xtestfile1
let l = g:Xgetlist()
call assert_equal('Xtestfile2', bufname(''))
call assert_equal('Xtestfile2', @%)
call assert_equal('Editor:Emacs EmAcS', l[0].text)
" Test for unloading a buffer after vimgrep searched the buffer
@@ -3394,7 +3394,7 @@ func Xqfjump_tests(cchar)
Xopen | only
2Xnext
call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
call assert_equal('F3', bufname('%'))
call assert_equal('F3', @%)
Xnext
call assert_equal(7, col('.'))
Xnext
@@ -4043,20 +4043,20 @@ func Xjumpto_first_error_test(cchar)
" Test for cexpr/lexpr
enew
Xexpr l
call assert_equal('Xtestfile1', bufname(''))
call assert_equal('Xtestfile1', @%)
call assert_equal(2, line('.'))
" Test for cfile/lfile
enew
call writefile(l, 'Xerr')
Xfile Xerr
call assert_equal('Xtestfile1', bufname(''))
call assert_equal('Xtestfile1', @%)
call assert_equal(2, line('.'))
" Test for cbuffer/lbuffer
edit Xerr
Xbuffer
call assert_equal('Xtestfile1', bufname(''))
call assert_equal('Xtestfile1', @%)
call assert_equal(2, line('.'))
call delete('Xerr')
@@ -4081,7 +4081,7 @@ func Xautocmd_changelist(cchar)
autocmd QuickFixCmdPost * Xolder
call writefile(['Xtestfile2:4:Line4'], 'Xerr')
Xfile Xerr
call assert_equal('Xtestfile2', bufname(''))
call assert_equal('Xtestfile2', @%)
call assert_equal(4, line('.'))
autocmd! QuickFixCmdPost
@@ -4092,7 +4092,7 @@ func Xautocmd_changelist(cchar)
call writefile(['Xtestfile2:4:Line4'], 'Xerr')
edit Xerr
Xbuffer
call assert_equal('Xtestfile2', bufname(''))
call assert_equal('Xtestfile2', @%)
call assert_equal(4, line('.'))
autocmd! QuickFixCmdPost
@@ -4101,7 +4101,7 @@ func Xautocmd_changelist(cchar)
Xexpr 'Xtestfile1:2:Line2'
autocmd QuickFixCmdPost * Xolder
Xexpr 'Xtestfile2:4:Line4'
call assert_equal('Xtestfile2', bufname(''))
call assert_equal('Xtestfile2', @%)
call assert_equal(4, line('.'))
autocmd! QuickFixCmdPost
@@ -4112,7 +4112,7 @@ func Xautocmd_changelist(cchar)
Xexpr 'Xtestfile1:2:Line2'
autocmd QuickFixCmdPost * Xolder
silent Xgrep Line5 Xtestfile2
call assert_equal('Xtestfile2', bufname(''))
call assert_equal('Xtestfile2', @%)
call assert_equal(5, line('.'))
autocmd! QuickFixCmdPost
endif
@@ -4122,7 +4122,7 @@ func Xautocmd_changelist(cchar)
Xexpr 'Xtestfile1:2:Line2'
autocmd QuickFixCmdPost * Xolder
silent Xvimgrep Line5 Xtestfile2
call assert_equal('Xtestfile2', bufname(''))
call assert_equal('Xtestfile2', @%)
call assert_equal(5, line('.'))
autocmd! QuickFixCmdPost
@@ -4415,7 +4415,7 @@ func Test_winonly_autocmd()
" positioned correctly.
ll 3
call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
call assert_equal('Xtest1', bufname(''))
call assert_equal('Xtest1', @%)
call assert_equal(15, line('.'))
" Cleanup
autocmd! WinEnter
@@ -4476,51 +4476,51 @@ func Xtest_below(cchar)
Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
edit +7 X2
Xabove
call assert_equal(['X2', 5], [bufname(''), line('.')])
call assert_equal(['X2', 5], [@%, line('.')])
call assert_fails('Xabove', 'E553:')
normal 7G
Xbefore
call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
call assert_fails('Xbefore', 'E553:')
normal 2j
Xbelow
call assert_equal(['X2', 10], [bufname(''), line('.')])
call assert_equal(['X2', 10], [@%, line('.')])
normal 7G
Xafter
call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
" Last error in this file
Xbelow 99
call assert_equal(['X2', 15], [bufname(''), line('.')])
call assert_equal(['X2', 15], [@%, line('.')])
call assert_fails('Xbelow', 'E553:')
normal gg
Xafter 99
call assert_equal(['X2', 15, 4], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 15, 4], [@%, line('.'), col('.')])
call assert_fails('Xafter', 'E553:')
" First error in this file
Xabove 99
call assert_equal(['X2', 5], [bufname(''), line('.')])
call assert_equal(['X2', 5], [@%, line('.')])
call assert_fails('Xabove', 'E553:')
normal G
Xbefore 99
call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
call assert_fails('Xbefore', 'E553:')
normal gg
Xbelow 2
call assert_equal(['X2', 10], [bufname(''), line('.')])
call assert_equal(['X2', 10], [@%, line('.')])
normal gg
Xafter 2
call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
normal G
Xabove 2
call assert_equal(['X2', 10], [bufname(''), line('.')])
call assert_equal(['X2', 10], [@%, line('.')])
normal G
Xbefore 2
call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 10, 3], [@%, line('.'), col('.')])
edit X4
call assert_fails('Xabove', 'E42:')
@@ -4544,45 +4544,45 @@ func Xtest_below(cchar)
\ "X2:15:1:L15_1", "X2:15:2:L15_2", "X2:15:3:L15_3", "X3:3:L3"]
edit +1 X2
Xbelow 2
call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
normal 1G
Xafter 2
call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 5, 2], [@%, line('.'), col('.')])
normal gg
Xbelow 99
call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
normal gg
Xafter 99
call assert_equal(['X2', 15, 3], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 15, 3], [@%, line('.'), col('.')])
normal G
Xabove 2
call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 10, 1], [@%, line('.'), col('.')])
normal G
Xbefore 2
call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
normal G
Xabove 99
call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
normal G
Xbefore 99
call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
normal 10G
Xabove
call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 5, 1], [@%, line('.'), col('.')])
normal 10G$
2Xbefore
call assert_equal(['X2', 10, 2], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 10, 2], [@%, line('.'), col('.')])
normal 10G
Xbelow
call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 15, 1], [@%, line('.'), col('.')])
normal 9G
5Xafter
call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
call assert_equal(['X2', 15, 2], [@%, line('.'), col('.')])
" Invalid range
if a:cchar == 'c'

View File

@@ -641,4 +641,22 @@ func Test_execute_reg_as_ex_cmd()
call assert_equal(repeat('abcdefghijklmnopqrstuvwxyz', 312), str)
endfunc
" Test for clipboard registers with ASCII NUL
func Test_clipboard_nul()
CheckFeature clipboard_working
new
" Test for putting ASCII NUL into the clipboard
set clipboard=unnamed
call append(0, "\ntest")
normal ggyyp
call assert_equal("^@test^@", strtrans(getreg('*')))
call assert_equal(getline(1), getline(2))
let b = split(execute(":reg *"), "\n")
call assert_match('"\*\s*\^@test\^J',b[1])
set clipboard&vim
bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -64,7 +64,17 @@ endfunc
func Test_statusline()
CheckFeature quickfix
new Xstatusline
" %a: Argument list ({current} of {max})
set statusline=%a
call assert_match('^\s*$', s:get_statusline())
arglocal a1 a2
rewind
call assert_match('^ (1 of 2)\s*$', s:get_statusline())
next
call assert_match('^ (2 of 2)\s*$', s:get_statusline())
e Xstatusline
call assert_match('^ ((2) of 2)\s*$', s:get_statusline())
only
set laststatus=2
set splitbelow

View File

@@ -784,78 +784,6 @@ func Test_tw_2_fo_tm_noai()
bwipe!
endfunc
func Test_tw_2_fo_cqm_com()
new
let t =<< trim END
{
a
a
a
}
END
call setline(1, t)
call cursor(2, 1)
set tw=2 fo=cqm comments=n:
exe "normal gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgq"
let t =<< trim END
a
a
a
END
exe "normal o\n" . join(t, "\n")
let expected =<< trim END
{
a
a
a
a
a
a
}
END
call assert_equal(expected, getline(1, '$'))
set tw& fo& comments&
bwipe!
endfunc
func Test_tw_2_fo_tm_replace()
new
let t =<< trim END
@@ -975,140 +903,6 @@ func Test_whichwrap_multi_byte()
bwipe!
endfunc
" Test for automatically adding comment leaders in insert mode
func Test_threepiece_comment()
new
setlocal expandtab
call setline(1, ["\t/*"])
setlocal formatoptions=croql
call cursor(1, 3)
call feedkeys("A\<cr>\<cr>/", 'tnix')
call assert_equal(["\t/*", " *", " */"], getline(1, '$'))
" If a comment ends in a single line, then don't add it in the next line
%d
call setline(1, '/* line1 */')
call feedkeys("A\<CR>next line", 'xt')
call assert_equal(['/* line1 */', 'next line'], getline(1, '$'))
%d
" Copy the trailing indentation from the leader comment to a new line
setlocal autoindent noexpandtab
call feedkeys("a\t/*\tone\ntwo\n/", 'xt')
call assert_equal(["\t/*\tone", "\t *\ttwo", "\t */"], getline(1, '$'))
close!
endfunc
" Test for the 'f' flag in 'comments' (only the first line has the comment
" string)
func Test_firstline_comment()
new
setlocal comments=f:- fo+=ro
exe "normal i- B\nD\<C-C>ggoC\<C-C>ggOA\<C-C>"
call assert_equal(['A', '- B', ' C', ' D'], getline(1, '$'))
%d
setlocal comments=:-
exe "normal i- B\nD\<C-C>ggoC\<C-C>ggOA\<C-C>"
call assert_equal(['- A', '- B', '- C', '- D'], getline(1, '$'))
%bw!
endfunc
" Test for the 'r' flag in 'comments' (right align comment)
func Test_comment_rightalign()
new
setlocal comments=sr:/***,m:**,ex-2:******/ fo+=ro
exe "normal i=\<C-C>o\t /***\nD\n/"
exe "normal 2GOA\<C-C>joB\<C-C>jOC\<C-C>joE\<C-C>GOF\<C-C>joG"
let expected =<< trim END
=
A
/***
** B
** C
** D
** E
** F
******/
G
END
call assert_equal(expected, getline(1, '$'))
%bw!
endfunc
" Test for the 'b' flag in 'comments'
func Test_comment_blank()
new
setlocal comments=b:* fo+=ro
exe "normal i* E\nF\n\<BS>G\nH\<C-C>ggOC\<C-C>O\<BS>B\<C-C>OA\<C-C>2joD"
let expected =<< trim END
A
*B
* C
* D
* E
* F
*G
H
END
call assert_equal(expected, getline(1, '$'))
%bw!
endfunc
" Test for the 'n' flag in comments
func Test_comment_nested()
new
setlocal comments=n:> fo+=ro
exe "normal i> B\nD\<C-C>ggOA\<C-C>joC\<C-C>Go\<BS>>>> F\nH"
exe "normal 5GOE\<C-C>6GoG"
let expected =<< trim END
> A
> B
> C
> D
>>>> E
>>>> F
>>>> G
>>>> H
END
call assert_equal(expected, getline(1, '$'))
%bw!
endfunc
" Test for a space character in 'comments' setting
func Test_comment_space()
new
setlocal comments=b:\ > fo+=ro
exe "normal i> B\nD\<C-C>ggOA\<C-C>joC"
exe "normal Go > F\nH\<C-C>kOE\<C-C>joG"
let expected =<< trim END
A
> B
C
D
> E
> F
> G
> H
END
call assert_equal(expected, getline(1, '$'))
%bw!
endfunc
" Test for the 'O' flag in 'comments'
func Test_comment_O()
new
setlocal comments=Ob:* fo+=ro
exe "normal i* B\nD\<C-C>kOA\<C-C>joC"
let expected =<< trim END
A
* B
* C
* D
END
call assert_equal(expected, getline(1, '$'))
%bw!
endfunc
" Test for 'a' and 'w' flags in 'formatoptions'
func Test_fo_a_w()
new
@@ -1143,25 +937,6 @@ func Test_fo_a_w()
%bw!
endfunc
" Test for 'j' flag in 'formatoptions'
func Test_fo_j()
new
setlocal fo+=j comments=://
call setline(1, ['i++; // comment1', ' // comment2'])
normal J
call assert_equal('i++; // comment1 comment2', getline(1))
setlocal fo-=j
call setline(1, ['i++; // comment1', ' // comment2'])
normal J
call assert_equal('i++; // comment1 // comment2', getline(1))
" Test with nested comments
setlocal fo+=j comments=n:>,n:)
call setline(1, ['i++; > ) > ) comment1', ' > ) comment2'])
normal J
call assert_equal('i++; > ) > ) comment1 comment2', getline(1))
%bw!
endfunc
" Test for formatting lines using gq in visual mode
func Test_visual_gq_format()
new
@@ -1296,51 +1071,4 @@ func Test_fo_2()
close!
endfunc
" Test for formatting lines where only the first line has a comment.
func Test_fo_gq_with_firstline_comment()
new
setlocal formatoptions=tcq
call setline(1, ['- one two', 'three'])
normal gggqG
call assert_equal(['- one two three'], getline(1, '$'))
%d
call setline(1, ['- one', '- two'])
normal gggqG
call assert_equal(['- one', '- two'], getline(1, '$'))
close!
endfunc
" Test for trying to join a comment line with a non-comment line
func Test_join_comments()
new
call setline(1, ['one', '/* two */', 'three'])
normal gggqG
call assert_equal(['one', '/* two */', 'three'], getline(1, '$'))
close!
endfunc
" Test for using 'a' in 'formatoptions' with comments
func Test_autoformat_comments()
new
setlocal formatoptions+=a
call feedkeys("a- one\n- two\n", 'xt')
call assert_equal(['- one', '- two', ''], getline(1, '$'))
%d
call feedkeys("a\none\n", 'xt')
call assert_equal(['', 'one', ''], getline(1, '$'))
setlocal formatoptions+=aw
%d
call feedkeys("aone \ntwo\n", 'xt')
call assert_equal(['one two', ''], getline(1, '$'))
%d
call feedkeys("aone\ntwo\n", 'xt')
call assert_equal(['one', 'two', ''], getline(1, '$'))
close!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -13,6 +13,9 @@ def Test_expr1()
assert_equal('one', 0.1 ? 'one' : 'two')
endif
assert_equal('one', 'x' ? 'one' : 'two')
assert_equal('one', 'x'
? 'one'
: 'two')
assert_equal('one', 0z1234 ? 'one' : 'two')
assert_equal('one', [0] ? 'one' : 'two')
assert_equal('one', #{x: 0} ? 'one' : 'two')
@@ -70,6 +73,8 @@ def Test_expr2()
0 ||
7)
assert_equal(0, 0 || 0)
assert_equal(0, 0
|| 0)
assert_equal('', 0 || '')
g:vals = []
@@ -81,7 +86,9 @@ def Test_expr2()
assert_equal([0, 5], g:vals)
g:vals = []
assert_equal(4, Record(0) || Record(4) || Record(0))
assert_equal(4, Record(0)
|| Record(4)
|| Record(0))
assert_equal([0, 4], g:vals)
g:vals = []
@@ -104,7 +111,9 @@ def Test_expr3()
assert_equal(0, 0 &&
0 &&
7)
assert_equal(7, 2 && 3 && 7)
assert_equal(7, 2
&& 3
&& 7)
assert_equal(0, 0 && 0)
assert_equal(0, 0 && '')
assert_equal('', 8 && '')
@@ -158,7 +167,8 @@ def Test_expr4_equal()
assert_equal(true, true == true)
assert_equal(false, true ==
false)
assert_equal(true, true == trueVar)
assert_equal(true, true
== trueVar)
assert_equal(false, true == falseVar)
assert_equal(true, true == g:atrue)
assert_equal(false, g:atrue == false)
@@ -250,7 +260,8 @@ def Test_expr4_notequal()
assert_equal(false, true != true)
assert_equal(true, true !=
false)
assert_equal(false, true != trueVar)
assert_equal(false, true
!= trueVar)
assert_equal(true, true != falseVar)
assert_equal(false, true != g:atrue)
assert_equal(true, g:atrue != false)
@@ -334,7 +345,8 @@ def Test_expr4_greater()
assert_true(nr2 >
1)
assert_false(nr2 > 2)
assert_false(nr2 > 3)
assert_false(nr2
> 3)
if has('float')
let ff = 2.0
assert_true(ff > 0.0)
@@ -367,7 +379,8 @@ def Test_expr4_smaller()
assert_false(2 < 0)
assert_false(2 <
2)
assert_true(2 < 3)
assert_true(2
< 3)
let nr2 = 2
assert_false(nr2 < 0)
assert_false(nr2 < 2)
@@ -385,7 +398,8 @@ def Test_expr4_smallerequal()
assert_false(2 <= 0)
assert_false(2 <=
1)
assert_true(2 <= 2)
assert_true(2
<= 2)
assert_true(2 <= 3)
let nr2 = 2
assert_false(nr2 <= 0)
@@ -404,6 +418,8 @@ enddef
" test =~ comperator
def Test_expr4_match()
assert_equal(false, '2' =~ '0')
assert_equal(false, ''
=~ '0')
assert_equal(true, '2' =~
'[0-9]')
enddef
@@ -411,6 +427,8 @@ enddef
" test !~ comperator
def Test_expr4_nomatch()
assert_equal(true, '2' !~ '0')
assert_equal(true, ''
!~ '0')
assert_equal(false, '2' !~
'[0-9]')
enddef
@@ -424,7 +442,8 @@ def Test_expr4_is()
other)
let myblob = 0z1234
assert_false(myblob is 0z1234)
assert_false(myblob
is 0z1234)
let otherblob = myblob
assert_true(myblob is otherblob)
enddef
@@ -439,7 +458,8 @@ def Test_expr4_isnot()
other)
let myblob = 0z1234
assert_true(myblob isnot 0z1234)
assert_true(myblob
isnot 0z1234)
let otherblob = myblob
assert_false(myblob isnot otherblob)
enddef
@@ -522,30 +542,54 @@ def Test_expr5()
assert_equal(66, 60 + 6)
assert_equal(70, 60 +
g:anint)
assert_equal(9, g:alsoint + 5)
assert_equal(9, g:alsoint
+ 5)
assert_equal(14, g:alsoint + g:anint)
assert_equal([1, 2, 3, 4], [1] + g:alist)
assert_equal(54, 60 - 6)
assert_equal(50, 60 -
g:anint)
assert_equal(-1, g:alsoint - 5)
assert_equal(-1, g:alsoint
- 5)
assert_equal(-6, g:alsoint - g:anint)
assert_equal('hello', 'hel' .. 'lo')
assert_equal('hello 123', 'hello ' ..
123)
assert_equal('hello 123', 'hello ' .. 123)
assert_equal('hello 123', 'hello '
.. 123)
assert_equal('123 hello', 123 .. ' hello')
assert_equal('123456', 123 .. 456)
assert_equal([1, 2, 3, 4], [1, 2] + [3, 4])
assert_equal(0z11223344, 0z1122 + 0z3344)
assert_equal(0z112201ab, 0z1122 + g:ablob)
assert_equal(0z112201ab, 0z1122
+ g:ablob)
assert_equal(0z01ab3344, g:ablob + 0z3344)
assert_equal(0z01ab01ab, g:ablob + g:ablob)
enddef
def Test_expr5_vim9script()
" only checks line continuation
let lines =<< trim END
vim9script
let var = 11
+ 77
- 22
assert_equal(66, var)
END
CheckScriptSuccess(lines)
lines =<< trim END
vim9script
let var = 'one'
.. 'two'
assert_equal('onetwo', var)
END
CheckScriptSuccess(lines)
enddef
def Test_expr5_float()
if !has('float')
MissingFeature 'float'
@@ -554,13 +598,15 @@ def Test_expr5_float()
assert_equal(66.0, 60.0 + 6)
assert_equal(66.0, 60 +
6.0)
assert_equal(5.1, g:afloat + 5)
assert_equal(5.1, g:afloat
+ 5)
assert_equal(8.1, 8 + g:afloat)
assert_equal(10.1, g:anint + g:afloat)
assert_equal(10.1, g:afloat + g:anint)
assert_equal(54.0, 60.0 - 6.0)
assert_equal(54.0, 60.0 - 6)
assert_equal(54.0, 60.0
- 6)
assert_equal(54.0, 60 - 6.0)
assert_equal(-4.9, g:afloat - 5)
assert_equal(7.9, 8 - g:afloat)
@@ -585,12 +631,12 @@ func Test_expr5_fails()
call CheckDefFailure(["let x = '1' ..'2'"], msg)
call CheckDefFailure(["let x = '1'.. '2'"], msg)
call CheckDefFailure(["let x = 0z1122 + 33"], 'E1035')
call CheckDefFailure(["let x = 0z1122 + [3]"], 'E1035')
call CheckDefFailure(["let x = 0z1122 + 'asd'"], 'E1035')
call CheckDefFailure(["let x = 33 + 0z1122"], 'E1035')
call CheckDefFailure(["let x = [3] + 0z1122"], 'E1035')
call CheckDefFailure(["let x = 'asdf' + 0z1122"], 'E1035')
call CheckDefFailure(["let x = 0z1122 + 33"], 'E1051')
call CheckDefFailure(["let x = 0z1122 + [3]"], 'E1051')
call CheckDefFailure(["let x = 0z1122 + 'asd'"], 'E1051')
call CheckDefFailure(["let x = 33 + 0z1122"], 'E1051')
call CheckDefFailure(["let x = [3] + 0z1122"], 'E1051')
call CheckDefFailure(["let x = 'asdf' + 0z1122"], 'E1051')
call CheckDefFailure(["let x = 6 + xxx"], 'E1001')
endfunc
@@ -599,20 +645,23 @@ def Test_expr6()
assert_equal(36, 6 * 6)
assert_equal(24, 6 *
g:alsoint)
assert_equal(24, g:alsoint * 6)
assert_equal(24, g:alsoint
* 6)
assert_equal(40, g:anint * g:alsoint)
assert_equal(10, 60 / 6)
assert_equal(6, 60 /
g:anint)
assert_equal(1, g:anint / 6)
assert_equal(2, g:anint / g:alsoint)
assert_equal(2, g:anint
/ g:alsoint)
assert_equal(5, 11 % 6)
assert_equal(4, g:anint % 6)
assert_equal(3, 13 %
g:anint)
assert_equal(2, g:anint % g:alsoint)
assert_equal(2, g:anint
% g:alsoint)
assert_equal(4, 6 * 4 / 6)
@@ -623,13 +672,35 @@ def Test_expr6()
if has('float')
let xf = [2.0]
let yf = [3.0]
assert_equal(5.0, xf[0] + yf[0])
assert_equal(6.0, xf[0] * yf[0])
assert_equal(5.0, xf[0]
+ yf[0])
assert_equal(6.0, xf[0]
* yf[0])
endif
call CheckDefFailure(["let x = 6 * xxx"], 'E1001')
enddef
def Test_expr6_vim9script()
" only checks line continuation
let lines =<< trim END
vim9script
let var = 11
* 22
/ 3
assert_equal(80, var)
END
CheckScriptSuccess(lines)
lines =<< trim END
vim9script
let var = 25
% 10
assert_equal(5, var)
END
CheckScriptSuccess(lines)
enddef
def Test_expr6_float()
if !has('float')
MissingFeature 'float'

View File

@@ -837,5 +837,16 @@ def Test_sort_return_type()
res = [1, 2, 3]->sort()
enddef
def Line_continuation_in_def(dir: string = ''): string
let path: string = empty(dir)
\ ? 'empty'
\ : 'full'
return path
enddef
def Test_line_continuation_in_def()
assert_equal('full', Line_continuation_in_def('.'))
enddef
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker

View File

@@ -468,6 +468,14 @@ func Test_const()
call CheckDefFailure(['const &option'], 'E996:')
endfunc
def Test_range_no_colon()
call CheckDefFailure(['%s/a/b/'], 'E1050:')
call CheckDefFailure(['+ s/a/b/'], 'E1050:')
call CheckDefFailure(['- s/a/b/'], 'E1050:')
call CheckDefFailure(['. s/a/b/'], 'E1050:')
enddef
def Test_block()
let outer = 1
{
@@ -1279,7 +1287,7 @@ def Test_echomsg_cmd()
echomsg 'some' 'more' # comment
assert_match('^some more$', Screenline(&lines))
echo 'clear'
1messages
:1messages
assert_match('^some more$', Screenline(&lines))
call CheckDefFailure(['echomsg "xxx"# comment'], 'E488:')
@@ -1898,7 +1906,7 @@ def Test_vim9_comment_not_compiled()
'vim9script',
'new'
'call setline(1, ["# define pat", "last"])',
'$',
':$',
'dsearch /pat/ #comment',
'bwipe!',
])
@@ -1907,7 +1915,7 @@ def Test_vim9_comment_not_compiled()
'vim9script',
'new'
'call setline(1, ["# define pat", "last"])',
'$',
':$',
'dsearch /pat/#comment',
'bwipe!',
], 'E488:')

View File

@@ -239,7 +239,7 @@ get_function_args(
whitep = p;
p = skipwhite(p);
expr = p;
if (eval1(&p, &rettv, 0) != FAIL)
if (eval1(&p, &rettv, NULL) != FAIL)
{
if (ga_grow(default_args, 1) == FAIL)
goto err_ret;
@@ -561,6 +561,10 @@ get_func_tv(
int ret = OK;
typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments
int argcount = 0; // number of arguments found
evalarg_T evalarg;
CLEAR_FIELD(evalarg);
evalarg.eval_flags = funcexe->evaluate ? EVAL_EVALUATE : 0;
/*
* Get the arguments.
@@ -572,8 +576,7 @@ get_func_tv(
argp = skipwhite(argp + 1); // skip the '(' or ','
if (*argp == ')' || *argp == ',' || *argp == NUL)
break;
if (eval1(&argp, &argvars[argcount],
funcexe->evaluate ? EVAL_EVALUATE : 0) == FAIL)
if (eval1(&argp, &argvars[argcount], &evalarg) == FAIL)
{
ret = FAIL;
break;
@@ -1249,7 +1252,7 @@ call_user_func(
default_expr = ((char_u **)(fp->uf_def_args.ga_data))
[ai + fp->uf_def_args.ga_len];
if (eval1(&default_expr, &def_rettv, EVAL_EVALUATE) == FAIL)
if (eval1(&default_expr, &def_rettv, &EVALARG_EVALUATE) == FAIL)
{
default_arg_err = 1;
break;
@@ -1394,7 +1397,7 @@ call_user_func(
// A Lambda always has the command "return {expr}". It is much faster
// to evaluate {expr} directly.
++ex_nesting_level;
(void)eval1(&p, rettv, EVAL_EVALUATE);
(void)eval1(&p, rettv, &EVALARG_EVALUATE);
--ex_nesting_level;
}
else
@@ -3697,6 +3700,7 @@ ex_return(exarg_T *eap)
char_u *arg = eap->arg;
typval_T rettv;
int returning = FALSE;
evalarg_T evalarg;
if (current_funccal == NULL)
{
@@ -3704,13 +3708,15 @@ ex_return(exarg_T *eap)
return;
}
CLEAR_FIELD(evalarg);
evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
if (eap->skip)
++emsg_skip;
eap->nextcmd = NULL;
if ((*arg != NUL && *arg != '|' && *arg != '\n')
&& eval0(arg, &rettv, &eap->nextcmd, eap->skip ? 0 : EVAL_EVALUATE)
!= FAIL)
&& eval0(arg, &rettv, &eap->nextcmd, &evalarg) != FAIL)
{
if (!eap->skip)
returning = do_return(eap, FALSE, TRUE, &rettv);
@@ -3767,7 +3773,7 @@ ex_call(exarg_T *eap)
// instead to skip to any following command, e.g. for:
// :if 0 | call dict.foo().bar() | endif
++emsg_skip;
if (eval0(eap->arg, &rettv, &eap->nextcmd, 0) != FAIL)
if (eval0(eap->arg, &rettv, &eap->nextcmd, NULL) != FAIL)
clear_tv(&rettv);
--emsg_skip;
return;

View File

@@ -754,6 +754,28 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1047,
/**/
1046,
/**/
1045,
/**/
1044,
/**/
1043,
/**/
1042,
/**/
1041,
/**/
1040,
/**/
1039,
/**/
1038,
/**/
1037,
/**/
1036,
/**/

View File

@@ -2665,10 +2665,6 @@ long elapsed(DWORD start_tick);
#define REPTERM_SPECIAL 4
#define REPTERM_NO_SIMPLIFY 8
// Flags for expression evaluation.
#define EVAL_EVALUATE 1 // when missing don't actually evaluate
#define EVAL_CONSTANT 2 // when not a constant return FAIL
// Flags for find_special_key()
#define FSK_KEYCODE 0x01 // prefer key code, e.g. K_DEL instead of DEL
#define FSK_KEEP_X_KEY 0x02 // don't translate xHome to Home key

View File

@@ -643,7 +643,7 @@ check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
|| type2 == VAR_ANY)))
{
if (*op == '+')
emsg(_("E1035: wrong argument type for +"));
emsg(_("E1051: wrong argument type for +"));
else
semsg(_("E1036: %c requires number or float arguments"), *op);
return FAIL;
@@ -2402,14 +2402,38 @@ peek_next_line(cctx_T *cctx)
while (++lnum < cctx->ctx_ufunc->uf_lines.ga_len)
{
char_u *line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[lnum];
char_u *p = skipwhite(line);
char_u *p;
if (line == NULL)
break;
p = skipwhite(line);
if (*p != NUL && !comment_start(p))
return p;
}
return NULL;
}
/*
* Called when checking for a following operator at "arg". When the rest of
* the line is empty or only a comment, peek the next line. If there is a next
* line return a pointer to it and set "nextp".
* Otherwise skip over white space.
*/
static char_u *
may_peek_next_line(cctx_T *cctx, char_u *arg, char_u **nextp)
{
char_u *p = skipwhite(arg);
*nextp = NULL;
if (*p == NUL || (VIM_ISWHITE(*arg) && comment_start(p)))
{
*nextp = peek_next_line(cctx);
if (*nextp != NULL)
return *nextp;
}
return p;
}
/*
* Get the next line of the function from "cctx".
* Skips over empty lines. Skips over comment lines if "skip_comment" is TRUE.
@@ -3944,6 +3968,7 @@ compile_expr7(
compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
char_u *op;
char_u *next;
int ppconst_used = ppconst->pp_used;
// get the first expression
@@ -3955,9 +3980,14 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
*/
for (;;)
{
op = skipwhite(*arg);
op = may_peek_next_line(cctx, *arg, &next);
if (*op != '*' && *op != '/' && *op != '%')
break;
if (next != NULL)
{
*arg = next_line_from_context(cctx, TRUE);
op = skipwhite(*arg);
}
if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
{
@@ -4015,6 +4045,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
char_u *op;
char_u *next;
int oplen;
int ppconst_used = ppconst->pp_used;
@@ -4027,10 +4058,15 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
*/
for (;;)
{
op = skipwhite(*arg);
if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
op = may_peek_next_line(cctx, *arg, &next);
if (*op != '+' && *op != '-' && !(*op == '.' && *(op + 1) == '.'))
break;
oplen = (*op == '.' ? 2 : 1);
if (next != NULL)
{
*arg = next_line_from_context(cctx, TRUE);
op = skipwhite(*arg);
}
if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
{
@@ -4124,6 +4160,7 @@ compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
exptype_T type = EXPR_UNKNOWN;
char_u *p;
char_u *next;
int len = 2;
int type_is = FALSE;
int ppconst_used = ppconst->pp_used;
@@ -4132,7 +4169,7 @@ compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
if (compile_expr5(arg, cctx, ppconst) == FAIL)
return FAIL;
p = skipwhite(*arg);
p = may_peek_next_line(cctx, *arg, &next);
type = get_compare_type(p, &len, &type_is);
/*
@@ -4142,6 +4179,11 @@ compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
int ic = FALSE; // Default: do not ignore case
if (next != NULL)
{
*arg = next_line_from_context(cctx, TRUE);
p = skipwhite(*arg);
}
if (type_is && (p[len] == '?' || p[len] == '#'))
{
semsg(_(e_invexpr2), *arg);
@@ -4218,7 +4260,8 @@ compile_and_or(
ppconst_T *ppconst,
int ppconst_used UNUSED)
{
char_u *p = skipwhite(*arg);
char_u *next;
char_u *p = may_peek_next_line(cctx, *arg, &next);
int opchar = *op;
if (p[0] == opchar && p[1] == opchar)
@@ -4232,6 +4275,12 @@ compile_and_or(
ga_init2(&end_ga, sizeof(int), 10);
while (p[0] == opchar && p[1] == opchar)
{
if (next != NULL)
{
*arg = next_line_from_context(cctx, TRUE);
p = skipwhite(*arg);
}
if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
{
semsg(_(e_white_both), op);
@@ -4262,7 +4311,8 @@ compile_and_or(
ga_clear(&end_ga);
return FAIL;
}
p = skipwhite(*arg);
p = may_peek_next_line(cctx, *arg, &next);
}
generate_ppconst(cctx, ppconst);
@@ -4346,12 +4396,13 @@ compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
char_u *p;
int ppconst_used = ppconst->pp_used;
char_u *next;
// Evaluate the first expression.
if (compile_expr2(arg, cctx, ppconst) == FAIL)
return FAIL;
p = skipwhite(*arg);
p = may_peek_next_line(cctx, *arg, &next);
if (*p == '?')
{
garray_T *instr = &cctx->ctx_instr;
@@ -4365,6 +4416,12 @@ compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
int const_value = FALSE;
int save_skip = cctx->ctx_skip;
if (next != NULL)
{
*arg = next_line_from_context(cctx, TRUE);
p = skipwhite(*arg);
}
if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
{
semsg(_(e_white_both), "?");
@@ -4412,12 +4469,18 @@ compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
}
// Check for the ":".
p = skipwhite(*arg);
p = may_peek_next_line(cctx, *arg, &next);
if (*p != ':')
{
emsg(_(e_missing_colon));
return FAIL;
}
if (next != NULL)
{
*arg = next_line_from_context(cctx, TRUE);
p = skipwhite(*arg);
}
if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
{
semsg(_(e_white_both), ":");
@@ -6692,6 +6755,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
{
exarg_T ea;
int starts_with_colon = FALSE;
char_u *cmd;
// Bail out on the first error to avoid a flood of errors and report
// the right line number when inside try/catch.
@@ -6850,7 +6914,13 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
/*
* COMMAND after range
*/
cmd = ea.cmd;
ea.cmd = skip_range(ea.cmd, NULL);
if (ea.cmd > cmd && !starts_with_colon)
{
emsg(_(e_colon_required));
goto erret;
}
p = find_ex_command(&ea, NULL, starts_with_colon ? NULL
: (void *(*)(char_u *, size_t, cctx_T *))lookup_local,
&cctx);
@@ -7005,8 +7075,9 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
line = compile_mult_expr(p, ea.cmdidx, &cctx);
break;
// TODO: other commands with an expression argument
default:
// TODO: other commands with an expression argument
// Not recognized, execute with do_cmdline_cmd().
ea.arg = p;
line = compile_exec(line, &ea, &cctx);

View File

@@ -422,7 +422,7 @@ clip_mch_request_selection(Clipboard_T *cbd)
}
}
if (str != NULL && *str != NUL)
if (str != NULL && metadata.txtlen != 0)
{
char_u *temp_clipboard;
@@ -543,7 +543,7 @@ clip_mch_set_selection(Clipboard_T *cbd)
if (lpszMem)
{
vim_strncpy((char_u *)lpszMem, str, metadata.txtlen);
mch_memmove((char_u *)lpszMem, str, metadata.txtlen);
GlobalUnlock(hMem);
}
}