tabled/settings/merge/
mod.rs1use crate::{
6 grid::config::ColoredConfig,
7 grid::records::{ExactRecords, PeekableRecords, Records},
8 settings::TableOption,
9};
10
11#[derive(Debug)]
15pub struct Merge;
16
17impl Merge {
18 pub fn vertical() -> MergeDuplicatesVertical {
20 MergeDuplicatesVertical
21 }
22
23 pub fn horizontal() -> MergeDuplicatesHorizontal {
25 MergeDuplicatesHorizontal
26 }
27}
28
29#[derive(Debug)]
35pub struct MergeDuplicatesVertical;
36
37impl<R, D> TableOption<R, ColoredConfig, D> for MergeDuplicatesVertical
38where
39 R: Records + PeekableRecords + ExactRecords,
40{
41 #[allow(clippy::assigning_clones)]
42 fn change(self, records: &mut R, cfg: &mut ColoredConfig, _: &mut D) {
45 let count_rows = records.count_rows();
46 let count_cols = records.count_columns();
47
48 if count_rows == 0 || count_cols == 0 {
49 return;
50 }
51
52 for column in 0..count_cols {
53 let mut repeat_length = 0;
54 let mut repeat_value = String::new();
55 let mut repeat_is_set = false;
56 let mut last_is_row_span = false;
57 for row in (0..count_rows).rev() {
58 if last_is_row_span {
59 last_is_row_span = false;
60 continue;
61 }
62
63 let is_cell_visible = cfg.is_cell_visible((row, column).into());
65 let is_row_span_cell = cfg.get_column_span((row, column).into()).is_some();
66
67 if !repeat_is_set {
68 if !is_cell_visible {
69 continue;
70 }
71
72 if is_row_span_cell {
73 continue;
74 }
75
76 repeat_length = 1;
77 repeat_value = records.get_text((row, column).into()).to_owned();
78 repeat_is_set = true;
79 continue;
80 }
81
82 if is_row_span_cell {
83 repeat_is_set = false;
84 last_is_row_span = true;
85 continue;
86 }
87
88 if !is_cell_visible {
89 repeat_is_set = false;
90 continue;
91 }
92
93 let text = records.get_text((row, column).into());
94 let is_duplicate = text == repeat_value;
95
96 if is_duplicate {
97 repeat_length += 1;
98 continue;
99 }
100
101 if repeat_length > 1 {
102 cfg.set_row_span((row + 1, column).into(), repeat_length);
103 }
104
105 repeat_length = 1;
106 repeat_value = records.get_text((row, column).into()).to_owned();
107 }
108
109 if repeat_length > 1 {
110 cfg.set_row_span((0, column).into(), repeat_length);
111 }
112 }
113 }
114}
115
116#[derive(Debug)]
122pub struct MergeDuplicatesHorizontal;
123
124impl<R, D> TableOption<R, ColoredConfig, D> for MergeDuplicatesHorizontal
125where
126 R: Records + PeekableRecords + ExactRecords,
127{
128 #[allow(clippy::assigning_clones)]
129 fn change(self, records: &mut R, cfg: &mut ColoredConfig, _: &mut D) {
132 let count_rows = records.count_rows();
133 let count_cols = records.count_columns();
134
135 if count_rows == 0 || count_cols == 0 {
136 return;
137 }
138
139 for row in 0..count_rows {
140 let mut repeat_length = 0;
141 let mut repeat_value = String::new();
142 let mut repeat_is_set = false;
143 let mut last_is_col_span = false;
144
145 for column in (0..count_cols).rev() {
146 if last_is_col_span {
147 last_is_col_span = false;
148 continue;
149 }
150
151 let is_cell_visible = cfg.is_cell_visible((row, column).into());
153 let is_col_span_cell = cfg.get_row_span((row, column).into()).is_some();
154
155 if !repeat_is_set {
156 if !is_cell_visible {
157 continue;
158 }
159
160 if is_col_span_cell {
161 continue;
162 }
163
164 repeat_length = 1;
165 repeat_value = records.get_text((row, column).into()).to_owned();
166 repeat_is_set = true;
167 continue;
168 }
169
170 if is_col_span_cell {
171 repeat_is_set = false;
172 last_is_col_span = true;
173 continue;
174 }
175
176 if !is_cell_visible {
177 repeat_is_set = false;
178 continue;
179 }
180
181 let text = records.get_text((row, column).into());
182 let is_duplicate = text == repeat_value;
183
184 if is_duplicate {
185 repeat_length += 1;
186 continue;
187 }
188
189 if repeat_length > 1 {
190 cfg.set_column_span((row, column + 1).into(), repeat_length);
191 }
192
193 repeat_length = 1;
194 repeat_value = records.get_text((row, column).into()).to_owned();
195 }
196
197 if repeat_length > 1 {
198 cfg.set_column_span((row, 0).into(), repeat_length);
199 }
200 }
201 }
202}