modcli/
console.rs

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    // Get shell configuration
10    let sconf = if let Some(sconf) = &config.modcli.shell {
11        sconf
12    } else {
13        panic!("Shell configuration is missing");
14    };
15
16    // Set prompt prefix or default to "Mod > "
17    let prompt = sconf.prompt.as_deref().unwrap_or("Mod > ");
18
19    // Show welcome message, scroll line-by-line with optional delay
20    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    // Show goodbye message, scroll line-by-line with optional delay
27    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    // Initialize ModCLI
36    let mut cli = ModCli::new();
37
38    // Optionally re-load commands if needed
39    // let source = crate::loader::sources::JsonFileSource::new("examples/commands.json");
40    // cli.registry.load_from(Box::new(source));
41
42    // Loop for shell commands
43    loop {
44        // Get input
45        let input = prompt_text(prompt);
46        let trimmed = input.trim();
47
48        // Check for exit commands
49        if matches!(trimmed, "exit" | "quit") {
50            break;
51        }
52
53        // Check internal shell commands
54        if dispatch_shell_command(trimmed, config) {
55            continue;
56        }
57
58        // Check custom shell commands
59        if dispatch(trimmed) {
60            continue;
61        }
62
63        // Parse input into command and args
64        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        // Execute command
74        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}