diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-15 12:29:41 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-09-15 17:24:42 -0300 |
| commit | 8b0bed0427064794725f95cb7b020d7d96956975 (patch) | |
| tree | e44dad51729bafd8a46a386af4a20674fc36c9d8 /test/panes.zig | |
| parent | a624a56e289e4a02a411f83741f0f2c9fc0f0b2e (diff) | |
| download | pardes-8b0bed0427064794725f95cb7b020d7d96956975.tar.gz pardes-8b0bed0427064794725f95cb7b020d7d96956975.zip | |
Preserve selections when navigating jump history
Diffstat (limited to 'test/panes.zig')
| -rw-r--r-- | test/panes.zig | 65 |
1 files changed, 65 insertions, 0 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"); |
