Skip to main content

vtcode_core/terminal_setup/terminals/
ghostty.rs

1//! Ghostty terminal configuration generator.
2//!
3//! Generates configuration for Ghostty terminal emulator.
4
5use crate::terminal_setup::config_writer::{ConfigFormat, ConfigWriter};
6use crate::terminal_setup::detector::TerminalType;
7use crate::terminal_setup::features::multiline;
8use crate::terminal_setup::features::shell_integration;
9use anyhow::Result;
10
11/// Generate complete Ghostty configuration with all features
12pub fn generate_config(features: &[crate::terminal_setup::detector::TerminalFeature]) -> Result<String> {
13    let mut config_lines = Vec::new();
14
15    // Add header comment
16    config_lines.push("# VT Code Terminal Configuration for Ghostty".to_string());
17    config_lines.push(String::new());
18
19    // Generate feature-specific configurations
20    for feature in features {
21        match feature {
22            crate::terminal_setup::detector::TerminalFeature::Multiline => {
23                config_lines.push("# Multiline input: Shift+Enter".to_string());
24                let multiline_config = multiline::generate_config(TerminalType::Ghostty)?;
25                config_lines.push(multiline_config);
26            }
27            crate::terminal_setup::detector::TerminalFeature::CopyPaste => {
28                config_lines.push("# Enhanced copy/paste".to_string());
29                config_lines.push("copy-on-select = true".to_string());
30                config_lines.push(String::new());
31            }
32            crate::terminal_setup::detector::TerminalFeature::ShellIntegration => {
33                let shell_config = shell_integration::generate_config(TerminalType::Ghostty)?;
34                config_lines.push(shell_config);
35            }
36            crate::terminal_setup::detector::TerminalFeature::ThemeSync => {
37                config_lines.push("# Theme synchronization".to_string());
38                let theme_config = crate::terminal_setup::features::theme_sync::generate_config(TerminalType::Ghostty)?;
39                config_lines.push(theme_config);
40            }
41            crate::terminal_setup::detector::TerminalFeature::Notifications => {
42                config_lines.push("# System notifications".to_string());
43                config_lines.push("bell = true".to_string());
44                config_lines.push(String::new());
45            }
46        }
47    }
48
49    Ok(config_lines.join("\n"))
50}
51
52/// Merge Ghostty configuration with existing config file
53pub fn merge_with_existing(existing_content: &str, new_config: &str) -> Result<String> {
54    ConfigWriter::merge_with_markers(existing_content, new_config, ConfigFormat::PlainText)
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60    use crate::terminal_setup::detector::TerminalFeature;
61
62    #[test]
63    fn test_generate_multiline_config() {
64        let features = vec![TerminalFeature::Multiline];
65        let config = generate_config(&features).unwrap();
66        assert!(config.contains("shift+enter"));
67        assert!(config.contains("keybind"));
68    }
69
70    #[test]
71    fn test_generate_all_features() {
72        let features = vec![
73            TerminalFeature::Multiline,
74            TerminalFeature::CopyPaste,
75            TerminalFeature::ShellIntegration,
76            TerminalFeature::ThemeSync,
77        ];
78        let config = generate_config(&features).unwrap();
79        assert!(config.contains("shift+enter"));
80        assert!(config.contains("copy-on-select"));
81        assert!(config.contains("shell-integration"));
82        assert!(config.contains("palette = 255="));
83    }
84
85    #[test]
86    fn test_merge_with_existing() {
87        let existing = "# User config\nfont-family = Monospace\n";
88        let new_config = "keybind = shift+enter=text:\\n";
89
90        let merged = merge_with_existing(existing, new_config).unwrap();
91
92        assert!(merged.contains("font-family"));
93        assert!(merged.contains("BEGIN VTCODE CONFIGURATION"));
94        assert!(merged.contains("keybind"));
95    }
96}