renderer: convert link to new state

This commit is contained in:
Mitchell Hashimoto
2024-03-15 20:58:59 -07:00
parent 5664c3e3c9
commit 7419794a7b

View File

@ -64,11 +64,13 @@ pub const Set = struct {
self: *const Set, self: *const Set,
alloc: Allocator, alloc: Allocator,
screen: *Screen, screen: *Screen,
mouse_vp_pt: point.Viewport, mouse_vp_pt: point.Coordinate,
mouse_mods: inputpkg.Mods, mouse_mods: inputpkg.Mods,
) !MatchSet { ) !MatchSet {
// Convert the viewport point to a screen point. // Convert the viewport point to a screen point.
const mouse_pt = mouse_vp_pt.toScreen(screen); const mouse_pin = screen.pages.pin(.{
.viewport = mouse_vp_pt,
}) orelse return .{};
// This contains our list of matches. The matches are stored // This contains our list of matches. The matches are stored
// as selections which contain the start and end points of // as selections which contain the start and end points of
@ -78,14 +80,25 @@ pub const Set = struct {
defer matches.deinit(); defer matches.deinit();
// Iterate over all the visible lines. // Iterate over all the visible lines.
var lineIter = screen.lineIterator(.viewport); var lineIter = screen.lineIterator(screen.pages.pin(.{
while (lineIter.next()) |line| { .viewport = .{},
const strmap = line.stringMap(alloc) catch |err| { }) orelse return .{});
log.warn( while (lineIter.next()) |line_sel| {
"failed to build string map for link checking err={}", const strmap: terminal.StringMap = strmap: {
.{err}, var strmap: terminal.StringMap = undefined;
); const str = screen.selectionString(alloc, .{
continue; .sel = line_sel,
.trim = false,
.map = &strmap,
}) catch |err| {
log.warn(
"failed to build string map for link checking err={}",
.{err},
);
continue;
};
alloc.free(str);
break :strmap strmap;
}; };
defer strmap.deinit(alloc); defer strmap.deinit(alloc);
@ -98,7 +111,7 @@ pub const Set = struct {
.always => {}, .always => {},
.always_mods => |v| if (!mouse_mods.equal(v)) continue, .always_mods => |v| if (!mouse_mods.equal(v)) continue,
inline .hover, .hover_mods => |v, tag| { inline .hover, .hover_mods => |v, tag| {
if (!line.selection().contains(mouse_pt)) continue; if (!line_sel.contains(screen, mouse_pin)) continue;
if (comptime tag == .hover_mods) { if (comptime tag == .hover_mods) {
if (!mouse_mods.equal(v)) continue; if (!mouse_mods.equal(v)) continue;
} }
@ -121,7 +134,7 @@ pub const Set = struct {
.always, .always_mods => {}, .always, .always_mods => {},
.hover, .hover,
.hover_mods, .hover_mods,
=> if (!sel.contains(mouse_pt)) continue, => if (!sel.contains(screen, mouse_pin)) continue,
} }
try matches.append(sel); try matches.append(sel);
@ -153,156 +166,228 @@ pub const MatchSet = struct {
/// results. /// results.
pub fn orderedContains( pub fn orderedContains(
self: *MatchSet, self: *MatchSet,
pt: point.ScreenPoint, screen: *const Screen,
pin: terminal.Pin,
) bool { ) bool {
// If we're beyond the end of our possible matches, we're done. // If we're beyond the end of our possible matches, we're done.
if (self.i >= self.matches.len) return false; if (self.i >= self.matches.len) return false;
// If our selection ends before the point, then no point will ever // If our selection ends before the point, then no point will ever
// again match this selection so we move on to the next one. // again match this selection so we move on to the next one.
while (self.matches[self.i].end.before(pt)) { while (self.matches[self.i].end().before(pin)) {
self.i += 1; self.i += 1;
if (self.i >= self.matches.len) return false; if (self.i >= self.matches.len) return false;
} }
return self.matches[self.i].contains(pt); return self.matches[self.i].contains(screen, pin);
} }
}; };
// TODO(paged-terminal) test "matchset" {
// test "matchset" { const testing = std.testing;
// const testing = std.testing; const alloc = testing.allocator;
// const alloc = testing.allocator;
// // Initialize our screen
// // Initialize our screen var s = try Screen.init(alloc, 5, 5, 0);
// var s = try Screen.init(alloc, 5, 5, 0); defer s.deinit();
// defer s.deinit(); const str = "1ABCD2EFGH\n3IJKL";
// const str = "1ABCD2EFGH\n3IJKL"; try s.testWriteString(str);
// try s.testWriteString(str);
// // Get a set
// // Get a set var set = try Set.fromConfig(alloc, &.{
// var set = try Set.fromConfig(alloc, &.{ .{
// .{ .regex = "AB",
// .regex = "AB", .action = .{ .open = {} },
// .action = .{ .open = {} }, .highlight = .{ .always = {} },
// .highlight = .{ .always = {} }, },
// },
// .{
// .{ .regex = "EF",
// .regex = "EF", .action = .{ .open = {} },
// .action = .{ .open = {} }, .highlight = .{ .always = {} },
// .highlight = .{ .always = {} }, },
// }, });
// }); defer set.deinit(alloc);
// defer set.deinit(alloc);
// // Get our matches
// // Get our matches var match = try set.matchSet(alloc, &s, .{}, .{});
// var match = try set.matchSet(alloc, &s, .{}, .{}); defer match.deinit(alloc);
// defer match.deinit(alloc); try testing.expectEqual(@as(usize, 2), match.matches.len);
// try testing.expectEqual(@as(usize, 2), match.matches.len);
// // Test our matches
// // Test our matches try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// try testing.expect(!match.orderedContains(.{ .x = 0, .y = 0 })); .x = 0,
// try testing.expect(match.orderedContains(.{ .x = 1, .y = 0 })); .y = 0,
// try testing.expect(match.orderedContains(.{ .x = 2, .y = 0 })); } }).?));
// try testing.expect(!match.orderedContains(.{ .x = 3, .y = 0 })); try testing.expect(match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// try testing.expect(match.orderedContains(.{ .x = 1, .y = 1 })); .x = 1,
// try testing.expect(!match.orderedContains(.{ .x = 1, .y = 2 })); .y = 0,
// } } }).?));
// try testing.expect(match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// test "matchset hover links" { .x = 2,
// const testing = std.testing; .y = 0,
// const alloc = testing.allocator; } }).?));
// try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// // Initialize our screen .x = 3,
// var s = try Screen.init(alloc, 5, 5, 0); .y = 0,
// defer s.deinit(); } }).?));
// const str = "1ABCD2EFGH\n3IJKL"; try testing.expect(match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// try s.testWriteString(str); .x = 1,
// .y = 1,
// // Get a set } }).?));
// var set = try Set.fromConfig(alloc, &.{ try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// .{ .x = 1,
// .regex = "AB", .y = 2,
// .action = .{ .open = {} }, } }).?));
// .highlight = .{ .hover = {} }, }
// },
// test "matchset hover links" {
// .{ const testing = std.testing;
// .regex = "EF", const alloc = testing.allocator;
// .action = .{ .open = {} },
// .highlight = .{ .always = {} }, // Initialize our screen
// }, var s = try Screen.init(alloc, 5, 5, 0);
// }); defer s.deinit();
// defer set.deinit(alloc); const str = "1ABCD2EFGH\n3IJKL";
// try s.testWriteString(str);
// // Not hovering over the first link
// { // Get a set
// var match = try set.matchSet(alloc, &s, .{}, .{}); var set = try Set.fromConfig(alloc, &.{
// defer match.deinit(alloc); .{
// try testing.expectEqual(@as(usize, 1), match.matches.len); .regex = "AB",
// .action = .{ .open = {} },
// // Test our matches .highlight = .{ .hover = {} },
// try testing.expect(!match.orderedContains(.{ .x = 0, .y = 0 })); },
// try testing.expect(!match.orderedContains(.{ .x = 1, .y = 0 }));
// try testing.expect(!match.orderedContains(.{ .x = 2, .y = 0 })); .{
// try testing.expect(!match.orderedContains(.{ .x = 3, .y = 0 })); .regex = "EF",
// try testing.expect(match.orderedContains(.{ .x = 1, .y = 1 })); .action = .{ .open = {} },
// try testing.expect(!match.orderedContains(.{ .x = 1, .y = 2 })); .highlight = .{ .always = {} },
// } },
// });
// // Hovering over the first link defer set.deinit(alloc);
// {
// var match = try set.matchSet(alloc, &s, .{ .x = 1, .y = 0 }, .{}); // Not hovering over the first link
// defer match.deinit(alloc); {
// try testing.expectEqual(@as(usize, 2), match.matches.len); var match = try set.matchSet(alloc, &s, .{}, .{});
// defer match.deinit(alloc);
// // Test our matches try testing.expectEqual(@as(usize, 1), match.matches.len);
// try testing.expect(!match.orderedContains(.{ .x = 0, .y = 0 }));
// try testing.expect(match.orderedContains(.{ .x = 1, .y = 0 })); // Test our matches
// try testing.expect(match.orderedContains(.{ .x = 2, .y = 0 })); try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// try testing.expect(!match.orderedContains(.{ .x = 3, .y = 0 })); .x = 0,
// try testing.expect(match.orderedContains(.{ .x = 1, .y = 1 })); .y = 0,
// try testing.expect(!match.orderedContains(.{ .x = 1, .y = 2 })); } }).?));
// } try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// } .x = 1,
// .y = 0,
// test "matchset mods no match" { } }).?));
// const testing = std.testing; try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// const alloc = testing.allocator; .x = 2,
// .y = 0,
// // Initialize our screen } }).?));
// var s = try Screen.init(alloc, 5, 5, 0); try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// defer s.deinit(); .x = 3,
// const str = "1ABCD2EFGH\n3IJKL"; .y = 0,
// try s.testWriteString(str); } }).?));
// try testing.expect(match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// // Get a set .x = 1,
// var set = try Set.fromConfig(alloc, &.{ .y = 1,
// .{ } }).?));
// .regex = "AB", try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// .action = .{ .open = {} }, .x = 1,
// .highlight = .{ .always = {} }, .y = 2,
// }, } }).?));
// }
// .{
// .regex = "EF", // Hovering over the first link
// .action = .{ .open = {} }, {
// .highlight = .{ .always_mods = .{ .ctrl = true } }, var match = try set.matchSet(alloc, &s, .{ .x = 1, .y = 0 }, .{});
// }, defer match.deinit(alloc);
// }); try testing.expectEqual(@as(usize, 2), match.matches.len);
// defer set.deinit(alloc);
// // Test our matches
// // Get our matches try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// var match = try set.matchSet(alloc, &s, .{}, .{}); .x = 0,
// defer match.deinit(alloc); .y = 0,
// try testing.expectEqual(@as(usize, 1), match.matches.len); } }).?));
// try testing.expect(match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// // Test our matches .x = 1,
// try testing.expect(!match.orderedContains(.{ .x = 0, .y = 0 })); .y = 0,
// try testing.expect(match.orderedContains(.{ .x = 1, .y = 0 })); } }).?));
// try testing.expect(match.orderedContains(.{ .x = 2, .y = 0 })); try testing.expect(match.orderedContains(&s, s.pages.pin(.{ .screen = .{
// try testing.expect(!match.orderedContains(.{ .x = 3, .y = 0 })); .x = 2,
// try testing.expect(!match.orderedContains(.{ .x = 1, .y = 1 })); .y = 0,
// try testing.expect(!match.orderedContains(.{ .x = 1, .y = 2 })); } }).?));
// } try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
.x = 3,
.y = 0,
} }).?));
try testing.expect(match.orderedContains(&s, s.pages.pin(.{ .screen = .{
.x = 1,
.y = 1,
} }).?));
try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
.x = 1,
.y = 2,
} }).?));
}
}
test "matchset mods no match" {
const testing = std.testing;
const alloc = testing.allocator;
// Initialize our screen
var s = try Screen.init(alloc, 5, 5, 0);
defer s.deinit();
const str = "1ABCD2EFGH\n3IJKL";
try s.testWriteString(str);
// Get a set
var set = try Set.fromConfig(alloc, &.{
.{
.regex = "AB",
.action = .{ .open = {} },
.highlight = .{ .always = {} },
},
.{
.regex = "EF",
.action = .{ .open = {} },
.highlight = .{ .always_mods = .{ .ctrl = true } },
},
});
defer set.deinit(alloc);
// Get our matches
var match = try set.matchSet(alloc, &s, .{}, .{});
defer match.deinit(alloc);
try testing.expectEqual(@as(usize, 1), match.matches.len);
// Test our matches
try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
.x = 0,
.y = 0,
} }).?));
try testing.expect(match.orderedContains(&s, s.pages.pin(.{ .screen = .{
.x = 1,
.y = 0,
} }).?));
try testing.expect(match.orderedContains(&s, s.pages.pin(.{ .screen = .{
.x = 2,
.y = 0,
} }).?));
try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
.x = 3,
.y = 0,
} }).?));
try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
.x = 1,
.y = 1,
} }).?));
try testing.expect(!match.orderedContains(&s, s.pages.pin(.{ .screen = .{
.x = 1,
.y = 2,
} }).?));
}