rush_sync_server/commands/help/
command.rs1use crate::commands::command::Command;
2use crate::core::prelude::*;
3
4#[derive(Debug, Default)]
5pub struct HelpCommand;
6
7impl HelpCommand {
8 pub fn new() -> Self {
9 Self
10 }
11}
12
13impl Command for HelpCommand {
14 fn name(&self) -> &'static str {
15 "help"
16 }
17
18 fn description(&self) -> &'static str {
19 "Show all available commands"
20 }
21
22 fn matches(&self, command: &str) -> bool {
23 let cmd = command.trim().to_lowercase();
24 cmd == "help" || cmd == "?" || cmd == "commands" || cmd == "list-commands"
25 }
26
27 fn execute_sync(&self, args: &[&str]) -> Result<String> {
28 let handler = crate::commands::CommandHandler::new();
29
30 match args.first() {
31 Some(&"--simple" | &"-s") => Ok(self.create_simple_list(&handler)),
32 Some(&"--detailed" | &"-d") => Ok(self.create_detailed_list(&handler)),
33 None => Ok(self.create_formatted_list(&handler)),
34 Some(&command_name) => Ok(self.show_command_help(command_name, &handler)),
35 }
36 }
37
38 fn priority(&self) -> u8 {
39 95
40 }
41}
42
43impl HelpCommand {
44 fn get_localized_description(&self, command_name: &str, original_description: &str) -> String {
46 let normalized_name = command_name.replace("-", "_");
48 let description_key = format!("system.commands.{}.description", normalized_name);
49
50 if crate::i18n::has_translation(&description_key) {
51 get_command_translation(&description_key, &[])
52 } else {
53 log::debug!(
54 "No translation found for key '{}', using original description",
55 description_key
56 );
57 original_description.to_string()
58 }
59 }
60
61 fn create_formatted_list(&self, handler: &crate::commands::CommandHandler) -> String {
63 let commands = handler.list_commands();
64
65 if commands.is_empty() {
66 return get_command_translation("system.commands.help.no_commands", &[]);
67 }
68
69 let mut result = String::new();
70 result.push_str(&get_command_translation("system.commands.help.header", &[]));
71 result.push_str("\n\n");
72
73 let mut categorized = std::collections::BTreeMap::new();
74
75 for (name, original_description) in commands {
76 let category_key = self.determine_category(name);
77 let localized_description = self.get_localized_description(name, original_description);
78
79 categorized
80 .entry(category_key)
81 .or_insert_with(Vec::new)
82 .push((name, localized_description));
83 }
84
85 for (category_key, commands) in categorized {
86 let category_translation_key =
87 format!("system.commands.help.category.{}", category_key);
88
89 let category_name = if crate::i18n::has_translation(&category_translation_key) {
90 get_command_translation(&category_translation_key, &[])
91 } else {
92 log::debug!(
93 "No translation for category '{}', using fallback",
94 category_key
95 );
96 self.get_fallback_category_name(category_key)
97 };
98
99 result.push_str(&format!("{}:\n", category_name));
100
101 for (name, description) in commands {
102 result.push_str(&format!(" {:12} - {}\n", name, description));
103 }
104 result.push('\n');
105 }
106
107 result.push_str(&get_command_translation("system.commands.help.footer", &[]));
108 result
109 }
110
111 fn determine_category(&self, command_name: &str) -> &'static str {
113 match command_name {
114 name if name.starts_with("start")
115 || name.starts_with("stop")
116 || name.starts_with("restart") =>
117 {
118 "server_control"
119 }
120 name if name.starts_with("create") || name.starts_with("list") => "server_management",
121 name if name.starts_with("remote") || name.starts_with("sync") => "deployment",
122 name if name.starts_with("cleanup") || name.starts_with("recover") => "maintenance",
123 name if name.starts_with("theme")
124 || name.starts_with("lang")
125 || name.starts_with("log-level") =>
126 {
127 "configuration"
128 }
129 name if name.starts_with("help")
130 || name.starts_with("version")
131 || name.starts_with("history") =>
132 {
133 "information"
134 }
135 name if name.starts_with("exit") || name.starts_with("clear") => "system",
136 _ => "other",
137 }
138 }
139
140 fn get_fallback_category_name(&self, category_key: &str) -> String {
142 match category_key {
143 "server_control" => "Server Control".to_string(),
144 "server_management" => "Server Management".to_string(),
145 "deployment" => "Deployment & Sync".to_string(),
146 "maintenance" => "Maintenance".to_string(),
147 "configuration" => "Configuration".to_string(),
148 "information" => "Information".to_string(),
149 "system" => "System".to_string(),
150 "other" => "Other".to_string(),
151 _ => category_key.to_string(),
152 }
153 }
154
155 fn create_simple_list(&self, handler: &crate::commands::CommandHandler) -> String {
157 let commands = handler.list_commands();
158 let names: Vec<&str> = commands.iter().map(|(name, _)| *name).collect();
159 let names_str = names.join(", ");
160
161 get_command_translation("system.commands.help.simple_list", &[&names_str])
162 }
163
164 fn create_detailed_list(&self, handler: &crate::commands::CommandHandler) -> String {
166 let commands = handler.list_commands();
167 let mut result = String::new();
168
169 result.push_str(&get_command_translation(
170 "system.commands.help.detailed_header",
171 &[],
172 ));
173 result.push('\n');
174 result.push_str(&get_command_translation(
175 "system.commands.help.detailed_separator",
176 &[],
177 ));
178 result.push_str("\n\n");
179
180 for (name, original_description) in commands {
181 let localized_description = self.get_localized_description(name, original_description);
182
183 let command_label = get_command_translation("system.commands.help.command_label", &[]);
184 let description_label =
185 get_command_translation("system.commands.help.description_label", &[]);
186 let usage_label = get_command_translation("system.commands.help.usage_label", &[]);
187 let separator = get_command_translation("system.commands.help.command_separator", &[]);
188
189 result.push_str(&format!("{} {}\n", command_label, name.to_uppercase()));
190 result.push_str(&format!(
191 "{} {}\n",
192 description_label, localized_description
193 ));
194 result.push_str(&format!("{} {} [options]\n", usage_label, name));
195 result.push_str(&format!("{}\n", separator));
196 }
197
198 result
199 }
200
201 fn show_command_help(
203 &self,
204 command_name: &str,
205 handler: &crate::commands::CommandHandler,
206 ) -> String {
207 let commands = handler.list_commands();
208
209 for (name, original_description) in commands {
210 if name.eq_ignore_ascii_case(command_name) {
211 let localized_description =
212 self.get_localized_description(name, original_description);
213
214 return get_command_translation(
215 "system.commands.help.specific_help_template",
216 &[name, &localized_description, name, name],
217 );
218 }
219 }
220
221 get_command_translation("system.commands.help.command_not_found", &[command_name])
222 }
223}