tabled/settings/disable/
mod.rs

1//! This module contains a [`Remove`] structure which helps to
2//! remove an etheir column or row from a [`Table`].
3//!
4//! # Example
5//!
6//! ```rust,no_run
7//! # use tabled::{Table, settings::{Remove, object::Rows}};
8//! # let data: Vec<&'static str> = Vec::new();
9//! let table = Table::new(&data).with(Remove::row(Rows::first()));
10//! ```
11//!
12//! [`Table`]: crate::Table
13
14use std::marker::PhantomData;
15
16use crate::{
17    grid::records::{ExactRecords, Records, Resizable},
18    settings::{location::Location, TableOption},
19};
20
21/// Remove removes particular rows/columns from a [`Table`].
22///
23/// It tries to keeps track of style changes which may occur.
24/// But it's not guaranteed will be the way you would expect it to be.
25///
26/// Generally you should avoid use of [`Remove`] because it's a slow function and modifies the underlying records.
27/// Providing correct data right away is better.
28///
29/// # Example
30///
31/// ```
32/// use tabled::{Table, settings::{Remove, object::Rows}};
33///
34/// let data = vec!["Hello", "World", "!!!"];
35///
36/// let table = Table::new(data).with(Remove::row(Rows::new(1..2))).to_string();
37///
38/// assert_eq!(
39///     table,
40///     "+-------+\n\
41///      | &str  |\n\
42///      +-------+\n\
43///      | World |\n\
44///      +-------+\n\
45///      | !!!   |\n\
46///      +-------+"
47/// );
48///
49/// ```
50/// [`Table`]: crate::Table
51#[derive(Debug)]
52pub struct Remove<L, Target> {
53    locator: L,
54    target: PhantomData<Target>,
55}
56
57impl<L> Remove<L, TargetColumn> {
58    /// Remove columns.
59    ///
60    /// Available locators are:
61    ///
62    /// - [`Columns`]
63    /// - [`Column`]
64    /// - [`FirstColumn`]
65    /// - [`LastColumn`]
66    /// - [`ByColumnName`]
67    ///
68    /// ```rust
69    /// use tabled::{builder::Builder, settings::{Remove, location::ByColumnName, object::Columns}};
70    ///
71    /// let mut builder = Builder::default();
72    /// builder.push_record(["col1", "col2", "col3"]);
73    /// builder.push_record(["Hello", "World", "1"]);
74    ///
75    /// let table = builder.build()
76    ///     .with(Remove::column(ByColumnName::new("col3")))
77    ///     .to_string();
78    ///
79    /// assert_eq!(
80    ///     table,
81    ///     "+-------+-------+\n\
82    ///      | col1  | col2  |\n\
83    ///      +-------+-------+\n\
84    ///      | Hello | World |\n\
85    ///      +-------+-------+"
86    /// );
87    /// ```
88    ///
89    /// [`Columns`]: crate::settings::object::Columns
90    /// [`Column`]: crate::settings::object::Column
91    /// [`FirstColumn`]: crate::settings::object::FirstColumn
92    /// [`LastColumn`]: crate::settings::object::LastColumn
93    /// [`ByColumnName`]: crate::settings::location::ByColumnName
94    pub fn column(locator: L) -> Self {
95        Self {
96            locator,
97            target: PhantomData,
98        }
99    }
100}
101
102impl<L> Remove<L, TargetRow> {
103    /// Remove rows.
104    ///
105    /// Available locators are:
106    ///
107    /// - [`Rows`]
108    /// - [`Row`]
109    /// - [`FirstRow`]
110    /// - [`LastRow`]
111    ///
112    /// ```rust
113    /// use tabled::{settings::{Remove, object::Rows}, builder::Builder};
114    ///
115    /// let mut builder = Builder::default();
116    /// builder.push_record(["col1", "col2", "col3"]);
117    /// builder.push_record(["Hello", "World", "1"]);
118    ///
119    /// let table = builder.build()
120    ///     .with(Remove::row(Rows::first()))
121    ///     .to_string();
122    ///
123    /// assert_eq!(
124    ///     table,
125    ///     "+-------+-------+---+\n\
126    ///      | Hello | World | 1 |\n\
127    ///      +-------+-------+---+"
128    /// );
129    /// ```
130    ///
131    /// [`Rows`]: crate::settings::object::Rows
132    /// [`Row`]: crate::settings::object::Row
133    /// [`FirstRow`]: crate::settings::object::FirstRow
134    /// [`LastRow`]: crate::settings::object::LastRow
135    pub fn row(locator: L) -> Self {
136        Self {
137            locator,
138            target: PhantomData,
139        }
140    }
141}
142
143/// A marker struct for [`Remove`].
144#[derive(Debug)]
145pub struct TargetRow;
146
147/// A marker struct for [`Remove`].
148#[derive(Debug)]
149pub struct TargetColumn;
150
151impl<L, R, D, C> TableOption<R, C, D> for Remove<L, TargetColumn>
152where
153    L: Location<R, Coordinate = usize>,
154    R: Records + Resizable,
155{
156    fn change(mut self, records: &mut R, _: &mut C, _: &mut D) {
157        let columns = self.locator.locate(records).into_iter().collect::<Vec<_>>();
158
159        let mut shift = 0;
160        for col in columns.into_iter() {
161            if col - shift > records.count_columns() {
162                continue;
163            }
164
165            records.remove_column(col - shift);
166            shift += 1;
167        }
168
169        // fixme: I am pretty sure that we violate span constrains by removing rows/cols
170        //        Because span may be bigger then the max number of rows/cols
171    }
172}
173
174impl<L, R, D, C> TableOption<R, C, D> for Remove<L, TargetRow>
175where
176    L: Location<R, Coordinate = usize>,
177    R: ExactRecords + Resizable,
178{
179    fn change(mut self, records: &mut R, _: &mut C, _: &mut D) {
180        let rows = self.locator.locate(records).into_iter().collect::<Vec<_>>();
181
182        let mut shift = 0;
183        for row in rows.into_iter() {
184            if row - shift > records.count_rows() {
185                continue;
186            }
187
188            records.remove_row(row - shift);
189            shift += 1;
190        }
191
192        // fixme: I am pretty sure that we violate span constrains by removing rows/cols
193        //        Because span may be bigger then the max number of rows/cols
194    }
195}