1use core::marker::PhantomData;
4
5use crate::{
6 grid::config::{Border as GridBorder, Borders, CompactConfig, CompactMultilineConfig},
7 settings::{
8 style::{HorizontalLine, VerticalLine},
9 Border, TableOption,
10 },
11};
12
13#[cfg(feature = "std")]
14use crate::grid::config::ColoredConfig;
15
16#[cfg_attr(feature = "std", doc = "```")]
59#[cfg_attr(not(feature = "std"), doc = "```ignore")]
60#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
77pub struct Style<T, B, L, R, H, V, const HSIZE: usize, const VSIZE: usize> {
78 borders: Borders<char>,
79 horizontals: HArray<HSIZE>,
80 verticals: VArray<VSIZE>,
81 _top: PhantomData<T>,
82 _bottom: PhantomData<B>,
83 _left: PhantomData<L>,
84 _right: PhantomData<R>,
85 _horizontal: PhantomData<H>,
86 _vertical: PhantomData<V>,
87}
88
89type HLine = crate::grid::config::HorizontalLine<char>;
90type VLine = crate::grid::config::VerticalLine<char>;
91
92type HArray<const N: usize> = [(usize, HLine); N];
93type VArray<const N: usize> = [(usize, VLine); N];
94
95#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Default, Hash)]
97pub struct On;
98
99impl Style<(), (), (), (), (), (), 0, 0> {
100 pub const fn empty() -> Style<(), (), (), (), (), (), 0, 0> {
122 Style::new(Borders::empty(), [], [])
123 }
124
125 pub const fn blank() -> Style<(), (), (), (), (), On, 0, 0> {
134 Style::new(
135 create_borders(
136 HLine::empty(),
137 HLine::empty(),
138 HLine::empty(),
139 None,
140 None,
141 Some(' '),
142 ),
143 [],
144 [],
145 )
146 }
147
148 pub const fn ascii() -> Style<On, On, On, On, On, On, 0, 0> {
164 Style::new(
165 create_borders(
166 HLine::full('-', '+', '+', '+'),
167 HLine::full('-', '+', '+', '+'),
168 HLine::full('-', '+', '+', '+'),
169 Some('|'),
170 Some('|'),
171 Some('|'),
172 ),
173 [],
174 [],
175 )
176 }
177
178 pub const fn psql() -> Style<(), (), (), (), (), On, 1, 0> {
191 Style::new(
192 create_borders(
193 HLine::empty(),
194 HLine::empty(),
195 HLine::empty(),
196 None,
197 None,
198 Some('|'),
199 ),
200 [(1, HLine::new(Some('-'), Some('+'), None, None))],
201 [],
202 )
203 }
204
205 pub const fn markdown() -> Style<(), (), On, On, (), On, 1, 0> {
215 Style::new(
216 create_borders(
217 HLine::empty(),
218 HLine::empty(),
219 HLine::empty(),
220 Some('|'),
221 Some('|'),
222 Some('|'),
223 ),
224 [(1, HLine::full('-', '|', '|', '|'))],
225 [],
226 )
227 }
228
229 pub const fn modern() -> Style<On, On, On, On, On, On, 0, 0> {
245 Style::new(
246 create_borders(
247 HLine::full('─', '┬', '┌', '┐'),
248 HLine::full('─', '┴', '└', '┘'),
249 HLine::full('─', '┼', '├', '┤'),
250 Some('│'),
251 Some('│'),
252 Some('│'),
253 ),
254 [],
255 [],
256 )
257 }
258
259 pub const fn sharp() -> Style<On, On, On, On, (), On, 1, 0> {
273 Style::new(
274 create_borders(
275 HLine::full('─', '┬', '┌', '┐'),
276 HLine::full('─', '┴', '└', '┘'),
277 HLine::empty(),
278 Some('│'),
279 Some('│'),
280 Some('│'),
281 ),
282 [(1, HLine::full('─', '┼', '├', '┤'))],
283 [],
284 )
285 }
286
287 pub const fn rounded() -> Style<On, On, On, On, (), On, 1, 0> {
301 Style::new(
302 create_borders(
303 HLine::full('─', '┬', '╭', '╮'),
304 HLine::full('─', '┴', '╰', '╯'),
305 HLine::empty(),
306 Some('│'),
307 Some('│'),
308 Some('│'),
309 ),
310 [(1, HLine::full('─', '┼', '├', '┤'))],
311 [],
312 )
313 }
314
315 pub const fn modern_rounded() -> Style<On, On, On, On, On, On, 0, 0> {
331 Style::new(
332 create_borders(
333 HLine::full('─', '┬', '╭', '╮'),
334 HLine::full('─', '┴', '╰', '╯'),
335 HLine::full('─', '┼', '├', '┤'),
336 Some('│'),
337 Some('│'),
338 Some('│'),
339 ),
340 [],
341 [],
342 )
343 }
344
345 pub const fn extended() -> Style<On, On, On, On, On, On, 0, 0> {
361 Style::new(
362 create_borders(
363 HLine::full('═', '╦', '╔', '╗'),
364 HLine::full('═', '╩', '╚', '╝'),
365 HLine::full('═', '╬', '╠', '╣'),
366 Some('║'),
367 Some('║'),
368 Some('║'),
369 ),
370 [],
371 [],
372 )
373 }
374
375 pub const fn dots() -> Style<On, On, On, On, On, On, 0, 0> {
390 Style::new(
391 create_borders(
392 HLine::full('.', '.', '.', '.'),
393 HLine::full('.', ':', ':', ':'),
394 HLine::full('.', ':', ':', ':'),
395 Some(':'),
396 Some(':'),
397 Some(':'),
398 ),
399 [],
400 [],
401 )
402 }
403
404 pub const fn re_structured_text() -> Style<On, On, (), (), (), On, 1, 0> {
416 Style::new(
417 create_borders(
418 HLine::new(Some('='), Some(' '), None, None),
419 HLine::new(Some('='), Some(' '), None, None),
420 HLine::empty(),
421 None,
422 None,
423 Some(' '),
424 ),
425 [(1, HLine::new(Some('='), Some(' '), None, None))],
426 [],
427 )
428 }
429
430 pub const fn ascii_rounded() -> Style<On, On, On, On, (), On, 0, 0> {
442 Style::new(
443 create_borders(
444 HLine::full('-', '-', '.', '.'),
445 HLine::full('-', '-', '\'', '\''),
446 HLine::empty(),
447 Some('|'),
448 Some('|'),
449 Some('|'),
450 ),
451 [],
452 [],
453 )
454 }
455}
456
457impl<T, B, L, R, H, V, const HSIZE: usize, const VSIZE: usize>
458 Style<T, B, L, R, H, V, HSIZE, VSIZE>
459{
460 pub(crate) const fn new(
461 borders: Borders<char>,
462 horizontals: HArray<HSIZE>,
463 verticals: VArray<VSIZE>,
464 ) -> Self {
465 Self {
466 borders,
467 horizontals,
468 verticals,
469 _top: PhantomData,
470 _bottom: PhantomData,
471 _left: PhantomData,
472 _right: PhantomData,
473 _horizontal: PhantomData,
474 _vertical: PhantomData,
475 }
476 }
477
478 pub(crate) const fn get_borders(&self) -> Borders<char> {
479 self.borders
480 }
481
482 #[cfg(feature = "std")]
483 pub(crate) const fn get_horizontals(&self) -> [(usize, HLine); HSIZE] {
484 self.horizontals
485 }
486}
487
488impl<T, B, L, R, H, V, const HN: usize, const VN: usize> Style<T, B, L, R, H, V, HN, VN> {
489 #[cfg_attr(feature = "derive", doc = "```")]
494 #[cfg_attr(not(feature = "derive"), doc = "```ignore")]
495 pub const fn horizontals<const SIZE: usize>(
524 self,
525 list: [(usize, HorizontalLine<L, R, V>); SIZE],
526 ) -> Style<T, B, L, R, H, V, SIZE, VN> {
527 let list = harr_convert(list);
528 Style::new(self.borders, list, self.verticals)
529 }
530
531 #[cfg_attr(feature = "derive", doc = "```")]
536 #[cfg_attr(not(feature = "derive"), doc = "```ignore")]
537 pub const fn verticals<const SIZE: usize>(
562 self,
563 list: [(usize, VerticalLine<T, B, H>); SIZE],
564 ) -> Style<T, B, L, R, H, V, HN, SIZE> {
565 let list = varr_convert(list);
566 Style::new(self.borders, self.horizontals, list)
567 }
568
569 pub const fn remove_horizontals(self) -> Style<T, B, L, R, H, V, 0, VN> {
571 Style::new(self.borders, [], self.verticals)
572 }
573
574 pub const fn remove_verticals(self) -> Style<T, B, L, R, H, V, HN, 0> {
576 Style::new(self.borders, self.horizontals, [])
577 }
578
579 pub const fn top(mut self, c: char) -> Style<On, B, L, R, H, V, HN, VN>
583 where
584 T: Copy,
585 B: Copy,
586 H: Copy,
587 {
588 self.borders.top = Some(c);
589
590 if self.borders.has_left() {
591 self.borders.top_left = Some(c);
592 }
593
594 if self.borders.has_right() {
595 self.borders.top_right = Some(c);
596 }
597
598 if self.borders.has_vertical() {
599 self.borders.top_intersection = Some(c);
600 }
601
602 let verticals = varr_set(self.verticals, VLine::new(None, None, Some(c), None));
603
604 Style::new(self.borders, self.horizontals, verticals)
605 }
606
607 pub const fn bottom(mut self, c: char) -> Style<T, On, L, R, H, V, HN, VN>
611 where
612 T: Copy,
613 B: Copy,
614 H: Copy,
615 {
616 self.borders.bottom = Some(c);
617
618 if self.borders.has_left() {
619 self.borders.bottom_left = Some(c);
620 }
621
622 if self.borders.has_right() {
623 self.borders.bottom_right = Some(c);
624 }
625
626 if self.borders.has_vertical() {
627 self.borders.bottom_intersection = Some(c);
628 }
629
630 let verticals = varr_set(self.verticals, VLine::new(None, None, None, Some(c)));
631
632 Style::new(self.borders, self.horizontals, verticals)
633 }
634
635 pub const fn left(mut self, c: char) -> Style<T, B, On, R, H, V, HN, VN>
639 where
640 L: Copy,
641 R: Copy,
642 V: Copy,
643 {
644 self.borders.left = Some(c);
645
646 if self.borders.has_top() {
647 self.borders.top_left = Some(c);
648 }
649
650 if self.borders.has_bottom() {
651 self.borders.bottom_left = Some(c);
652 }
653
654 if self.borders.has_horizontal() {
655 self.borders.left_intersection = Some(c);
656 }
657
658 let horizontals = harr_set(self.horizontals, HLine::new(None, None, Some(c), None));
659
660 Style::new(self.borders, horizontals, self.verticals)
661 }
662
663 pub const fn right(mut self, c: char) -> Style<T, B, L, On, H, V, HN, VN>
667 where
668 L: Copy,
669 R: Copy,
670 V: Copy,
671 {
672 self.borders.right = Some(c);
673
674 if self.borders.has_top() {
675 self.borders.top_right = Some(c);
676 }
677
678 if self.borders.has_bottom() {
679 self.borders.bottom_right = Some(c);
680 }
681
682 if self.borders.has_horizontal() {
683 self.borders.right_intersection = Some(c);
684 }
685
686 let horizontals = harr_set(self.horizontals, HLine::new(None, None, None, Some(c)));
687
688 Style::new(self.borders, horizontals, self.verticals)
689 }
690
691 pub const fn horizontal(mut self, c: char) -> Style<T, B, L, R, On, V, HN, VN>
695 where
696 T: Copy,
697 B: Copy,
698 H: Copy,
699 {
700 self.borders.horizontal = Some(c);
701
702 if self.borders.has_vertical() {
703 self.borders.intersection = Some(c);
704 }
705
706 if self.borders.has_left() {
707 self.borders.left_intersection = Some(c);
708 }
709
710 if self.borders.has_right() {
711 self.borders.right_intersection = Some(c);
712 }
713
714 let verticals = varr_set(self.verticals, VLine::new(None, Some(c), None, None));
715
716 Style::new(self.borders, self.horizontals, verticals)
717 }
718
719 pub const fn vertical(mut self, c: char) -> Style<T, B, L, R, H, On, HN, VN>
723 where
724 L: Copy,
725 R: Copy,
726 V: Copy,
727 {
728 self.borders.vertical = Some(c);
729
730 if self.borders.has_horizontal() {
731 self.borders.intersection = Some(c);
732 }
733
734 if self.borders.has_top() {
735 self.borders.top_intersection = Some(c);
736 }
737
738 if self.borders.has_bottom() {
739 self.borders.bottom_intersection = Some(c);
740 }
741
742 let horizontals = harr_set(self.horizontals, HLine::new(None, Some(c), None, None));
743
744 Style::new(self.borders, horizontals, self.verticals)
745 }
746
747 pub const fn line_vertical<Top, Bottom, Intersection>(
753 mut self,
754 line: VerticalLine<Top, Bottom, Intersection>,
755 ) -> Style<Top, Bottom, L, R, Intersection, On, HN, VN>
756 where
757 L: Copy,
758 R: Copy,
759 Top: Copy,
760 Bottom: Copy,
761 Intersection: Copy,
762 {
763 let line = line.into_inner();
764
765 self.borders.vertical = line.main;
766 self.borders.intersection = line.intersection;
767 self.borders.top_intersection = line.top;
768 self.borders.bottom_intersection = line.bottom;
769
770 if line.intersection.is_none() {
771 self.borders.horizontal = None;
772 self.borders.left_intersection = None;
773 self.borders.right_intersection = None;
774 self.borders.intersection = None;
775 } else {
776 if self.borders.has_left() && self.borders.left_intersection.is_none() {
777 self.borders.left_intersection = Some(' ');
778 }
779
780 if self.borders.has_right() && self.borders.right_intersection.is_none() {
781 self.borders.right_intersection = Some(' ');
782 }
783
784 if self.borders.horizontal.is_none() {
785 self.borders.horizontal = Some(' ');
786 }
787 }
788
789 if line.top.is_none() {
790 self.borders.top = None;
791 self.borders.top_left = None;
792 self.borders.top_right = None;
793 self.borders.top_intersection = None;
794 }
795
796 if line.bottom.is_none() {
797 self.borders.bottom = None;
798 self.borders.bottom_left = None;
799 self.borders.bottom_right = None;
800 self.borders.bottom_intersection = None;
801 }
802
803 let horizontals = harr_set(
804 self.horizontals,
805 HLine::new(None, line.intersection, None, None),
806 );
807 let verticals = varr_set(
808 self.verticals,
809 VLine::new(None, line.intersection, line.top, line.bottom),
810 );
811
812 Style::new(self.borders, horizontals, verticals)
813 }
814
815 pub const fn line_horizontal<Left, Right, Intersection>(
821 mut self,
822 line: HorizontalLine<Left, Right, Intersection>,
823 ) -> Style<T, B, Left, Right, On, Intersection, HN, VN>
824 where
825 L: Copy,
826 R: Copy,
827 Left: Copy,
828 Right: Copy,
829 Intersection: Copy,
830 {
831 let line = line.into_inner();
832
833 self.borders.horizontal = line.main;
834 self.borders.intersection = line.intersection;
835 self.borders.left_intersection = line.left;
836 self.borders.right_intersection = line.right;
837
838 if line.intersection.is_none() {
839 self.borders.vertical = None;
840 self.borders.top_intersection = None;
841 self.borders.bottom_intersection = None;
842 self.borders.intersection = None;
843 } else {
844 if self.borders.has_top() && self.borders.top_intersection.is_none() {
845 self.borders.top_intersection = Some(' ');
846 }
847
848 if self.borders.has_bottom() && self.borders.bottom_intersection.is_none() {
849 self.borders.bottom_intersection = Some(' ');
850 }
851
852 if self.borders.vertical.is_none() {
853 self.borders.vertical = Some(' ');
854 }
855 }
856
857 if line.left.is_none() {
858 self.borders.left = None;
859 self.borders.top_left = None;
860 self.borders.bottom_left = None;
861 self.borders.left_intersection = None;
862 }
863
864 if line.right.is_none() {
865 self.borders.right = None;
866 self.borders.top_right = None;
867 self.borders.bottom_right = None;
868 self.borders.right_intersection = None;
869 }
870
871 let horizontals = harr_set(
872 self.horizontals,
873 HLine::new(None, line.intersection, line.left, line.right),
874 );
875 let verticals = varr_set(
876 self.verticals,
877 VLine::new(None, line.intersection, None, None),
878 );
879
880 Style::new(self.borders, horizontals, verticals)
881 }
882
883 pub const fn line_top<Left, Right, Intersection>(
889 mut self,
890 line: HorizontalLine<Left, Right, Intersection>,
891 ) -> Style<On, B, Left, Right, H, Intersection, HN, VN>
892 where
893 L: Copy,
894 R: Copy,
895 Left: Copy,
896 Right: Copy,
897 Intersection: Copy,
898 {
899 let line = line.into_inner();
900
901 self.borders.top = line.main;
902 self.borders.top_intersection = line.intersection;
903 self.borders.top_left = line.left;
904 self.borders.top_right = line.right;
905
906 if line.intersection.is_none() {
907 self.borders.vertical = None;
908 self.borders.top_intersection = None;
909 self.borders.bottom_intersection = None;
910 self.borders.intersection = None;
911 } else {
912 if self.borders.has_top() && self.borders.top_intersection.is_none() {
913 self.borders.top_intersection = Some(' ');
914 }
915
916 if self.borders.has_bottom() && self.borders.bottom_intersection.is_none() {
917 self.borders.bottom_intersection = Some(' ');
918 }
919
920 if self.borders.vertical.is_none() {
921 self.borders.vertical = Some(' ');
922 }
923 }
924
925 if line.left.is_none() {
926 self.borders.left = None;
927 self.borders.top_left = None;
928 self.borders.bottom_left = None;
929 self.borders.left_intersection = None;
930 }
931
932 if line.right.is_none() {
933 self.borders.right = None;
934 self.borders.top_right = None;
935 self.borders.bottom_right = None;
936 self.borders.right_intersection = None;
937 }
938
939 let horizontals = harr_set(
940 self.horizontals,
941 HLine::new(None, line.intersection, line.left, line.right),
942 );
943 let verticals = varr_set(
944 self.verticals,
945 VLine::new(None, line.intersection, None, None),
946 );
947
948 Style::new(self.borders, horizontals, verticals)
949 }
950
951 pub const fn line_bottom<Left, Right, Intersection>(
957 mut self,
958 line: HorizontalLine<Left, Right, Intersection>,
959 ) -> Style<T, On, Left, Right, H, Intersection, HN, VN>
960 where
961 L: Copy,
962 R: Copy,
963 Left: Copy,
964 Right: Copy,
965 Intersection: Copy,
966 {
967 let line = line.into_inner();
968
969 self.borders.bottom = line.main;
970 self.borders.bottom_intersection = line.intersection;
971 self.borders.bottom_left = line.left;
972 self.borders.bottom_right = line.right;
973
974 if line.intersection.is_none() {
975 self.borders.vertical = None;
976 self.borders.top_intersection = None;
977 self.borders.bottom_intersection = None;
978 self.borders.intersection = None;
979 } else {
980 if self.borders.has_top() && self.borders.top_intersection.is_none() {
981 self.borders.top_intersection = Some(' ');
982 }
983
984 if self.borders.has_bottom() && self.borders.bottom_intersection.is_none() {
985 self.borders.bottom_intersection = Some(' ');
986 }
987
988 if self.borders.vertical.is_none() {
989 self.borders.vertical = Some(' ');
990 }
991 }
992
993 if line.left.is_none() {
994 self.borders.left = None;
995 self.borders.top_left = None;
996 self.borders.bottom_left = None;
997 self.borders.left_intersection = None;
998 }
999
1000 if line.right.is_none() {
1001 self.borders.right = None;
1002 self.borders.top_right = None;
1003 self.borders.bottom_right = None;
1004 self.borders.right_intersection = None;
1005 }
1006
1007 let horizontals = harr_set(
1008 self.horizontals,
1009 HLine::new(None, line.intersection, line.left, line.right),
1010 );
1011 let verticals = varr_set(
1012 self.verticals,
1013 VLine::new(None, line.intersection, None, None),
1014 );
1015
1016 Style::new(self.borders, horizontals, verticals)
1017 }
1018
1019 pub const fn line_left<Top, Bottom, Intersection>(
1025 mut self,
1026 line: VerticalLine<Top, Bottom, Intersection>,
1027 ) -> Style<Top, Bottom, On, R, Intersection, V, HN, VN>
1028 where
1029 L: Copy,
1030 R: Copy,
1031 Top: Copy,
1032 Bottom: Copy,
1033 Intersection: Copy,
1034 {
1035 let line = line.into_inner();
1036
1037 self.borders.left = line.main;
1038 self.borders.left_intersection = line.intersection;
1039 self.borders.top_left = line.top;
1040 self.borders.bottom_left = line.bottom;
1041
1042 if line.intersection.is_none() {
1043 self.borders.horizontal = None;
1044 self.borders.left_intersection = None;
1045 self.borders.right_intersection = None;
1046 self.borders.intersection = None;
1047 } else {
1048 if self.borders.has_left() && self.borders.left_intersection.is_none() {
1049 self.borders.left_intersection = Some(' ');
1050 }
1051
1052 if self.borders.has_right() && self.borders.right_intersection.is_none() {
1053 self.borders.right_intersection = Some(' ');
1054 }
1055
1056 if self.borders.horizontal.is_none() {
1057 self.borders.horizontal = Some(' ');
1058 }
1059 }
1060
1061 if line.top.is_none() {
1062 self.borders.top = None;
1063 self.borders.top_left = None;
1064 self.borders.top_right = None;
1065 self.borders.top_intersection = None;
1066 }
1067
1068 if line.bottom.is_none() {
1069 self.borders.bottom = None;
1070 self.borders.bottom_left = None;
1071 self.borders.bottom_right = None;
1072 self.borders.bottom_intersection = None;
1073 }
1074
1075 let horizontals = harr_set(
1076 self.horizontals,
1077 HLine::new(None, line.intersection, None, None),
1078 );
1079 let verticals = varr_set(
1080 self.verticals,
1081 VLine::new(None, line.intersection, line.top, line.bottom),
1082 );
1083
1084 Style::new(self.borders, horizontals, verticals)
1085 }
1086
1087 pub const fn line_right<Top, Bottom, Intersection>(
1093 mut self,
1094 line: VerticalLine<Top, Bottom, Intersection>,
1095 ) -> Style<Top, Bottom, L, On, Intersection, V, HN, VN>
1096 where
1097 L: Copy,
1098 R: Copy,
1099 Top: Copy,
1100 Bottom: Copy,
1101 Intersection: Copy,
1102 {
1103 let line = line.into_inner();
1104
1105 self.borders.right = line.main;
1106 self.borders.right_intersection = line.intersection;
1107 self.borders.top_right = line.top;
1108 self.borders.bottom_right = line.bottom;
1109
1110 if line.intersection.is_none() {
1111 self.borders.horizontal = None;
1112 self.borders.left_intersection = None;
1113 self.borders.right_intersection = None;
1114 self.borders.intersection = None;
1115 } else {
1116 if self.borders.has_left() && self.borders.left_intersection.is_none() {
1117 self.borders.left_intersection = Some(' ');
1118 }
1119
1120 if self.borders.has_right() && self.borders.right_intersection.is_none() {
1121 self.borders.right_intersection = Some(' ');
1122 }
1123
1124 if self.borders.horizontal.is_none() {
1125 self.borders.horizontal = Some(' ');
1126 }
1127 }
1128
1129 if line.top.is_none() {
1130 self.borders.top = None;
1131 self.borders.top_left = None;
1132 self.borders.top_right = None;
1133 self.borders.top_intersection = None;
1134 }
1135
1136 if line.bottom.is_none() {
1137 self.borders.bottom = None;
1138 self.borders.bottom_left = None;
1139 self.borders.bottom_right = None;
1140 self.borders.bottom_intersection = None;
1141 }
1142
1143 let horizontals = harr_set(
1144 self.horizontals,
1145 HLine::new(None, line.intersection, None, None),
1146 );
1147 let verticals = varr_set(
1148 self.verticals,
1149 VLine::new(None, line.intersection, line.top, line.bottom),
1150 );
1151
1152 Style::new(self.borders, horizontals, verticals)
1153 }
1154
1155 pub const fn frame<Top, Bottom, Left, Right>(
1183 mut self,
1184 border: Border<Top, Bottom, Left, Right>,
1185 ) -> Style<Top, Bottom, Left, Right, H, V, HN, VN>
1186 where
1187 T: Copy,
1188 B: Copy,
1189 L: Copy,
1190 R: Copy,
1191 H: Copy,
1192 V: Copy,
1193 Left: Copy,
1194 Right: Copy,
1195 Top: Copy,
1196 Bottom: Copy,
1197 {
1198 let border = border.into_inner();
1199 let border = correct_border(border);
1200
1201 let horizontals = harr_set(
1202 self.horizontals,
1203 HLine::new(None, None, border.left, border.right),
1204 );
1205 let verticals = varr_set(
1206 self.verticals,
1207 VLine::new(None, None, border.top, border.bottom),
1208 );
1209
1210 self.borders.top = border.top;
1211 self.borders.bottom = border.bottom;
1212 self.borders.left = border.left;
1213 self.borders.top_left = border.left_top_corner;
1214 self.borders.bottom_left = border.left_bottom_corner;
1215 self.borders.right = border.right;
1216 self.borders.top_right = border.right_top_corner;
1217 self.borders.bottom_right = border.right_bottom_corner;
1218
1219 Style::new(self.borders, horizontals, verticals)
1220 }
1221}
1222
1223impl<B, R, H, V, const HN: usize, const VN: usize> Style<On, B, On, R, H, V, HN, VN> {
1224 pub const fn corner_top_left(mut self, c: char) -> Self {
1226 self.borders.top_left = Some(c);
1227
1228 Style::new(self.borders, self.horizontals, self.verticals)
1229 }
1230}
1231
1232impl<B, L, H, V, const HN: usize, const VN: usize> Style<On, B, L, On, H, V, HN, VN> {
1233 pub const fn corner_top_right(mut self, c: char) -> Self {
1235 self.borders.top_right = Some(c);
1236
1237 Style::new(self.borders, self.horizontals, self.verticals)
1238 }
1239}
1240
1241impl<T, L, H, V, const HN: usize, const VN: usize> Style<T, On, L, On, H, V, HN, VN> {
1242 pub const fn corner_bottom_right(mut self, c: char) -> Self {
1244 self.borders.bottom_right = Some(c);
1245
1246 Style::new(self.borders, self.horizontals, self.verticals)
1247 }
1248}
1249
1250impl<T, R, H, V, const HN: usize, const VN: usize> Style<T, On, On, R, H, V, HN, VN> {
1251 pub const fn corner_bottom_left(mut self, c: char) -> Self {
1253 self.borders.bottom_left = Some(c);
1254
1255 Style::new(self.borders, self.horizontals, self.verticals)
1256 }
1257}
1258
1259impl<T, B, R, V, const HN: usize, const VN: usize> Style<T, B, On, R, On, V, HN, VN> {
1260 pub const fn intersection_left(mut self, c: char) -> Self {
1262 self.borders.left_intersection = Some(c);
1263
1264 Style::new(self.borders, self.horizontals, self.verticals)
1265 }
1266}
1267
1268impl<T, B, L, V, const HN: usize, const VN: usize> Style<T, B, L, On, On, V, HN, VN> {
1269 pub const fn intersection_right(mut self, c: char) -> Self {
1271 self.borders.right_intersection = Some(c);
1272
1273 Style::new(self.borders, self.horizontals, self.verticals)
1274 }
1275}
1276
1277impl<B, L, R, H, const HN: usize, const VN: usize> Style<On, B, L, R, H, On, HN, VN> {
1278 pub const fn intersection_top(mut self, c: char) -> Self {
1280 self.borders.top_intersection = Some(c);
1281
1282 Style::new(self.borders, self.horizontals, self.verticals)
1283 }
1284}
1285
1286impl<T, L, R, H, const HN: usize, const VN: usize> Style<T, On, L, R, H, On, HN, VN> {
1287 pub const fn intersection_bottom(mut self, c: char) -> Self {
1289 self.borders.bottom_intersection = Some(c);
1290
1291 Style::new(self.borders, self.horizontals, self.verticals)
1292 }
1293}
1294
1295impl<T, B, L, R, const HN: usize, const VN: usize> Style<T, B, L, R, On, On, HN, VN> {
1296 pub const fn intersection(mut self, c: char) -> Self
1299 where
1300 T: Copy,
1301 B: Copy,
1302 R: Copy,
1303 L: Copy,
1304 {
1305 self.borders.intersection = Some(c);
1306
1307 let horizontals = harr_set(self.horizontals, HLine::new(None, Some(c), None, None));
1308 let verticals = varr_set(self.verticals, VLine::new(None, Some(c), None, None));
1309
1310 Style::new(self.borders, horizontals, verticals)
1311 }
1312}
1313
1314impl<B, L, R, H, V, const HN: usize, const VN: usize> Style<On, B, L, R, H, V, HN, VN> {
1315 pub const fn remove_top(mut self) -> Style<(), B, L, R, H, V, HN, VN>
1317 where
1318 B: Copy,
1319 H: Copy,
1320 {
1321 self.borders.top = None;
1322 self.borders.top_intersection = None;
1323 self.borders.top_left = None;
1324 self.borders.top_right = None;
1325
1326 let verticals = varr_unset(self.verticals, VLine::new(None, None, Some(' '), None));
1327
1328 Style::new(self.borders, self.horizontals, verticals)
1329 }
1330}
1331
1332impl<T, L, R, H, V, const HN: usize, const VN: usize> Style<T, On, L, R, H, V, HN, VN> {
1333 pub const fn remove_bottom(mut self) -> Style<T, (), L, R, H, V, HN, VN>
1335 where
1336 T: Copy,
1337 H: Copy,
1338 {
1339 self.borders.bottom = None;
1340 self.borders.bottom_intersection = None;
1341 self.borders.bottom_left = None;
1342 self.borders.bottom_right = None;
1343
1344 let verticals = varr_unset(self.verticals, VLine::new(None, None, None, Some(' ')));
1345
1346 Style::new(self.borders, self.horizontals, verticals)
1347 }
1348}
1349
1350impl<T, B, R, H, V, const HN: usize, const VN: usize> Style<T, B, On, R, H, V, HN, VN> {
1351 pub const fn remove_left(mut self) -> Style<T, B, (), R, H, V, HN, VN>
1353 where
1354 R: Copy,
1355 V: Copy,
1356 {
1357 self.borders.left = None;
1358 self.borders.left_intersection = None;
1359 self.borders.top_left = None;
1360 self.borders.bottom_left = None;
1361
1362 let horizontals = harr_unset(self.horizontals, HLine::new(None, None, Some(' '), None));
1363
1364 Style::new(self.borders, horizontals, self.verticals)
1365 }
1366}
1367
1368impl<T, B, L, H, V, const HN: usize, const VN: usize> Style<T, B, L, On, H, V, HN, VN> {
1369 pub const fn remove_right(mut self) -> Style<T, B, L, (), H, V, HN, VN>
1371 where
1372 L: Copy,
1373 V: Copy,
1374 {
1375 self.borders.right = None;
1376 self.borders.right_intersection = None;
1377 self.borders.top_right = None;
1378 self.borders.bottom_right = None;
1379
1380 let horizontals = harr_unset(self.horizontals, HLine::new(None, None, None, Some(' ')));
1381
1382 Style::new(self.borders, horizontals, self.verticals)
1383 }
1384}
1385
1386impl<T, B, L, R, V, const HN: usize, const VN: usize> Style<T, B, L, R, On, V, HN, VN> {
1387 pub const fn remove_horizontal(mut self) -> Style<T, B, L, R, (), V, HN, VN>
1391 where
1392 T: Copy,
1393 B: Copy,
1394 V: Copy,
1395 {
1396 self.borders.horizontal = None;
1397 self.borders.left_intersection = None;
1398 self.borders.right_intersection = None;
1399 self.borders.intersection = None;
1400
1401 let verticals = self.verticals;
1403
1404 Style::new(self.borders, self.horizontals, verticals)
1405 }
1406}
1407
1408impl<T, B, L, R, H, const HN: usize, const VN: usize> Style<T, B, L, R, H, On, HN, VN> {
1409 pub const fn remove_vertical(mut self) -> Style<T, B, L, R, H, (), HN, VN>
1411 where
1412 R: Copy,
1413 L: Copy,
1414 {
1415 self.borders.vertical = None;
1416 self.borders.top_intersection = None;
1417 self.borders.bottom_intersection = None;
1418 self.borders.intersection = None;
1419
1420 let horizontals = self.horizontals;
1422
1423 Style::new(self.borders, horizontals, self.verticals)
1424 }
1425}
1426
1427impl<H, V, const HN: usize, const VN: usize> Style<On, On, On, On, H, V, HN, VN> {
1428 pub const fn remove_frame(self) -> Style<(), (), (), (), H, V, HN, VN>
1430 where
1431 V: Copy,
1432 H: Copy,
1433 {
1434 self.remove_bottom()
1435 .remove_top()
1436 .remove_left()
1437 .remove_right()
1438 }
1439}
1440
1441#[cfg(feature = "std")]
1442impl<T, B, L, R, H, V, Data, Dims, const HSIZE: usize, const VSIZE: usize>
1443 TableOption<Data, ColoredConfig, Dims> for Style<T, B, L, R, H, V, HSIZE, VSIZE>
1444{
1445 fn change(self, _: &mut Data, cfg: &mut ColoredConfig, _: &mut Dims) {
1446 cfg_clear_borders(cfg);
1447 cfg_set_custom_lines(cfg, &self.horizontals, &self.verticals);
1448 cfg.set_borders(self.borders);
1449 }
1450
1451 fn hint_change(&self) -> Option<papergrid::config::Entity> {
1452 None
1453 }
1454}
1455
1456impl<T, B, L, R, H, V, Data, Dims, const HSIZE: usize, const VSIZE: usize>
1457 TableOption<Data, CompactConfig, Dims> for Style<T, B, L, R, H, V, HSIZE, VSIZE>
1458{
1459 fn change(self, _: &mut Data, cfg: &mut CompactConfig, _: &mut Dims) {
1460 *cfg = cfg.set_borders(self.borders);
1461 }
1462
1463 fn hint_change(&self) -> Option<papergrid::config::Entity> {
1464 None
1465 }
1466}
1467
1468impl<T, B, L, R, H, V, Data, Dims, const HSIZE: usize, const VSIZE: usize>
1469 TableOption<Data, CompactMultilineConfig, Dims> for Style<T, B, L, R, H, V, HSIZE, VSIZE>
1470{
1471 fn change(self, _: &mut Data, cfg: &mut CompactMultilineConfig, _: &mut Dims) {
1472 cfg.set_borders(self.borders);
1473 }
1474
1475 fn hint_change(&self) -> Option<papergrid::config::Entity> {
1476 None
1477 }
1478}
1479
1480impl<T, B, L, R, H, V, const HSIZE: usize, const VSIZE: usize>
1481 From<Style<T, B, L, R, H, V, HSIZE, VSIZE>> for Borders<char>
1482{
1483 fn from(value: Style<T, B, L, R, H, V, HSIZE, VSIZE>) -> Self {
1484 value.borders
1485 }
1486}
1487
1488const fn correct_border(mut border: GridBorder<char>) -> GridBorder<char> {
1489 if border.has_top() && border.top.is_none() {
1490 border.top = Some(' ');
1491 }
1492
1493 if border.has_bottom() && border.bottom.is_none() {
1494 border.bottom = Some(' ');
1495 }
1496
1497 if border.has_left() && border.left.is_none() {
1498 border.left = Some(' ');
1499 }
1500
1501 if border.has_right() && border.right.is_none() {
1502 border.right = Some(' ');
1503 }
1504
1505 if border.has_top() && border.has_left() && border.left_top_corner.is_none() {
1506 border.left_top_corner = Some(' ');
1507 }
1508
1509 if border.has_top() && border.has_right() && border.right_top_corner.is_none() {
1510 border.right_top_corner = Some(' ');
1511 }
1512
1513 if border.has_bottom() && border.has_left() && border.left_top_corner.is_none() {
1514 border.left_bottom_corner = Some(' ');
1515 }
1516
1517 if border.has_bottom() && border.has_right() && border.right_bottom_corner.is_none() {
1518 border.right_bottom_corner = Some(' ');
1519 }
1520
1521 border
1522}
1523
1524const fn varr_convert<T, B, I, const N: usize>(
1525 lines: [(usize, VerticalLine<T, B, I>); N],
1526) -> VArray<N> {
1527 let mut buf = [(0, VLine::empty()); N];
1528 let mut i = 0;
1529 while i < N {
1530 let (index, line) = &lines[i];
1531 let index = *index;
1532 let line = line.into_inner();
1533
1534 buf[i].0 = index;
1535 buf[i].1 = line;
1536
1537 i += 1;
1538 }
1539
1540 buf
1541}
1542
1543const fn harr_convert<L, R, I, const N: usize>(
1544 lines: [(usize, HorizontalLine<L, R, I>); N],
1545) -> HArray<N> {
1546 let mut buf = [(0, HLine::empty()); N];
1547 let mut i = 0;
1548 while i < N {
1549 let (index, line) = &lines[i];
1550 let index = *index;
1551 let line = line.into_inner();
1552
1553 buf[i].0 = index;
1554 buf[i].1 = line;
1555
1556 i += 1;
1557 }
1558
1559 buf
1560}
1561
1562const fn harr_set<const N: usize>(lines: HArray<N>, set: HLine) -> HArray<N> {
1563 let mut buf = [(0, HLine::empty()); N];
1564 let mut i = 0;
1565 while i < N {
1566 let (index, mut line) = lines[i];
1567
1568 if set.left.is_some() {
1569 line.left = set.left;
1570 }
1571
1572 if set.right.is_some() {
1573 line.right = set.right;
1574 }
1575
1576 if set.intersection.is_some() {
1577 line.intersection = set.intersection;
1578 }
1579
1580 if set.main.is_some() {
1581 line.main = set.main;
1582 }
1583
1584 buf[i].0 = index;
1585 buf[i].1 = line;
1586
1587 i += 1;
1588 }
1589
1590 buf
1591}
1592
1593const fn harr_unset<const N: usize>(lines: HArray<N>, set: HLine) -> HArray<N> {
1594 let mut buf = [(0, HLine::empty()); N];
1595 let mut i = 0;
1596 while i < N {
1597 let (index, mut line) = lines[i];
1598
1599 if set.left.is_some() {
1600 line.left = None;
1601 }
1602
1603 if set.right.is_some() {
1604 line.right = None;
1605 }
1606
1607 if set.intersection.is_some() {
1608 line.intersection = None;
1609 }
1610
1611 if set.main.is_some() {
1612 line.main = None;
1613 }
1614
1615 buf[i].0 = index;
1616 buf[i].1 = line;
1617
1618 i += 1;
1619 }
1620
1621 buf
1622}
1623
1624const fn varr_set<const N: usize>(lines: VArray<N>, set: VLine) -> VArray<N> {
1625 let mut buf = [(0, VLine::empty()); N];
1626 let mut i = 0;
1627 while i < N {
1628 let (index, mut line) = lines[i];
1629
1630 if set.top.is_some() {
1631 line.top = set.top;
1632 }
1633
1634 if set.bottom.is_some() {
1635 line.bottom = set.bottom;
1636 }
1637
1638 if set.intersection.is_some() {
1639 line.intersection = set.intersection;
1640 }
1641
1642 if set.main.is_some() {
1643 line.main = set.main;
1644 }
1645
1646 buf[i].0 = index;
1647 buf[i].1 = line;
1648
1649 i += 1;
1650 }
1651
1652 buf
1653}
1654
1655const fn varr_unset<const N: usize>(lines: VArray<N>, set: VLine) -> VArray<N> {
1656 let mut buf = [(0, VLine::empty()); N];
1657 let mut i = 0;
1658 while i < N {
1659 let (index, mut line) = lines[i];
1660
1661 if set.top.is_some() {
1662 line.top = None;
1663 }
1664
1665 if set.bottom.is_some() {
1666 line.bottom = None;
1667 }
1668
1669 if set.intersection.is_some() {
1670 line.intersection = None;
1671 }
1672
1673 if set.main.is_some() {
1674 line.main = None;
1675 }
1676
1677 buf[i].0 = index;
1678 buf[i].1 = line;
1679
1680 i += 1;
1681 }
1682
1683 buf
1684}
1685
1686const fn create_borders(
1687 top: HLine,
1688 bottom: HLine,
1689 horizontal: HLine,
1690 left: Option<char>,
1691 right: Option<char>,
1692 vertical: Option<char>,
1693) -> Borders<char> {
1694 Borders {
1695 top: top.main,
1696 top_left: top.left,
1697 top_right: top.right,
1698 top_intersection: top.intersection,
1699 bottom: bottom.main,
1700 bottom_left: bottom.left,
1701 bottom_right: bottom.right,
1702 bottom_intersection: bottom.intersection,
1703 left_intersection: horizontal.left,
1704 right_intersection: horizontal.right,
1705 horizontal: horizontal.main,
1706 intersection: horizontal.intersection,
1707 left,
1708 right,
1709 vertical,
1710 }
1711}
1712
1713#[cfg(feature = "std")]
1714fn cfg_set_custom_lines(
1715 cfg: &mut ColoredConfig,
1716 hlines: &[(usize, HLine)],
1717 vlines: &[(usize, VLine)],
1718) {
1719 for &(row, line) in hlines {
1720 cfg.insert_horizontal_line(row, line);
1721 }
1722
1723 for &(col, line) in vlines {
1724 cfg.insert_vertical_line(col, line);
1725 }
1726}
1727
1728#[cfg(feature = "std")]
1729fn cfg_clear_borders(cfg: &mut ColoredConfig) {
1730 cfg.remove_borders();
1731 cfg.remove_vertical_chars();
1732 cfg.remove_horizontal_chars();
1733 cfg.remove_borders_colors();
1734 cfg.remove_color_line_horizontal();
1735 cfg.remove_color_line_vertical();
1736}