summaryrefslogtreecommitdiff
path: root/src/builtins.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 18:39:01 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commitc4ab29bce30f427decf3e199eebecfd415714a96 (patch)
tree69321fe5261c34dc27586e6d0a233d779368a49c /src/builtins.zig
parent00298cc24e12432a4120f4efb68728c008d9620f (diff)
downloadpardes-c4ab29bce30f427decf3e199eebecfd415714a96.tar.gz
pardes-c4ab29bce30f427decf3e199eebecfd415714a96.zip
Edit runs sam's command language on a pane's body, as acme's Edit does, in one undo step
Over 9P a rename everywhere was a loop of addr and data writes. Edit, from a tag, a pane ctl or exec, parses sam's commands as acme's edit.c does and runs them as ecmd.c does against the text as it was, collecting the changes in order as elog.c logs them and applying them at once: addresses (the addr file's, line:col included), x y g v c a i d s p = m t, u alone, and { }. One undo step; any error, in acme's words, changes nothing, fails a ctl write and is logged. p and = print to the directory's +Errors. Left out, and said: the file commands, the pipes, \1-\9 (mvzr keeps no submatches), and changes out of sequence, which acme applies with a warning. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/builtins.zig')
-rw-r--r--src/builtins.zig31
1 files changed, 31 insertions, 0 deletions
diff --git a/src/builtins.zig b/src/builtins.zig
index ef425c91..72df0271 100644
--- a/src/builtins.zig
+++ b/src/builtins.zig
@@ -883,6 +883,37 @@ pub const Togglettymode = struct {
}
};
+/// acme's Edit (exec.c `edit`, edit.c): sam's command language over the
+/// pane's body, from a tag, a pane ctl or exec. One undo step; a failure
+/// changes nothing and says why. src/sam_edit.zig has what is left out.
+pub const Edit = struct {
+ pub const takes_arg = true;
+ pub const requires_arg = true;
+ pub fn run(c: Ctx) void {
+ const sam = @import("sam_edit.zig");
+ const ninep_pane = @import("ninep/pane.zig");
+ const f = ninep_pane.fileOf(c.pane) orelse return c.p.reportFailure(c.id, "Edit: only a text pane is edited");
+ const arena = c.p.scratch.allocator();
+ var why: sam.Why = .{};
+ var said: [260]u8 = undefined;
+ const res = sam.run(arena, f.content, ninep_pane.dotOf(c.pane), f.path, c.arg orelse "", &why) catch |err| switch (err) {
+ error.Edit => return c.p.reportFailure(c.id, std.fmt.bufPrint(&said, "Edit: {s}", .{why.text()}) catch "Edit: failed"),
+ error.OutOfMemory => return c.p.reportError(c.id, "Edit", err),
+ };
+ if (res.undo != 0) {
+ for (0..@abs(res.undo)) |_| if (res.undo > 0) panes.File.undo(c.p, c.pane) else panes.File.redo(c.p, c.pane);
+ return;
+ }
+ if (res.ops.len > 0) {
+ const new = sam.apply(c.p.gpa, f.content, res.ops) catch |err| return c.p.reportError(c.id, "Edit", err);
+ panes.File.pushUndo(c.p, c.pane);
+ panes.File.setContent(c.p, f, new);
+ }
+ ninep_pane.setDot(c.pane, sam.moveDot(res.dot, res.ops));
+ if (res.printed.len > 0) _ = ninep_pane.appendErrors(c.p, c.id, res.printed);
+ }
+};
+
/// acme's Undo and Redo (exec.c `undo`): step the pane's body back or
/// forward through its edits, from a tag, a pane ctl or exec.
pub const Undo = struct {