1use std::borrow::Cow;
2
3use ratatui_core::{
4 buffer::Buffer,
5 layout::Rect,
6 style::{Color, Modifier, Style},
7 widgets::Widget,
8};
9use ratatui_widgets::{block::Block, clear::Clear};
10
11use crate::state;
12
13pub trait Screen {
24 type C: Cell;
26
27 fn cell(&self, row: u16, col: u16) -> Option<&Self::C>;
31 fn hide_cursor(&self) -> bool;
33 fn cursor_position(&self) -> (u16, u16);
44
45 fn cursor_shape(&self) -> CursorShape {
51 CursorShape::Default
52 }
53}
54
55pub trait Cell {
57 fn has_contents(&self) -> bool;
59 fn apply(&self, cell: &mut ratatui_core::buffer::Cell);
61}
62
63#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
65#[non_exhaustive]
66pub enum CursorShape {
67 #[default]
69 Default,
70 BlinkingBlock,
72 SteadyBlock,
74 BlinkingUnderline,
76 SteadyUnderline,
78 BlinkingBar,
80 SteadyBar,
82}
83
84#[non_exhaustive]
114pub struct PseudoTerminal<'a, S> {
115 screen: &'a S,
116 pub(crate) block: Option<Block<'a>>,
117 style: Option<Style>,
118 pub(crate) cursor: Cursor,
119}
120
121#[non_exhaustive]
122pub struct Cursor {
123 pub(crate) show: bool,
124 pub(crate) symbol: Cow<'static, str>,
125 pub(crate) style: Style,
126 pub(crate) overlay_style: Style,
127}
128
129impl Cursor {
130 #[inline]
145 #[must_use]
146 pub fn symbol(mut self, symbol: impl Into<Cow<'static, str>>) -> Self {
147 self.symbol = symbol.into();
148 self
149 }
150
151 #[inline]
166 #[must_use]
167 pub const fn style(mut self, style: Style) -> Self {
168 self.style = style;
169 self
170 }
171
172 #[inline]
189 #[must_use]
190 pub const fn overlay_style(mut self, overlay_style: Style) -> Self {
191 self.overlay_style = overlay_style;
192 self
193 }
194
195 #[inline]
197 #[must_use]
198 pub const fn visibility(mut self, show: bool) -> Self {
199 self.show = show;
200 self
201 }
202
203 #[inline]
205 pub fn show(&mut self) {
206 self.show = true;
207 }
208
209 #[inline]
211 pub fn hide(&mut self) {
212 self.show = false;
213 }
214}
215
216impl Default for Cursor {
217 #[inline]
218 fn default() -> Self {
219 Self {
220 show: true,
221 symbol: Cow::Borrowed("\u{2588}"), style: Style::default().fg(Color::Gray),
223 overlay_style: Style::default().add_modifier(Modifier::REVERSED),
224 }
225 }
226}
227
228impl<'a, S: Screen> PseudoTerminal<'a, S> {
229 #[inline]
245 #[must_use]
246 pub fn new(screen: &'a S) -> Self {
247 PseudoTerminal {
248 screen,
249 block: None,
250 style: None,
251 cursor: Cursor::default(),
252 }
253 }
254
255 #[inline]
273 #[must_use]
274 pub fn block(mut self, block: Block<'a>) -> Self {
275 self.block = Some(block);
276 self
277 }
278
279 #[inline]
299 #[must_use]
300 pub fn cursor(mut self, cursor: Cursor) -> Self {
301 self.cursor = cursor;
302 self
303 }
304
305 #[inline]
322 #[must_use]
323 pub const fn style(mut self, style: Style) -> Self {
324 self.style = Some(style);
325 self
326 }
327
328 #[inline]
329 #[must_use]
330 pub const fn screen(&self) -> &S {
331 self.screen
332 }
333}
334
335impl<S: Screen> Widget for &PseudoTerminal<'_, S> {
336 #[inline]
337 fn render(self, area: Rect, buf: &mut Buffer) {
338 Clear.render(area, buf);
339 let area = self.block.as_ref().map_or(area, |b| {
340 let inner_area = b.inner(area);
341 b.clone().render(area, buf);
342 inner_area
343 });
344 state::handle(self, area, buf);
345 }
346}
347
348impl<S: Screen> Widget for PseudoTerminal<'_, S> {
349 #[inline]
350 fn render(self, area: Rect, buf: &mut Buffer) {
351 (&self).render(area, buf);
352 }
353}
354
355#[cfg(all(test, feature = "vt100"))]
356mod tests {
357 use ratatui::Terminal;
358 use ratatui_core::backend::TestBackend;
359 use ratatui_widgets::borders::Borders;
360
361 use super::*;
362
363 fn snapshot_typescript(stream: &[u8]) -> String {
364 let backend = TestBackend::new(80, 24);
365 let mut terminal = Terminal::new(backend).unwrap();
366 let mut parser = vt100::Parser::new(24, 80, 0);
367 parser.process(stream);
368 let pseudo_term = PseudoTerminal::new(parser.screen());
369 terminal
370 .draw(|f| {
371 f.render_widget(pseudo_term, f.area());
372 })
373 .unwrap();
374 format!("{:?}", terminal.backend().buffer())
375 }
376
377 #[test]
378 fn scrollback_cursor_not_rendered_when_off_screen() {
379 let backend = TestBackend::new(40, 4);
380 let mut terminal = Terminal::new(backend).unwrap();
381 let mut parser = vt100::Parser::new(4, 40, 20);
382
383 for i in 0..10 {
386 parser.process(format!("[scrollback line {i}]\r\n").as_bytes());
387 }
388 parser.screen_mut().set_scrollback(4);
389
390 let pseudo_term = PseudoTerminal::new(parser.screen());
391 terminal
392 .draw(|f| {
393 f.render_widget(pseudo_term, f.area());
394 })
395 .unwrap();
396
397 let buf = terminal.backend().buffer();
398 for row in 0..4 {
399 for col in 0..40 {
400 let cell = &buf[(col, row)];
401 assert!(
402 !cell.modifier.contains(Modifier::REVERSED),
403 "REVERSED cursor style should not appear at ({col}, {row}) \
404 when cursor is off-screen due to scrollback"
405 );
406 }
407 }
408 let view = format!("{:?}", terminal.backend().buffer());
409 insta::assert_snapshot!(view);
410 }
411
412 #[test]
413 fn scrollback_partial_cursor_visible_at_adjusted_row() {
414 let backend = TestBackend::new(40, 6);
415 let mut terminal = Terminal::new(backend).unwrap();
416 let mut parser = vt100::Parser::new(6, 40, 20);
417
418 parser.process(b"[scrollback: hidden 1]\r\n");
421 parser.process(b"[scrollback: hidden 2]\r\n");
422 parser.process(b"[scrollback: shown at row 0]\r\n");
423 parser.process(b"[draw-0: cursor row]\r\n");
424 parser.process(b"[draw-1]\r\n");
425 parser.process(b"[draw-2]\r\n");
426 parser.process(b"[draw-3]\r\n");
427 parser.process(b"[draw-4]\r\n");
428 parser.process(b"\x1b[H");
429
430 parser.screen_mut().set_scrollback(1);
433
434 let pseudo_term = PseudoTerminal::new(parser.screen());
435 terminal
436 .draw(|f| {
437 f.render_widget(pseudo_term, f.area());
438 })
439 .unwrap();
440
441 let buf = terminal.backend().buffer();
442 for col in 0..40 {
443 let cell = &buf[(col, 0)];
444 assert!(
445 !cell.modifier.contains(Modifier::REVERSED),
446 "scrollback row 0 at col {col} should not have cursor styling"
447 );
448 }
449 let cursor_cell = &buf[(0, 1)];
450 assert!(
451 cursor_cell.modifier.contains(Modifier::REVERSED),
452 "cursor should render at visible row 1 (adjusted from drawing row 0)"
453 );
454 let view = format!("{:?}", terminal.backend().buffer());
455 insta::assert_snapshot!(view);
456 }
457
458 #[test]
459 fn scrollback_hide_cursor_suppresses_rendering() {
460 let backend = TestBackend::new(40, 6);
461 let mut terminal = Terminal::new(backend).unwrap();
462 let mut parser = vt100::Parser::new(6, 40, 20);
463
464 for i in 0..8 {
465 parser.process(format!("line {i}\r\n").as_bytes());
466 }
467 parser.process(b"\x1b[H");
468 parser.process(b"\x1b[?25l");
470 parser.screen_mut().set_scrollback(1);
471
472 let pseudo_term = PseudoTerminal::new(parser.screen());
473 terminal
474 .draw(|f| {
475 f.render_widget(pseudo_term, f.area());
476 })
477 .unwrap();
478
479 let buf = terminal.backend().buffer();
480 for row in 0..6 {
481 for col in 0..40 {
482 let cell = &buf[(col, row)];
483 assert!(
484 !cell.modifier.contains(Modifier::REVERSED),
485 "hidden cursor should not style ({col}, {row}) even with scrollback"
486 );
487 }
488 }
489 }
490
491 #[test]
492 fn scrollback_cursor_with_block() {
493 let backend = TestBackend::new(42, 8);
494 let mut terminal = Terminal::new(backend).unwrap();
495 let mut parser = vt100::Parser::new(6, 40, 20);
496
497 for i in 0..8 {
498 parser.process(format!("line {i}\r\n").as_bytes());
499 }
500 parser.process(b"\x1b[H");
501 parser.screen_mut().set_scrollback(1);
502
503 let block = Block::default().borders(Borders::ALL).title("pty");
504 let pseudo_term = PseudoTerminal::new(parser.screen()).block(block);
505 terminal
506 .draw(|f| {
507 f.render_widget(pseudo_term, f.area());
508 })
509 .unwrap();
510
511 let buf = terminal.backend().buffer();
515 let scrollback_cell = &buf[(1, 1)];
516 assert!(
517 !scrollback_cell.modifier.contains(Modifier::REVERSED),
518 "scrollback row inside block should not have cursor styling"
519 );
520 let cursor_cell = &buf[(1, 2)];
521 assert!(
522 cursor_cell.modifier.contains(Modifier::REVERSED),
523 "cursor should render at inner row 1 (buf row 2) with block border"
524 );
525 }
526
527 #[test]
528 fn empty_actions() {
529 let backend = TestBackend::new(80, 24);
530 let mut terminal = Terminal::new(backend).unwrap();
531 let mut parser = vt100::Parser::new(24, 80, 0);
532 parser.process(b" ");
533 let pseudo_term = PseudoTerminal::new(parser.screen());
534 terminal
535 .draw(|f| {
536 f.render_widget(pseudo_term, f.area());
537 })
538 .unwrap();
539 let view = format!("{:?}", terminal.backend().buffer());
540 insta::assert_snapshot!(view);
541 }
542 #[test]
543 fn boundary_rows_overshot_no_panic() {
544 let stream = include_bytes!("../test/typescript/simple_ls.typescript");
545 let backend = TestBackend::new(80, 4);
547 let mut terminal = Terminal::new(backend).unwrap();
548 let mut parser = vt100::Parser::new(24, 80, 0);
549 parser.process(stream);
550 let pseudo_term = PseudoTerminal::new(parser.screen());
551 terminal
552 .draw(|f| {
553 f.render_widget(pseudo_term, f.area());
554 })
555 .unwrap();
556 let view = format!("{:?}", terminal.backend().buffer());
557 insta::assert_snapshot!(view);
558 }
559
560 struct MockShapeScreen {
561 shape: CursorShape,
562 c_row: u16,
563 c_col: u16,
564 }
565 struct MockCell;
566 impl Cell for MockCell {
567 fn has_contents(&self) -> bool {
568 false
569 }
570 fn apply(&self, _cell: &mut ratatui_core::buffer::Cell) {}
571 }
572 impl Screen for MockShapeScreen {
573 type C = MockCell;
574 fn cell(&self, _row: u16, _col: u16) -> Option<&Self::C> {
575 Some(&MockCell)
576 }
577 fn hide_cursor(&self) -> bool {
578 false
579 }
580 fn cursor_position(&self) -> (u16, u16) {
581 (self.c_row, self.c_col)
582 }
583 fn cursor_shape(&self) -> CursorShape {
584 self.shape
585 }
586 }
587
588 fn assert_cursor_shape(shape: CursorShape, expected_symbol: &str) {
589 let backend = TestBackend::new(5, 5);
590 let mut terminal = Terminal::new(backend).unwrap();
591 let screen = MockShapeScreen {
592 shape,
593 c_row: 1,
594 c_col: 1,
595 };
596 let pseudo_term = PseudoTerminal::new(&screen);
597 terminal
598 .draw(|f| {
599 f.render_widget(pseudo_term, f.area());
600 })
601 .unwrap();
602 let buf = terminal.backend().buffer();
603 assert_eq!(buf[(1, 1)].symbol(), expected_symbol);
604 }
605
606 #[test]
607 fn cursor_shape_block() {
608 assert_cursor_shape(CursorShape::BlinkingBlock, "█");
609 }
610
611 #[test]
612 fn cursor_shape_underline() {
613 assert_cursor_shape(CursorShape::BlinkingUnderline, "▁");
614 }
615
616 #[test]
617 fn cursor_shape_bar() {
618 assert_cursor_shape(CursorShape::BlinkingBar, "▏");
619 }
620
621 #[test]
622 fn simple_ls() {
623 let stream = include_bytes!("../test/typescript/simple_ls.typescript");
624 let view = snapshot_typescript(stream);
625 insta::assert_snapshot!(view);
626 }
627 #[test]
628 fn simple_cursor_alternate_symbol() {
629 let stream = include_bytes!("../test/typescript/simple_ls.typescript");
630 let backend = TestBackend::new(80, 24);
631 let mut terminal = Terminal::new(backend).unwrap();
632 let mut parser = vt100::Parser::new(24, 80, 0);
633 let cursor = Cursor::default().symbol("|");
634 parser.process(stream);
635 let pseudo_term = PseudoTerminal::new(parser.screen()).cursor(cursor);
636 terminal
637 .draw(|f| {
638 f.render_widget(pseudo_term, f.area());
639 })
640 .unwrap();
641 let view = format!("{:?}", terminal.backend().buffer());
642 insta::assert_snapshot!(view);
643 }
644 #[test]
645 fn simple_cursor_styled() {
646 let stream = include_bytes!("../test/typescript/simple_ls.typescript");
647 let backend = TestBackend::new(80, 24);
648 let mut terminal = Terminal::new(backend).unwrap();
649 let mut parser = vt100::Parser::new(24, 80, 0);
650 let style = Style::default().bg(Color::Cyan).fg(Color::LightRed);
651 let cursor = Cursor::default().symbol("|").style(style);
652 parser.process(stream);
653 let pseudo_term = PseudoTerminal::new(parser.screen()).cursor(cursor);
654 terminal
655 .draw(|f| {
656 f.render_widget(pseudo_term, f.area());
657 })
658 .unwrap();
659 let view = format!("{:?}", terminal.backend().buffer());
660 insta::assert_snapshot!(view);
661 }
662 #[test]
663 fn simple_cursor_hide() {
664 let stream = include_bytes!("../test/typescript/simple_ls.typescript");
665 let backend = TestBackend::new(80, 24);
666 let mut terminal = Terminal::new(backend).unwrap();
667 let mut parser = vt100::Parser::new(24, 80, 0);
668 let cursor = Cursor::default().visibility(false);
669 parser.process(stream);
670 let pseudo_term = PseudoTerminal::new(parser.screen()).cursor(cursor);
671 terminal
672 .draw(|f| {
673 f.render_widget(pseudo_term, f.area());
674 })
675 .unwrap();
676 let view = format!("{:?}", terminal.backend().buffer());
677 insta::assert_snapshot!(view);
678 }
679 #[test]
680 fn simple_cursor_hide_alt() {
681 let stream = include_bytes!("../test/typescript/simple_ls.typescript");
682 let backend = TestBackend::new(80, 24);
683 let mut terminal = Terminal::new(backend).unwrap();
684 let mut parser = vt100::Parser::new(24, 80, 0);
685 let mut cursor = Cursor::default();
686 cursor.hide();
687 parser.process(stream);
688 let pseudo_term = PseudoTerminal::new(parser.screen()).cursor(cursor);
689 terminal
690 .draw(|f| {
691 f.render_widget(pseudo_term, f.area());
692 })
693 .unwrap();
694 let view = format!("{:?}", terminal.backend().buffer());
695 insta::assert_snapshot!(view);
696 }
697 #[test]
698 fn overlapping_cursor() {
699 let stream = include_bytes!("../test/typescript/overlapping_cursor.typescript");
700 let view = snapshot_typescript(stream);
701 insta::assert_snapshot!(view);
702 }
703 #[test]
704 fn overlapping_cursor_alternate_style() {
705 let stream = include_bytes!("../test/typescript/overlapping_cursor.typescript");
706 let backend = TestBackend::new(80, 24);
707 let mut terminal = Terminal::new(backend).unwrap();
708 let mut parser = vt100::Parser::new(24, 80, 0);
709 let style = Style::default().bg(Color::Cyan).fg(Color::LightRed);
710 let cursor = Cursor::default().overlay_style(style);
711 parser.process(stream);
712 let pseudo_term = PseudoTerminal::new(parser.screen()).cursor(cursor);
713 terminal
714 .draw(|f| {
715 f.render_widget(pseudo_term, f.area());
716 })
717 .unwrap();
718 let view = format!("{:?}", terminal.backend().buffer());
719 insta::assert_snapshot!(view);
720 }
721 #[test]
722 fn simple_ls_with_block() {
723 let stream = include_bytes!("../test/typescript/simple_ls.typescript");
724 let backend = TestBackend::new(100, 24);
725 let mut terminal = Terminal::new(backend).unwrap();
726 let mut parser = vt100::Parser::new(24, 80, 0);
727 parser.process(stream);
728 let block = Block::default().borders(Borders::ALL).title("ls");
729 let pseudo_term = PseudoTerminal::new(parser.screen()).block(block);
730 terminal
731 .draw(|f| {
732 f.render_widget(pseudo_term, f.area());
733 })
734 .unwrap();
735 let view = format!("{:?}", terminal.backend().buffer());
736 insta::assert_snapshot!(view);
737 }
738 #[test]
739 fn simple_ls_no_style_from_block() {
740 let stream = include_bytes!("../test/typescript/simple_ls.typescript");
741 let backend = TestBackend::new(100, 24);
742 let mut terminal = Terminal::new(backend).unwrap();
743 let mut parser = vt100::Parser::new(24, 80, 0);
744 parser.process(stream);
745 let block = Block::default()
746 .borders(Borders::ALL)
747 .style(Style::default().add_modifier(Modifier::BOLD))
748 .title("ls");
749 let pseudo_term = PseudoTerminal::new(parser.screen()).block(block);
750 terminal
751 .draw(|f| {
752 f.render_widget(pseudo_term, f.area());
753 })
754 .unwrap();
755 let view = format!("{:?}", terminal.backend().buffer());
756 insta::assert_snapshot!(view);
757 }
758 #[test]
759 fn italic_text() {
760 let stream = b"[3mThis line will be displayed in italic.[0m This should have no style.";
761 let view = snapshot_typescript(stream);
762 insta::assert_snapshot!(view);
763 }
764 #[test]
765 fn underlined_text() {
766 let stream =
767 b"[4mThis line will be displayed with an underline.[0m This should have no style.";
768 let view = snapshot_typescript(stream);
769 insta::assert_snapshot!(view);
770 }
771 #[test]
772 fn bold_text() {
773 let stream = b"[1mThis line will be displayed bold.[0m This should have no style.";
774 let view = snapshot_typescript(stream);
775 insta::assert_snapshot!(view);
776 }
777 #[test]
778 fn inverse_text() {
779 let stream = b"[7mThis line will be displayed inversed.[0m This should have no style.";
780 let view = snapshot_typescript(stream);
781 insta::assert_snapshot!(view);
782 }
783 #[test]
784 fn dim_text() {
785 let stream =
786 b"\x1b[2mThis line will be displayed dim/faint.\x1b[0m This should have no style.";
787 let view = snapshot_typescript(stream);
788 insta::assert_snapshot!(view);
789 }
790 #[test]
791 fn combined_modifier_text() {
792 let stream =
793 b"[4m[3mThis line will be displayed in italic and underlined.[0m This should have no style.";
794 let view = snapshot_typescript(stream);
795 insta::assert_snapshot!(view);
796 }
797 #[test]
798 fn dim_bold_text() {
799 let stream = b"\x1b[2m\x1b[1mThis is dim and bold. Bold takes precedence.\x1b[0m Normal.";
800 let view = snapshot_typescript(stream);
801 insta::assert_snapshot!(view);
802 }
803
804 #[test]
805 fn vttest_02_01() {
806 let stream = include_bytes!("../test/typescript/vttest_02_01.typescript");
807 let view = snapshot_typescript(stream);
808 insta::assert_snapshot!(view);
809 }
810 #[test]
811 fn vttest_02_02() {
812 let stream = include_bytes!("../test/typescript/vttest_02_02.typescript");
813 let view = snapshot_typescript(stream);
814 insta::assert_snapshot!(view);
815 }
816 #[test]
817 fn vttest_02_03() {
818 let stream = include_bytes!("../test/typescript/vttest_02_03.typescript");
819 let view = snapshot_typescript(stream);
820 insta::assert_snapshot!(view);
821 }
822 #[test]
823 fn vttest_02_04() {
824 let stream = include_bytes!("../test/typescript/vttest_02_04.typescript");
825 let view = snapshot_typescript(stream);
826 insta::assert_snapshot!(view);
827 }
828 #[test]
829 fn vttest_02_05() {
830 let stream = include_bytes!("../test/typescript/vttest_02_05.typescript");
831 let view = snapshot_typescript(stream);
832 insta::assert_snapshot!(view);
833 }
834 #[test]
835 fn vttest_02_06() {
836 let stream = include_bytes!("../test/typescript/vttest_02_06.typescript");
837 let view = snapshot_typescript(stream);
838 insta::assert_snapshot!(view);
839 }
840 #[test]
841 fn vttest_02_07() {
842 let stream = include_bytes!("../test/typescript/vttest_02_07.typescript");
843 let view = snapshot_typescript(stream);
844 insta::assert_snapshot!(view);
845 }
846 #[test]
847 fn vttest_02_08() {
848 let stream = include_bytes!("../test/typescript/vttest_02_08.typescript");
849 let view = snapshot_typescript(stream);
850 insta::assert_snapshot!(view);
851 }
852 #[test]
853 fn vttest_02_09() {
854 let stream = include_bytes!("../test/typescript/vttest_02_09.typescript");
855 let view = snapshot_typescript(stream);
856 insta::assert_snapshot!(view);
857 }
858 #[test]
859 fn vttest_02_10() {
860 let stream = include_bytes!("../test/typescript/vttest_02_10.typescript");
861 let view = snapshot_typescript(stream);
862 insta::assert_snapshot!(view);
863 }
864 #[test]
865 fn vttest_02_11() {
866 let stream = include_bytes!("../test/typescript/vttest_02_11.typescript");
867 let view = snapshot_typescript(stream);
868 insta::assert_snapshot!(view);
869 }
870 #[test]
871 fn vttest_02_12() {
872 let stream = include_bytes!("../test/typescript/vttest_02_12.typescript");
873 let view = snapshot_typescript(stream);
874 insta::assert_snapshot!(view);
875 }
876 #[test]
877 fn vttest_02_13() {
878 let stream = include_bytes!("../test/typescript/vttest_02_13.typescript");
879 let view = snapshot_typescript(stream);
880 insta::assert_snapshot!(view);
881 }
882 #[test]
883 fn vttest_02_14() {
884 let stream = include_bytes!("../test/typescript/vttest_02_14.typescript");
885 let view = snapshot_typescript(stream);
886 insta::assert_snapshot!(view);
887 }
888 #[test]
889 fn vttest_02_15() {
890 let stream = include_bytes!("../test/typescript/vttest_02_15.typescript");
891 let view = snapshot_typescript(stream);
892 insta::assert_snapshot!(view);
893 }
894
895 #[test]
896 fn vttest_03_01() {
897 let stream = include_bytes!("../test/typescript/vttest_03_01.typescript");
898 let view = snapshot_typescript(stream);
899 insta::assert_snapshot!(view);
900 }
901
902 #[test]
903 fn vttest_01_01() {
904 let stream = include_bytes!("../test/typescript/vttest_01_01.typescript");
905 let view = snapshot_typescript(stream);
906 insta::assert_snapshot!(view);
907 }
908
909 #[test]
910 fn vttest_01_02() {
911 let stream = include_bytes!("../test/typescript/vttest_01_02.typescript");
912 let view = snapshot_typescript(stream);
913 insta::assert_snapshot!(view);
914 }
915
916 #[test]
917 fn vttest_01_03() {
918 let stream = include_bytes!("../test/typescript/vttest_01_03.typescript");
919 let view = snapshot_typescript(stream);
920 insta::assert_snapshot!(view);
921 }
922
923 #[test]
924 fn vttest_01_04() {
925 let stream = include_bytes!("../test/typescript/vttest_01_04.typescript");
926 let view = snapshot_typescript(stream);
927 insta::assert_snapshot!(view);
928 }
929
930 #[test]
931 fn vttest_01_05() {
932 let stream = include_bytes!("../test/typescript/vttest_01_05.typescript");
933 let view = snapshot_typescript(stream);
934 insta::assert_snapshot!(view);
935 }
936
937 #[test]
938 fn vttest_menu() {
939 let stream = include_bytes!("../test/typescript/vttest_menu.typescript");
940 let view = snapshot_typescript(stream);
941 insta::assert_snapshot!(view);
942 }
943
944 #[test]
945 fn vttest_08_01() {
946 let stream = include_bytes!("../test/typescript/vttest_08_01.typescript");
947 let view = snapshot_typescript(stream);
948 insta::assert_snapshot!(view);
949 }
950
951 #[test]
952 fn vttest_08_02() {
953 let stream = include_bytes!("../test/typescript/vttest_08_02.typescript");
954 let view = snapshot_typescript(stream);
955 insta::assert_snapshot!(view);
956 }
957
958 #[test]
959 fn vttest_08_03() {
960 let stream = include_bytes!("../test/typescript/vttest_08_03.typescript");
961 let view = snapshot_typescript(stream);
962 insta::assert_snapshot!(view);
963 }
964
965 #[test]
966 fn vttest_08_04() {
967 let stream = include_bytes!("../test/typescript/vttest_08_04.typescript");
968 let view = snapshot_typescript(stream);
969 insta::assert_snapshot!(view);
970 }
971
972 #[test]
973 fn vttest_08_05() {
974 let stream = include_bytes!("../test/typescript/vttest_08_05.typescript");
975 let view = snapshot_typescript(stream);
976 insta::assert_snapshot!(view);
977 }
978
979 #[test]
980 fn vttest_08_06() {
981 let stream = include_bytes!("../test/typescript/vttest_08_06.typescript");
982 let view = snapshot_typescript(stream);
983 insta::assert_snapshot!(view);
984 }
985
986 #[test]
987 fn vttest_08_07() {
988 let stream = include_bytes!("../test/typescript/vttest_08_07.typescript");
989 let view = snapshot_typescript(stream);
990 insta::assert_snapshot!(view);
991 }
992
993 #[test]
994 fn vttest_08_08() {
995 let stream = include_bytes!("../test/typescript/vttest_08_08.typescript");
996 let view = snapshot_typescript(stream);
997 insta::assert_snapshot!(view);
998 }
999
1000 #[test]
1001 fn vttest_08_09() {
1002 let stream = include_bytes!("../test/typescript/vttest_08_09.typescript");
1003 let view = snapshot_typescript(stream);
1004 insta::assert_snapshot!(view);
1005 }
1006
1007 #[test]
1008 fn vttest_08_10() {
1009 let stream = include_bytes!("../test/typescript/vttest_08_10.typescript");
1010 let view = snapshot_typescript(stream);
1011 insta::assert_snapshot!(view);
1012 }
1013
1014 #[test]
1015 fn vttest_08_11() {
1016 let stream = include_bytes!("../test/typescript/vttest_08_11.typescript");
1017 let view = snapshot_typescript(stream);
1018 insta::assert_snapshot!(view);
1019 }
1020
1021 #[test]
1022 fn vttest_08_12() {
1023 let stream = include_bytes!("../test/typescript/vttest_08_12.typescript");
1024 let view = snapshot_typescript(stream);
1025 insta::assert_snapshot!(view);
1026 }
1027
1028 #[test]
1029 fn vttest_08_13() {
1030 let stream = include_bytes!("../test/typescript/vttest_08_13.typescript");
1031 let view = snapshot_typescript(stream);
1032 insta::assert_snapshot!(view);
1033 }
1034
1035 #[test]
1036 fn vttest_08_14() {
1037 let stream = include_bytes!("../test/typescript/vttest_08_14.typescript");
1038 let view = snapshot_typescript(stream);
1039 insta::assert_snapshot!(view);
1040 }
1041
1042 #[test]
1043 fn vttest_11_06_02() {
1044 let stream = include_bytes!("../test/typescript/vttest_11_06_02.typescript");
1045 let view = snapshot_typescript(stream);
1046 insta::assert_snapshot!(view);
1047 }
1048
1049 #[test]
1050 fn vttest_11_06_03() {
1051 let stream = include_bytes!("../test/typescript/vttest_11_06_03.typescript");
1052 let view = snapshot_typescript(stream);
1053 insta::assert_snapshot!(view);
1054 }
1055
1056 #[test]
1057 fn vttest_11_06_04() {
1058 let stream = include_bytes!("../test/typescript/vttest_11_06_04.typescript");
1059 let view = snapshot_typescript(stream);
1060 insta::assert_snapshot!(view);
1061 }
1062
1063 #[test]
1064 fn vttest_11_06_05() {
1065 let stream = include_bytes!("../test/typescript/vttest_11_06_05.typescript");
1066 let view = snapshot_typescript(stream);
1067 insta::assert_snapshot!(view);
1068 }
1069
1070 #[test]
1071 fn vttest_09_01() {
1072 let stream = include_bytes!("../test/typescript/vttest_09_01.typescript");
1073 let view = snapshot_typescript(stream);
1074 insta::assert_snapshot!(view);
1075 }
1076
1077 #[test]
1078 fn vttest_09_02() {
1079 let stream = include_bytes!("../test/typescript/vttest_09_02.typescript");
1080 let view = snapshot_typescript(stream);
1081 insta::assert_snapshot!(view);
1082 }
1083
1084 #[test]
1085 fn vttest_09_03() {
1086 let stream = include_bytes!("../test/typescript/vttest_09_03.typescript");
1087 let view = snapshot_typescript(stream);
1088 insta::assert_snapshot!(view);
1089 }
1090
1091 #[test]
1092 fn vttest_09_04() {
1093 let stream = include_bytes!("../test/typescript/vttest_09_04.typescript");
1094 let view = snapshot_typescript(stream);
1095 insta::assert_snapshot!(view);
1096 }
1097
1098 #[test]
1099 fn vttest_09_05() {
1100 let stream = include_bytes!("../test/typescript/vttest_09_05.typescript");
1101 let view = snapshot_typescript(stream);
1102 insta::assert_snapshot!(view);
1103 }
1104
1105 #[test]
1106 fn vttest_09_06() {
1107 let stream = include_bytes!("../test/typescript/vttest_09_06.typescript");
1108 let view = snapshot_typescript(stream);
1109 insta::assert_snapshot!(view);
1110 }
1111
1112 #[test]
1113 fn vttest_09_07() {
1114 let stream = include_bytes!("../test/typescript/vttest_09_07.typescript");
1115 let view = snapshot_typescript(stream);
1116 insta::assert_snapshot!(view);
1117 }
1118
1119 #[test]
1120 fn vttest_09_08() {
1121 let stream = include_bytes!("../test/typescript/vttest_09_08.typescript");
1122 let view = snapshot_typescript(stream);
1123 insta::assert_snapshot!(view);
1124 }
1125
1126 #[test]
1127 fn vttest_09_09() {
1128 let stream = include_bytes!("../test/typescript/vttest_09_09.typescript");
1129 let view = snapshot_typescript(stream);
1130 insta::assert_snapshot!(view);
1131 }
1132
1133 #[test]
1134 fn vttest_11_05_01() {
1135 let stream = include_bytes!("../test/typescript/vttest_11_05_01.typescript");
1136 let view = snapshot_typescript(stream);
1137 insta::assert_snapshot!(view);
1138 }
1139
1140 #[test]
1141 fn vttest_11_05_02() {
1142 let stream = include_bytes!("../test/typescript/vttest_11_05_02.typescript");
1143 let view = snapshot_typescript(stream);
1144 insta::assert_snapshot!(view);
1145 }
1146
1147 #[test]
1148 fn vttest_11_05_03() {
1149 let stream = include_bytes!("../test/typescript/vttest_11_05_03.typescript");
1150 let view = snapshot_typescript(stream);
1151 insta::assert_snapshot!(view);
1152 }
1153
1154 #[test]
1155 fn vttest_11_05_04() {
1156 let stream = include_bytes!("../test/typescript/vttest_11_05_04.typescript");
1157 let view = snapshot_typescript(stream);
1158 insta::assert_snapshot!(view);
1159 }
1160
1161 #[test]
1162 fn vttest_11_05_05() {
1163 let stream = include_bytes!("../test/typescript/vttest_11_05_05.typescript");
1164 let view = snapshot_typescript(stream);
1165 insta::assert_snapshot!(view);
1166 }
1167
1168 #[test]
1169 fn vttest_11_05_06() {
1170 let stream = include_bytes!("../test/typescript/vttest_11_05_06.typescript");
1171 let view = snapshot_typescript(stream);
1172 insta::assert_snapshot!(view);
1173 }
1174
1175 #[test]
1176 fn vttest_11_05_07() {
1177 let stream = include_bytes!("../test/typescript/vttest_11_05_07.typescript");
1178 let view = snapshot_typescript(stream);
1179 insta::assert_snapshot!(view);
1180 }
1181
1182 #[test]
1183 fn vttest_11_05_08() {
1184 let stream = include_bytes!("../test/typescript/vttest_11_05_08.typescript");
1185 let view = snapshot_typescript(stream);
1186 insta::assert_snapshot!(view);
1187 }
1188
1189 #[test]
1190 fn vttest_11_05_09() {
1191 let stream = include_bytes!("../test/typescript/vttest_11_05_09.typescript");
1192 let view = snapshot_typescript(stream);
1193 insta::assert_snapshot!(view);
1194 }
1195
1196 #[test]
1197 fn vttest_11_07_02() {
1198 let stream = include_bytes!("../test/typescript/vttest_11_07_02.typescript");
1199 let view = snapshot_typescript(stream);
1200 insta::assert_snapshot!(view);
1201 }
1202}