mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 13:15:09 -07:00
vim-patch:8.2.1080: Vim9: no line break allowed in a for loop
Problem: Vim9: no line break allowed in a for loop.
Solution: Skip line breaks in for command.
b7a78f7a67
Omit *_break_count and skip_for_lines(): Vim9 script only.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
parent
4b84b2e2aa
commit
8729c41f44
@ -173,6 +173,7 @@ Object nvim_eval(String expr, Error *err)
|
|||||||
|
|
||||||
TRY_WRAP(err, {
|
TRY_WRAP(err, {
|
||||||
ok = eval0(expr.data, &rettv, NULL, &EVALARG_EVALUATE);
|
ok = eval0(expr.data, &rettv, NULL, &EVALARG_EVALUATE);
|
||||||
|
clear_evalarg(&EVALARG_EVALUATE, NULL);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!ERROR_SET(err)) {
|
if (!ERROR_SET(err)) {
|
||||||
@ -294,6 +295,7 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err)
|
|||||||
api_set_error(err, kErrorTypeException,
|
api_set_error(err, kErrorTypeException,
|
||||||
"Failed to evaluate dict expression");
|
"Failed to evaluate dict expression");
|
||||||
}
|
}
|
||||||
|
clear_evalarg(&EVALARG_EVALUATE, NULL);
|
||||||
if (try_end(err)) {
|
if (try_end(err)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -494,7 +494,7 @@ static typval_T *eval_expr_no_emsg(struct debuggy *const bp)
|
|||||||
{
|
{
|
||||||
// Disable error messages, a bad expression would make Vim unusable.
|
// Disable error messages, a bad expression would make Vim unusable.
|
||||||
emsg_off++;
|
emsg_off++;
|
||||||
typval_T *const tv = eval_expr(bp->dbg_name);
|
typval_T *const tv = eval_expr(bp->dbg_name, NULL);
|
||||||
emsg_off--;
|
emsg_off--;
|
||||||
return tv;
|
return tv;
|
||||||
}
|
}
|
||||||
|
@ -849,6 +849,7 @@ char *eval_to_string_skip(char *arg, exarg_T *eap, const bool skip)
|
|||||||
if (skip) {
|
if (skip) {
|
||||||
emsg_skip--;
|
emsg_skip--;
|
||||||
}
|
}
|
||||||
|
clear_evalarg(&EVALARG_EVALUATE, eap);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -910,6 +911,7 @@ char *eval_to_string(char *arg, bool convert)
|
|||||||
}
|
}
|
||||||
tv_clear(&tv);
|
tv_clear(&tv);
|
||||||
}
|
}
|
||||||
|
clear_evalarg(&EVALARG_EVALUATE, NULL);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -964,12 +966,13 @@ varnumber_T eval_to_number(char *expr)
|
|||||||
///
|
///
|
||||||
/// @return an allocated typval_T with the result or
|
/// @return an allocated typval_T with the result or
|
||||||
/// NULL when there is an error.
|
/// NULL when there is an error.
|
||||||
typval_T *eval_expr(char *arg)
|
typval_T *eval_expr(char *arg, exarg_T *eap)
|
||||||
{
|
{
|
||||||
typval_T *tv = xmalloc(sizeof(*tv));
|
typval_T *tv = xmalloc(sizeof(*tv));
|
||||||
if (eval0(arg, tv, NULL, &EVALARG_EVALUATE) == FAIL) {
|
if (eval0(arg, tv, eap, &EVALARG_EVALUATE) == FAIL) {
|
||||||
XFREE_CLEAR(tv);
|
XFREE_CLEAR(tv);
|
||||||
}
|
}
|
||||||
|
clear_evalarg(&EVALARG_EVALUATE, eap);
|
||||||
return tv;
|
return tv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1215,6 +1218,7 @@ int eval_foldexpr(char *arg, int *cp)
|
|||||||
sandbox--;
|
sandbox--;
|
||||||
}
|
}
|
||||||
textlock--;
|
textlock--;
|
||||||
|
clear_evalarg(&EVALARG_EVALUATE, NULL);
|
||||||
|
|
||||||
return (int)retval;
|
return (int)retval;
|
||||||
}
|
}
|
||||||
@ -1797,14 +1801,14 @@ notify:
|
|||||||
/// @param[out] *errp set to true for an error, false otherwise;
|
/// @param[out] *errp set to true for an error, false otherwise;
|
||||||
///
|
///
|
||||||
/// @return a pointer that holds the info. Null when there is an error.
|
/// @return a pointer that holds the info. Null when there is an error.
|
||||||
void *eval_for_line(const char *arg, bool *errp, exarg_T *eap, int skip)
|
void *eval_for_line(const char *arg, bool *errp, exarg_T *eap, evalarg_T *const evalarg)
|
||||||
{
|
{
|
||||||
forinfo_T *fi = xcalloc(1, sizeof(forinfo_T));
|
forinfo_T *fi = xcalloc(1, sizeof(forinfo_T));
|
||||||
const char *expr;
|
const char *expr;
|
||||||
typval_T tv;
|
typval_T tv;
|
||||||
list_T *l;
|
list_T *l;
|
||||||
|
const bool skip = !(evalarg->eval_flags & EVAL_EVALUATE);
|
||||||
|
|
||||||
evalarg_T evalarg = { .eval_flags = skip ? 0 : EVAL_EVALUATE };
|
|
||||||
*errp = true; // Default: there is an error.
|
*errp = true; // Default: there is an error.
|
||||||
|
|
||||||
expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
|
expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
|
||||||
@ -1813,7 +1817,8 @@ void *eval_for_line(const char *arg, bool *errp, exarg_T *eap, int skip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
expr = skipwhite(expr);
|
expr = skipwhite(expr);
|
||||||
if (expr[0] != 'i' || expr[1] != 'n' || !ascii_iswhite(expr[2])) {
|
if (expr[0] != 'i' || expr[1] != 'n'
|
||||||
|
|| !(expr[2] == NUL || ascii_iswhite(expr[2]))) {
|
||||||
emsg(_("E690: Missing \"in\" after :for"));
|
emsg(_("E690: Missing \"in\" after :for"));
|
||||||
return fi;
|
return fi;
|
||||||
}
|
}
|
||||||
@ -1821,7 +1826,8 @@ void *eval_for_line(const char *arg, bool *errp, exarg_T *eap, int skip)
|
|||||||
if (skip) {
|
if (skip) {
|
||||||
emsg_skip++;
|
emsg_skip++;
|
||||||
}
|
}
|
||||||
if (eval0(skipwhite(expr + 2), &tv, eap, &evalarg) == OK) {
|
expr = skipwhite(expr + 2);
|
||||||
|
if (eval0((char *)expr, &tv, eap, evalarg) == OK) {
|
||||||
*errp = false;
|
*errp = false;
|
||||||
if (!skip) {
|
if (!skip) {
|
||||||
if (tv.v_type == VAR_LIST) {
|
if (tv.v_type == VAR_LIST) {
|
||||||
@ -2240,13 +2246,17 @@ static int eval_func(char **const arg, char *const name, const int name_len, typ
|
|||||||
/// After using "evalarg" filled from "eap" free the memory.
|
/// After using "evalarg" filled from "eap" free the memory.
|
||||||
void clear_evalarg(evalarg_T *evalarg, exarg_T *eap)
|
void clear_evalarg(evalarg_T *evalarg, exarg_T *eap)
|
||||||
{
|
{
|
||||||
if (evalarg != NULL && eap != NULL && evalarg->eval_tofree != NULL) {
|
if (evalarg != NULL && evalarg->eval_tofree != NULL) {
|
||||||
// We may need to keep the original command line, e.g. for
|
if (eap != NULL) {
|
||||||
// ":let" it has the variable names. But we may also need the
|
// We may need to keep the original command line, e.g. for
|
||||||
// new one, "nextcmd" points into it. Keep both.
|
// ":let" it has the variable names. But we may also need the
|
||||||
xfree(eap->cmdline_tofree);
|
// new one, "nextcmd" points into it. Keep both.
|
||||||
eap->cmdline_tofree = *eap->cmdlinep;
|
xfree(eap->cmdline_tofree);
|
||||||
*eap->cmdlinep = evalarg->eval_tofree;
|
eap->cmdline_tofree = *eap->cmdlinep;
|
||||||
|
*eap->cmdlinep = evalarg->eval_tofree;
|
||||||
|
} else {
|
||||||
|
xfree(evalarg->eval_tofree);
|
||||||
|
}
|
||||||
evalarg->eval_tofree = NULL;
|
evalarg->eval_tofree = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2301,8 +2311,6 @@ int eval0(char *arg, typval_T *rettv, exarg_T *eap, evalarg_T *const evalarg)
|
|||||||
eap->nextcmd = check_nextcmd(p);
|
eap->nextcmd = check_nextcmd(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_evalarg(evalarg, eap);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2996,6 +2996,7 @@ void ex_return(exarg_T *eap)
|
|||||||
if (eap->skip) {
|
if (eap->skip) {
|
||||||
emsg_skip--;
|
emsg_skip--;
|
||||||
}
|
}
|
||||||
|
clear_evalarg(&evalarg, eap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ":1,25call func(arg1, arg2)" function call.
|
/// ":1,25call func(arg1, arg2)" function call.
|
||||||
|
@ -794,11 +794,17 @@ void ex_eval(exarg_T *eap)
|
|||||||
typval_T tv;
|
typval_T tv;
|
||||||
evalarg_T evalarg = {
|
evalarg_T evalarg = {
|
||||||
.eval_flags = eap->skip ? 0 : EVAL_EVALUATE,
|
.eval_flags = eap->skip ? 0 : EVAL_EVALUATE,
|
||||||
.eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL,
|
|
||||||
};
|
};
|
||||||
|
if (getline_equal(eap->getline, eap->cookie, getsourceline)) {
|
||||||
|
evalarg.eval_getline = eap->getline;
|
||||||
|
evalarg.eval_cookie = eap->cookie;
|
||||||
|
}
|
||||||
|
|
||||||
if (eval0(eap->arg, &tv, eap, &evalarg) == OK) {
|
if (eval0(eap->arg, &tv, eap, &evalarg) == OK) {
|
||||||
tv_clear(&tv);
|
tv_clear(&tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear_evalarg(&evalarg, eap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle ":if".
|
/// Handle ":if".
|
||||||
@ -961,6 +967,14 @@ void ex_while(exarg_T *eap)
|
|||||||
} else {
|
} else {
|
||||||
void *fi;
|
void *fi;
|
||||||
|
|
||||||
|
evalarg_T evalarg = {
|
||||||
|
.eval_flags = eap->skip ? 0 : EVAL_EVALUATE,
|
||||||
|
};
|
||||||
|
if (getline_equal(eap->getline, eap->cookie, getsourceline)) {
|
||||||
|
evalarg.eval_getline = eap->getline;
|
||||||
|
evalarg.eval_cookie = eap->cookie;
|
||||||
|
}
|
||||||
|
|
||||||
// ":for var in list-expr"
|
// ":for var in list-expr"
|
||||||
if ((cstack->cs_lflags & CSL_HAD_LOOP) != 0) {
|
if ((cstack->cs_lflags & CSL_HAD_LOOP) != 0) {
|
||||||
// Jumping here from a ":continue" or ":endfor": use the
|
// Jumping here from a ":continue" or ":endfor": use the
|
||||||
@ -969,7 +983,7 @@ void ex_while(exarg_T *eap)
|
|||||||
error = false;
|
error = false;
|
||||||
} else {
|
} else {
|
||||||
// Evaluate the argument and get the info in a structure.
|
// Evaluate the argument and get the info in a structure.
|
||||||
fi = eval_for_line(eap->arg, &error, eap, skip);
|
fi = eval_for_line(eap->arg, &error, eap, &evalarg);
|
||||||
cstack->cs_forinfo[cstack->cs_idx] = fi;
|
cstack->cs_forinfo[cstack->cs_idx] = fi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -984,6 +998,7 @@ void ex_while(exarg_T *eap)
|
|||||||
free_for_info(fi);
|
free_for_info(fi);
|
||||||
cstack->cs_forinfo[cstack->cs_idx] = NULL;
|
cstack->cs_forinfo[cstack->cs_idx] = NULL;
|
||||||
}
|
}
|
||||||
|
clear_evalarg(&evalarg, eap);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this cstack entry was just initialised and is active, set the
|
// If this cstack entry was just initialised and is active, set the
|
||||||
|
@ -5266,7 +5266,7 @@ int option_set_callback_func(char *optval, Callback *optcb)
|
|||||||
|| (strncmp(optval, "function(", 9) == 0)
|
|| (strncmp(optval, "function(", 9) == 0)
|
||||||
|| (strncmp(optval, "funcref(", 8) == 0)) {
|
|| (strncmp(optval, "funcref(", 8) == 0)) {
|
||||||
// Lambda expression or a funcref
|
// Lambda expression or a funcref
|
||||||
tv = eval_expr(optval);
|
tv = eval_expr(optval, NULL);
|
||||||
if (tv == NULL) {
|
if (tv == NULL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
@ -6957,15 +6957,15 @@ void ex_cexpr(exarg_T *eap)
|
|||||||
|
|
||||||
// Evaluate the expression. When the result is a string or a list we can
|
// Evaluate the expression. When the result is a string or a list we can
|
||||||
// use it to fill the errorlist.
|
// use it to fill the errorlist.
|
||||||
typval_T tv;
|
typval_T *tv = eval_expr(eap->arg, eap);
|
||||||
if (eval0(eap->arg, &tv, eap, &EVALARG_EVALUATE) == FAIL) {
|
if (tv == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((tv.v_type == VAR_STRING && tv.vval.v_string != NULL)
|
if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL)
|
||||||
|| tv.v_type == VAR_LIST) {
|
|| tv->v_type == VAR_LIST) {
|
||||||
incr_quickfix_busy();
|
incr_quickfix_busy();
|
||||||
int res = qf_init_ext(qi, qi->qf_curlist, NULL, NULL, &tv, p_efm,
|
int res = qf_init_ext(qi, qi->qf_curlist, NULL, NULL, tv, p_efm,
|
||||||
(eap->cmdidx != CMD_caddexpr
|
(eap->cmdidx != CMD_caddexpr
|
||||||
&& eap->cmdidx != CMD_laddexpr),
|
&& eap->cmdidx != CMD_laddexpr),
|
||||||
(linenr_T)0, (linenr_T)0,
|
(linenr_T)0, (linenr_T)0,
|
||||||
@ -6996,7 +6996,7 @@ void ex_cexpr(exarg_T *eap)
|
|||||||
emsg(_("E777: String or List expected"));
|
emsg(_("E777: String or List expected"));
|
||||||
}
|
}
|
||||||
cleanup:
|
cleanup:
|
||||||
tv_clear(&tv);
|
tv_free(tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the location list for ":lhelpgrep"
|
// Get the location list for ":lhelpgrep"
|
||||||
|
Loading…
Reference in New Issue
Block a user