diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-15 18:59:33 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:14 -0300 |
| commit | b7914a0bd59334f618b62e0b98271211bbec46b9 (patch) | |
| tree | 53af62ce0ae022e580e35aadbd952e1656dcfa30 /test/panes.zig | |
| parent | 3f4f26e0e40d06427e72f72e760d01adcdc0326c (diff) | |
| download | pardes-b7914a0bd59334f618b62e0b98271211bbec46b9.tar.gz pardes-b7914a0bd59334f618b62e0b98271211bbec46b9.zip | |
Clear previous selections before resolving Look destinations
Diffstat (limited to 'test/panes.zig')
| -rw-r--r-- | test/panes.zig | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/test/panes.zig b/test/panes.zig index 28af8141..cb2e8169 100644 --- a/test/panes.zig +++ b/test/panes.zig @@ -4256,3 +4256,113 @@ test "terminal overlays preserve trailing blank styles without coloring inserted try std.testing.expectEqual(colors[2], extended.at(x, y + 4).style.bg); try std.testing.expect(p.shell_rows.pane == null); } + +const LookResetTests = struct { + fn seed(pane: *Pane, operand: []const u8) !void { + pane.cur_row = 0; + pane.cur_col = 3; + pane.vsel = .{ .active = true, .explicit = true, .row = 0, .col = 0 }; + pane.msel = .{ .active = true, .r0 = 0, .r1 = 1 }; + pane.sels[0] = .{ .row = 1, .col = 2, .arow = 0, .acol = 1 }; + pane.nsel = 1; + pane.select = true; + pane.normal.count = 5; + pane.append_at = .{ .row = 0, .col = 3 }; + pane.sticky_col = 7; + for (0..pane.sel.len) |slot| { + pane.clearPointerSelection(slot); + pane.sel[slot] = .{ .state = .done, .source_id = slot + 1, .r0 = 1, .r1 = 1, .c0 = 0, .c1 = 3 }; + const rows = try pane.gpa.alloc(Pane.PointerRow, 1); + rows[0] = .{ .row = 0, .lo = 0, .hi = 4 }; + pane.pointer_selections[slot] = .{ + .gesture = pane.sel[slot], + .rows = rows, + .raw_text = try pane.gpa.dupe(u8, operand), + }; + } + } + + fn cleared(pane: *const Pane) !void { + try std.testing.expect(!pane.msel.active); + try std.testing.expectEqual(@as(u8, 0), pane.nsel); + try std.testing.expect(!pane.select); + try std.testing.expectEqual(modal.Normal.State{}, pane.normal); + try std.testing.expect(pane.append_at == null); + try std.testing.expectEqual(@as(i32, -1), pane.sticky_col); + for (pane.sel) |selection| try std.testing.expectEqual(.none, selection.state); + for (pane.pointer_selections) |selection| try std.testing.expect(selection == null); + } + + fn selected(pane: *const Pane) []const u8 { + if (!pane.vsel.active or pane.cur_row != pane.vsel.row) return ""; + const line = modal.lineSlice(pane.file.?.content, @intCast(pane.cur_row)); + const lo: usize = @intCast(@min(pane.cur_col, pane.vsel.col)); + const hi: usize = @intCast(@max(pane.cur_col, pane.vsel.col)); + return line[lo..modal.nextGrapheme(line, hi)]; + } + + test "Look replaces old selection for same-pane addresses ranges and text fallback" { + const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 80, .rows = 24 }); + defer p.deinit(); + const pane = try p.setTestFile("alpha\nbravo\ncharlie\nneedle\n"); + try seed(pane, "/test.txt:3:2"); + // This operand is released by Look's selection cleanup. + p.lookAt(0, pane.pointer_selections[0].?.raw_text.?); + try cleared(pane); + try std.testing.expectEqual(@as(usize, 0), p.active); + try std.testing.expectEqual(@as(i32, 2), pane.cur_row); + try std.testing.expectEqual(@as(i32, 1), pane.cur_col); + try std.testing.expect(!pane.vsel.active); + + try seed(pane, "/test.txt:2:2-4"); + p.lookAt(0, pane.pointer_selections[0].?.raw_text.?); + try cleared(pane); + try std.testing.expectEqual(@as(i32, 1), pane.cur_row); + try std.testing.expectEqualStrings("rav", selected(pane)); + + p.gpa.free(pane.file.?.path); + pane.file.?.path = try p.gpa.dupe(u8, "/tmp/look-selection-source.txt"); + try seed(pane, "needle"); + p.lookAt(0, pane.pointer_selections[0].?.raw_text.?); + try cleared(pane); + try std.testing.expectEqual(@as(i32, 3), pane.cur_row); + try std.testing.expectEqualStrings("needle", selected(pane)); + } + + test "Look clears both source and existing destination selections before focus" { + const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 100, .rows = 30 }); + defer p.deinit(); + const source = try p.setTestFile("source\nlines\n"); + const id = p.freeSlot().?; + const destination = try p.newDocPane(id); + destination.file = .{ + .path = try p.gpa.dupe(u8, "/look-destination.txt"), + .content = try p.gpa.dupe(u8, "alpha\nbravo\ncharlie\n"), + .history = try panes.File.History.create(p.gpa), + }; + layout.insert(p, 0, 1, id); + layout.compute(p); + for ([_]bool{ false, true }) |range| { + p.active = 0; + try seed(source, if (range) "/look-destination.txt:2:2-4" else "/look-destination.txt:3:2"); + try seed(destination, "previous destination"); + p.lookAt(0, source.pointer_selections[0].?.raw_text.?); + try std.testing.expectEqual(id, p.active); + try cleared(source); + try cleared(destination); + try std.testing.expect(!source.vsel.active); + if (range) { + try std.testing.expectEqual(@as(i32, 1), destination.cur_row); + try std.testing.expectEqualStrings("rav", selected(destination)); + } else { + try std.testing.expectEqual(@as(i32, 2), destination.cur_row); + try std.testing.expectEqual(@as(i32, 1), destination.cur_col); + try std.testing.expect(!destination.vsel.active); + } + } + } +}; + +test { + _ = LookResetTests; +} |
