From 0b3c502268ffdc20408b85d7a377fe8e08c86a4a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 6 Mar 2024 21:35:36 -0800 Subject: [PATCH] terminal2: Selection.ordered --- src/terminal/Selection.zig | 1 + src/terminal2/Selection.zig | 114 +++++++++++++++++++++++++++++++++++- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/src/terminal/Selection.zig b/src/terminal/Selection.zig index bcb2aa592..6bb7c049a 100644 --- a/src/terminal/Selection.zig +++ b/src/terminal/Selection.zig @@ -1001,6 +1001,7 @@ test "bottomRight" { } } +// X test "ordered" { const testing = std.testing; { diff --git a/src/terminal2/Selection.zig b/src/terminal2/Selection.zig index e7c2c570a..c681e9263 100644 --- a/src/terminal2/Selection.zig +++ b/src/terminal2/Selection.zig @@ -79,6 +79,13 @@ pub fn deinit( } } +/// Returns true if this selection is equal to another selection. +pub fn eql(self: Selection, other: Selection) bool { + return self.start().eql(other.start()) and + self.end().eql(other.end()) and + self.rectangle == other.rectangle; +} + /// The starting pin of the selection. This is NOT ordered. pub fn startPtr(self: *Selection) *Pin { return switch (self.bounds) { @@ -137,7 +144,7 @@ pub fn track(self: *Selection, s: *Screen) !void { } /// Returns the top left point of the selection. -pub fn topLeft(self: Selection, s: *Screen) Pin { +pub fn topLeft(self: Selection, s: *const Screen) Pin { return switch (self.order(s)) { .forward => self.start(), .reverse => self.end(), @@ -155,7 +162,7 @@ pub fn topLeft(self: Selection, s: *Screen) Pin { } /// Returns the bottom right point of the selection. -pub fn bottomRight(self: Selection, s: *Screen) Pin { +pub fn bottomRight(self: Selection, s: *const Screen) Pin { return switch (self.order(s)) { .forward => self.end(), .reverse => self.start(), @@ -211,6 +218,28 @@ pub fn order(self: Selection, s: *const Screen) Order { return .reverse; } +/// Returns the selection in the given order. +/// +/// The returned selection is always a new untracked selection. +/// +/// Note that only forward and reverse are useful desired orders for this +/// function. All other orders act as if forward order was desired. +pub fn ordered(self: Selection, s: *const Screen, desired: Order) Selection { + if (self.order(s) == desired) return Selection.init( + self.start(), + self.end(), + self.rectangle, + ); + + const tl = self.topLeft(s); + const br = self.bottomRight(s); + return switch (desired) { + .forward => Selection.init(tl, br, self.rectangle), + .reverse => Selection.init(br, tl, self.rectangle), + else => Selection.init(tl, br, self.rectangle), + }; +} + /// Possible adjustments to the selection. pub const Adjustment = enum { left, @@ -974,3 +1003,84 @@ test "bottomRight" { } }, s.pages.pointFromPin(.screen, br)); } } + +test "ordered" { + const testing = std.testing; + + var s = try Screen.init(testing.allocator, 5, 10, 0); + defer s.deinit(); + { + // forward + const sel = Selection.init( + s.pages.pin(.{ .screen = .{ .x = 1, .y = 1 } }).?, + s.pages.pin(.{ .screen = .{ .x = 3, .y = 1 } }).?, + false, + ); + const sel_reverse = Selection.init( + s.pages.pin(.{ .screen = .{ .x = 3, .y = 1 } }).?, + s.pages.pin(.{ .screen = .{ .x = 1, .y = 1 } }).?, + false, + ); + try testing.expect(sel.ordered(&s, .forward).eql(sel)); + try testing.expect(sel.ordered(&s, .reverse).eql(sel_reverse)); + try testing.expect(sel.ordered(&s, .mirrored_forward).eql(sel)); + } + { + // reverse + const sel = Selection.init( + s.pages.pin(.{ .screen = .{ .x = 3, .y = 1 } }).?, + s.pages.pin(.{ .screen = .{ .x = 1, .y = 1 } }).?, + false, + ); + const sel_forward = Selection.init( + s.pages.pin(.{ .screen = .{ .x = 1, .y = 1 } }).?, + s.pages.pin(.{ .screen = .{ .x = 3, .y = 1 } }).?, + false, + ); + try testing.expect(sel.ordered(&s, .forward).eql(sel_forward)); + try testing.expect(sel.ordered(&s, .reverse).eql(sel)); + try testing.expect(sel.ordered(&s, .mirrored_forward).eql(sel_forward)); + } + { + // mirrored_forward + const sel = Selection.init( + s.pages.pin(.{ .screen = .{ .x = 3, .y = 1 } }).?, + s.pages.pin(.{ .screen = .{ .x = 1, .y = 3 } }).?, + true, + ); + const sel_forward = Selection.init( + s.pages.pin(.{ .screen = .{ .x = 1, .y = 1 } }).?, + s.pages.pin(.{ .screen = .{ .x = 3, .y = 3 } }).?, + true, + ); + const sel_reverse = Selection.init( + s.pages.pin(.{ .screen = .{ .x = 3, .y = 3 } }).?, + s.pages.pin(.{ .screen = .{ .x = 1, .y = 1 } }).?, + true, + ); + try testing.expect(sel.ordered(&s, .forward).eql(sel_forward)); + try testing.expect(sel.ordered(&s, .reverse).eql(sel_reverse)); + try testing.expect(sel.ordered(&s, .mirrored_reverse).eql(sel_forward)); + } + { + // mirrored_reverse + const sel = Selection.init( + s.pages.pin(.{ .screen = .{ .x = 1, .y = 3 } }).?, + s.pages.pin(.{ .screen = .{ .x = 3, .y = 1 } }).?, + true, + ); + const sel_forward = Selection.init( + s.pages.pin(.{ .screen = .{ .x = 1, .y = 1 } }).?, + s.pages.pin(.{ .screen = .{ .x = 3, .y = 3 } }).?, + true, + ); + const sel_reverse = Selection.init( + s.pages.pin(.{ .screen = .{ .x = 3, .y = 3 } }).?, + s.pages.pin(.{ .screen = .{ .x = 1, .y = 1 } }).?, + true, + ); + try testing.expect(sel.ordered(&s, .forward).eql(sel_forward)); + try testing.expect(sel.ordered(&s, .reverse).eql(sel_reverse)); + try testing.expect(sel.ordered(&s, .mirrored_forward).eql(sel_forward)); + } +}