use std::vec;
pub struct Table {
pub headers: Vec<String>,
pub rows: Vec<Vec<String>>,
size: usize,
sizes: Vec<usize>,
}
impl Table {
pub fn new(headers: Vec<String>, rows: Vec<Vec<String>>) -> Self {
let mut content = vec![headers];
for row in rows {
content.push(row)
}
let mut max_len = content[0].len();
for i in 0..content.len() {
let len = content[i].len();
if len > max_len {
max_len = len;
}
}
for i in 0..content.len() {
let len = content[i].len();
if len != max_len {
for _ in 0..max_len - len {
content[i].push(String::from("<None>"));
}
}
}
let new_headers = &content[0];
let new_rows = &content[1..];
let (x, _) = termion::terminal_size().unwrap();
let mut s = Self {
headers: new_headers.to_vec(),
rows: new_rows.to_vec(),
size: x as usize,
sizes: vec![0; new_headers.to_vec().len()],
};
s.set_sizes();
s
}
pub fn draw(&self) {
self.draw_header();
self.draw_rows();
}
fn draw_horizontal(&self) {
let border = "-".repeat(self.size as usize);
println!("{}", border)
}
fn set_sizes(&mut self) {
let headers = &self.headers;
let rows = &self.rows;
let mut content = vec![headers];
for row in rows {
content.push(row)
}
let mut max_lens = vec![0; content[0].len()];
for i in 0..content.len() {
for j in 0..content[i].len() {
let mut len = content[i][j].len() + 3;
if j == 0 {
len += 1;
}
if max_lens[j] < len {
max_lens[j] = len;
}
}
}
let mut summaric_len: usize;
let mut i = 0;
loop {
let value = max_lens[i];
let mut max = max_lens[0];
for i in 0..max_lens.len() {
if max_lens[i] > max {
max = max_lens[i];
}
}
if value != 3 && max == value {
max_lens[i] = max_lens[i] - 1;
}
i = (i + 1) % max_lens.len();
summaric_len = max_lens.iter().sum();
if summaric_len <= self.size {
break;
}
}
self.sizes = max_lens;
self.size = summaric_len;
}
fn draw_header(&self) {
self.draw_horizontal();
let headers = self.headers.to_vec();
let sizes = self.sizes.to_vec();
for i in 0..headers.len() {
let has_right = if i == 0 { 1 } else { 0 };
let total_space = sizes[i];
let whitespace_len = total_space - (headers[i].len() + has_right + 1);
let whitespace_left_len = (whitespace_len as f32 / 2_f32).floor() as usize;
let whitespace_right_len = whitespace_len - whitespace_left_len;
let whitespace_left = " ".repeat(whitespace_left_len);
let whitespace_right = " ".repeat(whitespace_right_len);
let cell_string = format!(
"{}{}{}{}|",
if has_right == 1 { "|" } else { "" },
whitespace_left,
headers[i],
whitespace_right
);
print!("{}", cell_string);
if i == headers.len() - 1 {
println!();
}
}
self.draw_horizontal();
}
fn draw_rows(&self) {
let headers = self.rows.to_vec();
let sizes = self.sizes.to_vec();
for j in 0..headers.len() {
for i in 0..headers[j].len() {
let has_right = if i == 0 { 1 } else { 0 };
let max_space = if headers[j][i].len() > sizes[i] {
sizes[i] - 3
} else {
headers[j][i].len()
};
let cell_string = &format!(
"{} {}",
if has_right == 1 { "|" } else { "" },
&headers[j][i][..max_space],
);
let cs;
if sizes[i] > cell_string.len() + 2 {
let whitespace_right_len = sizes[i] - (cell_string.len() + 1);
let whitespace_right = " ".repeat(whitespace_right_len);
cs = format!("{}{}|", cell_string, whitespace_right);
} else {
cs = format!("{} |", cell_string);
}
print!("{}", cs);
if i == headers.len() - 1 {}
}
println!();
if j != headers.len() - 1 {
self.draw_horizontal();
}
}
self.draw_horizontal();
}
}