rush_sync_server/commands/theme/
command.rs1use super::manager::ThemeManager;
6use super::themes::TomlThemeLoader;
7use crate::commands::command::Command;
8use crate::core::prelude::*;
9use std::future::Future;
10use std::pin::Pin;
11
12#[derive(Debug)]
13pub struct ThemeCommand;
14
15impl Command for ThemeCommand {
16 fn name(&self) -> &'static str {
17 "theme"
18 }
19
20 fn description(&self) -> &'static str {
21 "Change application theme (live update without restart, loaded from TOML)"
22 }
23
24 fn matches(&self, command: &str) -> bool {
25 command.trim().to_lowercase().starts_with("theme")
26 }
27
28 fn execute_sync(&self, args: &[&str]) -> Result<String> {
30 match args.first() {
31 None => Ok(ThemeManager::show_status()),
32 Some(&"--help" | &"-h") => Ok(Self::create_help_text()),
33 Some(&"preview") => match args.get(1) {
34 Some(&theme_name) => ThemeManager::preview_theme(theme_name),
35 None => Ok("❌ Theme name missing. Usage: theme preview <name>".to_string()),
36 },
37 Some(&theme_name) => {
38 if TomlThemeLoader::theme_exists_sync(theme_name) {
40 ThemeManager::change_theme_sync(theme_name)
42 } else {
43 let available = match Self::get_available_themes_for_error() {
45 Ok(themes) => themes.join(", "),
46 Err(_) => "dark, light, matrix, blue".to_string(),
47 };
48
49 Ok(format!(
50 "❌ Invalid theme: '{}'. Available themes in TOML: {}",
51 theme_name, available
52 ))
53 }
54 }
55 }
56 }
57
58 fn execute_async<'a>(
60 &'a self,
61 args: &'a [&'a str],
62 ) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'a>> {
63 Box::pin(async move {
64 match args.first() {
65 None => Ok(ThemeManager::show_status()),
66 Some(&"--help" | &"-h") => Ok(Self::create_help_text()),
67 Some(&"preview") => Ok(self.execute_sync(args)?),
68 Some(&theme_name) => {
69 if TomlThemeLoader::theme_exists_sync(theme_name) {
71 ThemeManager::change_theme(theme_name).await
73 } else {
74 let available = TomlThemeLoader::get_available_names().await.join(", ");
76 Ok(format!(
77 "❌ Invalid theme: '{}'. Available themes in TOML: {}",
78 theme_name, available
79 ))
80 }
81 }
82 }
83 })
84 }
85
86 fn supports_async(&self) -> bool {
87 true
88 }
89
90 fn priority(&self) -> u8 {
91 65
92 }
93}
94
95impl ThemeCommand {
96 fn create_help_text() -> String {
98 let available_themes = match Self::get_available_themes_for_error() {
99 Ok(themes) => themes.join(", "),
100 Err(_) => "dark, light, matrix, blue".to_string(),
101 };
102
103 format!(
104 "Theme Commands (Live Update - No Restart - Loaded from TOML!):\n\
105 theme Show available themes\n\
106 theme <name> Select theme: {}\n\
107 theme preview <name> Preview theme colors\n\
108 theme -h Show this help\n\n\
109 ✨ All theme changes apply instantly without restart!\n\
110 📁 Themes are loaded from your rush.toml [theme.*] sections",
111 available_themes
112 )
113 }
114
115 fn get_available_themes_for_error() -> Result<Vec<String>> {
117 let config_paths = crate::setup::setup_toml::get_config_paths();
118
119 for path in config_paths {
120 if path.exists() {
121 if let Ok(content) = std::fs::read_to_string(&path) {
122 if let Ok(themes) = TomlThemeLoader::parse_themes_from_toml(&content) {
123 let mut names: Vec<String> = themes.keys().cloned().collect();
124 names.sort();
125 return Ok(names);
126 }
127 }
128 }
129 }
130
131 Ok(vec![
133 "dark".to_string(),
134 "light".to_string(),
135 "matrix".to_string(),
136 "blue".to_string(),
137 ])
138 }
139}
140
141