intelli_shell/process/
mod.rs

1use clap::{Args, FromArgMatches};
2
3use crate::{component::Component, config::Config, service::IntelliShellService};
4
5pub mod export;
6pub mod fix;
7pub mod import;
8pub mod new;
9pub mod replace;
10pub mod search;
11pub mod tldr_clear;
12pub mod tldr_fetch;
13
14#[cfg(debug_assertions)]
15pub mod query;
16
17/// Represents the final outcome of a [`Process`] execution.
18///
19/// This enum determines the action the shell should take after a command has been processed.
20/// It can either lead to the execution of a new shell command or result in exiting the process with specific output
21/// information.
22pub enum ProcessOutput {
23    /// Instructs the shell to execute the specified command
24    Execute { cmd: String },
25    /// Instructs the shell to terminate and output the provided information
26    Output(OutputInfo),
27}
28
29/// Holds the information to be written to output streams upon process termination.
30///
31/// This structure defines what should be sent to standard output (stdout), standard error (stderr), and/or a dedicated
32/// file, along with a status indicating if the operation itself succeeded or failed.
33#[derive(Clone, PartialEq, Eq, Default)]
34#[cfg_attr(debug_assertions, derive(Debug))]
35pub struct OutputInfo {
36    /// Indicates whether the operation that generated this output bundle was considered a failure
37    pub failed: bool,
38
39    /// Content to be written to a specified output file.
40    ///
41    /// When this is `Some`, it typically takes precedence over `stdout`. This is useful for redirecting the main
42    /// output of a command to a file, for instance, via an `--output` flag.
43    pub fileout: Option<String>,
44
45    /// Content to be written to the standard output (stdout) stream.
46    ///
47    /// This is generally used when no file output is specified.
48    pub stdout: Option<String>,
49
50    /// Content to be written to the standard error (stderr) stream.
51    ///
52    /// Used for error messages or diagnostic information.
53    pub stderr: Option<String>,
54}
55
56impl ProcessOutput {
57    /// Creates a [`ProcessOutput::Execute`] variant to run a shell command
58    pub fn execute(cmd: impl Into<String>) -> Self {
59        Self::Execute { cmd: cmd.into() }
60    }
61
62    /// Creates a successful [`ProcessOutput::Output`] with no content and succesful exit code
63    pub fn success() -> Self {
64        Self::Output(OutputInfo {
65            failed: false,
66            ..Default::default()
67        })
68    }
69
70    /// Creates a failed [`ProcessOutput::Output`] with no content and failure exit code
71    pub fn fail() -> Self {
72        Self::Output(OutputInfo {
73            failed: true,
74            ..Default::default()
75        })
76    }
77
78    /// Sets the file output content for the [`ProcessOutput::Output`] variant.
79    ///
80    /// Note: This has no effect if the instance is a `ProcessOutput::Execute` variant.
81    pub fn fileout(self, fileout: impl Into<String>) -> Self {
82        match self {
83            e @ ProcessOutput::Execute { .. } => e,
84            ProcessOutput::Output(data) => ProcessOutput::Output(OutputInfo {
85                fileout: Some(fileout.into()),
86                ..data
87            }),
88        }
89    }
90
91    /// Sets the standard output content for the [`ProcessOutput::Output`] variant.
92    ///
93    /// Note: This has no effect if the instance is a `ProcessOutput::Execute` variant.
94    pub fn stdout(self, stdout: impl Into<String>) -> Self {
95        match self {
96            e @ ProcessOutput::Execute { .. } => e,
97            ProcessOutput::Output(data) => ProcessOutput::Output(OutputInfo {
98                stdout: Some(stdout.into()),
99                ..data
100            }),
101        }
102    }
103
104    /// Sets the standard error content for the [`ProcessOutput::Output`] variant.
105    ///
106    /// Note: This has no effect if the instance is a `ProcessOutput::Execute` variant.
107    pub fn stderr(self, stderr: impl Into<String>) -> Self {
108        match self {
109            e @ ProcessOutput::Execute { .. } => e,
110            ProcessOutput::Output(data) => ProcessOutput::Output(OutputInfo {
111                stderr: Some(stderr.into()),
112                ..data
113            }),
114        }
115    }
116}
117
118/// Trait for non-interactive processes
119#[trait_variant::make(Send)]
120pub trait Process {
121    /// Executes the process non-interactively and returns the output
122    async fn execute(self, config: Config, service: IntelliShellService) -> color_eyre::Result<ProcessOutput>;
123}
124
125/// Trait for interactive processes
126pub trait InteractiveProcess: Process + FromArgMatches + Args {
127    /// Converts the process into a renderable component
128    fn into_component(
129        self,
130        config: Config,
131        service: IntelliShellService,
132        inline: bool,
133    ) -> color_eyre::Result<Box<dyn Component>>;
134}