tabled/features/width/
min_width.rs
1use std::marker::PhantomData;
4
5use papergrid::{
6 records::{Records, RecordsMut},
7 width::CfgWidthFunction,
8 Entity,
9};
10
11use crate::{
12 measurment::Measurment,
13 peaker::{Peaker, PriorityNone},
14 CellOption, Table, TableOption, Width,
15};
16
17use super::get_table_widths_with_total;
18
19#[derive(Debug)]
55pub struct MinWidth<W = usize, P = PriorityNone> {
56 width: W,
57 fill: char,
58 _priority: PhantomData<P>,
59}
60
61impl<W> MinWidth<W>
62where
63 W: Measurment<Width>,
64{
65 pub fn new(width: W) -> Self {
67 Self {
68 width,
69 fill: ' ',
70 _priority: PhantomData::default(),
71 }
72 }
73}
74
75impl<W, P> MinWidth<W, P> {
76 pub fn fill_with(mut self, c: char) -> Self {
81 self.fill = c;
82 self
83 }
84
85 pub fn priority<PP: Peaker>(self) -> MinWidth<W, PP> {
94 MinWidth {
95 fill: self.fill,
96 width: self.width,
97 _priority: PhantomData::default(),
98 }
99 }
100}
101
102impl<W, R> CellOption<R> for MinWidth<W>
103where
104 W: Measurment<Width>,
105 R: Records + RecordsMut<String>,
106{
107 fn change_cell(&mut self, table: &mut Table<R>, entity: Entity) {
108 let width_ctrl = CfgWidthFunction::from_cfg(table.get_config());
109 let width = self.width.measure(table.get_records(), table.get_config());
110
111 let (count_rows, count_cols) = table.shape();
112 for pos in entity.iter(count_rows, count_cols) {
113 let records = table.get_records();
114 let cell_width = records.get_width(pos, &width_ctrl);
115 if cell_width >= width {
116 continue;
117 }
118
119 let content = records.get_text(pos);
120 let content = increase_width(content, width, self.fill);
121 let records = table.get_records_mut();
122 records.set(pos, content, &width_ctrl);
123 }
124
125 table.destroy_width_cache();
126 }
127}
128
129impl<W, P, R> TableOption<R> for MinWidth<W, P>
130where
131 W: Measurment<Width>,
132 P: Peaker,
133 R: Records + RecordsMut<String>,
134{
135 fn change(&mut self, table: &mut Table<R>) {
136 if table.is_empty() {
137 return;
138 }
139
140 let width = self.width.measure(table.get_records(), table.get_config());
141 let (widths, total_width) =
142 get_table_widths_with_total(table.get_records(), table.get_config());
143 if total_width >= width {
144 return;
145 }
146
147 increase_total_width(table, widths, total_width, width, P::create());
148 }
149}
150
151#[cfg(not(feature = "color"))]
152fn increase_width(s: &str, width: usize, fill_with: char) -> String {
153 use papergrid::util::string_width;
154
155 s.lines()
156 .map(|line| {
157 let length = string_width(line);
158 if width > length {
159 let remain = width - length;
160 let mut new_line = String::with_capacity(width);
161 new_line.push_str(line);
162 new_line.extend(std::iter::repeat(fill_with).take(remain));
163 std::borrow::Cow::Owned(new_line)
164 } else {
165 std::borrow::Cow::Borrowed(line)
166 }
167 })
168 .collect::<Vec<_>>()
169 .join("\n")
170}
171
172#[cfg(feature = "color")]
173fn increase_width(s: &str, width: usize, fill_with: char) -> String {
174 use papergrid::util::string_width;
175
176 ansi_str::AnsiStr::ansi_split(s, "\n")
177 .map(|line| {
178 let length = string_width(&line);
179 if length < width {
180 let mut line = line.into_owned();
181 let remain = width - length;
182 line.extend(std::iter::repeat(fill_with).take(remain));
183 std::borrow::Cow::Owned(line)
184 } else {
185 line
186 }
187 })
188 .collect::<Vec<_>>()
189 .join("\n")
190}
191
192fn increase_total_width<P, R>(
193 table: &mut Table<R>,
194 widths: Vec<usize>,
195 total_width: usize,
196 expected_width: usize,
197 priority: P,
198) where
199 P: Peaker,
200 R: Records + RecordsMut<String>,
201{
202 let increase_list = get_increase_list(widths, expected_width, total_width, priority);
203 table.cache_width(increase_list);
204}
205
206fn get_increase_list<F>(
207 mut widths: Vec<usize>,
208 total_width: usize,
209 mut width: usize,
210 mut peaker: F,
211) -> Vec<usize>
212where
213 F: Peaker,
214{
215 while width != total_width {
216 let col = match peaker.peak(&[], &widths) {
217 Some(col) => col,
218 None => break,
219 };
220
221 widths[col] += 1;
222 width += 1;
223 }
224
225 widths
226}