use std::path::Path;
pub fn hyperlink_name(path: &Path, text: &str, enabled: bool) -> String {
if !enabled {
return text.to_string();
}
let uri = file_uri(path);
format!("\x1b]8;;{uri}\x1b\\{text}\x1b]8;;\x1b\\")
}
fn file_uri(path: &Path) -> String {
let abs = if path.is_absolute() {
path.to_path_buf()
} else {
std::env::current_dir()
.map(|cwd| cwd.join(path))
.unwrap_or_else(|_| path.to_path_buf())
};
let host = hostname();
let mut uri = String::from("file://");
if !host.is_empty() {
uri.push_str(&host);
}
for b in abs.to_string_lossy().bytes() {
match b {
b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'/' | b'.' | b'-' | b'_' | b'~' => {
uri.push(b as char);
}
_ => uri.push_str(&format!("%{b:02X}")),
}
}
uri
}
fn hostname() -> String {
std::env::var("HOSTNAME")
.or_else(|_| std::env::var("COMPUTERNAME"))
.unwrap_or_default()
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn disabled_is_passthrough() {
assert_eq!(hyperlink_name(Path::new("/tmp/x"), "x", false), "x");
}
#[test]
fn enabled_wraps_osc8() {
let s = hyperlink_name(&PathBuf::from("/tmp/x"), "x", true);
assert!(s.contains("\x1b]8;;file://"), "{s:?}");
assert!(s.contains("/tmp/x") || s.contains("%"), "{s:?}");
assert!(s.ends_with("\x1b]8;;\x1b\\"), "{s:?}");
}
}