summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-15 12:29:41 -0300
committerGabriel Schneider <[email protected]>2026-09-15 17:24:42 -0300
commit8b0bed0427064794725f95cb7b020d7d96956975 (patch)
treee44dad51729bafd8a46a386af4a20674fc36c9d8 /test
parenta624a56e289e4a02a411f83741f0f2c9fc0f0b2e (diff)
downloadpardes-8b0bed0427064794725f95cb7b020d7d96956975.tar.gz
pardes-8b0bed0427064794725f95cb7b020d7d96956975.zip
Preserve selections when navigating jump history
Diffstat (limited to 'test')
-rw-r--r--test/panes.zig65
-rw-r--r--test/pdf.zig12
2 files changed, 73 insertions, 4 deletions
diff --git a/test/panes.zig b/test/panes.zig
index a324d74a..ab7726e1 100644
--- a/test/panes.zig
+++ b/test/panes.zig
@@ -12,6 +12,70 @@ const image = pardes.image;
const syntax = pardes.syntax;
const filesystem = pardes.filesystem;
+const JumpSelectionTests = struct {
+ fn drag(p: *Pardes, col0: u16, row0: u16, col1: u16, row1: u16) void {
+ p.update(.{ .mouse = .{ .button = .left, .kind = .press, .col = col0, .row = row0 } });
+ p.update(.{ .mouse = .{ .button = .left, .kind = .drag, .col = col1, .row = row1 } });
+ p.update(.{ .mouse = .{ .button = .left, .kind = .release, .col = col1, .row = row1 } });
+ }
+
+ fn exercise(prefix: []const u8, wrap: bool, reverse: bool, first_col: u16, last_col: u16, expected: ?[]const u8) !void {
+ const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 34, .rows = 10 });
+ defer p.deinit();
+ p.settings.wrap = wrap;
+ const text = try std.fmt.allocPrint(p.gpa, "{s}{s}", .{ prefix, "unrelated destination text\n" ** 80 });
+ defer p.gpa.free(text);
+ const pane = try p.setTestFile(text);
+ var frame = std.heap.ArenaAllocator.init(p.gpa);
+ defer frame.deinit();
+ _ = try p.render(frame.allocator());
+ if (wrap) try std.testing.expectEqual(pane.wrap_line[0], pane.wrap_line[1]);
+ const rect = p.rects[0];
+ const x = rect.x + config.GUTTER + panes.File.gutterWidth(pane);
+ const y = if (p.settings.tag_bottom) rect.y else rect.y + pardes.BOX_H;
+ if (reverse)
+ drag(p, x + last_col, y + 1, x + first_col, y)
+ else
+ drag(p, x + first_col, y, x + last_col, y + 1);
+
+ const selected = try p.gpa.dupe(u8, pardes.test_api.heldSelection(p, 0) orelse return error.MissingMouseSelection);
+ defer p.gpa.free(selected);
+ if (expected) |want| try std.testing.expectEqualStrings(want, selected);
+ try std.testing.expect(std.mem.indexOfScalar(u8, selected, '\n') != null);
+ if (wrap) try std.testing.expect(std.mem.indexOf(u8, selected, "界") != null);
+
+ // Seed two actual locations after the drag, so both history directions
+ // must scroll while retaining the rectangle's original source text.
+ p.njumps = 2;
+ p.jcur = 1;
+ p.jumps[0] = .{ .pane = 0, .serial = pane.serial, .line = 60, .col = 1 };
+ p.jumps[1] = .{ .pane = 0, .serial = pane.serial, .line = 1, .col = 1 };
+ p.update(.{ .key = .{ .cp = 'o', .ctrl = true } });
+ _ = frame.reset(.retain_capacity);
+ _ = try p.render(frame.allocator());
+ try std.testing.expectEqual(@as(usize, 0), p.jcur);
+ try std.testing.expect(pane.file.?.scroll > 20);
+ try std.testing.expectEqualStrings(selected, pardes.test_api.heldSelection(p, 0) orelse return error.LostMouseSelection);
+
+ p.update(.{ .key = .{ .cp = 'i', .ctrl = true } });
+ _ = frame.reset(.retain_capacity);
+ _ = try p.render(frame.allocator());
+ try std.testing.expectEqual(@as(usize, 1), p.jcur);
+ try std.testing.expectEqual(@as(usize, 0), pane.file.?.scroll);
+ try std.testing.expectEqualStrings(selected, pardes.test_api.heldSelection(p, 0) orelse return error.LostMouseSelection);
+ }
+
+ test "jump selection retains copied rectangle text after scrolling away and back" {
+ for ([_]bool{ false, true }) |reverse|
+ try exercise("alpha\nbravo\n", false, reverse, 1, 3, "lph\nrav");
+ }
+
+ test "jump selection retains wrapped Unicode and tab rectangle text" {
+ for ([_]bool{ false, true }) |reverse|
+ try exercise("界\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n", true, reverse, 0, 8, null);
+ }
+};
+
test "pane filename edits stage commit and cancel without changing body or command tail" {
const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 70, .rows = 12 });
defer p.deinit();
@@ -2627,6 +2691,7 @@ const TerminalTests = struct {
};
test {
+ _ = JumpSelectionTests;
_ = @import("output.zig");
_ = @import("pdf.zig");
_ = @import("fs_namespace.zig");
diff --git a/test/pdf.zig b/test/pdf.zig
index a5720f3f..4c0daf34 100644
--- a/test/pdf.zig
+++ b/test/pdf.zig
@@ -1629,7 +1629,7 @@ test "PDF native mouse selection, Look, and highlights share page geometry" {
p.scratch.allocator(),
panes.Pdf.highlightInput(p, 0, pane),
);
- const page_highlights = decorated.forPage(pv.page, pv.page);
+ const page_highlights = decorated.forPage(pv.page);
try std.testing.expectEqual(pdf_impl.HighlightKind.custom, page_highlights[0].kind);
try std.testing.expectEqual(pdf_impl.HighlightKind.selection, page_highlights[page_highlights.len - 1].kind);
_ = frame.reset(.retain_capacity);
@@ -1672,7 +1672,7 @@ test "PDF native mouse selection, Look, and highlights share page geometry" {
pv,
p.scratch.allocator(),
panes.Pdf.highlightInput(p, 0, pane),
- )).items;
+ )).forPage(pv.page);
try std.testing.expect(highlights.len > 1);
try std.testing.expectEqual(pdf_impl.HighlightKind.search, highlights[0].kind);
try std.testing.expectEqual(pdf_impl.HighlightKind.selection, highlights[highlights.len - 1].kind);
@@ -1814,9 +1814,13 @@ test "PDF native mouse selection, Look, and highlights share page geometry" {
const saved_query = try gpa.dupe(u8, pv.search_query);
defer gpa.free(saved_query);
+ const saved_selection = try gpa.dupe(u8, pv.selection_text);
+ defer gpa.free(saved_selection);
+ const selected_page = pv.selection_page;
panes.Pdf.setPage(p, pane, 1);
- try std.testing.expect(pv.selection == null);
- try std.testing.expectEqual(@as(usize, 0), pv.selection_text.len);
+ try std.testing.expect(pv.selection != null);
+ try std.testing.expectEqual(selected_page, pv.selection_page);
+ try std.testing.expectEqualStrings(saved_selection, pv.selection_text);
try std.testing.expectEqualStrings(saved_query, pv.search_query);
}