1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
use std::{
fmt::{self, Display},
iter::FromIterator,
string::ToString,
};
use tabled::{
grid::config::ColoredConfig,
grid::dimension::CompleteDimensionVecRecords,
grid::records::vec_records::{Text, VecRecords},
settings::{object::Segment, Alignment, Modify, TableOption},
Table, Tabled,
};
use super::matrix_list::MatrixList;
/// A helper table factory.
///
/// It uses center alignment by default, because it's more complex and may spot more issues.
#[derive(Debug, Clone)]
pub struct Matrix {
data: Vec<Vec<String>>,
size: (usize, usize),
}
impl Matrix {
pub fn empty() -> Self {
Self {
data: vec![],
size: (0, 0),
}
}
pub fn with_no_frame(rows: usize, columns: usize) -> Self {
Self {
data: create_matrix(rows, columns),
size: (rows, columns),
}
}
pub fn new(rows: usize, columns: usize) -> Self {
Self::with_no_frame(rows, columns)
.with_header()
.with_index()
}
pub fn vec(rows: usize, columns: usize) -> Vec<Vec<String>> {
Self::new(rows, columns).to_vec()
}
pub fn table(rows: usize, columns: usize) -> Table {
Self::new(rows, columns).to_table()
}
pub fn list<const ROWS: usize, const COLUMNS: usize>() -> Vec<MatrixList<COLUMNS, true>> {
create_list::<ROWS, COLUMNS>()
}
pub fn iter<I, T>(iter: I) -> Table
where
I: IntoIterator<Item = T>,
T: Tabled,
{
let mut table = tabled::Table::new(iter);
table.with(Modify::new(Segment::all()).with(Alignment::center()));
table
}
pub fn with_index(mut self) -> Self {
set_index(&mut self.data);
self
}
pub fn with_header(mut self) -> Self {
set_header(&mut self.data, self.size.1);
self
}
pub fn insert<V: ToString>(mut self, pos: tabled::grid::config::Position, value: V) -> Self {
self.data[pos.row()][pos.col()] = value.to_string();
self
}
pub fn to_table(&self) -> Table {
let mut table = tabled::Table::from_iter(self.data.clone());
table.with(Modify::new(Segment::all()).with(Alignment::center()));
table
}
pub fn to_vec(&self) -> Vec<Vec<String>> {
self.data.clone()
}
pub fn with<O>(self, opt: O) -> Table
where
for<'a> O:
TableOption<VecRecords<Text<String>>, ColoredConfig, CompleteDimensionVecRecords<'a>>,
{
let mut table = self.to_table();
table.with(opt);
table
}
}
impl Display for Matrix {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.clone().to_table().fmt(f)
}
}
fn create_matrix(rows: usize, columns: usize) -> Vec<Vec<String>> {
let mut arr = Vec::with_capacity(rows);
for row in 0..rows {
let mut data = Vec::with_capacity(columns);
for column in 0..columns {
let text = format!("{row}-{column}");
data.push(text);
}
arr.push(data);
}
arr
}
fn set_header(data: &mut Vec<Vec<String>>, columns: usize) {
data.insert(
0,
(0..columns)
.map(|n| format!("column {n}"))
.collect::<Vec<_>>(),
);
}
fn set_index(data: &mut [Vec<String>]) {
if data.is_empty() {
return;
}
data[0].insert(0, "N".to_owned());
for (n, row) in data.iter_mut().skip(1).enumerate() {
row.insert(0, n.to_string());
}
}
fn create_list<const ROWS: usize, const COLUMNS: usize>() -> Vec<MatrixList<COLUMNS, true>> {
let mut arr = Vec::with_capacity(ROWS);
for row in 0..ROWS {
let data = (0..COLUMNS)
.map(|column| format!("{row}-{column}"))
.collect::<Vec<_>>();
let list = MatrixList::with_index(row, data);
arr.push(list);
}
arr
}
|