tui/src/notifications/mod.rs
135 lines
mod bel;mod osc9;use std::io;use bel::BelBackend;use codex_config::types::NotificationMethod;use codex_terminal_detection::TerminalInfo;use codex_terminal_detection::TerminalName;use codex_terminal_detection::terminal_info;use osc9::Osc9Backend;#[derive(Debug)]pub enum DesktopNotificationBackend { Osc9(Osc9Backend), Bel(BelBackend),}impl DesktopNotificationBackend { pub fn for_method(method: NotificationMethod) -> Self { match method { NotificationMethod::Auto => { if supports_osc9(&terminal_info()) { Self::Osc9(Osc9Backend::new()) } else { Self::Bel(BelBackend) } } NotificationMethod::Osc9 => Self::Osc9(Osc9Backend::new()), NotificationMethod::Bel => Self::Bel(BelBackend), } } pub fn method(&self) -> NotificationMethod { match self { DesktopNotificationBackend::Osc9(_) => NotificationMethod::Osc9, DesktopNotificationBackend::Bel(_) => NotificationMethod::Bel, } } pub fn notify(&mut self, message: &str) -> io::Result<()> { match self { DesktopNotificationBackend::Osc9(backend) => backend.notify(message), DesktopNotificationBackend::Bel(backend) => backend.notify(message), } }}pub fn detect_backend(method: NotificationMethod) -> DesktopNotificationBackend { DesktopNotificationBackend::for_method(method)}fn supports_osc9(terminal: &TerminalInfo) -> bool { matches!( terminal.name, TerminalName::Ghostty | TerminalName::Iterm2 | TerminalName::Kitty | TerminalName::WarpTerminal | TerminalName::WezTerm )}#[cfg(test)]mod tests { use super::detect_backend; use super::supports_osc9; use codex_config::types::NotificationMethod; use codex_terminal_detection::TerminalInfo; use codex_terminal_detection::TerminalName; use pretty_assertions::assert_eq; fn test_terminal(name: TerminalName) -> TerminalInfo { TerminalInfo { name, term_program: None, version: None, term: None, multiplexer: None, } } #[test] fn selects_osc9_method() { assert!(matches!( detect_backend(NotificationMethod::Osc9), super::DesktopNotificationBackend::Osc9(_) )); } #[test] fn selects_bel_method() { assert!(matches!( detect_backend(NotificationMethod::Bel), super::DesktopNotificationBackend::Bel(_) )); } #[test] fn supports_osc9_for_supported_terminals() { for name in [ TerminalName::Ghostty, TerminalName::Iterm2, TerminalName::Kitty, TerminalName::WarpTerminal, TerminalName::WezTerm, ] { assert!( supports_osc9(&test_terminal(name)), "{name:?} should support OSC 9" ); } } #[test] fn supports_osc9_for_unsupported_terminals() { for name in [ TerminalName::AppleTerminal, TerminalName::Alacritty, TerminalName::Dumb, TerminalName::GnomeTerminal, TerminalName::Konsole, TerminalName::Unknown, TerminalName::VsCode, TerminalName::Vte, TerminalName::WindowsTerminal, ] { assert_eq!( supports_osc9(&test_terminal(name)), false, "{name:?} should not support OSC 9" ); } }}