mirror of
https://github.com/zoriya/vim.git
synced 2025-12-06 23:36:16 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
801ab06934 | ||
|
|
832adf9bb8 | ||
|
|
7acde51832 | ||
|
|
ca275a05d8 | ||
|
|
65a8ed37f7 | ||
|
|
b171fb1790 | ||
|
|
9d40c63c7d | ||
|
|
5409f5d8c9 | ||
|
|
b7e2483655 | ||
|
|
67fbdfefd2 | ||
|
|
ef6d86c173 | ||
|
|
4014e2ceb0 | ||
|
|
df069eec3b | ||
|
|
7eaafe65ee | ||
|
|
bdd2c290d3 | ||
|
|
25fd267287 | ||
|
|
b2b218d89b | ||
|
|
acd4c5e914 |
@@ -333,6 +333,14 @@ Examples:
|
||||
:lua l = d.len -- assign d as 'self'
|
||||
:lua print(l())
|
||||
<
|
||||
Lua functions and closures are automatically converted to a Vim |Funcref| and
|
||||
can be accessed in Vim scripts. Example:
|
||||
>
|
||||
lua <<EOF
|
||||
vim.fn.timer_start(1000, function(timer)
|
||||
print('timer callback')
|
||||
end)
|
||||
EOF
|
||||
|
||||
==============================================================================
|
||||
7. Buffer userdata *lua-buffer*
|
||||
|
||||
@@ -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 ~
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -285,7 +285,7 @@ general_beval_cb(BalloonEval *beval, int state UNUSED)
|
||||
++textwinlock;
|
||||
|
||||
vim_free(result);
|
||||
result = eval_to_string(bexpr, NULL, TRUE);
|
||||
result = eval_to_string(bexpr, TRUE);
|
||||
|
||||
// Remove one trailing newline, it is added when the result was a
|
||||
// list and it's hardly ever useful. If the user really wants a
|
||||
|
||||
@@ -4094,7 +4094,7 @@ build_stl_str_hl(
|
||||
tv.vval.v_number = wp->w_id;
|
||||
set_var((char_u *)"g:statusline_winid", &tv, FALSE);
|
||||
|
||||
usefmt = eval_to_string_safe(fmt + 2, NULL, use_sandbox);
|
||||
usefmt = eval_to_string_safe(fmt + 2, use_sandbox);
|
||||
if (usefmt == NULL)
|
||||
usefmt = fmt;
|
||||
|
||||
@@ -4434,7 +4434,7 @@ build_stl_str_hl(
|
||||
if (curwin != save_curwin)
|
||||
VIsual_active = FALSE;
|
||||
|
||||
str = eval_to_string_safe(p, &t, use_sandbox);
|
||||
str = eval_to_string_safe(p, use_sandbox);
|
||||
|
||||
curwin = save_curwin;
|
||||
curbuf = save_curbuf;
|
||||
|
||||
@@ -86,7 +86,7 @@ eval_client_expr_to_string(char_u *expr)
|
||||
// to be typed. Do generate errors so that try/catch works.
|
||||
++emsg_silent;
|
||||
|
||||
res = eval_to_string(expr, NULL, TRUE);
|
||||
res = eval_to_string(expr, TRUE);
|
||||
|
||||
debug_break_level = save_dbl;
|
||||
redir_off = save_ro;
|
||||
|
||||
11
src/dict.c
11
src/dict.c
@@ -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);
|
||||
|
||||
330
src/eval.c
330
src/eval.c
@@ -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);
|
||||
@@ -161,7 +161,7 @@ eval_clear(void)
|
||||
eval_to_bool(
|
||||
char_u *arg,
|
||||
int *error,
|
||||
char_u **nextcmd,
|
||||
exarg_T *eap,
|
||||
int skip) // only parse, don't execute
|
||||
{
|
||||
typval_T tv;
|
||||
@@ -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, eap, 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
|
||||
@@ -317,7 +317,7 @@ eval_expr_to_bool(typval_T *expr, int *error)
|
||||
char_u *
|
||||
eval_to_string_skip(
|
||||
char_u *arg,
|
||||
char_u **nextcmd,
|
||||
exarg_T *eap,
|
||||
int skip) // only parse, don't execute
|
||||
{
|
||||
typval_T tv;
|
||||
@@ -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, eap, 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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -360,7 +361,6 @@ skip_expr(char_u **pp)
|
||||
char_u *
|
||||
eval_to_string(
|
||||
char_u *arg,
|
||||
char_u **nextcmd,
|
||||
int convert)
|
||||
{
|
||||
typval_T tv;
|
||||
@@ -370,7 +370,7 @@ eval_to_string(
|
||||
char_u numbuf[NUMBUFLEN];
|
||||
#endif
|
||||
|
||||
if (eval0(arg, &tv, nextcmd, EVAL_EVALUATE) == FAIL)
|
||||
if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL)
|
||||
retval = NULL;
|
||||
else
|
||||
{
|
||||
@@ -408,7 +408,6 @@ eval_to_string(
|
||||
char_u *
|
||||
eval_to_string_safe(
|
||||
char_u *arg,
|
||||
char_u **nextcmd,
|
||||
int use_sandbox)
|
||||
{
|
||||
char_u *retval;
|
||||
@@ -418,7 +417,7 @@ eval_to_string_safe(
|
||||
if (use_sandbox)
|
||||
++sandbox;
|
||||
++textwinlock;
|
||||
retval = eval_to_string(arg, nextcmd, FALSE);
|
||||
retval = eval_to_string(arg, FALSE);
|
||||
if (use_sandbox)
|
||||
--sandbox;
|
||||
--textwinlock;
|
||||
@@ -440,7 +439,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
|
||||
{
|
||||
@@ -458,12 +457,12 @@ eval_to_number(char_u *expr)
|
||||
* Returns NULL when there is an error.
|
||||
*/
|
||||
typval_T *
|
||||
eval_expr(char_u *arg, char_u **nextcmd)
|
||||
eval_expr(char_u *arg, exarg_T *eap)
|
||||
{
|
||||
typval_T *tv;
|
||||
|
||||
tv = ALLOC_ONE(typval_T);
|
||||
if (tv != NULL && eval0(arg, tv, nextcmd, EVAL_EVALUATE) == FAIL)
|
||||
if (tv != NULL && eval0(arg, tv, eap, &EVALARG_EVALUATE) == FAIL)
|
||||
VIM_CLEAR(tv);
|
||||
|
||||
return tv;
|
||||
@@ -588,7 +587,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 +775,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 +813,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;
|
||||
@@ -1417,14 +1416,17 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
|
||||
eval_for_line(
|
||||
char_u *arg,
|
||||
int *errp,
|
||||
char_u **nextcmdp,
|
||||
exarg_T *eap,
|
||||
int skip)
|
||||
{
|
||||
forinfo_T *fi;
|
||||
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 +1446,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, eap, &evalarg) == OK)
|
||||
{
|
||||
*errp = FALSE;
|
||||
if (!skip)
|
||||
@@ -1763,6 +1764,46 @@ 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* To be called when eval_next_non_blank() sets "getnext" to TRUE.
|
||||
*/
|
||||
static char_u *
|
||||
eval_next_line(evalarg_T *evalarg)
|
||||
{
|
||||
vim_free(evalarg->eval_tofree);
|
||||
evalarg->eval_tofree = getsourceline(0, evalarg->eval_cookie, 0, TRUE);
|
||||
return skipwhite(evalarg->eval_tofree);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,23 +1815,27 @@ 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
|
||||
eval0(
|
||||
char_u *arg,
|
||||
typval_T *rettv,
|
||||
char_u **nextcmd,
|
||||
int flags)
|
||||
exarg_T *eap,
|
||||
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;
|
||||
|
||||
if (evalarg != NULL)
|
||||
evalarg->eval_tofree = NULL;
|
||||
p = skipwhite(arg);
|
||||
ret = eval1(&p, rettv, flags);
|
||||
ret = eval1(&p, rettv, evalarg);
|
||||
|
||||
if (ret == FAIL || !ends_excmd2(arg, p))
|
||||
{
|
||||
if (ret != FAIL)
|
||||
@@ -1808,8 +1853,27 @@ eval0(
|
||||
semsg(_(e_invexpr2), arg);
|
||||
ret = FAIL;
|
||||
}
|
||||
if (nextcmd != NULL)
|
||||
*nextcmd = check_nextcmd(p);
|
||||
|
||||
if (eap != NULL)
|
||||
eap->nextcmd = check_nextcmd(p);
|
||||
|
||||
if (evalarg != NULL)
|
||||
{
|
||||
if (eap != NULL)
|
||||
{
|
||||
if (evalarg->eval_tofree != NULL)
|
||||
{
|
||||
// We may need to keep the original command line, e.g. for
|
||||
// ":let" it has the variable names. But we may also need the
|
||||
// new one, "nextcmd" points into it. Keep both.
|
||||
vim_free(eap->cmdline_tofree);
|
||||
eap->cmdline_tofree = *eap->cmdlinep;
|
||||
*eap->cmdlinep = evalarg->eval_tofree;
|
||||
}
|
||||
}
|
||||
else
|
||||
vim_free(evalarg->eval_tofree);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1826,23 +1890,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;
|
||||
int evaluate;
|
||||
|
||||
if (evalarg == NULL)
|
||||
{
|
||||
CLEAR_FIELD(nested_evalarg);
|
||||
orig_flags = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nested_evalarg = *evalarg;
|
||||
orig_flags = evalarg->eval_flags;
|
||||
}
|
||||
|
||||
evaluate = nested_evalarg.eval_flags & EVAL_EVALUATE;
|
||||
result = FALSE;
|
||||
if (flags & EVAL_EVALUATE)
|
||||
if (evaluate)
|
||||
{
|
||||
int error = FALSE;
|
||||
|
||||
@@ -1857,7 +1934,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 +1954,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 +1979,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 +1989,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 +1999,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 +2030,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 +2066,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 +2076,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 +2086,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 +2116,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 +2161,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 +2173,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 +2241,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 +2308,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 +2323,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 = eval_next_line(evalarg);
|
||||
|
||||
if ((op != '+' || (rettv->v_type != VAR_LIST
|
||||
&& rettv->v_type != VAR_BLOB))
|
||||
@@ -2240,7 +2352,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 +2365,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 +2404,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 +2497,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 +2512,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 +2520,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 = eval_next_line(evalarg);
|
||||
|
||||
if (flags & EVAL_EVALUATE)
|
||||
if (evaluate)
|
||||
{
|
||||
#ifdef FEAT_FLOAT
|
||||
if (rettv->v_type == VAR_FLOAT)
|
||||
@@ -2431,10 +2553,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 +2673,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 +2796,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 +3156,11 @@ eval_index(
|
||||
}
|
||||
else
|
||||
{
|
||||
evalarg_T evalarg;
|
||||
|
||||
CLEAR_FIELD(evalarg);
|
||||
evalarg.eval_flags = flags;
|
||||
|
||||
/*
|
||||
* something[idx]
|
||||
*
|
||||
@@ -3038,7 +3169,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 +3187,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);
|
||||
@@ -4634,7 +4765,6 @@ make_expanded_name(
|
||||
char_u c1;
|
||||
char_u *retval = NULL;
|
||||
char_u *temp_result;
|
||||
char_u *nextcmd = NULL;
|
||||
|
||||
if (expr_end == NULL || in_end == NULL)
|
||||
return NULL;
|
||||
@@ -4643,8 +4773,8 @@ make_expanded_name(
|
||||
c1 = *in_end;
|
||||
*in_end = NUL;
|
||||
|
||||
temp_result = eval_to_string(expr_start + 1, &nextcmd, FALSE);
|
||||
if (temp_result != NULL && nextcmd == NULL)
|
||||
temp_result = eval_to_string(expr_start + 1, FALSE);
|
||||
if (temp_result != NULL)
|
||||
{
|
||||
retval = alloc(STRLEN(temp_result) + (expr_start - in_start)
|
||||
+ (in_end - expr_end) + 1);
|
||||
@@ -4947,6 +5077,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 +5091,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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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, &evalarg);
|
||||
if (eap->skip)
|
||||
--emsg_skip;
|
||||
}
|
||||
if (eap->skip)
|
||||
{
|
||||
if (i != FAIL)
|
||||
clear_tv(&rettv);
|
||||
--emsg_skip;
|
||||
}
|
||||
else if (i != FAIL)
|
||||
{
|
||||
|
||||
@@ -1841,6 +1841,9 @@ struct exarg
|
||||
char_u *nextcmd; // next command (NULL if none)
|
||||
char_u *cmd; // the name of the command (except for :make)
|
||||
char_u **cmdlinep; // pointer to pointer of allocated cmdline
|
||||
#ifdef FEAT_EVAL
|
||||
char_u *cmdline_tofree; // free later
|
||||
#endif
|
||||
cmdidx_T cmdidx; // the index for the command
|
||||
long argt; // flags for the command
|
||||
int skip; // don't execute the command, only parse it
|
||||
|
||||
@@ -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);
|
||||
@@ -2602,6 +2609,7 @@ doend:
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
--ex_nesting_level;
|
||||
vim_free(ea.cmdline_tofree);
|
||||
#endif
|
||||
|
||||
return ea.nextcmd;
|
||||
@@ -3446,7 +3454,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 *
|
||||
@@ -4905,7 +4913,7 @@ ex_colorscheme(exarg_T *eap)
|
||||
if (expr != NULL)
|
||||
{
|
||||
++emsg_off;
|
||||
p = eval_to_string(expr, NULL, FALSE);
|
||||
p = eval_to_string(expr, FALSE);
|
||||
--emsg_off;
|
||||
vim_free(expr);
|
||||
}
|
||||
|
||||
@@ -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, &evalarg) == OK)
|
||||
clear_tv(&tv);
|
||||
}
|
||||
|
||||
@@ -926,7 +929,7 @@ ex_if(exarg_T *eap)
|
||||
skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0
|
||||
&& !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
|
||||
|
||||
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
|
||||
result = eval_to_bool(eap->arg, &error, eap, skip);
|
||||
|
||||
if (!skip && !error)
|
||||
{
|
||||
@@ -1038,7 +1041,7 @@ ex_else(exarg_T *eap)
|
||||
|
||||
if (eap->cmdidx == CMD_elseif)
|
||||
{
|
||||
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
|
||||
result = eval_to_bool(eap->arg, &error, eap, skip);
|
||||
|
||||
// When throwing error exceptions, we want to throw always the first
|
||||
// of several errors in a row. This is what actually happens when
|
||||
@@ -1100,7 +1103,7 @@ ex_while(exarg_T *eap)
|
||||
/*
|
||||
* ":while bool-expr"
|
||||
*/
|
||||
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
|
||||
result = eval_to_bool(eap->arg, &error, eap, skip);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1119,7 +1122,7 @@ ex_while(exarg_T *eap)
|
||||
else
|
||||
{
|
||||
// Evaluate the argument and get the info in a structure.
|
||||
fi = eval_for_line(eap->arg, &error, &eap->nextcmd, skip);
|
||||
fi = eval_for_line(eap->arg, &error, eap, skip);
|
||||
cstack->cs_forinfo[cstack->cs_idx] = fi;
|
||||
}
|
||||
|
||||
@@ -1319,7 +1322,7 @@ ex_throw(exarg_T *eap)
|
||||
char_u *value;
|
||||
|
||||
if (*arg != NUL && *arg != '|' && *arg != '\n')
|
||||
value = eval_to_string_skip(arg, &eap->nextcmd, eap->skip);
|
||||
value = eval_to_string_skip(arg, eap, eap->skip);
|
||||
else
|
||||
{
|
||||
emsg(_(e_argreq));
|
||||
|
||||
@@ -3083,7 +3083,7 @@ expand_backtick(
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
if (*cmd == '=') // `={expr}`: Expand expression
|
||||
buffer = eval_to_string(cmd + 1, &p, TRUE);
|
||||
buffer = eval_to_string(cmd + 1, TRUE);
|
||||
else
|
||||
#endif
|
||||
buffer = get_cmd_output(cmd, NULL,
|
||||
|
||||
@@ -2079,7 +2079,7 @@ eval_includeexpr(char_u *ptr, int len)
|
||||
char_u *res;
|
||||
|
||||
set_vim_var_string(VV_FNAME, ptr, len);
|
||||
res = eval_to_string_safe(curbuf->b_p_inex, NULL,
|
||||
res = eval_to_string_safe(curbuf->b_p_inex,
|
||||
was_set_insecurely((char_u *)"includeexpr", OPT_LOCAL));
|
||||
set_vim_var_string(VV_FNAME, NULL, 0);
|
||||
return res;
|
||||
|
||||
@@ -1928,7 +1928,7 @@ get_foldtext(
|
||||
curbuf = wp->w_buffer;
|
||||
|
||||
++emsg_silent; // handle exceptions, but don't display errors
|
||||
text = eval_to_string_safe(wp->w_p_fdt, NULL,
|
||||
text = eval_to_string_safe(wp->w_p_fdt,
|
||||
was_set_insecurely((char_u *)"foldtext", OPT_LOCAL));
|
||||
--emsg_silent;
|
||||
|
||||
|
||||
@@ -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 INIT3(EVAL_EVALUATE, NULL, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef MSWIN
|
||||
|
||||
101
src/if_lua.c
101
src/if_lua.c
@@ -35,6 +35,13 @@ typedef struct {
|
||||
} luaV_Funcref;
|
||||
typedef void (*msgfunc_T)(char_u *);
|
||||
|
||||
typedef struct {
|
||||
int lua_funcref; // ref to a lua func
|
||||
int lua_tableref; // ref to a lua table if metatable else LUA_NOREF. used
|
||||
// for __call
|
||||
lua_State *L;
|
||||
} luaV_CFuncState;
|
||||
|
||||
static const char LUAVIM_DICT[] = "dict";
|
||||
static const char LUAVIM_LIST[] = "list";
|
||||
static const char LUAVIM_BLOB[] = "blob";
|
||||
@@ -45,6 +52,8 @@ static const char LUAVIM_FREE[] = "luaV_free";
|
||||
static const char LUAVIM_LUAEVAL[] = "luaV_luaeval";
|
||||
static const char LUAVIM_SETREF[] = "luaV_setref";
|
||||
|
||||
static const char LUA___CALL[] = "__call";
|
||||
|
||||
// most functions are closures with a cache table as first upvalue;
|
||||
// get/setudata manage references to vim userdata in cache table through
|
||||
// object pointers (light userdata)
|
||||
@@ -64,7 +73,7 @@ static const char LUAVIM_SETREF[] = "luaV_setref";
|
||||
#define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg)
|
||||
#define luaV_checktypval(L, a, v, msg) \
|
||||
do { \
|
||||
if (luaV_totypval(L, a, v) == FAIL) \
|
||||
if (luaV_totypval(L, a, v) == FAIL) \
|
||||
luaL_error(L, msg ": cannot convert value"); \
|
||||
} while (0)
|
||||
|
||||
@@ -72,6 +81,8 @@ static luaV_List *luaV_pushlist(lua_State *L, list_T *lis);
|
||||
static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic);
|
||||
static luaV_Blob *luaV_pushblob(lua_State *L, blob_T *blo);
|
||||
static luaV_Funcref *luaV_pushfuncref(lua_State *L, char_u *name);
|
||||
static int luaV_call_lua_func(int argcount, typval_T *argvars, typval_T *rettv, void *state);
|
||||
static void luaV_call_lua_func_free(void *state);
|
||||
|
||||
#if LUA_VERSION_NUM <= 501
|
||||
#define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n)
|
||||
@@ -591,6 +602,45 @@ luaV_totypval(lua_State *L, int pos, typval_T *tv)
|
||||
tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos);
|
||||
#endif
|
||||
break;
|
||||
case LUA_TFUNCTION:
|
||||
{
|
||||
char_u *name;
|
||||
lua_pushvalue(L, pos);
|
||||
luaV_CFuncState *state = ALLOC_CLEAR_ONE(luaV_CFuncState);
|
||||
state->lua_funcref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
state->L = L;
|
||||
state->lua_tableref = LUA_NOREF;
|
||||
name = register_cfunc(&luaV_call_lua_func,
|
||||
&luaV_call_lua_func_free, state);
|
||||
tv->v_type = VAR_FUNC;
|
||||
tv->vval.v_string = vim_strsave(name);
|
||||
break;
|
||||
}
|
||||
case LUA_TTABLE:
|
||||
{
|
||||
lua_pushvalue(L, pos);
|
||||
int lua_tableref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
if (lua_getmetatable(L, pos)) {
|
||||
lua_getfield(L, -1, LUA___CALL);
|
||||
if (lua_isfunction(L, -1)) {
|
||||
char_u *name;
|
||||
int lua_funcref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
luaV_CFuncState *state = ALLOC_CLEAR_ONE(luaV_CFuncState);
|
||||
state->lua_funcref = lua_funcref;
|
||||
state->L = L;
|
||||
state->lua_tableref = lua_tableref;
|
||||
name = register_cfunc(&luaV_call_lua_func,
|
||||
&luaV_call_lua_func_free, state);
|
||||
tv->v_type = VAR_FUNC;
|
||||
tv->vval.v_string = vim_strsave(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
tv->v_type = VAR_NUMBER;
|
||||
tv->vval.v_number = 0;
|
||||
status = FAIL;
|
||||
break;
|
||||
}
|
||||
case LUA_TUSERDATA:
|
||||
{
|
||||
void *p = lua_touserdata(L, pos);
|
||||
@@ -2415,4 +2465,53 @@ update_package_paths_in_lua()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Native C function callback
|
||||
*/
|
||||
static int
|
||||
luaV_call_lua_func(
|
||||
int argcount,
|
||||
typval_T *argvars,
|
||||
typval_T *rettv,
|
||||
void *state)
|
||||
{
|
||||
int i;
|
||||
int luaargcount = argcount;
|
||||
luaV_CFuncState *funcstate = (luaV_CFuncState*)state;
|
||||
lua_rawgeti(funcstate->L, LUA_REGISTRYINDEX, funcstate->lua_funcref);
|
||||
|
||||
if (funcstate->lua_tableref != LUA_NOREF)
|
||||
{
|
||||
// First arg for metatable __call method is a table
|
||||
luaargcount += 1;
|
||||
lua_rawgeti(funcstate->L, LUA_REGISTRYINDEX, funcstate->lua_tableref);
|
||||
}
|
||||
|
||||
for (i = 0; i < argcount; ++i)
|
||||
luaV_pushtypval(funcstate->L, &argvars[i]);
|
||||
|
||||
if (lua_pcall(funcstate->L, luaargcount, 1, 0))
|
||||
{
|
||||
luaV_emsg(funcstate->L);
|
||||
return FCERR_OTHER;
|
||||
}
|
||||
|
||||
luaV_checktypval(funcstate->L, -1, rettv, "get return value");
|
||||
return FCERR_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free up any lua references held by the func state.
|
||||
*/
|
||||
static void
|
||||
luaV_call_lua_func_free(void *state)
|
||||
{
|
||||
luaV_CFuncState *funcstate = (luaV_CFuncState*)state;
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, funcstate->lua_funcref);
|
||||
funcstate->L = NULL;
|
||||
if (funcstate->lua_tableref != LUA_NOREF)
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, funcstate->lua_tableref);
|
||||
VIM_CLEAR(funcstate);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -388,7 +388,7 @@ CVim::Eval(BSTR expr, BSTR *result)
|
||||
|
||||
/* Evaluate the expression */
|
||||
++emsg_skip;
|
||||
str = (char *)eval_to_string((char_u *)buffer, NULL, TRUE);
|
||||
str = (char *)eval_to_string((char_u *)buffer, TRUE);
|
||||
--emsg_skip;
|
||||
vim_free(buffer);
|
||||
if (str == NULL)
|
||||
|
||||
@@ -832,7 +832,6 @@ msg_split(
|
||||
char_u *
|
||||
eval_to_string(
|
||||
char_u *arg UNUSED,
|
||||
char_u **nextcmd UNUSED,
|
||||
int dolist UNUSED)
|
||||
{
|
||||
return NULL;
|
||||
@@ -1562,7 +1561,7 @@ Eval(str)
|
||||
PREINIT:
|
||||
char_u *value;
|
||||
PPCODE:
|
||||
value = eval_to_string((char_u *)str, (char_u **)0, TRUE);
|
||||
value = eval_to_string((char_u *)str, TRUE);
|
||||
if (value == NULL)
|
||||
{
|
||||
XPUSHs(sv_2mortal(newSViv(0)));
|
||||
|
||||
@@ -1373,7 +1373,7 @@ tclvimexpr(
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
expr = Tcl_GetStringFromObj(objv[objn], NULL);
|
||||
str = (char *)eval_to_string((char_u *)expr, NULL, TRUE);
|
||||
str = (char *)eval_to_string((char_u *)expr, TRUE);
|
||||
if (str == NULL)
|
||||
Tcl_SetResult(interp, _("invalid expression"), TCL_STATIC);
|
||||
else
|
||||
|
||||
14
src/list.c
14
src/list.c
@@ -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)
|
||||
{
|
||||
@@ -2457,6 +2461,8 @@ f_reduce(typval_T *argvars, typval_T *rettv)
|
||||
list_T *l = argvars[0].vval.v_list;
|
||||
listitem_T *li = NULL;
|
||||
int r;
|
||||
int prev_locked = l->lv_lock;
|
||||
int called_emsg_start = called_emsg;
|
||||
|
||||
CHECK_LIST_MATERIALIZE(l);
|
||||
if (argvars[2].v_type == VAR_UNKNOWN)
|
||||
@@ -2476,6 +2482,7 @@ f_reduce(typval_T *argvars, typval_T *rettv)
|
||||
li = l->lv_first;
|
||||
}
|
||||
|
||||
l->lv_lock = VAR_FIXED; // disallow the list changing here
|
||||
copy_tv(&initial, rettv);
|
||||
for ( ; li != NULL; li = li->li_next)
|
||||
{
|
||||
@@ -2484,9 +2491,10 @@ f_reduce(typval_T *argvars, typval_T *rettv)
|
||||
rettv->v_type = VAR_UNKNOWN;
|
||||
r = call_func(func_name, -1, rettv, 2, argv, &funcexe);
|
||||
clear_tv(&argv[0]);
|
||||
if (r == FAIL)
|
||||
return;
|
||||
if (r == FAIL || called_emsg != called_emsg_start)
|
||||
break;
|
||||
}
|
||||
l->lv_lock = prev_locked;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1614,7 +1614,7 @@ eval_map_expr(
|
||||
save_cursor = curwin->w_cursor;
|
||||
save_msg_col = msg_col;
|
||||
save_msg_row = msg_row;
|
||||
p = eval_to_string(expr, NULL, FALSE);
|
||||
p = eval_to_string(expr, FALSE);
|
||||
--textwinlock;
|
||||
--ex_normal_lock;
|
||||
curwin->w_cursor = save_cursor;
|
||||
|
||||
@@ -3,16 +3,16 @@ varnumber_T num_divide(varnumber_T n1, varnumber_T n2);
|
||||
varnumber_T num_modulus(varnumber_T n1, varnumber_T n2);
|
||||
void eval_init(void);
|
||||
void eval_clear(void);
|
||||
int eval_to_bool(char_u *arg, int *error, char_u **nextcmd, int skip);
|
||||
int eval_to_bool(char_u *arg, int *error, exarg_T *eap, int skip);
|
||||
int eval_expr_valid_arg(typval_T *tv);
|
||||
int eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv);
|
||||
int eval_expr_to_bool(typval_T *expr, int *error);
|
||||
char_u *eval_to_string_skip(char_u *arg, char_u **nextcmd, int skip);
|
||||
char_u *eval_to_string_skip(char_u *arg, exarg_T *eap, int skip);
|
||||
int skip_expr(char_u **pp);
|
||||
char_u *eval_to_string(char_u *arg, char_u **nextcmd, int convert);
|
||||
char_u *eval_to_string_safe(char_u *arg, char_u **nextcmd, int use_sandbox);
|
||||
char_u *eval_to_string(char_u *arg, int convert);
|
||||
char_u *eval_to_string_safe(char_u *arg, int use_sandbox);
|
||||
varnumber_T eval_to_number(char_u *expr);
|
||||
typval_T *eval_expr(char_u *arg, char_u **nextcmd);
|
||||
typval_T *eval_expr(char_u *arg, exarg_T *eap);
|
||||
int call_vim_function(char_u *func, int argc, typval_T *argv, typval_T *rettv);
|
||||
varnumber_T call_func_retnr(char_u *func, int argc, typval_T *argv);
|
||||
void *call_func_retstr(char_u *func, int argc, typval_T *argv);
|
||||
@@ -21,13 +21,13 @@ int eval_foldexpr(char_u *arg, int *cp);
|
||||
char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags);
|
||||
void clear_lval(lval_T *lp);
|
||||
void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int flags, char_u *op);
|
||||
void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip);
|
||||
void *eval_for_line(char_u *arg, int *errp, exarg_T *eap, int skip);
|
||||
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, exarg_T *eap, evalarg_T *evalarg);
|
||||
int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -4,6 +4,7 @@ hashtab_T *func_tbl_get(void);
|
||||
int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, garray_T *argtypes, int *varargs, garray_T *default_args, int skip, exarg_T *eap, char_u **line_to_free);
|
||||
char_u *get_lambda_name(void);
|
||||
int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate);
|
||||
char_u *register_cfunc(cfunc_T cb, cfunc_free_T free_cb, void *state);
|
||||
char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload);
|
||||
void emsg_funcname(char *ermsg, char_u *name);
|
||||
int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, funcexe_T *funcexe);
|
||||
|
||||
@@ -7680,7 +7680,7 @@ ex_cexpr(exarg_T *eap)
|
||||
|
||||
// Evaluate the expression. When the result is a string or a list we can
|
||||
// use it to fill the errorlist.
|
||||
tv = eval_expr(eap->arg, &eap->nextcmd);
|
||||
tv = eval_expr(eap->arg, eap);
|
||||
if (tv != NULL)
|
||||
{
|
||||
if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL)
|
||||
|
||||
@@ -2066,7 +2066,7 @@ vim_regsub_both(
|
||||
clear_tv(&rettv);
|
||||
}
|
||||
else
|
||||
eval_result = eval_to_string(source + 2, NULL, TRUE);
|
||||
eval_result = eval_to_string(source + 2, TRUE);
|
||||
|
||||
if (eval_result != NULL)
|
||||
{
|
||||
|
||||
@@ -136,7 +136,7 @@ get_expr_line(void)
|
||||
return expr_copy;
|
||||
|
||||
++nested;
|
||||
rv = eval_to_string(expr_copy, NULL, TRUE);
|
||||
rv = eval_to_string(expr_copy, TRUE);
|
||||
--nested;
|
||||
vim_free(expr_copy);
|
||||
return rv;
|
||||
|
||||
@@ -1148,7 +1148,7 @@ get_keymap_str(
|
||||
curwin = wp;
|
||||
STRCPY(buf, "b:keymap_name"); // must be writable
|
||||
++emsg_skip;
|
||||
s = p = eval_to_string(buf, NULL, FALSE);
|
||||
s = p = eval_to_string(buf, FALSE);
|
||||
--emsg_skip;
|
||||
curbuf = old_curbuf;
|
||||
curwin = old_curwin;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1529,6 +1529,9 @@ struct blobvar_S
|
||||
char bv_lock; // zero, VAR_LOCKED, VAR_FIXED
|
||||
};
|
||||
|
||||
typedef int (*cfunc_T)(int argcount, typval_T *argvars, typval_T *rettv, void *state);
|
||||
typedef void (*cfunc_free_T)(void *state);
|
||||
|
||||
#if defined(FEAT_EVAL) || defined(PROTO)
|
||||
typedef struct funccall_S funccall_T;
|
||||
|
||||
@@ -1562,6 +1565,11 @@ typedef struct
|
||||
char_u *uf_va_name; // name from "...name" or NULL
|
||||
type_T *uf_va_type; // type from "...name: type" or NULL
|
||||
type_T *uf_func_type; // type of the function, &t_func_any if unknown
|
||||
# if defined(FEAT_LUA)
|
||||
cfunc_T uf_cb; // callback function for cfunc
|
||||
cfunc_free_T uf_cb_free; // callback function to free cfunc
|
||||
void *uf_cb_state; // state of uf_cb
|
||||
# endif
|
||||
|
||||
garray_T uf_lines; // function lines
|
||||
# ifdef FEAT_PROFILE
|
||||
@@ -1607,6 +1615,7 @@ typedef struct
|
||||
#define FC_EXPORT 0x100 // "export def Func()"
|
||||
#define FC_NOARGS 0x200 // no a: variables in lambda
|
||||
#define FC_VIM9 0x400 // defined in vim9 script file
|
||||
#define FC_CFUNC 0x800 // defined as Lua C func
|
||||
|
||||
#define MAX_FUNC_ARGS 20 // maximum number of function arguments
|
||||
#define VAR_SHORT_LEN 20 // short variable name length
|
||||
@@ -1746,6 +1755,22 @@ 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()
|
||||
|
||||
// pointer to the line obtained with getsourceline()
|
||||
char_u *eval_tofree;
|
||||
} 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.
|
||||
@@ -1781,6 +1806,10 @@ typedef struct
|
||||
{
|
||||
int dummy;
|
||||
} scriptitem_T;
|
||||
typedef struct
|
||||
{
|
||||
int dummy;
|
||||
} evalarg_T;
|
||||
#endif
|
||||
|
||||
// Struct passed between functions dealing with function call execution.
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -2585,7 +2585,7 @@ func Test_autocmd_window()
|
||||
edit one.txt
|
||||
tabnew two.txt
|
||||
let g:blist = []
|
||||
augroup aucmd_win_test
|
||||
augroup aucmd_win_test1
|
||||
au!
|
||||
au BufEnter * call add(g:blist, [expand('<afile>'),
|
||||
\ win_gettype(bufwinnr(expand('<afile>')))])
|
||||
@@ -2594,10 +2594,29 @@ func Test_autocmd_window()
|
||||
doautoall BufEnter
|
||||
call assert_equal([['one.txt', 'autocmd'], ['two.txt', '']], g:blist)
|
||||
|
||||
augroup aucmd_win_test
|
||||
augroup aucmd_win_test1
|
||||
au!
|
||||
augroup END
|
||||
augroup! aucmd_win_test
|
||||
augroup! aucmd_win_test1
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
" Test for trying to close the temporary window used for executing an autocmd
|
||||
func Test_close_autocmd_window()
|
||||
%bw!
|
||||
edit one.txt
|
||||
tabnew two.txt
|
||||
augroup aucmd_win_test2
|
||||
au!
|
||||
au BufEnter * if expand('<afile>') == 'one.txt' | 1close | endif
|
||||
augroup END
|
||||
|
||||
call assert_fails('doautoall BufEnter', 'E813:')
|
||||
|
||||
augroup aucmd_win_test2
|
||||
au!
|
||||
augroup END
|
||||
augroup! aucmd_win_test2
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
277
src/testdir/test_comments.vim
Normal file
277
src/testdir/test_comments.vim
Normal 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
|
||||
{
|
||||
X
|
||||
Xa
|
||||
XaY
|
||||
XY
|
||||
XYZ
|
||||
X Y
|
||||
X YZ
|
||||
XX
|
||||
XXa
|
||||
XXY
|
||||
}
|
||||
END
|
||||
call setline(1, t)
|
||||
call cursor(2, 1)
|
||||
|
||||
set tw=2 fo=cqm comments=n:X
|
||||
exe "normal gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgq"
|
||||
let t =<< trim END
|
||||
X
|
||||
Xa
|
||||
XaY
|
||||
XY
|
||||
XYZ
|
||||
X Y
|
||||
X YZ
|
||||
XX
|
||||
XXa
|
||||
XXY
|
||||
END
|
||||
exe "normal o\n" . join(t, "\n")
|
||||
|
||||
let expected =<< trim END
|
||||
{
|
||||
X
|
||||
Xa
|
||||
Xa
|
||||
XY
|
||||
XY
|
||||
XY
|
||||
XZ
|
||||
X Y
|
||||
X Y
|
||||
X Z
|
||||
XX
|
||||
XXa
|
||||
XXY
|
||||
|
||||
X
|
||||
Xa
|
||||
Xa
|
||||
XY
|
||||
XY
|
||||
XY
|
||||
XZ
|
||||
X Y
|
||||
X Y
|
||||
X Z
|
||||
XX
|
||||
XXa
|
||||
XXY
|
||||
}
|
||||
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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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'],
|
||||
|
||||
@@ -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:')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -709,6 +709,15 @@ func Test_reduce()
|
||||
call assert_fails("call reduce({}, { acc, val -> acc + val }, 1)", 'E897:')
|
||||
call assert_fails("call reduce(0, { acc, val -> acc + val }, 1)", 'E897:')
|
||||
call assert_fails("call reduce('', { acc, val -> acc + val }, 1)", 'E897:')
|
||||
|
||||
let g:lut = [1, 2, 3, 4]
|
||||
func EvilRemove()
|
||||
call remove(g:lut, 1)
|
||||
return 1
|
||||
endfunc
|
||||
call assert_fails("call reduce(g:lut, { acc, val -> EvilRemove() }, 1)", 'E742:')
|
||||
unlet g:lut
|
||||
delfunc EvilRemove
|
||||
endfunc
|
||||
|
||||
" splitting a string to a List using split()
|
||||
|
||||
@@ -541,6 +541,35 @@ func Test_update_package_paths()
|
||||
call assert_equal("hello from lua", luaeval("require('testluaplugin').hello()"))
|
||||
endfunc
|
||||
|
||||
func Vim_func_call_lua_callback(Concat, Cb)
|
||||
let l:message = a:Concat("hello", "vim")
|
||||
call a:Cb(l:message)
|
||||
endfunc
|
||||
|
||||
func Test_pass_lua_callback_to_vim_from_lua()
|
||||
lua pass_lua_callback_to_vim_from_lua_result = ""
|
||||
call assert_equal("", luaeval("pass_lua_callback_to_vim_from_lua_result"))
|
||||
lua <<EOF
|
||||
vim.funcref('Vim_func_call_lua_callback')(
|
||||
function(greeting, message)
|
||||
return greeting .. " " .. message
|
||||
end,
|
||||
function(message)
|
||||
pass_lua_callback_to_vim_from_lua_result = message
|
||||
end)
|
||||
EOF
|
||||
call assert_equal("hello vim", luaeval("pass_lua_callback_to_vim_from_lua_result"))
|
||||
endfunc
|
||||
|
||||
func Vim_func_call_metatable_lua_callback(Greet)
|
||||
return a:Greet("world")
|
||||
endfunc
|
||||
|
||||
func Test_pass_lua_metatable_callback_to_vim_from_lua()
|
||||
let result = luaeval("vim.funcref('Vim_func_call_metatable_lua_callback')(setmetatable({ space = ' '}, { __call = function(tbl, msg) return 'hello' .. tbl.space .. msg end }) )")
|
||||
call assert_equal("hello world", result)
|
||||
endfunc
|
||||
|
||||
" Test vim.line()
|
||||
func Test_lua_line()
|
||||
new
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
" Test 'statusline'
|
||||
"
|
||||
" Not tested yet:
|
||||
" %a
|
||||
" %N
|
||||
" %T
|
||||
" %X
|
||||
|
||||
source view_util.vim
|
||||
source check.vim
|
||||
@@ -64,7 +61,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
|
||||
@@ -95,6 +102,18 @@ func Test_statusline()
|
||||
set statusline=%F
|
||||
call assert_match('/testdir/Xstatusline\s*$', s:get_statusline())
|
||||
|
||||
" Test for min and max width with %(. For some reason, if this test is moved
|
||||
" after the below test for the help buffer flag, then the code to truncate
|
||||
" the string is not executed.
|
||||
set statusline=%015(%f%)
|
||||
call assert_match('^ Xstatusline\s*$', s:get_statusline())
|
||||
set statusline=%.6(%f%)
|
||||
call assert_match('^<sline\s*$', s:get_statusline())
|
||||
set statusline=%14f
|
||||
call assert_match('^ Xstatusline\s*$', s:get_statusline())
|
||||
set statusline=%.4L
|
||||
call assert_match('^10>3\s*$', s:get_statusline())
|
||||
|
||||
" %h: Help buffer flag, text is "[help]".
|
||||
" %H: Help buffer flag, text is ",HLP".
|
||||
set statusline=%h,%H
|
||||
@@ -413,3 +432,5 @@ func Test_statusline_removed_group()
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('XTest_statusline')
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -70,3 +70,46 @@ func Test_redrawtabline()
|
||||
let &showtabline = showtabline_save
|
||||
au! Bufadd
|
||||
endfunc
|
||||
|
||||
" Test for the "%T" and "%X" flags in the 'tabline' option
|
||||
func MyTabLine()
|
||||
let s = ''
|
||||
for i in range(tabpagenr('$'))
|
||||
" set the tab page number (for mouse clicks)
|
||||
let s .= '%' . (i + 1) . 'T'
|
||||
|
||||
" the label is made by MyTabLabel()
|
||||
let s .= ' %{MyTabLabel(' . (i + 1) . ')} '
|
||||
endfor
|
||||
|
||||
" after the last tab fill with TabLineFill and reset tab page nr
|
||||
let s .= '%T'
|
||||
|
||||
" right-align the label to close the current tab page
|
||||
if tabpagenr('$') > 1
|
||||
let s .= '%=%Xclose'
|
||||
endif
|
||||
|
||||
return s
|
||||
endfunc
|
||||
|
||||
func MyTabLabel(n)
|
||||
let buflist = tabpagebuflist(a:n)
|
||||
let winnr = tabpagewinnr(a:n)
|
||||
return bufname(buflist[winnr - 1])
|
||||
endfunc
|
||||
|
||||
func Test_tabline_flags()
|
||||
if has('gui')
|
||||
set guioptions-=e
|
||||
endif
|
||||
set tabline=%!MyTabLine()
|
||||
edit Xtabline1
|
||||
tabnew Xtabline2
|
||||
redrawtabline
|
||||
call assert_match('^ Xtabline1 Xtabline2\s\+close$', Screenline(1))
|
||||
set tabline=
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -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
|
||||
{
|
||||
X
|
||||
Xa
|
||||
XaY
|
||||
XY
|
||||
XYZ
|
||||
X Y
|
||||
X YZ
|
||||
XX
|
||||
XXa
|
||||
XXY
|
||||
}
|
||||
END
|
||||
call setline(1, t)
|
||||
call cursor(2, 1)
|
||||
|
||||
set tw=2 fo=cqm comments=n:X
|
||||
exe "normal gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgq"
|
||||
let t =<< trim END
|
||||
X
|
||||
Xa
|
||||
XaY
|
||||
XY
|
||||
XYZ
|
||||
X Y
|
||||
X YZ
|
||||
XX
|
||||
XXa
|
||||
XXY
|
||||
END
|
||||
exe "normal o\n" . join(t, "\n")
|
||||
|
||||
let expected =<< trim END
|
||||
{
|
||||
X
|
||||
Xa
|
||||
Xa
|
||||
XY
|
||||
XY
|
||||
XY
|
||||
XZ
|
||||
X Y
|
||||
X Y
|
||||
X Z
|
||||
XX
|
||||
XXa
|
||||
XXY
|
||||
|
||||
X
|
||||
Xa
|
||||
Xa
|
||||
XY
|
||||
XY
|
||||
XY
|
||||
XZ
|
||||
X Y
|
||||
X Y
|
||||
X Z
|
||||
XX
|
||||
XXa
|
||||
XXY
|
||||
}
|
||||
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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:')
|
||||
|
||||
@@ -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;
|
||||
@@ -341,6 +341,51 @@ get_lambda_name(void)
|
||||
return name;
|
||||
}
|
||||
|
||||
#if defined(FEAT_LUA) || defined(PROTO)
|
||||
/*
|
||||
* Registers a native C callback which can be called from Vim script.
|
||||
* Returns the name of the Vim script function.
|
||||
*/
|
||||
char_u *
|
||||
register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state)
|
||||
{
|
||||
char_u *name = get_lambda_name();
|
||||
ufunc_T *fp = NULL;
|
||||
garray_T newargs;
|
||||
garray_T newlines;
|
||||
|
||||
ga_init(&newargs);
|
||||
ga_init(&newlines);
|
||||
|
||||
fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
|
||||
if (fp == NULL)
|
||||
goto errret;
|
||||
|
||||
fp->uf_dfunc_idx = UF_NOT_COMPILED;
|
||||
fp->uf_refcount = 1;
|
||||
fp->uf_varargs = TRUE;
|
||||
fp->uf_flags = FC_CFUNC;
|
||||
fp->uf_calls = 0;
|
||||
fp->uf_script_ctx = current_sctx;
|
||||
fp->uf_lines = newlines;
|
||||
fp->uf_args = newargs;
|
||||
fp->uf_cb = cb;
|
||||
fp->uf_cb_free = cb_free;
|
||||
fp->uf_cb_state = state;
|
||||
|
||||
set_ufunc_name(fp, name);
|
||||
hash_add(&func_hashtab, UF2HIKEY(fp));
|
||||
|
||||
return name;
|
||||
|
||||
errret:
|
||||
ga_clear_strings(&newargs);
|
||||
ga_clear_strings(&newlines);
|
||||
vim_free(fp);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Parse a lambda expression and get a Funcref from "*arg".
|
||||
* Return OK or FAIL. Returns NOTDONE for dict or {expr}.
|
||||
@@ -561,6 +606,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 +621,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;
|
||||
@@ -1024,6 +1072,17 @@ func_clear_items(ufunc_T *fp)
|
||||
vim_free(((type_T **)fp->uf_type_list.ga_data)
|
||||
[--fp->uf_type_list.ga_len]);
|
||||
ga_clear(&fp->uf_type_list);
|
||||
|
||||
#ifdef FEAT_LUA
|
||||
if (fp->uf_cb_free != NULL)
|
||||
{
|
||||
fp->uf_cb_free(fp->uf_cb_state);
|
||||
fp->uf_cb_free = NULL;
|
||||
}
|
||||
|
||||
fp->uf_cb_state = NULL;
|
||||
fp->uf_cb = NULL;
|
||||
#endif
|
||||
#ifdef FEAT_PROFILE
|
||||
VIM_CLEAR(fp->uf_tml_count);
|
||||
VIM_CLEAR(fp->uf_tml_total);
|
||||
@@ -1249,7 +1308,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 +1453,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
|
||||
@@ -1970,6 +2029,14 @@ call_func(
|
||||
|
||||
if (fp != NULL && (fp->uf_flags & FC_DELETED))
|
||||
error = FCERR_DELETED;
|
||||
#ifdef FEAT_LUA
|
||||
else if (fp != NULL && (fp->uf_flags & FC_CFUNC))
|
||||
{
|
||||
cfunc_T cb = fp->uf_cb;
|
||||
|
||||
error = (*cb)(argcount, argvars, rettv, fp->uf_cb_state);
|
||||
}
|
||||
#endif
|
||||
else if (fp != NULL)
|
||||
{
|
||||
if (funcexe->argv_func != NULL)
|
||||
@@ -3697,6 +3764,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 +3772,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, &evalarg) != FAIL)
|
||||
{
|
||||
if (!eap->skip)
|
||||
returning = do_return(eap, FALSE, TRUE, &rettv);
|
||||
@@ -3767,7 +3837,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, NULL) != FAIL)
|
||||
clear_tv(&rettv);
|
||||
--emsg_skip;
|
||||
return;
|
||||
|
||||
@@ -754,6 +754,42 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1054,
|
||||
/**/
|
||||
1053,
|
||||
/**/
|
||||
1052,
|
||||
/**/
|
||||
1051,
|
||||
/**/
|
||||
1050,
|
||||
/**/
|
||||
1049,
|
||||
/**/
|
||||
1048,
|
||||
/**/
|
||||
1047,
|
||||
/**/
|
||||
1046,
|
||||
/**/
|
||||
1045,
|
||||
/**/
|
||||
1044,
|
||||
/**/
|
||||
1043,
|
||||
/**/
|
||||
1042,
|
||||
/**/
|
||||
1041,
|
||||
/**/
|
||||
1040,
|
||||
/**/
|
||||
1039,
|
||||
/**/
|
||||
1038,
|
||||
/**/
|
||||
1037,
|
||||
/**/
|
||||
1036,
|
||||
/**/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user