//! Terminal detection utilities. //! //! Detects terminal emulator, multiplexer, and Byobu from environment variables. //! Pure env-map helpers (`detect_*_from_env`) enable full matrix testing. use std::collections::HashMap; use std::process::Command; use std::sync::OnceLock; use std::sync::atomic::{AtomicBool, Ordering}; use crate::host::HostOs; pub mod embedded_editor; pub mod hyperlinks; pub mod image; pub mod keyboard; pub mod overlay; pub(crate) mod probe; pub mod xtversion; pub use embedded_editor::{EmbeddedEditor, embedded_editor_from_env}; pub use hyperlinks::{ HyperlinkCapabilities, Osc8Support, SchemeFilter, SetDefaultCursor, SetPointerCursor, hyperlink_capabilities, }; pub use keyboard::{KeyboardCapabilities, ModifierDelivery, ModifierFate, keyboard_capabilities}; #[cfg(test)] mod test; /// Test-only: build an env `HashMap` from pairs. Shared by the `test` submodule /// and `embedded_editor`'s tests so the helper isn't duplicated. #[cfg(test)] pub(crate) fn env_from(pairs: &[(&str, &str)]) -> HashMap { pairs .iter() .map(|(k, v)| ((*k).to_owned(), (*v).to_owned())) .collect() } // TODO: make term seq codes invariant in a crate. /// Tracks whether Kitty keyboard enhancement flags were pushed during /// `init_terminal`, so teardown paths (`restore_terminal`, panic hook) /// only pop when flags were actually pushed. static KITTY_FLAGS_PUSHED: AtomicBool = AtomicBool::new(false); /// Whether Kitty keyboard enhancement flags were actually pushed during /// `init_terminal` — i.e. the brand wasn't in the skip list *and* the /// runtime probe (`supports_keyboard_enhancement`) succeeded. False means /// modified keys (Shift+Enter, Ctrl+.) arrive as legacy bytes. pub fn kitty_flags_pushed() -> bool { KITTY_FLAGS_PUSHED.load(Ordering::Acquire) } /// Record whether Kitty keyboard enhancement flags were pushed during /// `init_terminal`. pub fn set_kitty_flags_pushed(v: bool) { KITTY_FLAGS_PUSHED.store(v, Ordering::Release) } /// Atomically clear the Kitty-flags-pushed state, returning the prior value. /// Used by teardown paths so concurrent callers cannot both pop. pub fn take_kitty_flags_pushed() -> bool { KITTY_FLAGS_PUSHED.swap(false, Ordering::AcqRel) } /// Run `tmux show-option -gqv