shellfish/handler/
async_app.rs1use std::collections::HashMap;
2use std::env;
3use std::path::PathBuf;
4
5use async_trait::async_trait;
6use yansi::Paint;
7
8use super::{AsyncHandler, CommandLineHandler};
9use crate::command::CommandType;
10use crate::Command;
11
12#[derive(Default, Clone, Eq, PartialEq)]
19pub struct DefaultAsyncCLIHandler {
20 pub proj_name: Option<String>,
21}
22
23impl CommandLineHandler for DefaultAsyncCLIHandler {
24 fn get_cache(&self) -> Option<PathBuf> {
25 let mut path = home::home_dir()?;
26 #[cfg(target_os = "windows")]
27 {
28 path.push("AppData");
29 path.push("Local");
30 }
31 #[cfg(target_os = "linux")]
32 {
33 path.push(".cache");
34 }
35 #[cfg(target_os = "macos")]
36 {
37 path.push("Library Support");
38 }
39 path.push(self.proj_name.as_ref().unwrap_or(&env::args().next()?));
40 path.push("shellfish.json");
41 Some(path)
42 }
43}
44
45#[async_trait]
46impl<T: Send> AsyncHandler<T> for DefaultAsyncCLIHandler {
47 async fn handle_async(
48 &self,
49 line: Vec<String>,
50 commands: &HashMap<&str, Command<T>>,
51 state: &mut T,
52 description: &str,
53 ) -> bool {
54 if let Some(command) = line.get(1) {
55 match command.as_str() {
56 "quit" | "exit" | "--quit" | "--exit" => return true,
57 "help" | "--help" => {
58 println!("{}", line[0]);
60
61 println!("{}", description);
63
64 println!("USAGE:");
66 println!(
67 " {} [SUBCOMMAND]",
68 self.proj_name.as_ref().unwrap_or(&line[0])
69 );
70 println!();
71
72 println!("Where [SUBCOMMAND] is one of:");
74
75 let mut cmd_help = HashMap::new();
77 let mut cmd_len = 4;
78
79 cmd_help.insert("help", "displays help information.");
81 cmd_help.insert(
82 "quit",
83 "deletes all temporary state information.",
84 );
85 cmd_help.insert(
86 "exit",
87 "deletes all temporary state information.",
88 );
89
90 for (name, command) in commands {
92 cmd_help.insert(name, &command.help);
93 cmd_len = cmd_len.max(name.len());
94 }
95
96 for (name, command) in cmd_help {
98 println!(
99 " {:<width$}{}",
100 name,
101 command,
102 width = cmd_len + 5
103 );
104 }
105 }
106 _ => {
107 let command = commands.get(command as &str);
108 let line =
109 line[1..].iter().map(|x| x.to_string()).collect();
110
111 match command {
113 Some(command) => {
114 if let Err(e) = match command.command {
115 CommandType::Sync(c) => c(state, line),
116 #[cfg(feature = "async")]
117 CommandType::Async(a) => a(state, line).await,
118 } {
119 eprintln!("{}", Paint::red(&format!("Command exited unsuccessfully:\n{}\n({:?})", &e, &e)))
120 }
121 }
122 None => {
123 eprintln!(
124 "{}",
125 Paint::red(&format!(
126 "Command not found: {}",
127 line[0]
128 )),
129 )
130 }
131 }
132 }
133 }
134
135 println!();
137 }
138 false
139 }
140}