tabled/features/style/
border_text.rs

1use std::borrow::Cow;
2
3use papergrid::records::Records;
4
5use crate::{Table, TableOption};
6
7use super::Offset;
8
9/// [`BorderText`] writes a custom text on a border.
10///
11/// # Example
12///
13/// ```rust
14/// use tabled::{Table, BorderText};
15///
16/// let mut table = Table::new(["Hello World"]);
17/// table
18///     .with(BorderText::first("+-.table"));
19///
20/// assert_eq!(
21///     table.to_string(),
22///     "+-.table------+\n\
23///      | &str        |\n\
24///      +-------------+\n\
25///      | Hello World |\n\
26///      +-------------+"
27/// );
28/// ```
29#[derive(Debug)]
30pub struct BorderText<'a> {
31    // todo: offset from which we start overriding border
32    // offset: usize,
33    text: Cow<'a, str>,
34    row: SplitLineIndex,
35    offset: Offset,
36}
37
38#[derive(Debug)]
39enum SplitLineIndex {
40    First,
41    Last,
42    Line(usize),
43}
44
45impl<'a> BorderText<'a> {
46    /// Creates a [`BorderText`] instance.
47    ///
48    /// Lines are numbered from 0 to the `count_rows` included
49    /// (`line >= 0 && line <= count_rows`).
50    pub fn new<S>(line: usize, text: S) -> Self
51    where
52        S: Into<Cow<'a, str>>,
53    {
54        Self {
55            text: text.into(),
56            row: SplitLineIndex::Line(line),
57            offset: Offset::Begin(0),
58        }
59    }
60
61    /// Creates a [`BorderText`] instance for a top line.
62    pub fn first<S>(text: S) -> Self
63    where
64        S: Into<Cow<'a, str>>,
65    {
66        Self {
67            text: text.into(),
68            row: SplitLineIndex::First,
69            offset: Offset::Begin(0),
70        }
71    }
72
73    /// Creates a [`BorderText`] instance for a bottom line.
74    pub fn last<S>(text: S) -> Self
75    where
76        S: Into<Cow<'a, str>>,
77    {
78        Self {
79            text: text.into(),
80            row: SplitLineIndex::Last,
81            offset: Offset::Begin(0),
82        }
83    }
84
85    /// Set an offset from which the text will be started.
86    pub fn offset(mut self, offset: Offset) -> Self {
87        self.offset = offset;
88        self
89    }
90}
91
92impl<'a, R> TableOption<R> for BorderText<'a>
93where
94    R: Records,
95{
96    fn change(&mut self, table: &mut Table<R>) {
97        let row = match self.row {
98            SplitLineIndex::First => 0,
99            SplitLineIndex::Last => table.shape().0,
100            SplitLineIndex::Line(row) => {
101                if row > table.shape().0 {
102                    return;
103                }
104
105                row
106            }
107        };
108
109        table
110            .get_config_mut()
111            .override_split_line(row, self.text.as_ref(), self.offset.into());
112    }
113}