mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
selection: containedRow for getting the row that contains a screen point
This commit is contained in:
@ -3,6 +3,7 @@
|
|||||||
const Selection = @This();
|
const Selection = @This();
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
const point = @import("point.zig");
|
const point = @import("point.zig");
|
||||||
const Screen = @import("Screen.zig");
|
const Screen = @import("Screen.zig");
|
||||||
const ScreenPoint = point.ScreenPoint;
|
const ScreenPoint = point.ScreenPoint;
|
||||||
@ -93,6 +94,42 @@ pub fn containsRow(self: Selection, p: ScreenPoint) bool {
|
|||||||
return p.y >= tl.y and p.y <= br.y;
|
return p.y >= tl.y and p.y <= br.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a selection for a single row in the screen. This will return null
|
||||||
|
/// if the row is not included in the selection.
|
||||||
|
pub fn containedRow(self: Selection, screen: *const Screen, p: ScreenPoint) ?Selection {
|
||||||
|
const tl = self.topLeft();
|
||||||
|
const br = self.bottomRight();
|
||||||
|
if (p.y < tl.y or p.y > br.y) return null;
|
||||||
|
|
||||||
|
if (p.y == tl.y) {
|
||||||
|
// If the selection is JUST this line, return it as-is.
|
||||||
|
if (p.y == br.y) return self;
|
||||||
|
|
||||||
|
// Selection top-left line matches only.
|
||||||
|
return .{
|
||||||
|
.start = tl,
|
||||||
|
.end = .{ .y = tl.y, .x = screen.cols - 1 },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Row is our bottom selection, so we return the selection from the
|
||||||
|
// beginning of the line to the br. We know our selection is more than
|
||||||
|
// one line (due to conditionals above)
|
||||||
|
if (p.y == br.y) {
|
||||||
|
assert(p.y != tl.y);
|
||||||
|
return .{
|
||||||
|
.start = .{ .y = br.y, .x = 0 },
|
||||||
|
.end = br,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Row is somewhere between our selection lines so we return the full line.
|
||||||
|
return .{
|
||||||
|
.start = .{ .y = p.y, .x = 0 },
|
||||||
|
.end = .{ .y = p.y, .x = screen.cols - 1 },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the top left point of the selection.
|
/// Returns the top left point of the selection.
|
||||||
pub fn topLeft(self: Selection) ScreenPoint {
|
pub fn topLeft(self: Selection) ScreenPoint {
|
||||||
return switch (self.order()) {
|
return switch (self.order()) {
|
||||||
@ -162,6 +199,58 @@ test "Selection: contains" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "Selection: containedRow" {
|
||||||
|
const testing = std.testing;
|
||||||
|
var screen = try Screen.init(testing.allocator, 5, 10, 0);
|
||||||
|
defer screen.deinit();
|
||||||
|
|
||||||
|
{
|
||||||
|
const sel: Selection = .{
|
||||||
|
.start = .{ .x = 5, .y = 1 },
|
||||||
|
.end = .{ .x = 3, .y = 3 },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Not contained
|
||||||
|
try testing.expect(sel.containedRow(&screen, .{ .x = 1, .y = 4 }) == null);
|
||||||
|
|
||||||
|
// Start line
|
||||||
|
try testing.expectEqual(Selection{
|
||||||
|
.start = sel.start,
|
||||||
|
.end = .{ .x = screen.cols - 1, .y = 1 },
|
||||||
|
}, sel.containedRow(&screen, .{ .x = 1, .y = 1 }).?);
|
||||||
|
|
||||||
|
// End line
|
||||||
|
try testing.expectEqual(Selection{
|
||||||
|
.start = .{ .x = 0, .y = 3 },
|
||||||
|
.end = sel.end,
|
||||||
|
}, sel.containedRow(&screen, .{ .x = 2, .y = 3 }).?);
|
||||||
|
|
||||||
|
// Middle line
|
||||||
|
try testing.expectEqual(Selection{
|
||||||
|
.start = .{ .x = 0, .y = 2 },
|
||||||
|
.end = .{ .x = screen.cols - 1, .y = 2 },
|
||||||
|
}, sel.containedRow(&screen, .{ .x = 2, .y = 2 }).?);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single-line selection
|
||||||
|
{
|
||||||
|
const sel: Selection = .{
|
||||||
|
.start = .{ .x = 2, .y = 1 },
|
||||||
|
.end = .{ .x = 6, .y = 1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Not contained
|
||||||
|
try testing.expect(sel.containedRow(&screen, .{ .x = 1, .y = 0 }) == null);
|
||||||
|
try testing.expect(sel.containedRow(&screen, .{ .x = 1, .y = 2 }) == null);
|
||||||
|
|
||||||
|
// Contained
|
||||||
|
try testing.expectEqual(Selection{
|
||||||
|
.start = sel.start,
|
||||||
|
.end = sel.end,
|
||||||
|
}, sel.containedRow(&screen, .{ .x = 1, .y = 1 }).?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test "Selection: within" {
|
test "Selection: within" {
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user