1use crate::command::{Command, GenericCommand};
2use crate::error_handler::{ErrorHandler, NErrorHandler};
3use colored::Colorize;
4use std::io;
5use std::io::{stdout, Write};
6
7pub mod command;
8pub mod error_handler;
9
10pub fn log(log_type: LogTypes, message: String) {
11 match log_type {
12 LogTypes::INFO => println!("{} {}", "[INFO]".green(), message),
13 LogTypes::WARN => println!("{} {}", "[WARNING]".yellow(), message),
14 LogTypes::ERR => println!("{} {}", "[ERROR]".red(), message),
15 }
16}
17
18pub struct CommandsRegister<E> {
19 commands: Vec<GenericCommand>,
20 error_handler: E,
21 help_command: bool,
22}
23
24impl Default for CommandsRegister<NErrorHandler> {
25 fn default() -> Self {
26 Self::new(NErrorHandler::new(), true)
27 }
28}
29
30impl<E: ErrorHandler> CommandsRegister<E> {
31 pub fn new(error_handle: E, help_command: bool) -> Self {
32 Self {
33 commands: vec![],
34 error_handler: error_handle,
35 help_command,
36 }
37 }
38
39 pub fn get_error_handler(&self) -> &E {
40 &self.error_handler
41 }
42
43 pub fn get_command(&mut self, command_str: &str) -> Option<&mut GenericCommand> {
44 for command in self.commands.iter_mut() {
45 if command.get_command_name() == command_str {
46 return Some(command);
47 }
48 for alias in command.get_command_alias() {
49 if alias == command_str {
50 return Some(command);
51 }
52 }
53 }
54
55 None
56 }
57
58 pub fn start(&mut self) {
59 self.commands.iter_mut().for_each(|command| {
60 command.start();
61 });
62 }
63
64 pub fn end(&mut self) {
65 self.commands.iter_mut().for_each(|command| {
66 command.end();
67 });
68 }
69
70 pub fn register_command(&mut self, command: GenericCommand) {
71 self.commands.push(command);
72 }
73
74 pub fn check_input(&mut self, input: String) -> bool {
75 let mut input = input.split_whitespace();
76 let command_or_alias = input.next().unwrap();
77
78 let mut args: Vec<&str> = vec![];
79 for arg in input {
80 args.push(arg);
81 }
82
83 if let Some(command) = self.get_command(command_or_alias) {
84 command.on_command(args);
85 true
86 } else if self.help_command && Self::is_help_command(command_or_alias) {
87 self.help(&args);
88 true
89 } else {
90 false
91 }
92 }
93
94 pub fn help(&mut self, args: &[&str]) {
95 match args.len() {
96 0 => {
97 let mut content = String::new();
98 for command in &self.commands {
99 content.push_str(command.get_command_name());
100 content.push('\n');
101 content.push_str(command.get_help());
102 content.push_str("\n\n");
103 }
104 println!("{content}");
105 }
106 1 => {
107 let command = if let Some(c) = self.get_command(args[0]) {
108 c
109 } else {
110 return;
111 };
112 let mut content = String::new();
113 content.push_str(command.get_command_name());
114 content.push('\n');
115 content.push_str(command.get_help());
116 content.push_str("\n\n");
117 println!("{content}");
118 }
119 _ => {}
120 }
121 }
122
123 fn is_help_command(command_str: &str) -> bool {
124 command_str == "help" || command_str == "h" || command_str == "?"
125 }
126}
127
128pub enum LogTypes {
129 INFO,
130 WARN,
131 ERR,
132}
133
134pub struct Console<E: ErrorHandler> {
135 prompt: String,
136 commands_register: CommandsRegister<E>,
137}
138
139impl<E: ErrorHandler> Console<E> {
140 pub fn new(prompt: String, commands_register: CommandsRegister<E>) -> Self {
141 Self {
142 prompt,
143 commands_register,
144 }
145 }
146
147 pub fn update(&mut self) {
148 let mut input = String::new();
149 print!("{}", self.prompt);
150 stdout().flush().unwrap();
151
152 io::stdin()
153 .read_line(&mut input)
154 .expect("Failed to read line");
155
156 if input.trim().is_empty() {
157 self.commands_register.get_error_handler().input_void();
158 return;
159 }
160 let copy = input.clone();
161 let command = copy.split_ascii_whitespace().next().unwrap();
162
163 let handled = self.commands_register.check_input(input);
164
165 if !handled {
166 self.commands_register
167 .get_error_handler()
168 .wrong_command(command);
169 }
170 }
171}
172
173#[cfg(test)]
174mod tests {}