Skip to main content

vtcode_core/terminal_setup/features/
notifications.rs

1//! Notification system configuration for terminal setup
2//!
3//! Generates terminal-specific configuration for system notifications
4//! when tasks complete, including iTerm2 alerts and bell settings.
5
6use crate::terminal_setup::detector::TerminalType;
7
8/// Generate notification configuration for a terminal
9pub fn generate_notification_config(
10    terminal_type: TerminalType,
11    _features: &[crate::terminal_setup::detector::TerminalFeature],
12) -> Result<String, anyhow::Error> {
13    let mut config_lines = Vec::new();
14
15    // Add notification-specific configuration based on terminal type
16    match terminal_type {
17        TerminalType::ITerm2 => {
18            config_lines.push("# iTerm2 Notification Configuration".to_string());
19            config_lines.push("# To enable system notifications for task completion:".to_string());
20            config_lines.push("# 1. Open iTerm2 Preferences".to_string());
21            config_lines.push("# 2. Navigate to Profiles → Terminal".to_string());
22            config_lines.push("# 3. Enable 'Silence bell' and Filter Alerts → 'Send escape sequence-generated alerts'".to_string());
23            config_lines.push("# 4. Set your preferred notification delay".to_string());
24            config_lines.push("#".to_string());
25            config_lines.push(
26                "# For shell integration notifications, add to your shell profile:".to_string(),
27            );
28            config_lines.push("# export ITERM2_SHELL_INTEGRATION_INSTALLED=1".to_string());
29        }
30        TerminalType::VSCode => {
31            config_lines.push("# VS Code Terminal Notification Configuration".to_string());
32            config_lines
33                .push("# VS Code terminal supports system notifications through:".to_string());
34            config_lines.push("# 1. Settings → Terminal → Integrated → Bell Duration".to_string());
35            config_lines.push("# 2. Enable 'Terminal > Integrated: Enable Bell'".to_string());
36            config_lines.push("#".to_string());
37            config_lines.push("# For shell integration with notifications, consider:".to_string());
38            config_lines
39                .push("# - Using 'oh-my-zsh' or 'bash-it' with notification plugins".to_string());
40        }
41        TerminalType::Hyper => {
42            config_lines.push("# Hyper Terminal Notification Configuration".to_string());
43            config_lines.push("# Hyper supports notifications via plugins:".to_string());
44            config_lines
45                .push("# 1. Install hyper-statusline plugin for enhanced integration".to_string());
46            config_lines.push("# 2. Add to ~/.hyper.js plugins array:".to_string());
47            config_lines.push("#    plugins: [\"hyper-statusline\", \"hyper-search\"]".to_string());
48        }
49        TerminalType::WindowsTerminal => {
50            config_lines.push("# Windows Terminal Notification Configuration".to_string());
51            config_lines.push("# Windows Terminal supports notifications through:".to_string());
52            config_lines.push("# 1. Settings → Profiles → Advanced → Bell style".to_string());
53            config_lines
54                .push("# 2. Enable 'Show terminal bell alert' in appearance settings".to_string());
55        }
56        TerminalType::Ghostty => {
57            config_lines.push("# Ghostty Notification Configuration".to_string());
58            config_lines.push("# Ghostty supports system notifications through:".to_string());
59            config_lines.push("# 1. Settings → Terminal → Bell".to_string());
60            config_lines
61                .push("# 2. Enable 'Visual Bell' or 'Audible Bell' as preferred".to_string());
62            config_lines
63                .push("# 3. Configure 'Bell Duration' for visual notifications".to_string());
64            config_lines.push("#".to_string());
65            config_lines
66                .push("# Ghostty also supports shell integration notifications via:".to_string());
67            config_lines.push("# - Terminal bell escape sequences (\\a)".to_string());
68        }
69        TerminalType::WezTerm => {
70            config_lines.push("# WezTerm Notification Configuration".to_string());
71            config_lines.push("# WezTerm supports terminal bell notifications and can".to_string());
72            config_lines.push("# surface desktop alerts depending on OS integration.".to_string());
73            config_lines.push("#".to_string());
74            config_lines.push("# Recommended: keep bell enabled and test with:".to_string());
75            config_lines.push("# echo -e \"\\a\"".to_string());
76        }
77        TerminalType::TerminalApp => {
78            config_lines.push("# Terminal.app Notification Configuration".to_string());
79            config_lines
80                .push("# macOS Terminal supports audible alerts via terminal bell.".to_string());
81            config_lines.push("#".to_string());
82            config_lines.push("# 1. Open Terminal → Settings → Profiles → Advanced".to_string());
83            config_lines.push("# 2. Configure bell/alerts according to preference".to_string());
84            config_lines.push("# 3. Test with: echo -e \"\\a\"".to_string());
85        }
86        TerminalType::Xterm => {
87            config_lines.push("# xterm Notification Configuration".to_string());
88            config_lines
89                .push("# xterm provides reliable bell notifications (audible/visual).".to_string());
90            config_lines.push("#".to_string());
91            config_lines.push("# Ensure bell is enabled in your X resources.".to_string());
92            config_lines.push("# Test with: echo -e \"\\a\"".to_string());
93        }
94        _ => {
95            config_lines.push(format!("# {:?} Notification Configuration", terminal_type));
96            config_lines
97                .push("# This terminal supports standard ANSI bell notifications.".to_string());
98            config_lines.push(
99                "# Check your terminal's documentation for specific notification settings."
100                    .to_string(),
101            );
102        }
103    }
104
105    Ok(config_lines.join("\n"))
106}
107
108/// Get notification setup instructions for a terminal
109pub fn get_notification_instructions(terminal_type: TerminalType) -> Vec<String> {
110    match terminal_type {
111        TerminalType::ITerm2 => vec![
112            "1. OPEN: iTerm2 → Preferences → Profiles → Terminal".to_string(),
113            "2. ENABLE: 'Silence bell' and 'Send escape sequence-generated alerts'".to_string(),
114            "3. CONFIGURE: Set preferred notification delay".to_string(),
115            "4. TEST: Run a long command followed by 'echo -e \"\\a\"'".to_string(),
116        ],
117        TerminalType::VSCode => vec![
118            "1. OPEN: VS Code Settings (Cmd/Ctrl + ,)".to_string(),
119            "2. SEARCH: 'terminal integrated bell'".to_string(),
120            "3. ENABLE: 'Terminal > Integrated: Enable Bell'".to_string(),
121            "4. CONFIGURE: Set 'Terminal > Integrated: Bell Duration'".to_string(),
122        ],
123        TerminalType::WindowsTerminal => vec![
124            "1. OPEN: Windows Terminal Settings (Ctrl + ,)".to_string(),
125            "2. SELECT: Your profile".to_string(),
126            "3. GO TO: Appearance section".to_string(),
127            "4. ENABLE: 'Show terminal bell alert'".to_string(),
128        ],
129        TerminalType::Ghostty => vec![
130            "1. OPEN: Ghostty Settings".to_string(),
131            "2. GO TO: Terminal → Bell section".to_string(),
132            "3. ENABLE: 'Visual Bell' or 'Audible Bell' as preferred".to_string(),
133            "4. CONFIGURE: Set 'Bell Duration' for visual notifications".to_string(),
134        ],
135        TerminalType::WezTerm => vec![
136            "1. OPEN: WezTerm settings (~/.wezterm.lua)".to_string(),
137            "2. ENABLE: Bell/alert behavior as preferred".to_string(),
138            "3. TEST: Run 'echo -e \"\\a\"'".to_string(),
139        ],
140        TerminalType::TerminalApp => vec![
141            "1. OPEN: Terminal → Settings → Profiles → Advanced".to_string(),
142            "2. CONFIGURE: Alert/Bell behavior".to_string(),
143            "3. TEST: Run 'echo -e \"\\a\"'".to_string(),
144        ],
145        TerminalType::Xterm => vec![
146            "1. CHECK: xterm bell settings in X resources".to_string(),
147            "2. ENABLE: Audible or visual bell".to_string(),
148            "3. TEST: Run 'echo -e \"\\a\"'".to_string(),
149        ],
150        _ => vec![
151            format!("1. CHECK: Documentation for {:?}", terminal_type),
152            "2. CONFIGURE: Terminal bell/notifications in preferences".to_string(),
153            "3. TEST: Use 'echo -e \"\\a\"' to test bell notification".to_string(),
154        ],
155    }
156}
157
158#[cfg(test)]
159mod tests {
160    use super::*;
161
162    #[test]
163    fn test_notification_config_generation() {
164        let features = vec![
165            crate::terminal_setup::detector::TerminalFeature::Multiline,
166            crate::terminal_setup::detector::TerminalFeature::CopyPaste,
167        ];
168
169        let config = generate_notification_config(TerminalType::ITerm2, &features).unwrap();
170        assert!(config.contains("iTerm2"));
171        assert!(config.contains("Notification"));
172    }
173
174    #[test]
175    fn test_notification_instructions() {
176        let instructions = get_notification_instructions(TerminalType::ITerm2);
177        assert!(instructions.iter().any(|i| i.contains("iTerm2")));
178        assert!(instructions.iter().any(|i| i.contains("Preferences")));
179    }
180}