#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImageProtocol {
Kitty,
ITerm2,
}
#[derive(Debug, Clone, Default)]
pub struct TerminalCapabilities {
pub image_protocol: Option<ImageProtocol>,
pub true_color: bool,
pub hyperlinks: bool,
pub kitty_protocol: bool,
pub cell_size: Option<(u16, u16)>,
}
impl TerminalCapabilities {
pub fn detect() -> Self {
let term = std::env::var("TERM").unwrap_or_default();
let term_program = std::env::var("TERM_PROGRAM").unwrap_or_default();
let colorterm = std::env::var("COLORTERM").unwrap_or_default();
let kitty_window_id = std::env::var("KITTY_WINDOW_ID").ok();
let iterm_session_id = std::env::var("ITERM_SESSION_ID").ok();
let ghostty_env = std::env::var("GHOSTTY_RESOURCES_DIR").ok();
let wezterm = std::env::var("WEZTERM_PANE").ok();
let image_protocol = if kitty_window_id.is_some() || ghostty_env.is_some() {
Some(ImageProtocol::Kitty)
} else if iterm_session_id.is_some() || wezterm.is_some() {
if wezterm.is_some() {
Some(ImageProtocol::Kitty)
} else {
Some(ImageProtocol::ITerm2)
}
} else if term_program == "WezTerm" {
Some(ImageProtocol::Kitty)
} else {
None
};
let true_color = colorterm == "truecolor"
|| colorterm == "24bit"
|| term.contains("256color")
|| term_program == "iTerm.app"
|| term_program == "WezTerm"
|| term_program == "Ghostty"
|| kitty_window_id.is_some();
let hyperlinks = term_program == "iTerm.app"
|| term_program == "WezTerm"
|| term_program == "Ghostty"
|| kitty_window_id.is_some();
let kitty_protocol =
kitty_window_id.is_some() || ghostty_env.is_some() || term_program == "WezTerm";
TerminalCapabilities {
image_protocol,
true_color,
hyperlinks,
kitty_protocol,
cell_size: None, }
}
pub fn supports_images(&self) -> bool {
self.image_protocol.is_some()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_capabilities() {
let caps = TerminalCapabilities::default();
assert!(caps.image_protocol.is_none());
assert!(!caps.true_color);
assert!(!caps.hyperlinks);
assert!(!caps.kitty_protocol);
assert!(!caps.supports_images());
}
#[test]
fn test_supports_images_with_kitty() {
let caps = TerminalCapabilities {
image_protocol: Some(ImageProtocol::Kitty),
..Default::default()
};
assert!(caps.supports_images());
}
#[test]
fn test_supports_images_with_iterm2() {
let caps = TerminalCapabilities {
image_protocol: Some(ImageProtocol::ITerm2),
..Default::default()
};
assert!(caps.supports_images());
}
#[test]
fn test_detect_runs() {
let caps = TerminalCapabilities::detect();
let _ = caps.true_color;
}
}