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.

d5053d015a

Omit getline_peek(): Vim9 script only.

Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
zeertzjq
2023-04-14 13:38:14 +08:00
parent e99f28e57d
commit 4b84b2e2aa
4 changed files with 45 additions and 31 deletions

View File

@@ -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;
}
}