1use crate::error::Error;
6use crate::parse;
7pub use crate::result::Result;
8use crate::terminal::Terminal;
9use async_trait::async_trait;
10use downcast::{AnySync, downcast_sync};
11use std::{
12 collections::HashMap,
13 sync::{Arc, Mutex, MutexGuard},
14};
15pub use workflow_terminal_macros::{Handler, declare_handler, register_handlers};
16
17#[async_trait]
22pub trait Cli: Sync + Send {
23 fn init(self: Arc<Self>, _term: &Arc<Terminal>) -> Result<()> {
25 Ok(())
26 }
27 async fn digest(self: Arc<Self>, term: Arc<Terminal>, cmd: String) -> Result<()>;
29 async fn complete(
31 self: Arc<Self>,
32 term: Arc<Terminal>,
33 cmd: String,
34 ) -> Result<Option<Vec<String>>>;
35 fn prompt(&self) -> Option<String>;
37}
38
39pub trait Context: Sync + Send + AnySync {
42 fn term(&self) -> Arc<Terminal>;
44}
45downcast_sync!(dyn Context);
46downcast_sync!(dyn Context + Sync + Send);
47
48impl From<&dyn Context> for Arc<Terminal> {
49 fn from(ctx: &dyn Context) -> Arc<Terminal> {
50 ctx.term()
51 }
52}
53
54#[async_trait]
57pub trait Handler: Sync + Send + AnySync {
58 fn verb(&self, _ctx: &Arc<dyn Context>) -> Option<&'static str> {
60 None
61 }
62 fn condition(&self, ctx: &Arc<dyn Context>) -> bool {
64 self.verb(ctx).is_some()
65 }
66 fn help(&self, _ctx: &Arc<dyn Context>) -> &'static str {
68 ""
69 }
70 fn dyn_help(&self, _ctx: &Arc<dyn Context>) -> String {
72 "".to_owned()
73 }
74 async fn complete(&self, _ctx: &Arc<dyn Context>, _cmd: &str) -> Result<Option<Vec<String>>> {
76 Ok(None)
77 }
78 async fn start(self: Arc<Self>, _ctx: &Arc<dyn Context>) -> Result<()> {
80 Ok(())
81 }
82 async fn stop(self: Arc<Self>, _ctx: &Arc<dyn Context>) -> Result<()> {
84 Ok(())
85 }
86 async fn handle(
88 self: Arc<Self>,
89 ctx: &Arc<dyn Context>,
90 argv: Vec<String>,
91 cmd: &str,
92 ) -> Result<()>;
93}
94
95downcast_sync!(dyn Handler);
96
97pub fn get_handler_help(handler: Arc<dyn Handler>, ctx: &Arc<dyn Context>) -> String {
100 let s = handler.help(ctx);
101 if s.is_empty() {
102 handler.dyn_help(ctx)
103 } else {
104 s.to_string()
105 }
106}
107
108#[derive(Default)]
109struct Inner {
110 handlers: HashMap<String, Arc<dyn Handler>>,
111}
112
113#[derive(Default)]
114pub struct HandlerCli {
117 inner: Arc<Mutex<Inner>>,
118}
119
120impl HandlerCli {
121 pub fn new() -> Self {
123 Self {
124 inner: Arc::new(Mutex::new(Inner::default())),
125 }
126 }
127
128 fn inner(&self) -> MutexGuard<'_, Inner> {
129 self.inner.lock().unwrap()
130 }
131
132 pub fn collect(&self) -> Vec<Arc<dyn Handler>> {
134 self.inner().handlers.values().cloned().collect::<Vec<_>>()
135 }
136
137 pub fn get(&self, name: &str) -> Option<Arc<dyn Handler>> {
139 self.inner().handlers.get(name).cloned()
140 }
141
142 pub fn register<T, H>(&self, ctx: &Arc<T>, handler: H)
145 where
146 T: Context + Sized,
147 H: Handler + Send + Sync + 'static,
148 {
149 let ctx: Arc<dyn Context> = ctx.clone();
150 match handler.verb(&ctx) {
151 Some(name) if handler.condition(&ctx) => {
152 self.inner()
153 .handlers
154 .insert(name.to_lowercase(), Arc::new(handler));
155 }
156 _ => {}
157 }
158 }
159
160 pub fn register_arc<T, H>(&self, ctx: &Arc<T>, handler: &Arc<H>)
163 where
164 T: Context + Sized,
165 H: Handler + Send + Sync + 'static,
166 {
167 let ctx: Arc<dyn Context> = ctx.clone();
168 match handler.verb(&ctx) {
169 Some(name) if handler.condition(&ctx) => {
170 self.inner()
171 .handlers
172 .insert(name.to_lowercase(), handler.clone());
173 }
174 _ => {}
175 }
176 }
177
178 pub fn unregister(&self, name: &str) -> Option<Arc<dyn Handler>> {
180 self.inner().handlers.remove(name)
181 }
182
183 pub fn clear(&self) -> Result<()> {
185 self.inner().handlers.clear();
186 Ok(())
187 }
188
189 pub async fn start<T>(&self, ctx: &Arc<T>) -> Result<()>
191 where
192 T: Context + Sized,
193 {
194 let ctx: Arc<dyn Context> = ctx.clone();
195 let handlers = self.collect();
196 for handler in handlers.iter() {
197 handler.clone().start(&ctx).await?;
198 }
199 Ok(())
200 }
201
202 pub async fn stop<T>(&self, ctx: &Arc<T>) -> Result<()>
204 where
205 T: Context + Sized,
206 {
207 let handlers = self.collect();
208 let ctx: Arc<dyn Context> = ctx.clone();
209 for handler in handlers.into_iter() {
210 handler.clone().start(&ctx).await?;
211 }
212 Ok(())
213 }
214
215 pub async fn execute<T>(&self, ctx: &Arc<T>, cmd: &str) -> Result<()>
218 where
219 T: Context + Sized,
220 {
221 let ctx: Arc<dyn Context> = ctx.clone();
222
223 let argv = parse(cmd);
224 let action = argv[0].to_lowercase();
225
226 let handler = self.get(action.as_str());
227 if let Some(handler) = handler {
228 handler
229 .clone()
230 .handle(&ctx, argv[1..].to_vec(), cmd)
231 .await?;
232 Ok(())
233 } else {
234 Err(Error::CommandNotFound(action))
235 }
236 }
237
238 pub async fn complete<T>(&self, ctx: &Arc<T>, cmd: &str) -> Result<Option<Vec<String>>>
241 where
242 T: Context + Sized,
243 {
244 let ctx: Arc<dyn Context> = ctx.clone();
245
246 let argv = parse(cmd);
247 let action = argv[0].to_lowercase();
248
249 let handler = self.get(action.as_str());
250 if let Some(handler) = handler {
251 Ok(handler.clone().complete(&ctx, cmd).await?)
252 } else {
253 Err(Error::CommandNotFound(action))
254 }
255 }
256}