rush_sync_server/commands/theme/
command.rs

1// =====================================================
2// FILE: src/commands/theme/command.rs - VEREINFACHT
3// =====================================================
4
5use super::ThemeSystem;
6use crate::commands::command::Command;
7use crate::core::prelude::*;
8use std::future::Future;
9use std::pin::Pin;
10
11#[derive(Debug)]
12pub struct ThemeCommand {
13    theme_system: std::sync::Mutex<Option<ThemeSystem>>,
14}
15
16impl ThemeCommand {
17    pub fn new() -> Self {
18        Self {
19            theme_system: std::sync::Mutex::new(None),
20        }
21    }
22
23    fn get_or_init_theme_system(&self) -> Result<std::sync::MutexGuard<Option<ThemeSystem>>> {
24        let mut guard = self.theme_system.lock().unwrap();
25        if guard.is_none() {
26            *guard = Some(ThemeSystem::load()?);
27        }
28        Ok(guard)
29    }
30}
31
32impl Command for ThemeCommand {
33    fn name(&self) -> &'static str {
34        "theme"
35    }
36
37    fn description(&self) -> &'static str {
38        "Change application theme (live update without restart, loaded from TOML)"
39    }
40
41    fn matches(&self, command: &str) -> bool {
42        command.trim().to_lowercase().starts_with("theme")
43    }
44
45    fn execute_sync(&self, args: &[&str]) -> Result<String> {
46        let mut guard = self.get_or_init_theme_system()?;
47        let theme_system = guard.as_mut().unwrap();
48
49        match args.first() {
50            None => Ok(theme_system.show_status()),
51            Some(&"--help" | &"-h") => Ok(Self::create_help_text(theme_system)),
52            Some(&"preview") => match args.get(1) {
53                Some(&theme_name) => theme_system.preview_theme(theme_name),
54                None => Ok("❌ Theme name missing. Usage: theme preview <name>".to_string()),
55            },
56            Some(&theme_name) => theme_system.change_theme(theme_name),
57        }
58    }
59
60    fn execute_async<'a>(
61        &'a self,
62        args: &'a [&'a str],
63    ) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'a>> {
64        Box::pin(async move { self.execute_sync(args) })
65    }
66
67    fn supports_async(&self) -> bool {
68        true
69    }
70
71    fn priority(&self) -> u8 {
72        65
73    }
74}
75
76impl ThemeCommand {
77    fn create_help_text(theme_system: &ThemeSystem) -> String {
78        let available_themes = theme_system.get_available_names();
79
80        if available_themes.is_empty() {
81            return "❌ Keine Themes verfügbar!\n\n📝 Füge [theme.xyz] Sektionen zur rush.toml hinzu:\n\n[theme.mein_theme]\ninput_text = \"White\"\ninput_bg = \"Black\"\ncursor = \"Green\"\noutput_text = \"Gray\"\noutput_bg = \"Black\"\nprompt_text = \">> \"\nprompt_color = \"Cyan\"".to_string();
82        }
83
84        let themes_list = available_themes.join(", ");
85
86        format!(
87            "🎨 TOML-Theme Commands (Live Update - Geladen aus rush.toml!):\n\
88            theme                Show available TOML-themes\n\
89            theme <name>         Select theme: {}\n\
90            theme preview <name> Preview theme colors\n\
91            theme -h             Show this help\n\n\
92            ✨ Alle Themes werden LIVE aus [theme.*] Sektionen der rush.toml geladen!\n\
93            📁 Füge beliebige [theme.dein_name] Sektionen hinzu für neue Themes\n\
94            🔄 Änderungen werden sofort angewendet (kein Restart nötig)",
95            themes_list
96        )
97    }
98}
99
100impl Default for ThemeCommand {
101    fn default() -> Self {
102        Self::new()
103    }
104}