summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/builtins.zig56
-rw-r--r--src/panes.zig5
2 files changed, 42 insertions, 19 deletions
diff --git a/src/builtins.zig b/src/builtins.zig
index 93eae8ec..88c65704 100644
--- a/src/builtins.zig
+++ b/src/builtins.zig
@@ -226,6 +226,18 @@ test "Exit asks once about unsaved text, and quits when asked again" {
try std.testing.expect(p.quit);
}
+test "Restore asks about unsaved text as Exit does, and restores when asked again" {
+ const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true });
+ defer p.deinit();
+ const pane = try p.setTestFile("saved\n");
+ pane.file.?.saved_revision = pane.file.?.revision -% 1; // modified
+ try std.testing.expect(p.executeBuiltinLine(p.active, "Restore /tmp/some.dump.zon"));
+ try std.testing.expect(p.restore_req == null);
+ try std.testing.expect(std.mem.endsWith(u8, pane.msg[0..pane.msg_len], ": Modified"));
+ try std.testing.expect(p.executeBuiltinLine(p.active, "Restore /tmp/some.dump.zon"));
+ try std.testing.expectEqualStrings("/tmp/some.dump.zon", p.restore_req.?);
+}
+
test "Kill stops the commands pardes typed, bare all and by name those that match, and never quits" {
const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 80, .rows = 24 });
defer p.deinit();
@@ -340,26 +352,33 @@ pub const Exec = struct {
// ---- session ----
-/// acme's Exit (editors/acme/exec.c, `exit` and rowclean): quit, unless a
-/// pane holds unsaved text nobody has been told about. Each such pane says
-/// so, `<name>: Modified`, and the Exit goes no further; an Exit after that,
-/// with nothing edited since, quits. A scratch of under 100 bytes is no
-/// loss worth the question, as acme's winclean does not ask for one.
+/// acme's rowclean (editors/acme/wind.c:511-529, winclean), asked before
+/// what would throw unsaved text away: each pane holding some nobody has
+/// been told about says so, `<name>: Modified`, and is then clean for the
+/// asking, as winclean clears `dirty`; so the same word again, with
+/// nothing edited since, goes ahead. A scratch of under 100 bytes is no
+/// loss worth the question, as winclean does not ask for one.
+fn warnModified(c: Ctx) bool {
+ var modified = false;
+ for (c.p.panes, 0..) |slot, id| {
+ const pane = slot orelse continue;
+ const f = pane.file orelse continue;
+ if (f.revision == f.saved_revision or !panes.Output.fileTraits(f.output).saves) continue;
+ if (f.output != null and f.content.len < 100) continue;
+ if (pane.discard_warned == f.revision) continue;
+ pane.discard_warned = f.revision;
+ c.p.reportError(id, f.path, error.Modified);
+ modified = true;
+ }
+ return modified;
+}
+
+/// acme's Exit (editors/acme/exec.c:892): quit, once warnModified has
+/// nothing to say.
pub const Exit = struct {
pub const scope: Scope = .session;
pub fn run(c: Ctx) void {
- var modified = false;
- for (c.p.panes, 0..) |slot, id| {
- const pane = slot orelse continue;
- const f = pane.file orelse continue;
- if (f.revision == f.saved_revision or !panes.Output.fileTraits(f.output).saves) continue;
- if (f.output != null and f.content.len < 100) continue;
- if (pane.exit_warned == f.revision) continue;
- pane.exit_warned = f.revision;
- c.p.reportError(id, f.path, error.Modified);
- modified = true;
- }
- if (modified) return;
+ if (warnModified(c)) return;
c.p.quit = true;
c.p.emit(.quit);
}
@@ -412,6 +431,9 @@ pub const Restore = struct {
pub fn run(c: Ctx) void {
const path = c.arg orelse (c.p.last_dump orelse return);
if (path.len > c.p.restore_buf.len) return;
+ // acme's Load adds a dump's windows to the ones there; a Restore
+ // replaces them all, so it asks what Exit asks first.
+ if (warnModified(c)) return;
@memcpy(c.p.restore_buf[0..path.len], path);
c.p.restore_req = c.p.restore_buf[0..path.len];
}
diff --git a/src/panes.zig b/src/panes.zig
index 70b461eb..d4b336d7 100644
--- a/src/panes.zig
+++ b/src/panes.zig
@@ -99,8 +99,9 @@ pub const Pane = struct {
/// middle click, a pty/run): its first word, which Kill matches, and
/// the shell's command count its start (C mark) reaches.
sent_command: ?struct { word: [64]u8 = undefined, len: u8 = 0, seq: u32 = 0 } = null,
- /// The revision an Exit last warned this pane was modified at.
- exit_warned: ?u32 = null,
+ /// The revision an Exit or a Restore last warned this pane was modified
+ /// at (builtins.zig warnModified).
+ discard_warned: ?u32 = null,
/// Native host queues the Linux v9fs launcher in this pane's initial shell.
v9fs_on_spawn: bool = false,
file: ?File.State = null,