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