fukurow_cli/
interactive.rs1use crate::commands::{CommandExecutor, Cli};
4use clap::Parser;
5use std::io::{self, Write};
6use anyhow::Result;
7
8pub struct InteractiveSession {
10 executor: CommandExecutor,
11}
12
13impl InteractiveSession {
14 pub fn new() -> Self {
15 Self {
16 executor: CommandExecutor::new(),
17 }
18 }
19
20 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 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 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
103pub async fn start_interactive() -> Result<()> {
105 let mut session = InteractiveSession::new();
106 session.run().await
107}