diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/builtins.zig | 36 | ||||
| -rw-r--r-- | src/panes.zig | 8 |
2 files changed, 32 insertions, 12 deletions
diff --git a/src/builtins.zig b/src/builtins.zig index d6b89cf2..d06897ff 100644 --- a/src/builtins.zig +++ b/src/builtins.zig @@ -238,6 +238,21 @@ test "Restore asks about unsaved text as Exit does, and restores when asked agai try std.testing.expectEqualStrings("/tmp/some.dump.zon", p.restore_req.?); } +test "a Restore's warning is not an Exit's: each word is warned on its own" { + 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); + // The Restore warned; an Exit after it has not been, and asks. + try std.testing.expect(p.executeBuiltinLine(p.active, "Exit")); + try std.testing.expect(!p.quit); + try std.testing.expect(std.mem.endsWith(u8, pane.msg[0..pane.msg_len], ": Modified (Exit again to discard)")); + try std.testing.expect(p.executeBuiltinLine(p.active, "Exit")); + try std.testing.expect(p.quit); +} + 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(); @@ -356,21 +371,22 @@ pub const Exec = struct { /// what would throw unsaved text away: each pane holding some nobody has /// been told about says so, `<name>: Modified (Exit again to discard)`, /// naming the word asking, since repeating it throws the text away, 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, asking: []const u8) bool { +/// then clean for the asking, as winclean clears `dirty`; so the same word +/// again, with nothing edited since, goes ahead. Only the same word: a +/// Restore a script was refused does not spend the warning an Exit owes +/// the person at the keyboard. A scratch of under 100 bytes is no loss +/// worth the question, as winclean does not ask for one. +fn warnModified(c: Ctx, asking: Pane.Discarding) 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; + if (pane.discard_warned) |w| if (w.revision == f.revision and w.by == asking) continue; + pane.discard_warned = .{ .revision = f.revision, .by = asking }; var buf: [limits.host_path_cap + 48]u8 = undefined; - c.p.reportFailure(id, std.fmt.bufPrint(&buf, "{s}: Modified ({s} again to discard)", .{ f.path, asking }) catch f.path); + c.p.reportFailure(id, std.fmt.bufPrint(&buf, "{s}: Modified ({s} again to discard)", .{ f.path, @tagName(asking) }) catch f.path); modified = true; } return modified; @@ -381,7 +397,7 @@ fn warnModified(c: Ctx, asking: []const u8) bool { pub const Exit = struct { pub const scope: Scope = .session; pub fn run(c: Ctx) void { - if (warnModified(c, "Exit")) return; + if (warnModified(c, .Exit)) return; c.p.quit = true; c.p.emit(.quit); } @@ -436,7 +452,7 @@ pub const Restore = struct { 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, "Restore")) return; + if (warnModified(c, .Restore)) 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 888465f7..09b93aa3 100644 --- a/src/panes.zig +++ b/src/panes.zig @@ -24,6 +24,9 @@ const Key = pardes.Key; pub const EditText = struct { text: []u8, row0: i32 }; pub const Pane = struct { + /// The words that throw unsaved text away (builtins.zig warnModified). + pub const Discarding = enum { Exit, Restore }; + /// One mouse selection (block-shaped), per button. c/r are text-area relative; /// r counts from the tag's first row (the body starts at Pane.tag_rows). pub const Sel = struct { @@ -100,8 +103,9 @@ pub const Pane = struct { /// 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 or a Restore last warned this pane was modified - /// at (builtins.zig warnModified). - discard_warned: ?u32 = null, + /// at, and which of them: only that word goes ahead on the warning + /// (builtins.zig warnModified). + discard_warned: ?struct { revision: u32, by: Discarding } = null, /// Native host queues the Linux v9fs launcher in this pane's initial shell. v9fs_on_spawn: bool = false, file: ?File.State = null, |
