1 | //! This module contains a Margin settings of a [`Table`]. |
2 | //! |
3 | //! # Example |
4 | //! |
5 | #![cfg_attr (feature = "std" , doc = "```" )] |
6 | #![cfg_attr (not(feature = "std" ), doc = "```ignore" )] |
7 | //! use tabled::{settings::{Margin, Style}, Table}; |
8 | //! |
9 | //! let data = vec!["Hello" , "World" , "!" ]; |
10 | //! |
11 | //! let mut table = Table::new(data); |
12 | //! table.with(Style::markdown()).with(Margin::new(3, 3, 1, 0)); |
13 | //! |
14 | //! assert_eq!( |
15 | //! table.to_string(), |
16 | //! concat!( |
17 | //! " \n" , |
18 | //! " | &str | \n" , |
19 | //! " |-------| \n" , |
20 | //! " | Hello | \n" , |
21 | //! " | World | \n" , |
22 | //! " | ! | " , |
23 | //! ) |
24 | //! ); |
25 | //! ``` |
26 | //! |
27 | //! [`Table`]: crate::Table |
28 | |
29 | use crate::{ |
30 | grid::{ |
31 | color::StaticColor, |
32 | config::{CompactConfig, CompactMultilineConfig}, |
33 | config::{Indent, Sides}, |
34 | }, |
35 | settings::TableOption, |
36 | }; |
37 | |
38 | #[cfg (feature = "std" )] |
39 | use crate::grid::{color::AnsiColor, config::ColoredConfig}; |
40 | |
41 | /// Margin is responsible for a left/right/top/bottom outer indent of a grid. |
42 | /// |
43 | #[cfg_attr (feature = "std" , doc = "```" )] |
44 | #[cfg_attr (not(feature = "std" ), doc = "```ignore" )] |
45 | /// # use tabled::{settings::Margin, Table}; |
46 | /// # let data: Vec<&'static str> = Vec::new(); |
47 | /// let table = Table::new(&data) |
48 | /// .with(Margin::new(1, 1, 1, 1).fill('>' , '<' , 'V' , '^' )); |
49 | /// ``` |
50 | #[derive (Debug, Clone)] |
51 | pub struct Margin<C = StaticColor> { |
52 | indent: Sides<Indent>, |
53 | colors: Option<Sides<C>>, |
54 | } |
55 | |
56 | impl Margin { |
57 | /// Construct's an Margin object. |
58 | /// |
59 | /// It uses space(' ') as a default fill character. |
60 | /// To set a custom character you can use [`Margin::fill`] function. |
61 | pub const fn new(left: usize, right: usize, top: usize, bottom: usize) -> Self { |
62 | Self { |
63 | indent: Sides::new( |
64 | left:Indent::spaced(left), |
65 | right:Indent::spaced(right), |
66 | top:Indent::spaced(top), |
67 | bottom:Indent::spaced(size:bottom), |
68 | ), |
69 | colors: None, |
70 | } |
71 | } |
72 | } |
73 | |
74 | impl<Color> Margin<Color> { |
75 | /// The function, sets a characters for the margin on an each side. |
76 | pub const fn fill(mut self, left: char, right: char, top: char, bottom: char) -> Self { |
77 | self.indent.left.fill = left; |
78 | self.indent.right.fill = right; |
79 | self.indent.top.fill = top; |
80 | self.indent.bottom.fill = bottom; |
81 | self |
82 | } |
83 | |
84 | /// The function, sets a characters for the margin on an each side. |
85 | pub fn colorize<C>(self, left: C, right: C, top: C, bottom: C) -> Margin<C> { |
86 | Margin { |
87 | indent: self.indent, |
88 | colors: Some(Sides::new(left, right, top, bottom)), |
89 | } |
90 | } |
91 | } |
92 | |
93 | #[cfg (feature = "std" )] |
94 | impl<R, D, C> TableOption<R, D, ColoredConfig> for Margin<C> |
95 | where |
96 | C: Into<AnsiColor<'static>> + Clone, |
97 | { |
98 | fn change(self, _: &mut R, cfg: &mut ColoredConfig, _: &mut D) { |
99 | let indent: Sides = self.indent; |
100 | let margin: Sides = Sides::new(indent.left, indent.right, indent.top, indent.bottom); |
101 | cfg.set_margin(margin); |
102 | |
103 | if let Some(colors: &Sides) = &self.colors { |
104 | let margin: Sides = Sides::new( |
105 | left:Some(colors.left.clone().into()), |
106 | right:Some(colors.right.clone().into()), |
107 | top:Some(colors.top.clone().into()), |
108 | bottom:Some(colors.bottom.clone().into()), |
109 | ); |
110 | cfg.set_margin_color(margin); |
111 | } |
112 | } |
113 | } |
114 | |
115 | impl<R, D, C> TableOption<R, D, CompactConfig> for Margin<C> |
116 | where |
117 | C: Into<StaticColor> + Clone, |
118 | { |
119 | fn change(self, _: &mut R, cfg: &mut CompactConfig, _: &mut D) { |
120 | *cfg = cfg.set_margin(self.indent); |
121 | |
122 | if let Some(c: Sides) = self.colors { |
123 | // todo: make a new method (BECAUSE INTO doesn't work) try_into(); |
124 | let colors: Sides = Sides::new(left:c.left.into(), right:c.right.into(), top:c.top.into(), bottom:c.bottom.into()); |
125 | *cfg = cfg.set_margin_color(colors); |
126 | } |
127 | } |
128 | } |
129 | |
130 | impl<R, D, C> TableOption<R, D, CompactMultilineConfig> for Margin<C> |
131 | where |
132 | C: Into<StaticColor> + Clone, |
133 | { |
134 | fn change(self, records: &mut R, cfg: &mut CompactMultilineConfig, dimension: &mut D) { |
135 | self.change(records, cfg:cfg.as_mut(), dimension) |
136 | } |
137 | } |
138 | |