aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-04-14 13:38:14 +0800
committerzeertzjq <zeertzjq@outlook.com>2023-04-14 16:10:09 +0800
commit4b84b2e2aa3d7ab6a4e346c7439826700682f5f1 (patch)
tree375334bffd4ce6f59b0dbbac65ced8fbf97ea186
parente99f28e57d69cfa1bd38ab531a0954f4f875ca47 (diff)
downloadrneovim-4b84b2e2aa3d7ab6a4e346c7439826700682f5f1.tar.gz
rneovim-4b84b2e2aa3d7ab6a4e346c7439826700682f5f1.tar.bz2
rneovim-4b84b2e2aa3d7ab6a4e346c7439826700682f5f1.zip
vim-patch:8.2.1079: Vim9: no line break allowed in a while loop
Problem: Vim9: no line break allowed in a while loop. Solution: Update stored loop lines when finding line breaks. https://github.com/vim/vim/commit/d5053d015a957b343ad9c9e45e0abd2978f10cf0 Omit getline_peek(): Vim9 script only. Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r--src/nvim/eval.c10
-rw-r--r--src/nvim/eval.h5
-rw-r--r--src/nvim/eval/vars.c5
-rw-r--r--src/nvim/ex_docmd.c56
4 files changed, 45 insertions, 31 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index a79a464860..e5193cdfb8 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -705,8 +705,11 @@ int eval_to_bool(char *arg, bool *error, exarg_T *eap, int skip)
evalarg_T evalarg = {
.eval_flags = skip ? 0 : EVAL_EVALUATE,
- .eval_cookie = eap != NULL && eap->getline == getsourceline ? eap->cookie : NULL,
};
+ if (eap != NULL && getline_equal(eap->getline, eap->cookie, getsourceline)) {
+ evalarg.eval_getline = eap->getline;
+ evalarg.eval_cookie = eap->cookie;
+ }
if (skip) {
emsg_skip++;
@@ -7461,8 +7464,11 @@ void ex_echo(exarg_T *eap)
evalarg_T evalarg = {
.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 (eap->skip) {
emsg_skip++;
diff --git a/src/nvim/eval.h b/src/nvim/eval.h
index 4f517551c6..4e0eb6ebb8 100644
--- a/src/nvim/eval.h
+++ b/src/nvim/eval.h
@@ -272,7 +272,8 @@ 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()
+ LineGetter eval_getline;
+ void *eval_cookie; ///< argument for eval_getline()
/// pointer to the line obtained with getsourceline()
char *eval_tofree;
@@ -284,7 +285,7 @@ enum {
};
/// Passed to an eval() function to enable evaluation.
-EXTERN evalarg_T EVALARG_EVALUATE INIT(= { EVAL_EVALUATE, NULL, NULL });
+EXTERN evalarg_T EVALARG_EVALUATE INIT(= { EVAL_EVALUATE, NULL, NULL, NULL });
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval.h.generated.h"
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index 868d03a115..4bce555d75 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -261,8 +261,11 @@ void ex_let(exarg_T *eap)
}
evalarg_T evalarg = {
.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;
+ }
int eval_res = eval0(expr, &rettv, eap, &evalarg);
if (eap->skip) {
emsg_skip--;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index f9f4a2514f..8e55672615 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -484,24 +484,6 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
}
}
- if (cstack.cs_looplevel > 0) {
- // Inside a while/for loop we need to store the lines and use them
- // again. Pass a different "fgetline" function to do_one_cmd()
- // below, so that it stores lines in or reads them from
- // "lines_ga". Makes it possible to define a function inside a
- // while/for loop.
- cmd_getline = get_loop_line;
- cmd_cookie = (void *)&cmd_loop_cookie;
- cmd_loop_cookie.lines_gap = &lines_ga;
- cmd_loop_cookie.current_line = current_line;
- cmd_loop_cookie.getline = fgetline;
- cmd_loop_cookie.cookie = cookie;
- cmd_loop_cookie.repeating = (current_line < lines_ga.ga_len);
- } else {
- cmd_getline = fgetline;
- cmd_cookie = cookie;
- }
-
// 2. If no line given, get an allocated line with fgetline().
if (next_cmdline == NULL) {
// Need to set msg_didout for the first line after an ":if",
@@ -540,15 +522,37 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
}
cmdline_copy = next_cmdline;
- // Save the current line when inside a ":while" or ":for", and when
- // the command looks like a ":while" or ":for", because we may need it
- // later. When there is a '|' and another command, it is stored
- // separately, because we need to be able to jump back to it from an
+ int current_line_before = 0;
+ // Inside a while/for loop, and when the command looks like a ":while"
+ // or ":for", the line is stored, because we may need it later when
+ // looping.
+ //
+ // When there is a '|' and another command, it is stored separately,
+ // because we need to be able to jump back to it from an
// :endwhile/:endfor.
- if (current_line == lines_ga.ga_len
- && (cstack.cs_looplevel || has_loop_cmd(next_cmdline))) {
- store_loop_line(&lines_ga, next_cmdline);
+ //
+ // Pass a different "fgetline" function to do_one_cmd() below,
+ // that it stores lines in or reads them from "lines_ga". Makes it
+ // possible to define a function inside a while/for loop.
+ if ((cstack.cs_looplevel > 0 || has_loop_cmd(next_cmdline))) {
+ cmd_getline = get_loop_line;
+ cmd_cookie = (void *)&cmd_loop_cookie;
+ cmd_loop_cookie.lines_gap = &lines_ga;
+ cmd_loop_cookie.current_line = current_line;
+ cmd_loop_cookie.getline = fgetline;
+ cmd_loop_cookie.cookie = cookie;
+ cmd_loop_cookie.repeating = (current_line < lines_ga.ga_len);
+
+ // Save the current line when encountering it the first time.
+ if (current_line == lines_ga.ga_len) {
+ store_loop_line(&lines_ga, next_cmdline);
+ }
+ current_line_before = current_line;
+ } else {
+ cmd_getline = fgetline;
+ cmd_cookie = cookie;
}
+
did_endif = false;
if (count++ == 0) {
@@ -651,7 +655,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
} else if (cstack.cs_lflags & CSL_HAD_LOOP) {
// For a ":while" or ":for" we need to remember the line number.
cstack.cs_lflags &= ~CSL_HAD_LOOP;
- cstack.cs_line[cstack.cs_idx] = current_line - 1;
+ cstack.cs_line[cstack.cs_idx] = current_line_before;
}
}