Skip to content

Commit b16f75b

Browse files
authored
Clippy now supports multiline and long text ##visual
1 parent 666adf5 commit b16f75b

File tree

2 files changed

+262
-143
lines changed

2 files changed

+262
-143
lines changed

libr/core/clippy.inc.c

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
typedef struct {
2+
const char *name;
3+
int w;
4+
int h;
5+
int count;
6+
const char *lines[];
7+
} Avatar;
8+
9+
static Avatar avatar_orangg = {
10+
.name = "orangg",
11+
.w = 19,
12+
.h = 9,
13+
.count = 1,
14+
.lines = {
15+
" _______ ",
16+
" / \\ ",
17+
" _| ( o) (o)\\_ ",
18+
" / _ .\\. | \\ ",
19+
" \\| \\ ____ / 7` ",
20+
" '|\\| `---'/ ",
21+
" | /----. \\ ",
22+
" | \\___/ |___ ",
23+
" `-----'`-----'"
24+
}
25+
};
26+
27+
static Avatar avatar_croco = {
28+
.name = "croco",
29+
.w = 16,
30+
.h = 6,
31+
.count = 2,
32+
.lines = {
33+
" __ __ ",
34+
"(o |_| o)_____ ",
35+
"| ___________) ",
36+
"\\ / ",
37+
" \\ / ",
38+
" \\________/ ",
39+
" __ __ ",
40+
"( o|_|o )_____ ",
41+
"| .___________) ",
42+
"\\ `___' / ",
43+
" \\ / ",
44+
" \\________/ "
45+
}
46+
};
47+
48+
static Avatar avatar_cybcat = {
49+
.name = "cybercat",
50+
.w = 19,
51+
.h = 5,
52+
.count = 3,
53+
.lines = {
54+
" /\\.---./\\ ",
55+
" '-- --' ",
56+
"---- ^ ^ ----",
57+
" _.- Y -._ ",
58+
" ",
59+
" /\\.---./\\ ",
60+
" '-- @ @ --' ",
61+
"---- Y ----",
62+
" _.- O -._ ",
63+
" ",
64+
" /\\.---./\\ ",
65+
" '-- = = --' ",
66+
"---- Y ----",
67+
" _.- U -._ ",
68+
" "
69+
}
70+
};
71+
72+
static Avatar avatar_clippy_utf8 = {
73+
.name = "clippy",
74+
.w = 7,
75+
.h = 7,
76+
.count = 3,
77+
.lines = {
78+
" ╭──╮ ",
79+
" │ _│ ",
80+
" │ O O ",
81+
" │ │╭ ",
82+
" ││ ││ ",
83+
" │└─┘│ ",
84+
" ╰───╯ ",
85+
" ╭──╮ ",
86+
" │ ╶│╶ ",
87+
" │ O o ",
88+
" │ │ ╱",
89+
" │ ╭┘ ╱ ",
90+
" │ ╰ ╱ ",
91+
" ╰──' ",
92+
" ╭──╮ ",
93+
" │ _│_ ",
94+
" │ O O ",
95+
" │ │╷ ",
96+
" │ ││ ",
97+
" │ ─╯│ ",
98+
" ╰───╯ "
99+
}
100+
};
101+
102+
static Avatar avatar_clippy = {
103+
.name = "clippy",
104+
.w = 8,
105+
.h = 7,
106+
.count = 3,
107+
.lines = {
108+
" .--. ",
109+
" | _| ",
110+
" | O O ",
111+
" | | |",
112+
" || | / ",
113+
" |`-'| ",
114+
" `---' ",
115+
" .--. ",
116+
" | \\ ",
117+
" | O o ",
118+
" | | /",
119+
" | ( / ",
120+
" | / ",
121+
" `--' ",
122+
" .--. ",
123+
" | _|_ ",
124+
" | O O ",
125+
" | || ",
126+
" | _:| ",
127+
" | | ",
128+
" `---' "
129+
}
130+
};
131+
132+
enum {
133+
R_AVATAR_ORANGG,
134+
R_AVATAR_CYBCAT,
135+
R_AVATAR_CROCO,
136+
R_AVATAR_CLIPPY,
137+
};
138+
139+
R_API void r_core_clippy(RCore *core, const char *msg) {
140+
int type = R_AVATAR_CLIPPY;
141+
switch (*msg) {
142+
case '+':
143+
case '3':
144+
case 'C':
145+
{
146+
const char *space = strchr (msg, ' ');
147+
if (!space) {
148+
space = msg;
149+
}
150+
type = (*msg == '+')? R_AVATAR_ORANGG: (*msg == 'C')? R_AVATAR_CROCO: R_AVATAR_CYBCAT;
151+
msg = space + 1;
152+
}
153+
break;
154+
}
155+
156+
int w = r_cons_get_size (core->cons, NULL);
157+
158+
int i;
159+
Avatar *avatar;
160+
const bool utf8 = r_config_get_b (core->config, "scr.utf8");
161+
162+
switch (type) {
163+
case R_AVATAR_ORANGG:
164+
avatar = &avatar_orangg;
165+
break;
166+
case R_AVATAR_CROCO:
167+
avatar = &avatar_croco;
168+
break;
169+
case R_AVATAR_CYBCAT:
170+
avatar = &avatar_cybcat;
171+
break;
172+
default:
173+
avatar = utf8? &avatar_clippy_utf8 : &avatar_clippy;
174+
break;
175+
}
176+
int baseline = 0;
177+
if (avatar->count > 1) {
178+
baseline += r_num_rand (avatar->count) * avatar->h;
179+
}
180+
int margin_right = avatar->w * 4;
181+
char *m = r_str_wrap (msg, w - margin_right - 1);
182+
RList *lines = r_str_split_list (m, "\n", 0);
183+
const int lines_length = r_list_length (lines);
184+
int bubble_w;
185+
if (lines_length == 1) {
186+
bubble_w = strlen (m);
187+
} else {
188+
bubble_w = (w < margin_right) ? 10: w - margin_right;
189+
}
190+
int rows = R_MAX (lines_length + 4, avatar->h);
191+
for (i = 0; i < rows; i++) {
192+
// draw clippy
193+
if (i < avatar->h) {
194+
const char *avatar_line = avatar->lines[baseline + i];
195+
r_cons_printf (core->cons, "%s ", avatar_line);
196+
} else {
197+
r_cons_printf (core->cons, r_str_pad (' ', avatar->w + 1));
198+
}
199+
// draw bubble
200+
const char *bubble_begin = "";
201+
const char *bubble_end = "";
202+
if (i == 0) {
203+
if (utf8) {
204+
bubble_begin = " ╭─";
205+
bubble_end = "─╮";
206+
} else {
207+
bubble_begin = " .-";
208+
bubble_end = "-. ";
209+
}
210+
} else if (i == 2) {
211+
bubble_begin = "< ";
212+
if (utf8) {
213+
bubble_end = " │ ";
214+
} else {
215+
bubble_end = " | ";
216+
}
217+
} else if (i == lines_length + 3) {
218+
if (utf8) {
219+
bubble_begin = " ╰─";
220+
bubble_end = "─╯";
221+
} else {
222+
bubble_begin = " `-";
223+
bubble_end = "-' ";
224+
}
225+
} else if (i < lines_length + 3) {
226+
if (utf8) {
227+
bubble_begin = " │ ";
228+
bubble_end = " │ ";
229+
} else {
230+
bubble_begin = " | ";
231+
bubble_end = " | ";
232+
}
233+
}
234+
r_cons_print (core->cons, bubble_begin);
235+
// print text
236+
if (i > 1 && i < lines_length + 2) {
237+
RListIter *line = r_list_get_nth (lines, i - 2);
238+
if (line) {
239+
r_cons_printf (core->cons, "%s", line->data);
240+
const int tw = strlen (line->data);
241+
r_cons_printf (core->cons, r_str_pad (' ', bubble_w - tw));
242+
}
243+
} else {
244+
if (i == 0 || i == lines_length + 3) {
245+
// pad with lines
246+
if (utf8) {
247+
int j;
248+
for (j = 0; j < bubble_w; j++) {
249+
r_cons_printf (core->cons, "─");
250+
}
251+
} else {
252+
r_cons_printf (core->cons, r_str_pad ('-', bubble_w));
253+
}
254+
} else {
255+
r_cons_printf (core->cons, r_str_pad (' ', bubble_w));
256+
}
257+
}
258+
// print bubble_end
259+
r_cons_println (core->cons, bubble_end);
260+
}
261+
}

0 commit comments

Comments
 (0)