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
use textwrap::wrap;

use unicode_width::UnicodeWidthStr;

pub static KITTY: &str = "
      /l、
    (゚、 。 7
      l  ~ヽ
      じしf_,)ノ
	";

pub struct FormatOptions {
	pub think: bool,
	pub width: u16,
}

struct Chars {
	arrow: &'static str,
	top: &'static str,
	bottom: &'static str,
	left: &'static str,
	right: &'static str,
	single_left: &'static str,
	single_right: &'static str,
	angled_up_right: &'static str,
	angled_up_left: &'static str,
	angled_down_right: &'static str,
	angled_down_left: &'static str,
}

static SAY_CHARS: Chars = Chars {
	arrow: "\\",
	top: "-",
	bottom: "-",
	left: "|",
	right: "|",
	single_left: "<",
	single_right: ">",
	angled_up_right: "/",
	angled_up_left: "\\",
	angled_down_right: "\\",
	angled_down_left: "/",
};

static THINK_CHARS: Chars = Chars {
	arrow: "○",
	top: "⏜",
	bottom: "⏝",
	left: "(",
	right: ")",
	single_left: "(",
	single_right: ")",
	angled_up_right: "⎛",
	angled_up_left: "⎞",
	angled_down_right: "⎝",
	angled_down_left: "⎠",
};

#[must_use]
pub fn generate(message: &str, format_opts: &FormatOptions) -> String {
	let think = format_opts.think;
	let width = format_opts.width;

	let chars = if think { &THINK_CHARS } else { &SAY_CHARS };
	let mut lines = wrap(message, width as usize);
	let longest = lines.iter().map(|line| line.width()).max().unwrap();

	format!(
		"
  {}
{}
  {}
  {}
    {}",
		chars.top.repeat(longest),
		if lines.len() == 1 {
			format!("{} {} {}", chars.single_left, lines[0], chars.single_right)
		} else {
			let mut result = format!(
				"{} {}{}{}",
				chars.angled_up_right,
				lines[0],
				" ".repeat(longest - lines[0].width() + 1),
				chars.angled_up_left
			);
			lines.remove(0);
			let last = lines.pop().unwrap();

			for line in lines {
				result = format!(
					"{}\n{} {}{}{}",
					result,
					chars.left,
					line,
					" ".repeat(longest - line.width() + 1),
					chars.right,
				);
			}

			format!(
				"{}\n{} {}{}{}",
				result,
				chars.angled_down_right,
				last,
				" ".repeat(longest - last.width() + 1),
				chars.angled_down_left,
			)
		},
		chars.bottom.repeat(longest),
		chars.arrow,
		chars.arrow,
	)
}