-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcmd_say.rs
139 lines (129 loc) · 5.47 KB
/
cmd_say.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use anyhow::Result;
use clap::Parser;
/// Prints your text in a text bubble with Zoo as ASCII art
///
/// $ zoo say
/// $ zoo say hello!
/// $ zoo say Hello World!
#[derive(Parser, Debug, Clone)]
#[clap(verbatim_doc_comment)]
pub struct CmdSay {
/// What kitty says
#[clap(name = "input", required = false, num_args(1..))]
pub input: Vec<String>,
}
#[async_trait::async_trait(?Send)]
impl crate::cmd::Command for CmdSay {
async fn run(&self, ctx: &mut crate::context::Context) -> Result<()> {
let kitty_speaking = !self.input.is_empty();
let kitty_string = format_kitty(kitty_speaking);
if kitty_speaking {
let text = self.input.join(" ");
let border = "-".repeat(text.len() + 2);
let print_text = format!("|{text}|");
writeln!(ctx.io.out, "{border}").ok();
writeln!(ctx.io.out, "{print_text}").ok();
writeln!(ctx.io.out, "{border}").ok();
}
writeln!(ctx.io.out, "{kitty_string}").ok();
Ok(())
}
}
fn format_kitty(is_speaking: bool) -> String {
let speech_bar = if is_speaking { r"\" } else { " " };
format!(
" {speech_bar}
{speech_bar} .....
{speech_bar} .::-:... .....
{speech_bar} ..:---..:... .::::...
{speech_bar} ..------:.::::::::::.:----......
{speech_bar} .::::------:::::::::::..------:..::::::::-.
{speech_bar} .::::..........::::::::::::::----:::::::::---.
{speech_bar} ::::::::::::::::::::::::...........::::::::---.
{speech_bar} :--:::::::::::::::::::::::::::::::::::::::----.
:--::=#@@@%%%###***+++===---::::::::--::-=----.
:--::#@@@@@@@@@@@@@@@@@@@@@@@@@#-:::---:=-=---.
:--::#@@@@@@@@@@@@@@@@@@@@@@@@@@@:::----++=---.
:--::#@@@@%***#@@@@@@@@@*+*@@@@@@:::----=+----.
:--::#@@@**%%%#+@@@@@@@@=-=@@@@@@:::----------
:---:#@@@@@@@@@@@%%%%@@@=-=@@@@@@:::---------=
-----#@@@@@@@**@@#+-+#@@#%%@@@@@@:::--------==
-----#@@@@@@@@%+#%#-%@%+*#@@@@@@@::--------===
-----*%@@@@@@@@@***+++*%@@@@@@@@@----------===.
------=+***####%%%@@@@@@@@@@@@@@@---------====.
----------::::::::::::--===+++*+:--------=====
--==---===---::::::::::::::::-----------=====+
-------+**+----------------------------====***
---------------::::::::::------------======#**
-----=+++++-----------------=-=--=---======*+=
-----=+++++--#@@@%%%%###+---=-=--+---======:.
.......::----+####%%%%@@*---++++++---===:.
.*########*:.......:==--------.
:*#%%%%%%%%%%+ -%######*#+.
=#########%%%+ =#%%%%%%%%%##-
-++***#####=. *############:
-==++***##+:
"
)
}
#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;
use crate::cmd::Command;
pub struct TestItem {
name: String,
cmd: crate::cmd_say::CmdSay,
want_out: String,
}
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
#[serial_test::serial]
async fn test_cmd_say() {
let tests: Vec<TestItem> = vec![
TestItem {
name: "no input string".to_string(),
cmd: crate::cmd_say::CmdSay {
input: vec!["Hello".to_string(), "World!".to_string()],
},
want_out: "--------------\n|Hello World!|\n--------------\n".to_owned()
+ &crate::cmd_say::format_kitty(true),
},
TestItem {
name: "given input string".to_string(),
cmd: crate::cmd_say::CmdSay { input: vec![] },
want_out: crate::cmd_say::format_kitty(false),
},
];
let mut config = crate::config::new_blank_config().unwrap();
let mut c = crate::config_from_env::EnvConfig::inherit_env(&mut config);
for t in tests {
let (mut io, stdout_path, stderr_path) = crate::iostreams::IoStreams::test();
// We need to also turn off the fancy terminal colors.
// This ensures it also works in GitHub actions/any CI.
io.set_color_enabled(false);
// TODO: we should figure out how to test the prompts.
io.set_never_prompt(true);
let mut ctx = crate::context::Context {
config: &mut c,
io,
debug: false,
};
let cmd_say = crate::cmd_say::CmdSay { input: t.cmd.input };
match cmd_say.run(&mut ctx).await {
Ok(()) => {
let stdout = std::fs::read_to_string(stdout_path).unwrap();
let stderr = std::fs::read_to_string(stderr_path).unwrap();
assert!(stderr.is_empty(), "test {}: {}", t.name, stderr);
if !stdout.contains(&t.want_out) {
assert_eq!(stdout, t.want_out, "test {}: stdout mismatch", t.name);
}
}
Err(_err) => {
let stdout = std::fs::read_to_string(stdout_path).unwrap();
let stderr = std::fs::read_to_string(stderr_path).unwrap();
assert_eq!(stdout, t.want_out, "test {}", t.name);
assert!(stderr.is_empty(), "test {}: {}", t.name, stderr);
}
}
}
}
}