diff --git a/src/picker.rs b/src/picker.rs index df9057a..05e09c2 100644 --- a/src/picker.rs +++ b/src/picker.rs @@ -117,27 +117,28 @@ impl Picker { capabilities: Vec::new(), }; + let mut options_with_blacklist = options; + let is_wezterm = env::var("WEZTERM_EXECUTABLE").is_ok_and(|s| !s.is_empty()); + let is_konsole = env::var("KONSOLE_VERSION").is_ok_and(|s| !s.is_empty()); + if is_wezterm || is_konsole { + // WezTerm could use Sixel, but iTerm2 (detected later is better). + // Konsole's Sixel implementation is buggy: https://github.com/benjajaja/ratatui-image?tab=readme-ov-file#compatibility-matrix + // Neither implement the placeholder part of kitty correctly. + options_with_blacklist + .blacklist_protocols(vec![ProtocolType::Kitty, ProtocolType::Sixel]); + } + // Write and read to stdin to query protocol capabilities and font-size. - match query_with_timeout(is_tmux, options) { + match query_with_timeout(is_tmux, options_with_blacklist) { Ok((capability_proto, font_size, caps)) => { let iterm2_proto = iterm2_from_env(); - // Wezterm reports kitty support but its implementation is incomplete. - // Suppress kitty and default to iterm2 (which wezterm fully supports). - let is_wezterm = env::var("WEZTERM_EXECUTABLE").is_ok_and(|s| !s.is_empty()); - // IO-based detection is authoritative; env-based hints are fallbacks // (env vars like KITTY_WINDOW_ID can be stale in tmux sessions). - let protocol_type = if is_wezterm { - capability_proto - .filter(|p| *p != ProtocolType::Kitty) - .unwrap_or(ProtocolType::Iterm2) - } else { - capability_proto - .or(tmux_proto) - .or(iterm2_proto) - .unwrap_or(ProtocolType::Halfblocks) - }; + let protocol_type = capability_proto + .or(tmux_proto) + .or(iterm2_proto) + .unwrap_or(ProtocolType::Halfblocks); if let Some(font_size) = font_size { Ok(Self { diff --git a/src/picker/cap_parser.rs b/src/picker/cap_parser.rs index ea3fa7a..fd51575 100644 --- a/src/picker/cap_parser.rs +++ b/src/picker/cap_parser.rs @@ -1,7 +1,7 @@ //! Terminal stdio query parser module. use std::{fmt::Write, time::Duration}; -use crate::picker::STDIN_READ_TIMEOUT_MILLIS; +use crate::picker::{ProtocolType, STDIN_READ_TIMEOUT_MILLIS}; pub struct Parser { data: String, @@ -27,13 +27,22 @@ pub enum Response { /// Extra query options pub struct QueryStdioOptions { - // Timeout for the stdio query. + /// Timeout for the stdio query. pub timeout: Duration, /// Query for [Text Sizing Protocol]. The result can be checked by searching for /// [crate::picker::Capability::TextSizingProtocol] in [crate::picker::Picker::capabilities]. /// /// [Text Sizing Protocol] pub text_sizing_protocol: bool, + /// Blacklist protocols from the detection query. Currently only kitty can be detected, so that + /// is the only ProtocolType that can have any effect here. + /// [`crate::picker::Picker`] currently sets ProtocolType::Kitty for WezTerm and Konsole. + blacklist_protocols: Vec, +} +impl QueryStdioOptions { + pub(crate) fn blacklist_protocols(&mut self, protocol_types: Vec) { + self.blacklist_protocols = protocol_types; + } } impl Default for QueryStdioOptions { @@ -41,6 +50,7 @@ impl Default for QueryStdioOptions { Self { timeout: Duration::from_millis(STDIN_READ_TIMEOUT_MILLIS), text_sizing_protocol: false, + blacklist_protocols: Vec::new(), } } } @@ -74,11 +84,15 @@ impl Parser { let mut buf = String::with_capacity(100); buf.push_str(start); - // Kitty graphics - write!(buf, "{escape}_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA{escape}\\").unwrap(); + if !options.blacklist_protocols.contains(&ProtocolType::Kitty) { + // Kitty graphics + write!(buf, "{escape}_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA{escape}\\").unwrap(); + } - // Device Attributes Report 1 (sixel support) - write!(buf, "{escape}[c").unwrap(); + if !options.blacklist_protocols.contains(&ProtocolType::Sixel) { + // Device Attributes Report 1 (sixel support) + write!(buf, "{escape}[c").unwrap(); + } // Font size in pixels write!(buf, "{escape}[16t").unwrap();