use crate::table_theme::TableTheme; use nu_ansi_term::Style; use nu_color_config::TextStyle; use nu_protocol::TrimStrategy; use std::{cmp::min, collections::HashMap}; use tabled::{ alignment::AlignmentHorizontal, builder::Builder, color::Color, formatting::AlignmentStrategy, object::{Cell, Columns, Rows, Segment}, papergrid::{ records::{ cell_info::CellInfo, tcell::TCell, vec_records::VecRecords, Records, RecordsMut, }, util::string_width_multiline, width::{CfgWidthFunction, WidthEstimator}, Estimate, }, peaker::Peaker, Alignment, Modify, ModifyObject, TableOption, Width, }; /// Table represent a table view. #[derive(Debug, Clone)] pub struct Table { data: Data, } type Data = VecRecords, TextStyle>>; impl Table { /// Creates a [Table] instance. /// /// If `headers.is_empty` then no headers will be rendered. pub fn new(data: Vec, TextStyle>>>, size: (usize, usize)) -> Table { // it's not guaranteed that data will have all rows with the same number of columns. // but VecRecords::with_hint require this constrain. // // so we do a check to make it certainly true let mut data = data; make_data_consistent(&mut data, size); let data = VecRecords::with_hint(data, size.1); Table { data } } pub fn count_rows(&self) -> usize { self.data.count_rows() } pub fn create_cell( text: impl Into, style: TextStyle, ) -> TCell, TextStyle> { TCell::new(CellInfo::new(text.into(), CfgWidthFunction::new(4)), style) } pub fn truncate(&mut self, width: usize, theme: &TableTheme) -> bool { let mut truncated = false; while self.data.count_rows() > 0 && self.data.count_columns() > 0 { let total; { let mut table = Builder::custom(self.data.clone()).build(); load_theme(&mut table, theme, false, false, None); total = table.total_width(); } if total > width { truncated = true; self.data.truncate(self.data.count_columns() - 1); } else { break; } } let is_empty = self.data.count_rows() == 0 || self.data.count_columns() == 0; if is_empty { return true; } if truncated { self.data.push(Table::create_cell( String::from("..."), TextStyle::default(), )); } false } /// Converts a table to a String. /// /// It returns None in case where table cannot be fit to a terminal width. pub fn draw(self, config: TableConfig, termwidth: usize) -> Option { build_table(self.data, config, termwidth) } } fn make_data_consistent(data: &mut Vec>>, size: (usize, usize)) { for row in data { if row.len() < size.1 { row.extend( std::iter::repeat(Table::create_cell(String::default(), TextStyle::default())) .take(size.1 - row.len()), ); } } } #[derive(Debug, Clone)] pub struct TableConfig { theme: TableTheme, alignments: Alignments, trim: TrimStrategy, split_color: Option