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}