summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 19:01:38 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commit8ce3e3c62a22d0e70df4f241ff28de6f6cae78d3 (patch)
treef7fb503b298cf82966ae9938a4d065cfea3a96d6 /src
parent8948c9ec1b8ade3d1e4ed7103fd4f6d17a8ea23e (diff)
downloadpardes-8ce3e3c62a22d0e70df4f241ff28de6f6cae78d3.tar.gz
pardes-8ce3e3c62a22d0e70df4f241ff28de6f6cae78d3.zip
An Edit with an unclosed { is refused, not run
Edit ,x/area_of/{ answered ok and did nothing: the group ran out of text and ran what it had. sam reads on for the }; an Edit has nothing more to read, so it now fails with unmatched `{', in the words sam uses for the other side. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/sam_edit.zig12
1 files changed, 11 insertions, 1 deletions
diff --git a/src/sam_edit.zig b/src/sam_edit.zig
index 40221628..e8e90b67 100644
--- a/src/sam_edit.zig
+++ b/src/sam_edit.zig
@@ -95,6 +95,8 @@ const Parser = struct {
i: usize = 0,
/// The last pattern given, for an empty one (edit.c:562, getregexp).
lastpat: []const u8 = "",
+ /// The last `parse` that answered null met a `}`, not the end.
+ braced: bool = false,
why: *Why,
fn getch(ps: *Parser) ?u8 {
@@ -326,12 +328,18 @@ const Parser = struct {
var last: ?*Cmd = null;
while (true) {
if (ps.skipbl() == '\n') ps.i += 1;
- const next = (try ps.parse(nest + 1)) orelse break;
+ ps.braced = false;
+ const next = (try ps.parse(nest + 1)) orelse {
+ // sam reads on for the `}`; an Edit has no more to read.
+ if (!ps.braced) return fail(ps.why, "unmatched `{{'", .{});
+ break;
+ };
if (last) |l| l.next = next else cmd.sub = next;
last = next;
}
},
'}' => {
+ ps.braced = true;
try ps.atnl();
if (nest == 0) return fail(ps.why, "right brace with no left brace", .{});
return null;
@@ -655,6 +663,8 @@ test "an Edit that fails halfway changes nothing, and says why in acme's words"
.{ "k", "unknown command k" },
.{ ",x/a/{\na/1/\ni/2/\n}", "changes out of sequence" },
.{ "}", "right brace with no left brace" },
+ .{ ",x/foo/{", "unmatched `{'" },
+ .{ ",x/foo/{\nd", "unmatched `{'" },
.{ "w /tmp/x", "w is not supported in pardes" },
.{ ",s/(a)/\\1/", "no \\1: mvzr keeps no submatches" },
.{ "1 m 1,2", "move overlaps itself" },