1use std::fmt::Display;
18use tabled::{
19 Table,
20 settings::{
21 Format, Modify, Panel, Remove,
22 object::{Rows, Segment},
23 style::Style,
24 },
25};
26
27pub use tabled::settings::Padding;
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
31pub enum TableStyle {
32 #[default]
34 Modern,
35 Borderless,
37 Markdown,
39 Sharp,
41 Ascii,
43 Psql,
45 Dots,
47}
48
49impl TableStyle {
50 pub fn apply(self, table: &mut Table) {
52 match self {
53 TableStyle::Modern => {
54 table.with(Style::rounded());
55 }
56 TableStyle::Borderless => {
57 table.with(Style::blank());
58 }
59 TableStyle::Markdown => {
60 table.with(Style::markdown());
61 }
62 TableStyle::Sharp => {
63 table.with(Style::sharp());
64 }
65 TableStyle::Ascii => {
66 table.with(Style::ascii());
67 }
68 TableStyle::Psql => {
69 table.with(Style::psql());
70 }
71 TableStyle::Dots => {
72 table.with(Style::dots());
73 }
74 }
75 }
76}
77
78pub struct StyledTable {
80 style: TableStyle,
81 header: Option<String>,
82 remove_header_row: bool,
83 padding: Option<Padding>,
84 newline_replacement: Option<String>,
85}
86
87impl Default for StyledTable {
88 fn default() -> Self {
89 Self::new()
90 }
91}
92
93impl StyledTable {
94 pub fn new() -> Self {
96 Self {
97 style: TableStyle::default(),
98 header: None,
99 remove_header_row: false,
100 padding: None,
101 newline_replacement: None,
102 }
103 }
104
105 pub fn style(mut self, style: TableStyle) -> Self {
107 self.style = style;
108 self
109 }
110
111 pub fn header(mut self, header: impl Into<String>) -> Self {
113 self.header = Some(header.into());
114 self
115 }
116
117 pub fn remove_header_row(mut self) -> Self {
121 self.remove_header_row = true;
122 self
123 }
124
125 pub fn padding(mut self, padding: Padding) -> Self {
129 self.padding = Some(padding);
130 self
131 }
132
133 pub fn replace_newlines(mut self, replacement: impl Into<String>) -> Self {
138 self.newline_replacement = Some(replacement.into());
139 self
140 }
141
142 pub fn build<T: tabled::Tabled>(self, data: Vec<T>) -> Table {
144 let mut table = Table::new(data);
145
146 self.style.apply(&mut table);
147
148 if let Some(header) = self.header {
149 table.with(Panel::header(header));
150 }
151
152 if let Some(padding) = self.padding {
153 table.with(padding);
154 }
155
156 if self.remove_header_row {
157 table.with(Remove::row(Rows::first()));
158 }
159
160 if let Some(replacement) = self.newline_replacement {
161 table.with(
162 Modify::new(Segment::all())
163 .with(Format::content(move |s| s.replace('\n', &replacement))),
164 );
165 }
166
167 table
168 }
169}
170
171pub fn display_option<T: Display>(opt: &Option<T>) -> String {
175 opt.as_ref().map_or_else(String::new, |val| val.to_string())
176}
177
178pub fn display_option_or<T: Display>(opt: &Option<T>, default: &str) -> String {
180 opt.as_ref()
181 .map_or_else(|| default.to_string(), |val| val.to_string())
182}