Sweep every first-party crate source (1956 .rs files) to the project comment guidelines: delete redundant restatements, decorative banners, change narration, and end-of-line comments; keep and tighten the crucial ones (invariants, bug rationale, SAFETY blocks, ported-source attribution). No functional code changed. Every edit is proven comment-only against the prior tree by a comment-stripping lexer (string/char/raw-string aware) plus a separate doctest-fence check. Where removing a comment made rustfmt or clippy want to re-lay-out adjacent code, the minimal triggering comment is restored so code tokens stay byte-identical. Gates green: cargo fmt --all --check (0 diffs), cargo check and cargo clippy --workspace --all-targets (0 warnings). Adds scripts/check_codegen_comment_guidelines.py — the enforcement gate for these guidelines (flags banners, end-of-line comments, change narration, and commented-out code).
242 lines
6.8 KiB
Rust
242 lines
6.8 KiB
Rust
//! Per-environment hyperlink route policy.
|
|
//!
|
|
//! Mirrors [`crate::clipboard::resolve_clipboard_route`]. Combines per-brand
|
|
//! [`HyperlinkCapabilities`] with multiplexer/SSH/Byobu state into a single
|
|
//! decision struct cached once per process.
|
|
|
|
use std::sync::OnceLock;
|
|
|
|
use crate::terminal::{Osc8Support, TerminalContext};
|
|
|
|
/// Describes the hyperlink strategy for the current environment.
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub struct HyperlinkRoute {
|
|
/// Whether to emit OSC 8 sequences around link text.
|
|
pub emit_osc8: bool,
|
|
/// Whether to include the `id=` parameter in OSC 8 sequences
|
|
/// (enables hover-grouping across wrapped lines).
|
|
pub emit_id: bool,
|
|
/// Human-readable reason why OSC 8 is disabled, or `None` if enabled.
|
|
pub skip_reason: Option<&'static str>,
|
|
}
|
|
|
|
/// Cached hyperlink route resolved at first use from the terminal context.
|
|
pub fn hyperlink_route() -> &'static HyperlinkRoute {
|
|
static ROUTE: OnceLock<HyperlinkRoute> = OnceLock::new();
|
|
ROUTE.get_or_init(|| {
|
|
let ctx = crate::terminal::terminal_context();
|
|
resolve_hyperlink_route(ctx)
|
|
})
|
|
}
|
|
|
|
/// Resolve the hyperlink route from a terminal context.
|
|
pub fn resolve_hyperlink_route(ctx: &TerminalContext) -> HyperlinkRoute {
|
|
let caps = ctx.hyperlink_capabilities();
|
|
let skip = ctx.hyperlink_skip_reason();
|
|
|
|
let emit_osc8 = caps.osc8 == Osc8Support::Native && skip.is_none();
|
|
let emit_id = emit_osc8 && caps.id_param;
|
|
|
|
HyperlinkRoute {
|
|
emit_osc8,
|
|
emit_id,
|
|
skip_reason: skip,
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::terminal::{MultiplexerKind, TerminalContext, TerminalName, TmuxClientMeta};
|
|
|
|
fn iterm2_ctx() -> TerminalContext {
|
|
TerminalContext {
|
|
brand: TerminalName::Iterm2,
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
fn apple_terminal_ctx() -> TerminalContext {
|
|
TerminalContext {
|
|
brand: TerminalName::AppleTerminal,
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
fn warp_ctx() -> TerminalContext {
|
|
TerminalContext {
|
|
brand: TerminalName::WarpTerminal,
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
fn iterm2_tmux_34_ctx() -> TerminalContext {
|
|
TerminalContext {
|
|
brand: TerminalName::Iterm2,
|
|
multiplexer: MultiplexerKind::Tmux,
|
|
tmux_version: Some("tmux 3.4".to_owned()),
|
|
tmux_meta: TmuxClientMeta {
|
|
tmux_env: Some("/tmp/tmux-501/default,12345,0".to_owned()),
|
|
tmux_pane: Some("%0".to_owned()),
|
|
},
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
fn iterm2_tmux_33_ctx() -> TerminalContext {
|
|
TerminalContext {
|
|
brand: TerminalName::Iterm2,
|
|
multiplexer: MultiplexerKind::Tmux,
|
|
tmux_version: Some("tmux 3.3a".to_owned()),
|
|
tmux_meta: TmuxClientMeta {
|
|
tmux_env: Some("/tmp/tmux-501/default,12345,0".to_owned()),
|
|
tmux_pane: Some("%0".to_owned()),
|
|
},
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
fn screen_ctx() -> TerminalContext {
|
|
TerminalContext {
|
|
brand: TerminalName::Iterm2,
|
|
multiplexer: MultiplexerKind::Screen,
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
fn vte_old_ctx() -> TerminalContext {
|
|
TerminalContext {
|
|
brand: TerminalName::Vte,
|
|
vte_version: Some("4800".to_owned()),
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
fn vte_new_ctx() -> TerminalContext {
|
|
TerminalContext {
|
|
brand: TerminalName::Vte,
|
|
vte_version: Some("7402".to_owned()),
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
fn unknown_ctx() -> TerminalContext {
|
|
TerminalContext::default()
|
|
}
|
|
|
|
#[test]
|
|
fn apple_terminal_skip_reason() {
|
|
assert_eq!(
|
|
apple_terminal_ctx().hyperlink_skip_reason(),
|
|
Some("apple_terminal")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn warp_skip_reason() {
|
|
assert_eq!(
|
|
warp_ctx().hyperlink_skip_reason(),
|
|
Some("unsupported_terminal")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn iterm2_no_skip() {
|
|
assert_eq!(iterm2_ctx().hyperlink_skip_reason(), None);
|
|
}
|
|
|
|
#[test]
|
|
fn screen_skip_reason() {
|
|
assert_eq!(screen_ctx().hyperlink_skip_reason(), Some("screen"));
|
|
}
|
|
|
|
#[test]
|
|
fn tmux_33_skip_reason() {
|
|
assert_eq!(
|
|
iterm2_tmux_33_ctx().hyperlink_skip_reason(),
|
|
Some("tmux_old")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn tmux_34_no_skip() {
|
|
assert_eq!(iterm2_tmux_34_ctx().hyperlink_skip_reason(), None);
|
|
}
|
|
|
|
#[test]
|
|
fn vte_old_skip_reason() {
|
|
assert_eq!(vte_old_ctx().hyperlink_skip_reason(), Some("vte_old"));
|
|
}
|
|
|
|
#[test]
|
|
fn vte_new_no_skip() {
|
|
assert_eq!(vte_new_ctx().hyperlink_skip_reason(), None);
|
|
}
|
|
|
|
#[test]
|
|
fn unknown_terminal_skip_reason() {
|
|
// Unknown brand must report a skip_reason so telemetry/feedback
|
|
// doesn't log "none" alongside emit_osc8=false.
|
|
assert_eq!(
|
|
unknown_ctx().hyperlink_skip_reason(),
|
|
Some("unknown_terminal"),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn vte_old_inside_old_tmux_blames_vte() {
|
|
// VTE 0.48 inside tmux 3.2: VTE is the deeper cause, so a tmux
|
|
// upgrade alone wouldn't fix OSC 8. Diagnostic should point at VTE.
|
|
let ctx = TerminalContext {
|
|
brand: TerminalName::Vte,
|
|
multiplexer: MultiplexerKind::Tmux,
|
|
tmux_version: Some("tmux 3.2".to_owned()),
|
|
vte_version: Some("4800".to_owned()),
|
|
..Default::default()
|
|
};
|
|
assert_eq!(ctx.hyperlink_skip_reason(), Some("vte_old"));
|
|
}
|
|
|
|
#[test]
|
|
fn iterm2_emits_osc8() {
|
|
let route = resolve_hyperlink_route(&iterm2_ctx());
|
|
assert!(route.emit_osc8);
|
|
assert!(route.emit_id);
|
|
}
|
|
|
|
#[test]
|
|
fn apple_terminal_fallback() {
|
|
let route = resolve_hyperlink_route(&apple_terminal_ctx());
|
|
assert!(!route.emit_osc8);
|
|
assert_eq!(route.skip_reason, Some("apple_terminal"));
|
|
}
|
|
|
|
#[test]
|
|
fn warp_fallback() {
|
|
let route = resolve_hyperlink_route(&warp_ctx());
|
|
assert!(!route.emit_osc8);
|
|
}
|
|
|
|
#[test]
|
|
fn tmux_33_fallback() {
|
|
let route = resolve_hyperlink_route(&iterm2_tmux_33_ctx());
|
|
assert!(!route.emit_osc8);
|
|
assert_eq!(route.skip_reason, Some("tmux_old"));
|
|
}
|
|
|
|
#[test]
|
|
fn tmux_34_emits() {
|
|
let route = resolve_hyperlink_route(&iterm2_tmux_34_ctx());
|
|
assert!(route.emit_osc8);
|
|
assert!(route.emit_id);
|
|
}
|
|
|
|
#[test]
|
|
fn unknown_terminal_no_emit() {
|
|
let route = resolve_hyperlink_route(&unknown_ctx());
|
|
// Unknown brand -> osc8 == Unknown -> not Native -> no emit
|
|
assert!(!route.emit_osc8);
|
|
assert_eq!(route.skip_reason, Some("unknown_terminal"));
|
|
}
|
|
}
|