use std::mem::take;
use textwrap::wrap;
const CLIPPY_ART: &str = r#"/‾‾\
| |
@ @
|| |/
|| ||
|\_/|
\___/
/\
"#;
#[derive(Default, Clone, PartialOrd, PartialEq)]
pub struct ClippyOutput {
buf: String,
output_width: u16,
line: String,
line_char_length: u16,
}
impl ClippyOutput {
pub fn new(mut output_width: u16) -> Self {
if output_width < 5 {
output_width = 5;
}
let mut s = CLIPPY_ART.to_string() + "/‾ ";
for _ in 0..output_width - 5 {
s.push('‾');
}
s.push_str("\\\n");
Self {
buf: s,
output_width,
line: String::new(),
line_char_length: 0,
}
}
pub fn add_str(&mut self, s: &str) {
let lines = wrap(s, usize::min((self.output_width - 4) as usize, 2000));
for (i, line) in lines.iter().enumerate() {
for char in line.chars() {
if char == '\n' {
ClippyOutput::add_string_to_buffer(
&mut self.buf,
&self.line,
self.output_width - 4 - self.line_char_length,
);
self.line.clear();
self.line_char_length = 0;
} else {
self.line.push(char);
self.line_char_length += 1;
}
if self.line_char_length == self.output_width - 4 {
ClippyOutput::add_string_to_buffer(&mut self.buf, &self.line, 0);
self.line.clear();
self.line_char_length = 0;
}
}
if i < lines.len() - 1 {
ClippyOutput::add_string_to_buffer(
&mut self.buf,
&self.line,
self.output_width - 4 - self.line_char_length,
);
self.line.clear();
self.line_char_length = 0;
}
}
}
fn add_string_to_buffer(buf: &mut String, line: &str, space_count: u16) {
if !line.is_empty() {
buf.push_str("| ");
buf.push_str(&line);
for _ in 0..space_count {
buf.push(' ');
}
buf.push_str(" |\n");
}
}
pub fn finish(&mut self) {
if !self.line.is_empty() {
ClippyOutput::add_string_to_buffer(
&mut self.buf,
&self.line,
self.output_width - 4 - self.line.chars().count() as u16,
);
self.line.clear();
self.line_char_length = 0;
}
self.buf.push('\\');
for _ in 0..self.output_width - 2 {
self.buf.push('_');
}
self.buf.push_str("/\n");
}
}
impl Iterator for ClippyOutput {
type Item = String;
fn next(&mut self) -> Option<String> {
let result = take(&mut self.buf);
if result.is_empty() {
None
} else {
Some(result)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn clippy_output() {
{
let mut clippy = ClippyOutput::new(0);
let result: String = clippy.by_ref().collect();
assert_eq!(result, CLIPPY_ART.to_string() + "/‾ \\\n");
clippy.finish();
let result: String = clippy.by_ref().collect();
assert_eq!(result, "\\___/\n");
}
{
let mut clippy = ClippyOutput::new(0);
clippy.add_str("");
clippy.finish();
let result: String = clippy.collect();
assert_eq!(result, CLIPPY_ART.to_string() + "/‾ \\\n\\___/\n");
}
{
let mut clippy = ClippyOutput::new(0);
clippy.add_str("a");
let result: String = clippy.by_ref().collect();
assert_eq!(result, CLIPPY_ART.to_string() + "/‾ \\\n| a |\n");
clippy.finish();
let result: String = clippy.by_ref().collect();
assert_eq!(result, "\\___/\n");
clippy.add_str("a");
clippy.finish();
let result: String = clippy.collect();
assert_eq!(result, "| a |\n\\___/\n");
}
{
let mut clippy = ClippyOutput::new(6);
clippy.add_str("aa");
clippy.finish();
let result: String = clippy.collect();
assert_eq!(
result,
CLIPPY_ART.to_string() + "/‾ ‾\\\n| aa |\n\\____/\n"
);
}
{
let mut clippy = ClippyOutput::new(6);
clippy.add_str("aaa");
clippy.finish();
let result: String = clippy.collect();
assert_eq!(
result,
CLIPPY_ART.to_string() + "/‾ ‾\\\n| aa |\n| a |\n\\____/\n"
);
}
{
let mut clippy = ClippyOutput::new(6);
clippy.add_str("a");
let result: String = clippy.by_ref().collect();
assert_eq!(result, CLIPPY_ART.to_string() + "/‾ ‾\\\n");
clippy.add_str("a");
clippy.finish();
let result: String = clippy.collect();
assert_eq!(result, "| aa |\n\\____/\n");
}
{
let mut clippy = ClippyOutput::new(6);
clippy.add_str("a\n");
let result: String = clippy.by_ref().collect();
assert_eq!(result, CLIPPY_ART.to_string() + "/‾ ‾\\\n| a |\n");
clippy.add_str("b");
clippy.finish();
let result: String = clippy.collect();
assert_eq!(result, "| b |\n\\____/\n");
}
{
let mut clippy = ClippyOutput::new(7);
clippy.add_str("a");
clippy.add_str("\n");
clippy.add_str("aaaa\n");
clippy.add_str("b");
clippy.finish();
let result: String = clippy.collect();
assert_eq!(
result,
CLIPPY_ART.to_string() + "/‾ ‾‾\\\n| a |\n| aaa |\n| a |\n| b |\n\\_____/\n"
);
}
}
}