etop_format/table_formats/
column_format.rs1use crate::{
2 BinaryFormat, BoolFormat, CellFormat, CellFormatShorthand, FormatError, NumberFormat,
3 StringFormat, UnknownFormat,
4};
5use polars::prelude::*;
6use unicode_truncate::{Alignment, UnicodeTruncateStr};
7
8#[derive(Debug, Clone)]
10pub struct ColumnFormatShorthand {
11 pub name: String,
13 pub display_name: String,
15 pub format: CellFormatShorthand,
17 pub align: ColumnAlign,
19}
20
21impl ColumnFormatShorthand {
22 pub fn finalize(self, dtype: &DataType) -> Result<ColumnFormat, FormatError> {
24 Ok(ColumnFormat {
25 name: self.name,
26 display_name: self.display_name,
27 format: self.format.finalize(dtype)?,
28 align: self.align,
29 })
30 }
31}
32
33impl Default for ColumnFormatShorthand {
34 fn default() -> ColumnFormatShorthand {
35 let format = UnknownFormat { min_width: None, max_width: None };
36 ColumnFormatShorthand {
37 name: "".to_string(),
38 display_name: "".to_string(),
39 format: CellFormatShorthand::Unknown(format),
40 align: ColumnAlign::Right,
41 }
42 }
43}
44
45#[derive(Debug, Clone)]
47pub struct ColumnFormat {
48 pub name: String,
50 pub display_name: String,
52 pub format: CellFormat,
54 pub align: ColumnAlign,
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
60pub enum ColumnAlign {
61 Left,
63 Right,
65}
66
67impl ColumnFormat {
68 pub fn header_width(&self) -> usize {
70 self.display_name
71 .split('\n')
72 .map(|s| s.chars().count())
75 .max()
76 .unwrap_or(0)
77 }
78
79 pub fn get_min_width(&self) -> usize {
81 self.format.get_min_width().unwrap_or(0)
82 }
83
84 pub fn get_max_width(&self) -> usize {
86 self.format.get_max_width().unwrap_or(usize::MAX)
87 }
88
89 pub fn format(&self, series: &Series) -> Result<Vec<String>, FormatError> {
91 let formatted: Result<Vec<String>, FormatError> = match series.dtype() {
92 DataType::Binary => {
93 let fmt: BinaryFormat = self.format.clone().try_into()?;
94 series.binary()?.into_iter().map(|v| fmt.format_option(v, "")).collect()
95 }
96 DataType::Utf8 => {
97 let fmt: StringFormat = self.format.clone().try_into()?;
98 series.utf8()?.into_iter().map(|v| fmt.format_option(v, "")).collect()
99 }
100 dtype if dtype.is_numeric() => {
101 let fmt: NumberFormat = self.format.clone().try_into()?;
102 series.to_float()?.f64()?.into_iter().map(|v| fmt.format_option(v, "")).collect()
103 }
104 DataType::Boolean => {
105 let fmt: BoolFormat = self.format.clone().try_into()?;
106 series.bool()?.into_iter().map(|v| fmt.format_option(v, "")).collect()
107 }
108 dtype => {
109 let message = format!("column {} has type {}", series.name(), dtype);
110 return Err(FormatError::UnsupportedDatatype(message));
111 }
112 };
113 let formatted = formatted?;
114
115 let max_width = formatted
116 .iter()
117 .map(|s| s.chars().count())
120 .max()
121 .unwrap_or(0);
122
123 let formatted = if self.align == ColumnAlign::Right {
124 formatted
125 .into_iter()
126 .map(|s| s.unicode_pad(max_width, Alignment::Right, true).to_string())
127 .collect()
128 } else {
129 formatted
130 .into_iter()
131 .map(|s| s.unicode_pad(max_width, Alignment::Left, true).to_string())
132 .collect()
133 };
134
135 Ok(formatted)
136 }
137}
138
139impl ColumnFormat {
141 pub fn name<T: AsRef<str>>(mut self, name: T) -> ColumnFormat {
143 let name = name.as_ref().to_string();
144 self.name = name.clone();
145 if self.display_name.is_empty() {
146 self.display_name = name
147 };
148 self
149 }
150
151 pub fn display_name<T: AsRef<str>>(mut self, display_name: T) -> ColumnFormat {
153 self.display_name = display_name.as_ref().to_string();
154 self
155 }
156
157 pub fn newline_underscores(mut self) -> ColumnFormat {
159 self.display_name = self.display_name.replace('_', "\n");
160 self
161 }
162
163 pub fn width(self, width: usize) -> ColumnFormat {
165 self.min_width(width).max_width(width)
166 }
167
168 pub fn min_width(mut self, width: usize) -> ColumnFormat {
170 self.format = self.format.min_width(width);
171 self
172 }
173
174 pub fn max_width(mut self, width: usize) -> ColumnFormat {
176 self.format = self.format.max_width(width);
177 self
178 }
179}
180
181impl ColumnFormatShorthand {
183 pub fn new() -> ColumnFormatShorthand {
185 ColumnFormatShorthand::default()
186 }
187
188 pub fn name<T: AsRef<str>>(mut self, name: T) -> ColumnFormatShorthand {
190 let name = name.as_ref().to_string();
191 self.name = name.clone();
192 if self.display_name.is_empty() {
193 self.display_name = name
194 };
195 self
196 }
197
198 pub fn display_name<T: AsRef<str>>(mut self, display_name: T) -> ColumnFormatShorthand {
200 self.display_name = display_name.as_ref().to_string();
201 self
202 }
203
204 pub fn newline_underscores(mut self) -> ColumnFormatShorthand {
206 self.display_name = self.display_name.replace('_', "\n");
207 self
208 }
209
210 pub fn width(self, width: usize) -> ColumnFormatShorthand {
212 self.min_width(width).max_width(width)
213 }
214
215 pub fn min_width(mut self, width: usize) -> ColumnFormatShorthand {
217 self.format = self.format.min_width(width);
218 self
219 }
220
221 pub fn max_width(mut self, width: usize) -> ColumnFormatShorthand {
223 self.format = self.format.max_width(width);
224 self
225 }
226
227 pub fn set_format<T: Into<CellFormatShorthand>>(mut self, format: T) -> ColumnFormatShorthand {
229 self.format = format.into();
230 self
231 }
232}