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