1use crate::config::CliConfig;
2use crate::input::prompt_text;
3use crate::output::print;
4use crate::shell_commands::dispatch;
5use crate::shell_extensions::dispatch_shell_command;
6use crate::ModCli;
7
8pub fn run_shell(config: &CliConfig) {
9 let sconf = if let Some(sconf) = &config.modcli.shell {
11 sconf
12 } else {
13 panic!("Shell configuration is missing");
14 };
15
16 let prompt = sconf.prompt.as_deref().unwrap_or("Mod > ");
18
19 if let Some(welcome) = &sconf.welcome {
21 let delay = &config.modcli.delay.unwrap_or(0);
22 let lines: Vec<&str> = welcome.iter().flat_map(|s| s.lines()).collect();
23 print::scroll(&lines, *delay);
24 }
25
26 let goodbye_message = if let Some(goodbye) = &sconf.goodbye {
28 let delay = &config.modcli.delay.unwrap_or(0);
29 let lines: Vec<&str> = goodbye.iter().flat_map(|s| s.lines()).collect();
30 Some((lines, *delay))
31 } else {
32 None
33 };
34
35 let mut cli = ModCli::new();
37
38 loop {
44 let input = prompt_text(prompt);
46 let trimmed = input.trim();
47
48 if matches!(trimmed, "exit" | "quit") {
50 break;
51 }
52
53 if dispatch_shell_command(trimmed, config) {
55 continue;
56 }
57
58 if dispatch(trimmed) {
60 continue;
61 }
62
63 let parts: Vec<String> = trimmed.split_whitespace().map(String::from).collect();
65
66 if parts.is_empty() {
67 continue;
68 }
69
70 let cmd = parts[0].clone();
71 let args = parts[1..].to_vec();
72
73 cli.run([cmd].into_iter().chain(args).collect());
75 }
76
77 if let Some((lines, delay)) = goodbye_message {
78 print::scroll(&lines, delay);
79 }
80}