1use crate::Result;
2
3pub trait Command {
8 type Input;
10
11 type Output;
13
14 fn execute(&self, input: Self::Input) -> Result<Self::Output>;
16
17 fn name(&self) -> &'static str;
19
20 fn description(&self) -> &'static str;
22
23 fn requires_git_repo(&self) -> bool {
25 true
26 }
27
28 fn is_destructive(&self) -> bool {
30 false
31 }
32}
33
34pub trait ActionCommand: Command<Output = ()> {
36 fn run(&self, input: Self::Input) -> Result<()> {
38 self.execute(input)
39 }
40}
41
42pub trait QueryCommand: Command<Output = String> {
44 fn query(&self, input: Self::Input) -> Result<String> {
46 self.execute(input)
47 }
48}
49
50impl<T> ActionCommand for T where T: Command<Output = ()> {}
52
53impl<T> QueryCommand for T where T: Command<Output = String> {}
55
56pub trait SimpleCommand: Command<Input = ()> {
58 fn run_simple(&self) -> Result<Self::Output> {
59 self.execute(())
60 }
61}
62
63impl<T> SimpleCommand for T where T: Command<Input = ()> {}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 struct MockActionCommand;
71
72 impl Command for MockActionCommand {
73 type Input = String;
74 type Output = ();
75
76 fn execute(&self, input: String) -> Result<()> {
77 println!("Mock action: {input}");
78 Ok(())
79 }
80
81 fn name(&self) -> &'static str {
82 "mock-action"
83 }
84
85 fn description(&self) -> &'static str {
86 "A mock action command for testing"
87 }
88 }
89
90 struct MockQueryCommand;
91
92 impl Command for MockQueryCommand {
93 type Input = ();
94 type Output = String;
95
96 fn execute(&self, _input: ()) -> Result<String> {
97 Ok("Mock query result".to_string())
98 }
99
100 fn name(&self) -> &'static str {
101 "mock-query"
102 }
103
104 fn description(&self) -> &'static str {
105 "A mock query command for testing"
106 }
107 }
108
109 #[test]
110 fn test_action_command_trait() {
111 let cmd = MockActionCommand;
112 assert_eq!(cmd.name(), "mock-action");
113 assert_eq!(cmd.description(), "A mock action command for testing");
114 assert!(cmd.requires_git_repo());
115 assert!(!cmd.is_destructive());
116
117 let result = cmd.run("test input".to_string());
118 assert!(result.is_ok());
119 }
120
121 #[test]
122 fn test_query_command_trait() {
123 let cmd = MockQueryCommand;
124 assert_eq!(cmd.name(), "mock-query");
125 assert_eq!(cmd.description(), "A mock query command for testing");
126
127 let result = cmd.query(());
128 assert!(result.is_ok());
129 assert_eq!(result.unwrap(), "Mock query result");
130 }
131
132 #[test]
133 fn test_simple_command_trait() {
134 let cmd = MockQueryCommand;
135 let result = cmd.run_simple();
136 assert!(result.is_ok());
137 assert_eq!(result.unwrap(), "Mock query result");
138 }
139}