Skip to main content

fukurow_cli/
interactive.rs

1//! Interactive CLI mode
2
3use crate::commands::{CommandExecutor, Cli};
4use clap::Parser;
5use std::io::{self, Write};
6use anyhow::Result;
7
8/// Interactive CLI session
9pub struct InteractiveSession {
10    executor: CommandExecutor,
11}
12
13impl InteractiveSession {
14    pub fn new() -> Self {
15        Self {
16            executor: CommandExecutor::new(),
17        }
18    }
19
20    /// Start interactive session
21    pub async fn run(&mut self) -> Result<()> {
22        println!("Welcome to Reasoner CLI Interactive Mode");
23        println!("Type 'help' for available commands, 'quit' to exit");
24        println!("{}", "=".repeat(50));
25
26        loop {
27            print!("reasoner> ");
28            io::stdout().flush()?;
29
30            let mut input = String::new();
31            io::stdin().read_line(&mut input)?;
32            let input = input.trim();
33
34            if input.is_empty() {
35                continue;
36            }
37
38            match input {
39                "quit" | "exit" | "q" => {
40                    println!("Goodbye!");
41                    break;
42                }
43                "help" | "h" => {
44                    self.show_help();
45                }
46                "clear" => {
47                    // Clear screen (Unix-like systems)
48                    print!("\x1B[2J\x1B[1;1H");
49                }
50                _ => {
51                    if let Err(e) = self.execute_command(input).await {
52                        eprintln!("Error: {}", e);
53                    }
54                }
55            }
56        }
57
58        Ok(())
59    }
60
61    async fn execute_command(&mut self, input: &str) -> Result<()> {
62        // Parse the input as CLI arguments
63        let args = shell_words::split(input)?;
64        let cli = match Cli::try_parse_from(args) {
65            Ok(cli) => cli,
66            Err(e) => {
67                eprintln!("Parse error: {}", e);
68                return Ok(());
69            }
70        };
71
72        let result = self.executor.execute(cli.command).await?;
73
74        if !result.message.is_empty() {
75            println!("{}", result.message);
76        }
77
78        Ok(())
79    }
80
81    fn show_help(&self) {
82        println!("Available commands:");
83        println!("  serve [options]     Start API server");
84        println!("  analyze [options]   Analyze single event");
85        println!("  process [options]   Process events from file");
86        println!("  query [options]     Query knowledge graph");
87        println!("  threat [subcommand] Threat intelligence operations");
88        println!("  info                Show system information");
89        println!("  help                Show this help");
90        println!("  clear               Clear screen");
91        println!("  quit                Exit interactive mode");
92        println!();
93        println!("Use '<command> --help' for detailed help on each command");
94    }
95}
96
97impl Default for InteractiveSession {
98    fn default() -> Self {
99        Self::new()
100    }
101}
102
103/// Start interactive mode
104pub async fn start_interactive() -> Result<()> {
105    let mut session = InteractiveSession::new();
106    session.run().await
107}