comfy_table/
cell.rs

1#[cfg(feature = "tty")]
2use crate::{Attribute, Color};
3
4use crate::style::CellAlignment;
5
6/// A stylable table cell with content.
7#[derive(Clone, Debug, PartialEq, Eq, Hash)]
8pub struct Cell {
9    /// The content is a list of strings.\
10    /// This is done to make working with newlines more easily.\
11    /// When creating a new [Cell], the given content is split by newline.
12    pub(crate) content: Vec<String>,
13    /// The delimiter which is used to split the text into consistent pieces.\
14    /// The default is ` `.
15    pub(crate) delimiter: Option<char>,
16    pub(crate) alignment: Option<CellAlignment>,
17    #[cfg(feature = "tty")]
18    pub(crate) fg: Option<Color>,
19    #[cfg(feature = "tty")]
20    pub(crate) bg: Option<Color>,
21    #[cfg(feature = "tty")]
22    pub(crate) attributes: Vec<Attribute>,
23}
24
25impl Cell {
26    /// Create a new Cell
27    #[allow(clippy::needless_pass_by_value)]
28    pub fn new<T: ToString>(content: T) -> Self {
29        let content = content.to_string();
30        #[cfg_attr(not(feature = "custom_styling"), allow(unused_mut))]
31        let mut split_content: Vec<String> = content.split('\n').map(ToString::to_string).collect();
32
33        // Correct ansi codes so style is terminated and resumed around the split
34        #[cfg(feature = "custom_styling")]
35        crate::utils::formatting::content_split::fix_style_in_split_str(&mut split_content);
36
37        Self {
38            content: split_content,
39            delimiter: None,
40            alignment: None,
41            #[cfg(feature = "tty")]
42            fg: None,
43            #[cfg(feature = "tty")]
44            bg: None,
45            #[cfg(feature = "tty")]
46            attributes: Vec::new(),
47        }
48    }
49
50    /// Return a copy of the content contained in this cell.
51    pub fn content(&self) -> String {
52        self.content.join("\n")
53    }
54
55    /// Set the delimiter used to split text for this cell. \
56    /// Normal text uses spaces (` `) as delimiters. This is necessary to help comfy-table
57    /// understand the concept of _words_.
58    #[must_use]
59    pub fn set_delimiter(mut self, delimiter: char) -> Self {
60        self.delimiter = Some(delimiter);
61
62        self
63    }
64
65    /// Set the alignment of content for this cell.
66    ///
67    /// Setting this overwrites alignment settings of the
68    /// [Column](crate::column::Column::set_cell_alignment) for this specific cell.
69    /// ```
70    /// use comfy_table::CellAlignment;
71    /// use comfy_table::Cell;
72    ///
73    /// let mut cell = Cell::new("Some content")
74    ///     .set_alignment(CellAlignment::Center);
75    /// ```
76    #[must_use]
77    pub fn set_alignment(mut self, alignment: CellAlignment) -> Self {
78        self.alignment = Some(alignment);
79
80        self
81    }
82
83    /// Set the foreground text color for this cell.
84    ///
85    /// Look at [Color](crate::Color) for a list of all possible Colors.
86    /// ```
87    /// use comfy_table::Color;
88    /// use comfy_table::Cell;
89    ///
90    /// let mut cell = Cell::new("Some content")
91    ///     .fg(Color::Red);
92    /// ```
93    #[cfg(feature = "tty")]
94    #[must_use]
95    pub fn fg(mut self, color: Color) -> Self {
96        self.fg = Some(color);
97
98        self
99    }
100
101    /// Set the background color for this cell.
102    ///
103    /// Look at [Color](crate::Color) for a list of all possible Colors.
104    /// ```
105    /// use comfy_table::Color;
106    /// use comfy_table::Cell;
107    ///
108    /// let mut cell = Cell::new("Some content")
109    ///     .bg(Color::Red);
110    /// ```
111    #[cfg(feature = "tty")]
112    #[must_use]
113    pub fn bg(mut self, color: Color) -> Self {
114        self.bg = Some(color);
115
116        self
117    }
118
119    /// Add a styling attribute to the content cell.\
120    /// Those can be **bold**, _italic_, blinking and many more.
121    ///
122    /// Look at [Attribute](crate::Attribute) for a list of all possible Colors.
123    /// ```
124    /// use comfy_table::Attribute;
125    /// use comfy_table::Cell;
126    ///
127    /// let mut cell = Cell::new("Some content")
128    ///     .add_attribute(Attribute::Bold);
129    /// ```
130    #[cfg(feature = "tty")]
131    #[must_use]
132    pub fn add_attribute(mut self, attribute: Attribute) -> Self {
133        self.attributes.push(attribute);
134
135        self
136    }
137
138    /// Same as add_attribute, but you can pass a vector of [Attributes](Attribute)
139    #[cfg(feature = "tty")]
140    #[must_use]
141    pub fn add_attributes(mut self, mut attribute: Vec<Attribute>) -> Self {
142        self.attributes.append(&mut attribute);
143
144        self
145    }
146}
147
148/// Convert anything with [ToString] to a new [Cell].
149///
150/// ```
151/// # use comfy_table::Cell;
152/// let cell: Cell = "content".into();
153/// let cell: Cell = 5u32.into();
154/// ```
155impl<T: ToString> From<T> for Cell {
156    fn from(content: T) -> Self {
157        Self::new(content)
158    }
159}
160
161/// A simple wrapper type for a `Vec<Cell>`.
162///
163/// This wrapper is needed to support generic conversions between iterables and `Vec<Cell>`.
164/// Check the trait implementations for more docs.
165pub struct Cells(pub Vec<Cell>);
166
167/// Allow the conversion of a type to a [Cells], which is a simple vector of cells.
168///
169/// By default this is implemented for all Iterators over items implementing [ToString].
170///
171/// ```
172/// use comfy_table::{Row, Cells};
173///
174/// let cells_string: Cells = vec!["One", "Two", "Three"].into();
175/// let cells_integer: Cells = vec![1, 2, 3, 4].into();
176/// ```
177impl<T> From<T> for Cells
178where
179    T: IntoIterator,
180    T::Item: Into<Cell>,
181{
182    fn from(cells: T) -> Self {
183        Self(cells.into_iter().map(Into::into).collect())
184    }
185}
186
187#[cfg(test)]
188mod tests {
189    use super::*;
190
191    #[test]
192    fn test_column_generation() {
193        let content = "This is\nsome multiline\nstring".to_string();
194        let cell = Cell::new(content.clone());
195
196        assert_eq!(cell.content(), content);
197    }
198}