intelli_shell/process/
fix.rs

1use std::time::Duration;
2
3use indicatif::{ProgressBar, ProgressStyle};
4
5use super::{Process, ProcessOutput};
6use crate::{
7    ai::CommandFix,
8    cli::CommandFixProcess,
9    config::Config,
10    errors::AppError,
11    format_error,
12    service::{AiFixProgress, IntelliShellService},
13    widgets::SPINNER_CHARS,
14};
15
16impl Process for CommandFixProcess {
17    async fn execute(self, config: Config, service: IntelliShellService) -> color_eyre::Result<ProcessOutput> {
18        // Setup the progress bar
19        let pb = ProgressBar::new_spinner();
20        pb.set_style(
21            ProgressStyle::with_template("{spinner:.blue} {wide_msg}")
22                .unwrap()
23                .tick_strings(&SPINNER_CHARS),
24        );
25
26        // Setup callback for progress updates
27        let on_progress = |progress: AiFixProgress| match progress {
28            // When the command has been executed
29            AiFixProgress::Thinking => {
30                // Print a separator line to indicate the end of the command output
31                eprintln!("\n────────────────────────────────────────────────────────────────────────────────\n");
32                // Display the spinner
33                pb.enable_steady_tick(Duration::from_millis(100));
34                pb.set_message("Thinking ...");
35            }
36        };
37
38        // Call the service to fix the command
39        let res = service
40            .fix_command(&self.command, self.history.as_deref(), on_progress)
41            .await;
42
43        // Clear the spinner
44        pb.finish_and_clear();
45
46        // Handle the result
47        match res {
48            Ok(None) => Ok(ProcessOutput::success()),
49            Ok(Some(CommandFix {
50                summary,
51                diagnosis,
52                proposal,
53                fixed_command,
54            })) => {
55                let mut msg = format!(
56                    r"🧠 IntelliShell Diagnosis
57
58❌ {summary}
59{}
60
61✨ Fix
62{}
63",
64                    config.theme.secondary.apply(diagnosis),
65                    config.theme.secondary.apply(proposal)
66                );
67                let mut out = ProcessOutput::success();
68                if !fixed_command.trim().is_empty() {
69                    msg += "\nSuggested Command 👉";
70                    out = out.stdout(&fixed_command).fileout(fixed_command);
71                }
72                Ok(out.stderr(msg))
73            }
74            Err(AppError::UserFacing(err)) => Ok(ProcessOutput::fail().stderr(format_error!(config.theme, "{err}"))),
75            Err(AppError::Unexpected(report)) => Err(report),
76        }
77    }
78}