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