1pub trait BufWrite {
4 fn write_buf(&self, buf: &mut Vec<u8>);
5}
6
7#[derive(Default, Debug)]
8#[must_use = "this struct does nothing unless you call write_buf"]
9pub struct ClearScreen;
10
11impl BufWrite for ClearScreen {
12 fn write_buf(&self, buf: &mut Vec<u8>) {
13 buf.extend_from_slice(b"\x1b[H\x1b[J");
14 }
15}
16
17#[derive(Default, Debug)]
18#[must_use = "this struct does nothing unless you call write_buf"]
19pub struct ClearRowForward;
20
21impl BufWrite for ClearRowForward {
22 fn write_buf(&self, buf: &mut Vec<u8>) {
23 buf.extend_from_slice(b"\x1b[K");
24 }
25}
26
27#[derive(Default, Debug)]
28#[must_use = "this struct does nothing unless you call write_buf"]
29pub struct Crlf;
30
31impl BufWrite for Crlf {
32 fn write_buf(&self, buf: &mut Vec<u8>) {
33 buf.extend_from_slice(b"\r\n");
34 }
35}
36
37#[derive(Default, Debug)]
38#[must_use = "this struct does nothing unless you call write_buf"]
39pub struct Backspace;
40
41impl BufWrite for Backspace {
42 fn write_buf(&self, buf: &mut Vec<u8>) {
43 buf.extend_from_slice(b"\x08");
44 }
45}
46
47#[derive(Default, Debug)]
48#[must_use = "this struct does nothing unless you call write_buf"]
49pub struct SaveCursor;
50
51impl BufWrite for SaveCursor {
52 fn write_buf(&self, buf: &mut Vec<u8>) {
53 buf.extend_from_slice(b"\x1b7");
54 }
55}
56
57#[derive(Default, Debug)]
58#[must_use = "this struct does nothing unless you call write_buf"]
59pub struct RestoreCursor;
60
61impl BufWrite for RestoreCursor {
62 fn write_buf(&self, buf: &mut Vec<u8>) {
63 buf.extend_from_slice(b"\x1b8");
64 }
65}
66
67#[derive(Default, Debug)]
68#[must_use = "this struct does nothing unless you call write_buf"]
69pub struct MoveTo {
70 row: u16,
71 col: u16,
72}
73
74impl MoveTo {
75 pub fn new(pos: crate::grid::Pos) -> Self {
76 Self {
77 row: pos.row,
78 col: pos.col,
79 }
80 }
81}
82
83impl BufWrite for MoveTo {
84 fn write_buf(&self, buf: &mut Vec<u8>) {
85 if self.row == 0 && self.col == 0 {
86 buf.extend_from_slice(b"\x1b[H");
87 } else {
88 buf.extend_from_slice(b"\x1b[");
89 extend_itoa(buf, self.row + 1);
90 buf.push(b';');
91 extend_itoa(buf, self.col + 1);
92 buf.push(b'H');
93 }
94 }
95}
96
97#[derive(Default, Debug)]
98#[must_use = "this struct does nothing unless you call write_buf"]
99pub struct ClearAttrs;
100
101impl BufWrite for ClearAttrs {
102 fn write_buf(&self, buf: &mut Vec<u8>) {
103 buf.extend_from_slice(b"\x1b[m");
104 }
105}
106
107#[derive(Default, Debug)]
108#[must_use = "this struct does nothing unless you call write_buf"]
109pub struct Attrs {
110 fgcolor: Option<crate::attrs::Color>,
111 bgcolor: Option<crate::attrs::Color>,
112 bold: Option<bool>,
113 italic: Option<bool>,
114 underline: Option<bool>,
115 inverse: Option<bool>,
116}
117
118impl Attrs {
119 pub fn fgcolor(mut self, fgcolor: crate::attrs::Color) -> Self {
120 self.fgcolor = Some(fgcolor);
121 self
122 }
123
124 pub fn bgcolor(mut self, bgcolor: crate::attrs::Color) -> Self {
125 self.bgcolor = Some(bgcolor);
126 self
127 }
128
129 pub fn bold(mut self, bold: bool) -> Self {
130 self.bold = Some(bold);
131 self
132 }
133
134 pub fn italic(mut self, italic: bool) -> Self {
135 self.italic = Some(italic);
136 self
137 }
138
139 pub fn underline(mut self, underline: bool) -> Self {
140 self.underline = Some(underline);
141 self
142 }
143
144 pub fn inverse(mut self, inverse: bool) -> Self {
145 self.inverse = Some(inverse);
146 self
147 }
148}
149
150impl BufWrite for Attrs {
151 #[allow(unused_assignments)]
152 #[allow(clippy::branches_sharing_code)]
153 fn write_buf(&self, buf: &mut Vec<u8>) {
154 if self.fgcolor.is_none()
155 && self.bgcolor.is_none()
156 && self.bold.is_none()
157 && self.italic.is_none()
158 && self.underline.is_none()
159 && self.inverse.is_none()
160 {
161 return;
162 }
163
164 buf.extend_from_slice(b"\x1b[");
165 let mut first = true;
166
167 macro_rules! write_param {
168 ($i:expr) => {
169 if first {
170 first = false;
171 } else {
172 buf.push(b';');
173 }
174 extend_itoa(buf, $i);
175 };
176 }
177
178 if let Some(fgcolor) = self.fgcolor {
179 match fgcolor {
180 crate::attrs::Color::Default => {
181 write_param!(39);
182 }
183 crate::attrs::Color::Idx(i) => {
184 if i < 8 {
185 write_param!(i + 30);
186 } else if i < 16 {
187 write_param!(i + 82);
188 } else {
189 write_param!(38);
190 write_param!(5);
191 write_param!(i);
192 }
193 }
194 crate::attrs::Color::Rgb(r, g, b) => {
195 write_param!(38);
196 write_param!(2);
197 write_param!(r);
198 write_param!(g);
199 write_param!(b);
200 }
201 }
202 }
203
204 if let Some(bgcolor) = self.bgcolor {
205 match bgcolor {
206 crate::attrs::Color::Default => {
207 write_param!(49);
208 }
209 crate::attrs::Color::Idx(i) => {
210 if i < 8 {
211 write_param!(i + 40);
212 } else if i < 16 {
213 write_param!(i + 92);
214 } else {
215 write_param!(48);
216 write_param!(5);
217 write_param!(i);
218 }
219 }
220 crate::attrs::Color::Rgb(r, g, b) => {
221 write_param!(48);
222 write_param!(2);
223 write_param!(r);
224 write_param!(g);
225 write_param!(b);
226 }
227 }
228 }
229
230 if let Some(bold) = self.bold {
231 if bold {
232 write_param!(1);
233 } else {
234 write_param!(22);
235 }
236 }
237
238 if let Some(italic) = self.italic {
239 if italic {
240 write_param!(3);
241 } else {
242 write_param!(23);
243 }
244 }
245
246 if let Some(underline) = self.underline {
247 if underline {
248 write_param!(4);
249 } else {
250 write_param!(24);
251 }
252 }
253
254 if let Some(inverse) = self.inverse {
255 if inverse {
256 write_param!(7);
257 } else {
258 write_param!(27);
259 }
260 }
261
262 buf.push(b'm');
263 }
264}
265
266#[derive(Debug)]
267#[must_use = "this struct does nothing unless you call write_buf"]
268pub struct MoveRight {
269 count: u16,
270}
271
272impl MoveRight {
273 pub fn new(count: u16) -> Self {
274 Self { count }
275 }
276}
277
278impl Default for MoveRight {
279 fn default() -> Self {
280 Self { count: 1 }
281 }
282}
283
284impl BufWrite for MoveRight {
285 fn write_buf(&self, buf: &mut Vec<u8>) {
286 match self.count {
287 0 => {}
288 1 => buf.extend_from_slice(b"\x1b[C"),
289 n => {
290 buf.extend_from_slice(b"\x1b[");
291 extend_itoa(buf, n);
292 buf.push(b'C');
293 }
294 }
295 }
296}
297
298#[derive(Debug)]
299#[must_use = "this struct does nothing unless you call write_buf"]
300pub struct EraseChar {
301 count: u16,
302}
303
304impl EraseChar {
305 pub fn new(count: u16) -> Self {
306 Self { count }
307 }
308}
309
310impl Default for EraseChar {
311 fn default() -> Self {
312 Self { count: 1 }
313 }
314}
315
316impl BufWrite for EraseChar {
317 fn write_buf(&self, buf: &mut Vec<u8>) {
318 match self.count {
319 0 => {}
320 1 => buf.extend_from_slice(b"\x1b[X"),
321 n => {
322 buf.extend_from_slice(b"\x1b[");
323 extend_itoa(buf, n);
324 buf.push(b'X');
325 }
326 }
327 }
328}
329
330#[derive(Default, Debug)]
331#[must_use = "this struct does nothing unless you call write_buf"]
332pub struct HideCursor {
333 state: bool,
334}
335
336impl HideCursor {
337 pub fn new(state: bool) -> Self {
338 Self { state }
339 }
340}
341
342impl BufWrite for HideCursor {
343 fn write_buf(&self, buf: &mut Vec<u8>) {
344 if self.state {
345 buf.extend_from_slice(b"\x1b[?25l");
346 } else {
347 buf.extend_from_slice(b"\x1b[?25h");
348 }
349 }
350}
351
352#[derive(Debug)]
353#[must_use = "this struct does nothing unless you call write_buf"]
354pub struct MoveFromTo {
355 from: crate::grid::Pos,
356 to: crate::grid::Pos,
357}
358
359impl MoveFromTo {
360 pub fn new(from: crate::grid::Pos, to: crate::grid::Pos) -> Self {
361 Self { from, to }
362 }
363}
364
365impl BufWrite for MoveFromTo {
366 fn write_buf(&self, buf: &mut Vec<u8>) {
367 if self.to.row == self.from.row + 1 && self.to.col == 0 {
368 crate::term::Crlf::default().write_buf(buf);
369 } else if self.from.row == self.to.row && self.from.col < self.to.col
370 {
371 crate::term::MoveRight::new(self.to.col - self.from.col)
372 .write_buf(buf);
373 } else if self.to != self.from {
374 crate::term::MoveTo::new(self.to).write_buf(buf);
375 }
376 }
377}
378
379#[derive(Default, Debug)]
380#[must_use = "this struct does nothing unless you call write_buf"]
381pub struct AudibleBell;
382
383impl BufWrite for AudibleBell {
384 fn write_buf(&self, buf: &mut Vec<u8>) {
385 buf.push(b'\x07');
386 }
387}
388
389#[derive(Default, Debug)]
390#[must_use = "this struct does nothing unless you call write_buf"]
391pub struct VisualBell;
392
393impl BufWrite for VisualBell {
394 fn write_buf(&self, buf: &mut Vec<u8>) {
395 buf.extend_from_slice(b"\x1bg");
396 }
397}
398
399#[must_use = "this struct does nothing unless you call write_buf"]
400pub struct ChangeTitle<'a> {
401 icon_name: &'a str,
402 title: &'a str,
403 prev_icon_name: &'a str,
404 prev_title: &'a str,
405}
406
407impl<'a> ChangeTitle<'a> {
408 pub fn new(
409 icon_name: &'a str,
410 title: &'a str,
411 prev_icon_name: &'a str,
412 prev_title: &'a str,
413 ) -> Self {
414 Self {
415 icon_name,
416 title,
417 prev_icon_name,
418 prev_title,
419 }
420 }
421}
422
423impl<'a> BufWrite for ChangeTitle<'a> {
424 fn write_buf(&self, buf: &mut Vec<u8>) {
425 if self.icon_name == self.title
426 && (self.icon_name != self.prev_icon_name
427 || self.title != self.prev_title)
428 {
429 buf.extend_from_slice(b"\x1b]0;");
430 buf.extend_from_slice(self.icon_name.as_bytes());
431 buf.push(b'\x07');
432 } else {
433 if self.icon_name != self.prev_icon_name {
434 buf.extend_from_slice(b"\x1b]1;");
435 buf.extend_from_slice(self.icon_name.as_bytes());
436 buf.push(b'\x07');
437 }
438 if self.title != self.prev_title {
439 buf.extend_from_slice(b"\x1b]2;");
440 buf.extend_from_slice(self.title.as_bytes());
441 buf.push(b'\x07');
442 }
443 }
444 }
445}
446
447#[derive(Default, Debug)]
448#[must_use = "this struct does nothing unless you call write_buf"]
449pub struct ApplicationKeypad {
450 state: bool,
451}
452
453impl ApplicationKeypad {
454 pub fn new(state: bool) -> Self {
455 Self { state }
456 }
457}
458
459impl BufWrite for ApplicationKeypad {
460 fn write_buf(&self, buf: &mut Vec<u8>) {
461 if self.state {
462 buf.extend_from_slice(b"\x1b=");
463 } else {
464 buf.extend_from_slice(b"\x1b>");
465 }
466 }
467}
468
469#[derive(Default, Debug)]
470#[must_use = "this struct does nothing unless you call write_buf"]
471pub struct ApplicationCursor {
472 state: bool,
473}
474
475impl ApplicationCursor {
476 pub fn new(state: bool) -> Self {
477 Self { state }
478 }
479}
480
481impl BufWrite for ApplicationCursor {
482 fn write_buf(&self, buf: &mut Vec<u8>) {
483 if self.state {
484 buf.extend_from_slice(b"\x1b[?1h");
485 } else {
486 buf.extend_from_slice(b"\x1b[?1l");
487 }
488 }
489}
490
491#[derive(Default, Debug)]
492#[must_use = "this struct does nothing unless you call write_buf"]
493pub struct BracketedPaste {
494 state: bool,
495}
496
497impl BracketedPaste {
498 pub fn new(state: bool) -> Self {
499 Self { state }
500 }
501}
502
503impl BufWrite for BracketedPaste {
504 fn write_buf(&self, buf: &mut Vec<u8>) {
505 if self.state {
506 buf.extend_from_slice(b"\x1b[?2004h");
507 } else {
508 buf.extend_from_slice(b"\x1b[?2004l");
509 }
510 }
511}
512
513#[derive(Default, Debug)]
514#[must_use = "this struct does nothing unless you call write_buf"]
515pub struct MouseProtocolMode {
516 mode: crate::screen::MouseProtocolMode,
517 prev: crate::screen::MouseProtocolMode,
518}
519
520impl MouseProtocolMode {
521 pub fn new(
522 mode: crate::screen::MouseProtocolMode,
523 prev: crate::screen::MouseProtocolMode,
524 ) -> Self {
525 Self { mode, prev }
526 }
527}
528
529impl BufWrite for MouseProtocolMode {
530 fn write_buf(&self, buf: &mut Vec<u8>) {
531 if self.mode == self.prev {
532 return;
533 }
534
535 match self.mode {
536 crate::screen::MouseProtocolMode::None => match self.prev {
537 crate::screen::MouseProtocolMode::None => {}
538 crate::screen::MouseProtocolMode::Press => {
539 buf.extend_from_slice(b"\x1b[?9l");
540 }
541 crate::screen::MouseProtocolMode::PressRelease => {
542 buf.extend_from_slice(b"\x1b[?1000l");
543 }
544 crate::screen::MouseProtocolMode::ButtonMotion => {
545 buf.extend_from_slice(b"\x1b[?1002l");
546 }
547 crate::screen::MouseProtocolMode::AnyMotion => {
548 buf.extend_from_slice(b"\x1b[?1003l");
549 }
550 },
551 crate::screen::MouseProtocolMode::Press => {
552 buf.extend_from_slice(b"\x1b[?9h");
553 }
554 crate::screen::MouseProtocolMode::PressRelease => {
555 buf.extend_from_slice(b"\x1b[?1000h");
556 }
557 crate::screen::MouseProtocolMode::ButtonMotion => {
558 buf.extend_from_slice(b"\x1b[?1002h");
559 }
560 crate::screen::MouseProtocolMode::AnyMotion => {
561 buf.extend_from_slice(b"\x1b[?1003h");
562 }
563 }
564 }
565}
566
567#[derive(Default, Debug)]
568#[must_use = "this struct does nothing unless you call write_buf"]
569pub struct MouseProtocolEncoding {
570 encoding: crate::screen::MouseProtocolEncoding,
571 prev: crate::screen::MouseProtocolEncoding,
572}
573
574impl MouseProtocolEncoding {
575 pub fn new(
576 encoding: crate::screen::MouseProtocolEncoding,
577 prev: crate::screen::MouseProtocolEncoding,
578 ) -> Self {
579 Self { encoding, prev }
580 }
581}
582
583impl BufWrite for MouseProtocolEncoding {
584 fn write_buf(&self, buf: &mut Vec<u8>) {
585 if self.encoding == self.prev {
586 return;
587 }
588
589 match self.encoding {
590 crate::screen::MouseProtocolEncoding::Default => {
591 match self.prev {
592 crate::screen::MouseProtocolEncoding::Default => {}
593 crate::screen::MouseProtocolEncoding::Utf8 => {
594 buf.extend_from_slice(b"\x1b[?1005l");
595 }
596 crate::screen::MouseProtocolEncoding::Sgr => {
597 buf.extend_from_slice(b"\x1b[?1006l");
598 }
599 }
600 }
601 crate::screen::MouseProtocolEncoding::Utf8 => {
602 buf.extend_from_slice(b"\x1b[?1005h");
603 }
604 crate::screen::MouseProtocolEncoding::Sgr => {
605 buf.extend_from_slice(b"\x1b[?1006h");
606 }
607 }
608 }
609}
610
611fn extend_itoa<I: itoa::Integer>(buf: &mut Vec<u8>, i: I) {
612 let mut itoa_buf = itoa::Buffer::new();
613 buf.extend_from_slice(itoa_buf.format(i).as_bytes());
614}