Add link-previews option

This commit is contained in:
Gregory Anders
2025-06-29 10:52:24 -05:00
parent dc18f1a2b9
commit 9f3f9205d8
3 changed files with 40 additions and 11 deletions

View File

@ -270,6 +270,7 @@ const DerivedConfig = struct {
title: ?[:0]const u8, title: ?[:0]const u8,
title_report: bool, title_report: bool,
links: []Link, links: []Link,
link_previews: configpkg.LinkPreviews,
const Link = struct { const Link = struct {
regex: oni.Regex, regex: oni.Regex,
@ -336,6 +337,7 @@ const DerivedConfig = struct {
.title = config.title, .title = config.title,
.title_report = config.@"title-report", .title_report = config.@"title-report",
.links = links, .links = links,
.link_previews = config.@"link-previews",
// Assignments happen sequentially so we have to do this last // Assignments happen sequentially so we have to do this last
// so that the memory is captured from allocs above. // so that the memory is captured from allocs above.
@ -1242,7 +1244,7 @@ fn mouseRefreshLinks(
// Get our link at the current position. This returns null if there // Get our link at the current position. This returns null if there
// isn't a link OR if we shouldn't be showing links for some reason // isn't a link OR if we shouldn't be showing links for some reason
// (see further comments for cases). // (see further comments for cases).
const link_: ?apprt.action.MouseOverLink = link: { const link_: ?apprt.action.MouseOverLink, const preview: bool = link: {
// If we clicked and our mouse moved cells then we never // If we clicked and our mouse moved cells then we never
// highlight links until the mouse is unclicked. This follows // highlight links until the mouse is unclicked. This follows
// standard macOS and Linux behavior where a click and drag cancels // standard macOS and Linux behavior where a click and drag cancels
@ -1257,18 +1259,21 @@ fn mouseRefreshLinks(
if (!click_pt.coord().eql(pos_vp)) { if (!click_pt.coord().eql(pos_vp)) {
log.debug("mouse moved while left click held, ignoring link hover", .{}); log.debug("mouse moved while left click held, ignoring link hover", .{});
break :link null; break :link .{ null, false };
} }
} }
const link = (try self.linkAtPos(pos)) orelse break :link null; const link = (try self.linkAtPos(pos)) orelse break :link .{ null, false };
switch (link[0]) { switch (link[0]) {
.open => { .open => {
const str = try self.io.terminal.screen.selectionString(alloc, .{ const str = try self.io.terminal.screen.selectionString(alloc, .{
.sel = link[1], .sel = link[1],
.trim = false, .trim = false,
}); });
break :link .{ .url = str }; break :link .{
.{ .url = str },
self.config.link_previews == .true,
};
}, },
._open_osc8 => { ._open_osc8 => {
@ -1276,9 +1281,14 @@ fn mouseRefreshLinks(
const pin = link[1].start(); const pin = link[1].start();
const uri = self.osc8URI(pin) orelse { const uri = self.osc8URI(pin) orelse {
log.warn("failed to get URI for OSC8 hyperlink", .{}); log.warn("failed to get URI for OSC8 hyperlink", .{});
break :link null; break :link .{ null, false };
};
break :link .{
.{
.url = uri,
},
self.config.link_previews != .false,
}; };
break :link .{ .url = uri };
}, },
} }
}; };
@ -1294,11 +1304,15 @@ fn mouseRefreshLinks(
.mouse_shape, .mouse_shape,
.pointer, .pointer,
); );
_ = try self.rt_app.performAction(
.{ .surface = self }, if (preview) {
.mouse_over_link, _ = try self.rt_app.performAction(
link, .{ .surface = self },
); .mouse_over_link,
link,
);
}
try self.queueRender(); try self.queueRender();
return; return;
} }

View File

@ -37,6 +37,7 @@ pub const ShellIntegrationFeatures = Config.ShellIntegrationFeatures;
pub const WindowPaddingColor = Config.WindowPaddingColor; pub const WindowPaddingColor = Config.WindowPaddingColor;
pub const BackgroundImagePosition = Config.BackgroundImagePosition; pub const BackgroundImagePosition = Config.BackgroundImagePosition;
pub const BackgroundImageFit = Config.BackgroundImageFit; pub const BackgroundImageFit = Config.BackgroundImageFit;
pub const LinkPreviews = Config.LinkPreviews;
// Alternate APIs // Alternate APIs
pub const CAPI = @import("config/CAPI.zig"); pub const CAPI = @import("config/CAPI.zig");

View File

@ -1046,6 +1046,14 @@ link: RepeatableLink = .{},
/// `link`). If you want to customize URL matching, use `link` and disable this. /// `link`). If you want to customize URL matching, use `link` and disable this.
@"link-url": bool = true, @"link-url": bool = true,
/// Show link previews for a matched URL.
///
/// When true, link previews are shown for all matched URLs. When false, link
/// previews are never shown. When set to "osc8", link previews are only shown
/// for hyperlinks created with the OSC 8 sequence (in this case, the link text
/// can differ from the link destination).
@"link-previews": LinkPreviews = .true,
/// Whether to start the window in a maximized state. This setting applies /// Whether to start the window in a maximized state. This setting applies
/// to new windows and does not apply to tabs, splits, etc. However, this setting /// to new windows and does not apply to tabs, splits, etc. However, this setting
/// will apply to all new windows, not just the first one. /// will apply to all new windows, not just the first one.
@ -4326,6 +4334,12 @@ pub const WindowSubtitle = enum {
@"working-directory", @"working-directory",
}; };
pub const LinkPreviews = enum {
false,
true,
osc8,
};
/// Color represents a color using RGB. /// Color represents a color using RGB.
/// ///
/// This is a packed struct so that the C API to read color values just /// This is a packed struct so that the C API to read color values just