diff options
-rw-r--r-- | src/nvim/eval.c | 10 | ||||
-rw-r--r-- | src/nvim/eval.h | 5 | ||||
-rw-r--r-- | src/nvim/eval/vars.c | 5 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 56 |
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; } } |