1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
use serde::Serialize;
use crate::{
r_println,
systems::cmd::{
errors::{CmdExecuteError, CmdPrepareError, CmdProcessError, CmdRenderError},
renderer::{JVRenderResult, JVResultRenderer},
},
};
use std::future::Future;
pub struct JVCommandContext {
pub help: bool,
pub confirmed: bool,
}
pub trait JVCommand<Argument, Input, Output, Renderer>
where
Argument: clap::Parser + Send + Sync,
Input: Send + Sync,
Output: Serialize + Send + Sync,
Renderer: JVResultRenderer<Output> + Send + Sync,
{
/// Get help string for the command
fn get_help_str() -> String;
/// Process the command with a specified renderer, performing any necessary post-execution processing
fn process_with_renderer_flag(
args: Vec<String>,
ctx: JVCommandContext,
renderer: String,
) -> impl Future<Output = Result<JVRenderResult, CmdProcessError>> + Send
where
Self: Sync,
{
async move {
let renderer_str = renderer.as_str();
include!("_renderers.rs")
}
}
/// performing any necessary post-execution processing
fn process(
args: Vec<String>,
ctx: JVCommandContext,
) -> impl Future<Output = Result<JVRenderResult, CmdProcessError>> + Send
where
Self: Sync,
{
Self::process_with_renderer::<Renderer>(args, ctx)
}
/// Process the command output with a custom renderer,
/// performing any necessary post-execution processing
fn process_with_renderer<R: JVResultRenderer<Output> + Send + Sync>(
args: Vec<String>,
ctx: JVCommandContext,
) -> impl Future<Output = Result<JVRenderResult, CmdProcessError>> + Send
where
Self: Sync,
{
async move {
let mut full_args = vec!["jv".to_string()];
full_args.extend(args);
let parsed_args = match Argument::try_parse_from(full_args) {
Ok(args) => args,
Err(_) => return Err(CmdProcessError::ParseError(Self::get_help_str())),
};
// If the help flag is used, skip execution and directly print help
if ctx.help {
let mut r = JVRenderResult::default();
r_println!(r, "{}", Self::get_help_str());
return Ok(r);
}
let input = match Self::prepare(parsed_args, ctx).await {
Ok(input) => input,
Err(e) => return Err(CmdProcessError::from(e)),
};
let output = match Self::exec(input).await {
Ok(output) => output,
Err(e) => return Err(CmdProcessError::from(e)),
};
match R::render(&output).await {
Ok(r) => Ok(r),
Err(e) => Err(CmdProcessError::from(e)),
}
}
}
/// Prepare to run the command,
/// converting Clap input into the command's supported input
fn prepare(
args: Argument,
ctx: JVCommandContext,
) -> impl Future<Output = Result<Input, CmdPrepareError>> + Send;
/// Run the command phase,
/// returning an output structure, waiting for rendering
fn exec(input: Input) -> impl Future<Output = Result<Output, CmdExecuteError>> + Send;
}
|