mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-25 13:16:11 +03:00
renderer: convert link to new state
This commit is contained in:
@ -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,
|
||||||
|
} }).?));
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user