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
29use crate::{
30 grid::{
31 color::StaticColor,
32 config::{CompactConfig, CompactMultilineConfig},
33 config::{Indent, Sides},
34 },
35 settings::TableOption,
36};
37
38#[cfg(feature = "std")]
39use 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)]
51pub struct Margin<C = StaticColor> {
52 indent: Sides<Indent>,
53 colors: Option<Sides<C>>,
54}
55
56impl 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
74impl<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")]
94impl<R, D, C> TableOption<R, D, ColoredConfig> for Margin<C>
95where
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
115impl<R, D, C> TableOption<R, D, CompactConfig> for Margin<C>
116where
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
130impl<R, D, C> TableOption<R, D, CompactMultilineConfig> for Margin<C>
131where
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