summaryrefslogtreecommitdiff
path: root/src/builtins.zig
diff options
context:
space:
mode:
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 {