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