terminal: Screen clone should preserve selection order

This commit is contained in:
Mitchell Hashimoto
2024-03-13 13:05:53 -07:00
parent a3509f32a9
commit 9351cab038

View File

@ -263,12 +263,28 @@ pub fn clonePool(
// Preserve our selection if we have one. // Preserve our selection if we have one.
const sel: ?Selection = if (self.selection) |sel| sel: { const sel: ?Selection = if (self.selection) |sel| sel: {
assert(sel.tracked()); assert(sel.tracked());
const start_pin = pin_remap.get(sel.bounds.tracked.start) orelse start: {
const ordered: struct {
tl: *Pin,
br: *Pin,
} = switch (sel.order(self)) {
.forward, .mirrored_forward => .{
.tl = sel.bounds.tracked.start,
.br = sel.bounds.tracked.end,
},
.reverse, .mirrored_reverse => .{
.tl = sel.bounds.tracked.end,
.br = sel.bounds.tracked.start,
},
};
const start_pin = pin_remap.get(ordered.tl) orelse start: {
// No start means it is outside the cloned area. We change it // No start means it is outside the cloned area. We change it
// to the top-left. // to the top-left.
break :start try pages.trackPin(.{ .page = pages.pages.first.? }); break :start try pages.trackPin(.{ .page = pages.pages.first.? });
}; };
const end_pin = pin_remap.get(sel.bounds.tracked.end) orelse end: {
const end_pin = pin_remap.get(ordered.br) orelse end: {
// No end means it is outside the cloned area. We change it // No end means it is outside the cloned area. We change it
// to the bottom-right. // to the bottom-right.
break :end try pages.trackPin(pages.pin(.{ .active = .{ break :end try pages.trackPin(pages.pin(.{ .active = .{
@ -276,6 +292,7 @@ pub fn clonePool(
.y = pages.rows - 1, .y = pages.rows - 1,
} }) orelse break :sel null); } }) orelse break :sel null);
}; };
break :sel .{ break :sel .{
.bounds = .{ .tracked = .{ .bounds = .{ .tracked = .{
.start = start_pin, .start = start_pin,
@ -2877,6 +2894,43 @@ test "Screen: clone contains selection end cutoff" {
} }
} }
test "Screen: clone contains selection end cutoff reversed" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 5, 3, 1);
defer s.deinit();
try s.testWriteString("1ABCD\n2EFGH\n3IJKL");
// Select a single line
try s.select(Selection.init(
s.pages.pin(.{ .active = .{ .x = 2, .y = 2 } }).?,
s.pages.pin(.{ .active = .{ .x = 0, .y = 1 } }).?,
false,
));
// Clone
var s2 = try s.clone(
alloc,
.{ .active = .{ .y = 0 } },
.{ .active = .{ .y = 1 } },
);
defer s2.deinit();
// Our selection should remain valid
{
const sel = s2.selection.?;
try testing.expectEqual(point.Point{ .active = .{
.x = 0,
.y = 1,
} }, s2.pages.pointFromPin(.active, sel.start()).?);
try testing.expectEqual(point.Point{ .active = .{
.x = s2.pages.cols - 1,
.y = 2,
} }, s2.pages.pointFromPin(.active, sel.end()).?);
}
}
test "Screen: clone basic" { test "Screen: clone basic" {
const testing = std.testing; const testing = std.testing;
const alloc = testing.allocator; const alloc = testing.allocator;