xacli_core/command/
cmd.rs1use std::fmt::Debug;
4
5use crate::{Arg, Context, Result};
6
7#[derive(Debug, Clone, PartialEq)]
8pub struct CommandInfo {
9 pub name: String,
10 pub aliases: Vec<String>,
11 pub title: String,
12 pub description: String,
13}
14
15pub type RunFn = dyn Fn(&mut dyn Context) -> Result<()>;
17
18pub struct Command {
19 pub info: CommandInfo,
20 pub args: Vec<Arg>,
21 pub subcommands: Vec<Command>,
22 pub hooks: Hooks,
23}
24
25pub struct Hooks {
26 pub run_fn: Option<Box<RunFn>>,
27 pub pre_run_fn: Option<Box<RunFn>>,
28 pub post_run_fn: Option<Box<RunFn>>,
29}
30
31impl Command {
32 pub fn new(name: impl Into<String>) -> Self {
34 Self {
35 info: CommandInfo {
36 name: name.into(),
37 aliases: Vec::new(),
38 title: String::new(),
39 description: String::new(),
40 },
41 args: Vec::new(),
42 subcommands: Vec::new(),
43 hooks: Hooks {
44 run_fn: None,
45 pre_run_fn: None,
46 post_run_fn: None,
47 },
48 }
49 }
50
51 pub fn alias(mut self, alias: impl Into<String>) -> Self {
56 self.info.aliases.push(alias.into());
57 self
58 }
59
60 pub fn aliases(mut self, aliases: Vec<String>) -> Self {
61 self.info.aliases = aliases;
62 self
63 }
64
65 pub fn title(mut self, title: impl Into<String>) -> Self {
66 self.info.title = title.into();
67 self
68 }
69
70 pub fn description(mut self, description: impl Into<String>) -> Self {
71 self.info.description = description.into();
72 self
73 }
74
75 pub fn arg(mut self, arg: Arg) -> Self {
77 self.args.push(arg);
78 self
79 }
80
81 pub fn subcommand(mut self, command: Command) -> Self {
82 self.subcommands.push(command);
83 self
84 }
85
86 pub fn run(mut self, f: Box<RunFn>) -> Self {
87 self.hooks.run_fn = Some(f);
88 self
89 }
90
91 pub fn pre_run(mut self, f: Box<RunFn>) -> Self {
92 self.hooks.pre_run_fn = Some(f);
93 self
94 }
95
96 pub fn post_run(mut self, f: Box<RunFn>) -> Self {
97 self.hooks.post_run_fn = Some(f);
98 self
99 }
100
101 pub fn is_leaf(&self) -> bool {
107 self.subcommands.is_empty()
108 }
109
110 pub fn execute(&self, ctx: &mut dyn Context) -> Result<()> {
114 if let Some(ref pre_run) = self.hooks.pre_run_fn {
116 pre_run(ctx)?;
117 }
118
119 if let Some(ref run_fn) = self.hooks.run_fn {
121 run_fn(ctx)?;
122 }
123
124 if let Some(ref post_run) = self.hooks.post_run_fn {
126 post_run(ctx)?;
127 }
128
129 Ok(())
130 }
131}