From 388d496e466085c2fadbea5ffa4e842682f4738e Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 31 Aug 2024 09:28:30 +0300 Subject: [PATCH 1/9] format_tools : evolve records format --- .../src/format/output_format/records.rs | 77 +++++++++++++++++-- module/core/format_tools/src/format/print.rs | 16 ++-- .../format_tools/tests/inc/collection_test.rs | 1 - .../tests/inc/format_records_test.rs | 2 +- 4 files changed, 78 insertions(+), 18 deletions(-) diff --git a/module/core/format_tools/src/format/output_format/records.rs b/module/core/format_tools/src/format/output_format/records.rs index 263177edb8..d4d61d6d6f 100644 --- a/module/core/format_tools/src/format/output_format/records.rs +++ b/module/core/format_tools/src/format/output_format/records.rs @@ -63,28 +63,89 @@ impl Default for Records impl TableOutputFormat for Records { - fn extract_write< 'buf, 'data > - ( + + fn extract_write< 'buf, 'data >( & self, x : & InputExtract< 'data >, c : & mut Context< 'buf >, ) -> fmt::Result { - for ( i, row ) in x.row_descriptors.iter().enumerate() + // Calculate max width for each column + // let mut labels = vec![ "".to_string(); x.row_descriptors.len() ]; + let mut max_widths = vec![ 0; x.col_descriptors.len() ]; + + for ( icol, _col ) in x.col_descriptors.iter().enumerate() + { + // labels[ icol ] = format!( " = {}\n", icol ); + // println!( "labels[ icol ] : {}", labels[ icol ].len() ); + + // let label = &labels[ icol ]; + max_widths[ icol ] = 0; + for row_data in &x.data + { + let sz = string::size( &row_data[ icol ].0 ); + if sz[ 0 ] > max_widths[ icol ] + { + max_widths[ icol ] = sz[ 0 ]; + } + } + + } + + // + + // xxx : test with highest title + + let mut slices_dim = [ 1, x.mcells[ 0 ], x.mcells[ 1 ] ]; + slices_dim[ 0 ] = x.row_descriptors + .iter() + .fold( 0, | acc : usize, row | acc.max( row.height ) ) + ; + + let slices_len = slices_dim[ 0 ] * slices_dim[ 1 ] * slices_dim[ 2 ]; + let slices : Vec< &str > = vec![ "" ; slices_len ]; + let labels : Vec< &str > = vec![ "" ; slices_dim[ 0 ] ]; + +// let mut irow : isize = -1; +// for row_data in x.data.iter() +// { +// +// irow += 1; +// +// for icol in 0 .. x.col_descriptors.len() +// { +// let cell = &row_data[ icol ]; +// string::lines( cell.0.as_ref() ) +// .enumerate() +// .for_each( | ( layer, s ) | +// { +// let md_index = [ layer, icol, irow as usize ]; +// slices[ x.slices_dim.md_offset( md_index ) ] = s; +// }) +// ; +// x.col_descriptors[ icol ].label = cell.0.as_ref(); // xxx +// } +// +// } + + // Write each record + for ( irow, row ) in x.row_descriptors.iter().enumerate() { if !row.vis { continue; } - writeln!( c.buf, "-[ RECORD {} ]", i + 1 )?; - for ( icol, col ) in x.col_descriptors.iter().enumerate() + writeln!( c.buf, "{}", irow )?; + for ( icol, _col ) in x.col_descriptors.iter().enumerate() { - // let cell_width = x.data[ i ][ icol ].1[ 0 ]; - let md_index = [ 0, icol, i ]; + let md_index = [ 0, icol, irow ]; let slice = x.slices[ x.slices_dim.md_offset( md_index ) ]; - writeln!( c.buf, "{} | {}", col.width, slice )?; + let width = max_widths[ icol ]; + writeln!( c.buf, "{: { pub icol : usize, pub width : usize, + pub label : &'label str, } /// A struct for extracting and organizing table data for formatting. @@ -270,12 +271,9 @@ mod private /// Descriptors for each column, including optional title, width, and index. // width, index - // pub col_descriptors : Vec< ( usize, usize ) >, - pub col_descriptors : Vec< ColDescriptor >, + pub col_descriptors : Vec< ColDescriptor< 'data > >, /// Descriptors for each row, including height. - // height - // pub row_descriptors : Vec< ( usize, ) >, pub row_descriptors : Vec< RowDescriptor >, /// Extracted data for each cell, including string content and size. @@ -306,6 +304,7 @@ mod private -> fmt::Result where 'data : 't, + // 't : 'data, Table : TableRows< RowKey = RowKey, Row = Row, CellKey = CellKey, CellRepr = CellRepr >, Table : TableHeader< CellKey = CellKey >, RowKey : table::RowKey, @@ -323,7 +322,7 @@ mod private // key width, index let mut key_to_ikey : HashMap< &'t CellKey, usize > = HashMap::new(); - let mut col_descriptors : Vec< ColDescriptor > = Vec::with_capacity( mcells[ 0 ] ); + let mut col_descriptors : Vec< ColDescriptor< '_ > > = Vec::with_capacity( mcells[ 0 ] ); let mut row_descriptors : Vec< RowDescriptor > = Vec::with_capacity( mcells[ 1 ] ); let mut has_header = false; @@ -377,12 +376,13 @@ mod private { let col = &mut col_descriptors[ *icol ]; col.width = col.width.max( sz[ 0 ] ); + col.label = ""; // xxx }) .or_insert_with( || { let icol = l; let width = sz[ 0 ]; - let col = ColDescriptor { width, icol }; + let col = ColDescriptor { width, icol, label : "" }; // xxx col_descriptors.push( col ); icol }); @@ -496,7 +496,6 @@ mod private std::mem::swap( &mut x.slices, &mut slices ); let mut irow : isize = -1; - for row_data in x.data.iter() { @@ -513,6 +512,7 @@ mod private slices[ x.slices_dim.md_offset( md_index ) ] = s; }) ; + x.col_descriptors[ icol ].label = cell.0.as_ref(); // xxx } } diff --git a/module/core/format_tools/tests/inc/collection_test.rs b/module/core/format_tools/tests/inc/collection_test.rs index 941f9a498b..2178a52991 100644 --- a/module/core/format_tools/tests/inc/collection_test.rs +++ b/module/core/format_tools/tests/inc/collection_test.rs @@ -12,7 +12,6 @@ use the_module:: use std:: { collections::HashMap, - // borrow::Cow, }; use test_object::TestObject; diff --git a/module/core/format_tools/tests/inc/format_records_test.rs b/module/core/format_tools/tests/inc/format_records_test.rs index c1e2cf2b26..6e591199ab 100644 --- a/module/core/format_tools/tests/inc/format_records_test.rs +++ b/module/core/format_tools/tests/inc/format_records_test.rs @@ -48,7 +48,7 @@ fn basic() // gap | 5 let exp = r#"xxx"#; - // a_id!( output.as_str(), exp ); + a_id!( output.as_str(), exp ); } From 99fe76c79af88887780711e12f6d13b9e2d3a224 Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 31 Aug 2024 09:30:01 +0300 Subject: [PATCH 2/9] format_tools : refactoring --- module/core/format_tools/src/format/print.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/core/format_tools/src/format/print.rs b/module/core/format_tools/src/format/print.rs index 6ca81a37a1..266bd69679 100644 --- a/module/core/format_tools/src/format/print.rs +++ b/module/core/format_tools/src/format/print.rs @@ -282,9 +282,9 @@ mod private /// Dimensions of slices for retrieving data from multi-matrix. pub slices_dim : [ usize ; 3 ], - /// Extracted slices or strings for further processing. pub slices : Vec< &'data str >, + // xxx : move out that maybe } From fcde098926f35505c436939579e8a75967e51145 Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 31 Aug 2024 18:21:14 +0300 Subject: [PATCH 3/9] format_tools : evolve records format --- .../src/format/output_format/records.rs | 204 ++++++++++++------ module/core/format_tools/src/format/print.rs | 73 ++++++- .../tests/inc/format_records_test.rs | 24 ++- 3 files changed, 238 insertions(+), 63 deletions(-) diff --git a/module/core/format_tools/src/format/output_format/records.rs b/module/core/format_tools/src/format/output_format/records.rs index d4d61d6d6f..ced3afad3d 100644 --- a/module/core/format_tools/src/format/output_format/records.rs +++ b/module/core/format_tools/src/format/output_format/records.rs @@ -39,7 +39,51 @@ use std::sync::OnceLock; /// `Records` provides an implementation for table formatting that outputs /// each row as a separate table with 2 columns, first is name of column in the original data and second is cell value itself. #[derive( Debug )] -pub struct Records; +pub struct Records +{ + /// Delimitting header with grid line or not. + pub delimitting_header : bool, + /// Prefix added to each row. + pub table_prefix : String, + /// Postfix added to each row. + pub table_postfix : String, + /// Separator used between rows. + pub table_separator : String, + /// Prefix added to each row. + pub row_prefix : String, + /// Postfix added to each row. + pub row_postfix : String, + /// Separator used between rows. + pub row_separator : String, + /// Prefix added to each cell. + pub cell_prefix : String, + /// Postfix added to each cell. + pub cell_postfix : String, + /// Separator used between table columns. + pub cell_separator : String, + /// Horizontal line character. + pub h : char, + /// Vertical line character. + pub v : char, + /// Left T-junction character. + pub t_l : char, + /// Right T-junction character. + pub t_r : char, + /// Top T-junction character. + pub t_t : char, + /// Bottom T-junction character. + pub t_b : char, + /// Cross junction character. + pub cross : char, + /// Top-left corner character. + pub corner_lt : char, + /// Top-right corner character. + pub corner_rt : char, + /// Bottom-left corner character. + pub corner_lb : char, + /// Bottom-right corner character. + pub corner_rb : char, +} impl Records { @@ -47,7 +91,7 @@ impl Records pub fn instance() -> & 'static dyn TableOutputFormat { static INSTANCE : OnceLock< Records > = OnceLock::new(); - INSTANCE.get_or_init( || Records ) + INSTANCE.get_or_init( || Records::default() ) } } @@ -55,12 +99,68 @@ impl Default for Records { fn default() -> Self { + + let delimitting_header = true; + + let cell_prefix = "".to_string(); + let cell_postfix = "".to_string(); + let cell_separator = " │ ".to_string(); + let row_prefix = "│ ".to_string(); + let row_postfix = " │".to_string(); + let row_separator = "\n".to_string(); + let table_prefix = "".to_string(); + let table_postfix = "".to_string(); + let table_separator = "\n".to_string(); + + let h = '─'; + let v = '|'; + let t_l = '├'; + let t_r = '┤'; + let t_t = '┬'; + let t_b = '┴'; + let cross = '┼'; + let corner_lt = '┌'; + let corner_rt = '┐'; + let corner_lb = '└'; + let corner_rb = '┘'; + Self { + delimitting_header, + table_prefix, + table_postfix, + table_separator, + row_prefix, + row_postfix, + row_separator, + cell_prefix, + cell_postfix, + cell_separator, + h, + v, + t_l, + t_r, + t_t, + t_b, + cross, + corner_lt, + corner_rt, + corner_lb, + corner_rb, } } } +// impl Default for Records +// { +// fn default() -> Self +// { +// Self +// { +// } +// } +// } + impl TableOutputFormat for Records { @@ -70,81 +170,63 @@ impl TableOutputFormat for Records c : & mut Context< 'buf >, ) -> fmt::Result { - // Calculate max width for each column - // let mut labels = vec![ "".to_string(); x.row_descriptors.len() ]; - let mut max_widths = vec![ 0; x.col_descriptors.len() ]; - for ( icol, _col ) in x.col_descriptors.iter().enumerate() + let label_width = x.header().fold( 0, | acc, cell | acc.max( cell.1[ 0 ] ) ); + + write!( c.buf, "{}", self.table_prefix )?; + + // Write each record + for ( irow, row ) in x.rows() { - // labels[ icol ] = format!( " = {}\n", icol ); - // println!( "labels[ icol ] : {}", labels[ icol ].len() ); - // let label = &labels[ icol ]; - max_widths[ icol ] = 0; - for row_data in &x.data + if irow > 0 { - let sz = string::size( &row_data[ icol ].0 ); - if sz[ 0 ] > max_widths[ icol ] - { - max_widths[ icol ] = sz[ 0 ]; - } + write!( c.buf, "{}", self.table_separator )?; } - } - - // - - // xxx : test with highest title + let slice_width = x.data[ irow ].iter().fold( 0, | acc, cell | acc.max( cell.1[ 0 ] ) ); - let mut slices_dim = [ 1, x.mcells[ 0 ], x.mcells[ 1 ] ]; - slices_dim[ 0 ] = x.row_descriptors - .iter() - .fold( 0, | acc : usize, row | acc.max( row.height ) ) - ; - - let slices_len = slices_dim[ 0 ] * slices_dim[ 1 ] * slices_dim[ 2 ]; - let slices : Vec< &str > = vec![ "" ; slices_len ]; - let labels : Vec< &str > = vec![ "" ; slices_dim[ 0 ] ]; - -// let mut irow : isize = -1; -// for row_data in x.data.iter() -// { -// -// irow += 1; -// -// for icol in 0 .. x.col_descriptors.len() -// { -// let cell = &row_data[ icol ]; -// string::lines( cell.0.as_ref() ) -// .enumerate() -// .for_each( | ( layer, s ) | -// { -// let md_index = [ layer, icol, irow as usize ]; -// slices[ x.slices_dim.md_offset( md_index ) ] = s; -// }) -// ; -// x.col_descriptors[ icol ].label = cell.0.as_ref(); // xxx -// } -// -// } - - // Write each record - for ( irow, row ) in x.row_descriptors.iter().enumerate() - { if !row.vis { continue; } - writeln!( c.buf, "{}", irow )?; + writeln!( c.buf, " = {}", irow )?; + for ( icol, _col ) in x.col_descriptors.iter().enumerate() { - let md_index = [ 0, icol, irow ]; - let slice = x.slices[ x.slices_dim.md_offset( md_index ) ]; - let width = max_widths[ icol ]; - writeln!( c.buf, "{: 0 || islice > 0 + { + write!( c.buf, "{}", self.row_separator )?; + } + + write!( c.buf, "{}", self.row_prefix )?; + + write!( c.buf, "{}", self.cell_prefix )?; + write!( c.buf, "{:, [ usize ; 2 ] ) > >, + pub data : Vec< Vec< ( Cow< 'data, str >, [ usize ; 2 ] ) > >, // xxx : use maybe flat vector /// Dimensions of slices for retrieving data from multi-matrix. pub slices_dim : [ usize ; 3 ], @@ -293,6 +294,76 @@ mod private impl< 'data > InputExtract< 'data > { + /// Returns an iterator over the row descriptors, skipping the header if present. + /// + /// This function provides an iterator that yields each row descriptor along with its index. + /// If the table has a header, the first row is skipped, ensuring that iteration starts from + /// the first data row. + /// + /// # Returns + /// + /// An iterator over tuples containing: + /// - `usize`: The index of the row. + /// - `&RowDescriptor`: A reference to the row descriptor. + /// + pub fn rows( & self ) -> impl _IteratorTrait< Item = ( usize, &RowDescriptor ) > + { + self.row_descriptors + .iter() + .enumerate() + .skip( if self.has_header { 1 } else { 0 } ) + } + + /// Returns an iterator over the header cells, or a default value if no header is present. + /// + /// This function provides an iterator that yields each cell in the header row. If the table + /// does not have a header, it returns an iterator over default values, which are empty strings + /// with a size of `[0, 1]`. + /// + /// # Returns + /// + /// A boxed iterator yielding tuples containing: + /// - `Cow<'data, str>`: A clone-on-write string representing the cell content. + /// - `[usize; 2]`: An array representing the size of the cell. + /// + pub fn header( & self ) -> Box< dyn Iterator< Item = ( Cow< 'data, str >, [ usize ; 2 ] ) > + '_ > + { + if self.has_header + { + Box::new( self.data[ 0 ].iter().cloned() ) + } + else + { + Box::new( std::iter::repeat( ( Cow::Borrowed( "" ), [ 0, 1 ] ) ).take( self.mcells[ 0 ] ) ) + } + } + + /// Returns a slice from the header, or an empty string if no header is present. + /// + /// This function retrieves a specific slice from the header row based on the provided indices. + /// If the table does not have a header, it returns an empty string. + /// + /// # Arguments + /// + /// - `islice`: The slice index within the header cell. + /// - `icol`: The column index within the header row. + /// + /// # Returns + /// + /// A string slice representing the header content at the specified indices. + /// + pub fn header_slice( & self, islice : usize, icol : usize ) -> & str + { + if self.has_header + { + let md_index = [ islice, icol, 0 ]; + self.slices[ self.slices_dim.md_offset( md_index ) ] + } + else + { + "" + } + } /// Extract input data from and collect it in a format consumable by output formatter. pub fn extract< 't, 'context, Table, RowKey, Row, CellKey, CellRepr > ( diff --git a/module/core/format_tools/tests/inc/format_records_test.rs b/module/core/format_tools/tests/inc/format_records_test.rs index 6e591199ab..1fe86e6b02 100644 --- a/module/core/format_tools/tests/inc/format_records_test.rs +++ b/module/core/format_tools/tests/inc/format_records_test.rs @@ -47,7 +47,29 @@ fn basic() // sname | Boris // gap | 5 - let exp = r#"xxx"#; + let exp = r#" = 1 +│ id │ 1 │ +│ created_at │ 1627845583 │ +│ file_ids │ [ │ +│ │ "file1", │ +│ │ "file2", │ +│ │ ] │ +│ tools │ │ + = 2 +│ id │ 2 │ +│ created_at │ 13 │ +│ file_ids │ [ │ +│ │ "file3", │ +│ │ "file4\nmore details", │ +│ │ ] │ +│ tools │ [ │ +│ │ { │ +│ │ "tool1": "value1", │ +│ │ }, │ +│ │ { │ +│ │ "tool2": "value2", │ +│ │ }, │ +│ │ ] │"#; a_id!( output.as_str(), exp ); } From e71aac5ffb97874abe62acf19d9820c0f43572bd Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 31 Aug 2024 18:30:44 +0300 Subject: [PATCH 4/9] format_tools : cleaning --- .../src/format/output_format/records.rs | 5 ----- module/core/format_tools/src/format/print.rs | 9 ++++----- .../format_tools/tests/inc/format_records_test.rs | 13 ------------- 3 files changed, 4 insertions(+), 23 deletions(-) diff --git a/module/core/format_tools/src/format/output_format/records.rs b/module/core/format_tools/src/format/output_format/records.rs index ced3afad3d..32b70d5ece 100644 --- a/module/core/format_tools/src/format/output_format/records.rs +++ b/module/core/format_tools/src/format/output_format/records.rs @@ -41,8 +41,6 @@ use std::sync::OnceLock; #[derive( Debug )] pub struct Records { - /// Delimitting header with grid line or not. - pub delimitting_header : bool, /// Prefix added to each row. pub table_prefix : String, /// Postfix added to each row. @@ -100,8 +98,6 @@ impl Default for Records fn default() -> Self { - let delimitting_header = true; - let cell_prefix = "".to_string(); let cell_postfix = "".to_string(); let cell_separator = " │ ".to_string(); @@ -126,7 +122,6 @@ impl Default for Records Self { - delimitting_header, table_prefix, table_postfix, table_separator, diff --git a/module/core/format_tools/src/format/print.rs b/module/core/format_tools/src/format/print.rs index f65db73df6..1c58fb1ef6 100644 --- a/module/core/format_tools/src/format/print.rs +++ b/module/core/format_tools/src/format/print.rs @@ -84,7 +84,7 @@ mod private // .field( "row_prefix", & self.row_prefix ) // .field( "row_postfix", & self.row_postfix ) // .field( "row_separator", & self.row_separator ) - // .field( "output_format", & format_args!( "{:?}", self.output_format ) ) // xxx + // .field( "output_format", & format_args!( "{:?}", self.output_format ) ) // .field( "filter_col", & format_args!( "{:?}", self.filter_col ) ) .finish() } @@ -285,7 +285,6 @@ mod private pub slices_dim : [ usize ; 3 ], /// Extracted slices or strings for further processing. pub slices : Vec< &'data str >, - // xxx : move out that maybe } @@ -447,13 +446,13 @@ mod private { let col = &mut col_descriptors[ *icol ]; col.width = col.width.max( sz[ 0 ] ); - col.label = ""; // xxx + col.label = ""; }) .or_insert_with( || { let icol = l; let width = sz[ 0 ]; - let col = ColDescriptor { width, icol, label : "" }; // xxx + let col = ColDescriptor { width, icol, label : "" }; col_descriptors.push( col ); icol }); @@ -583,7 +582,7 @@ mod private slices[ x.slices_dim.md_offset( md_index ) ] = s; }) ; - x.col_descriptors[ icol ].label = cell.0.as_ref(); // xxx + x.col_descriptors[ icol ].label = cell.0.as_ref(); } } diff --git a/module/core/format_tools/tests/inc/format_records_test.rs b/module/core/format_tools/tests/inc/format_records_test.rs index 1fe86e6b02..9d88c944d8 100644 --- a/module/core/format_tools/tests/inc/format_records_test.rs +++ b/module/core/format_tools/tests/inc/format_records_test.rs @@ -34,19 +34,6 @@ fn basic() assert!( got.is_ok() ); println!( "{}", &output ); - // -[ RECORD 1 ] - // sid | 3 - // sname | Alice - // gap | 5 - // -[ RECORD 2 ] - // sid | 6 - // sname | Joe - // gap | 1 - // -[ RECORD 3 ] - // sid | 10 - // sname | Boris - // gap | 5 - let exp = r#" = 1 │ id │ 1 │ │ created_at │ 1627845583 │ From 3239584640fee80f8d0e5629c9ba19051d0e58df Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 31 Aug 2024 20:16:32 +0300 Subject: [PATCH 5/9] format_tools : cleaning --- .../src/format/output_format/records.rs | 26 ++++++++----------- module/core/format_tools/src/format/print.rs | 1 + 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/module/core/format_tools/src/format/output_format/records.rs b/module/core/format_tools/src/format/output_format/records.rs index 32b70d5ece..0b894572ca 100644 --- a/module/core/format_tools/src/format/output_format/records.rs +++ b/module/core/format_tools/src/format/output_format/records.rs @@ -146,16 +146,6 @@ impl Default for Records } } -// impl Default for Records -// { -// fn default() -> Self -// { -// Self -// { -// } -// } -// } - impl TableOutputFormat for Records { @@ -170,21 +160,27 @@ impl TableOutputFormat for Records write!( c.buf, "{}", self.table_prefix )?; + let mut first = true; // Write each record for ( irow, row ) in x.rows() { - if irow > 0 + if !row.vis + { + continue; + } + + if first + { + first = false; + } + else { write!( c.buf, "{}", self.table_separator )?; } let slice_width = x.data[ irow ].iter().fold( 0, | acc, cell | acc.max( cell.1[ 0 ] ) ); - if !row.vis - { - continue; - } writeln!( c.buf, " = {}", irow )?; for ( icol, _col ) in x.col_descriptors.iter().enumerate() diff --git a/module/core/format_tools/src/format/print.rs b/module/core/format_tools/src/format/print.rs index 1c58fb1ef6..29437961b8 100644 --- a/module/core/format_tools/src/format/print.rs +++ b/module/core/format_tools/src/format/print.rs @@ -42,6 +42,7 @@ mod private /// used to add a consistent end to each row. /// /// ``` + // xxx : enable // #[ derive( Debug, Former ) ] // #[ derive( Debug ) ] From ff06ee41134689a80575c9989d11fd2837ed536a Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 31 Aug 2024 22:35:05 +0300 Subject: [PATCH 6/9] format_tools : evolve records format --- .../tests/inc/format_records_test.rs | 205 ++++++++---------- 1 file changed, 94 insertions(+), 111 deletions(-) diff --git a/module/core/format_tools/tests/inc/format_records_test.rs b/module/core/format_tools/tests/inc/format_records_test.rs index 9d88c944d8..e93e8bbe81 100644 --- a/module/core/format_tools/tests/inc/format_records_test.rs +++ b/module/core/format_tools/tests/inc/format_records_test.rs @@ -63,120 +63,103 @@ fn basic() // -// #[ test ] -// fn table_to_string() -// { -// use the_module::TableFormatter; -// let test_objects = test_object::test_objects_gen(); -// -// // with explicit arguments -// -// let as_table : AsTable< '_, Vec< test_object::TestObject >, usize, test_object::TestObject, str, WithRef > = AsTable::new( &test_objects ); -// let table_string = as_table.table_to_string(); -// println!( "\ntable_string\n{table_string}" ); -// assert!( table_string.contains( "id" ) ); -// assert!( table_string.contains( "created_at" ) ); -// assert!( table_string.contains( "file_ids" ) ); -// assert!( table_string.contains( "tools" ) ); -// -// // without explicit arguments -// -// println!( "" ); -// let as_table = AsTable::new( &test_objects ); -// let table_string = as_table.table_to_string(); -// assert!( table_string.contains( "id" ) ); -// assert!( table_string.contains( "created_at" ) ); -// assert!( table_string.contains( "file_ids" ) ); -// assert!( table_string.contains( "tools" ) ); -// println!( "\ntable_string\n{table_string}" ); -// -// } -// -// // -// -// #[ test ] -// fn custom_format() -// { -// // use the_module::TableFormatter; -// let test_objects = test_object::test_objects_gen(); -// -// let mut format = output_format::Ordinary::default(); -// format.cell_prefix = "( ".into(); -// format.cell_postfix = " )".into(); -// format.cell_separator = "|".into(); -// format.row_prefix = ">".into(); -// format.row_postfix = "<".into(); -// format.row_separator = "\n".into(); -// -// let printer = print::Printer::with_format( &format ); -// let as_table = AsTable::new( &test_objects ); -// let mut output = String::new(); -// let mut context = print::Context::new( &mut output, printer ); -// let result = the_module::TableFormatter::fmt( &as_table, &mut context ); -// assert!( result.is_ok() ); -// -// println!( "\noutput\n{output}" ); -// assert!( output.contains( "id" ) ); -// assert!( output.contains( "created_at" ) ); -// assert!( output.contains( "file_ids" ) ); -// assert!( output.contains( "tools" ) ); -// -// let exp = r#">( id )|( created_at )|( file_ids )|( tools )< -// ───────────────────────────────────────────────────────────────────────────────────── -// >( 1 )|( 1627845583 )|( [ )|( )< -// >( )|( )|( "file1", )|( )< -// >( )|( )|( "file2", )|( )< -// >( )|( )|( ] )|( )< -// >( 2 )|( 13 )|( [ )|( [ )< -// >( )|( )|( "file3", )|( { )< -// >( )|( )|( "file4\nmore details", )|( "tool1": "value1", )< -// >( )|( )|( ] )|( }, )< -// >( )|( )|( )|( { )< -// >( )|( )|( )|( "tool2": "value2", )< -// >( )|( )|( )|( }, )< -// >( )|( )|( )|( ] )<"#; -// a_id!( output.as_str(), exp ); -// -// // using table_to_string_with_format -// -// use the_module::TableFormatter; -// -// let mut format = output_format::Ordinary::default(); -// format.cell_prefix = "( ".into(); -// format.cell_postfix = " )".into(); -// format.cell_separator = "|".into(); -// format.row_prefix = ">".into(); -// format.row_postfix = "<".into(); -// format.row_separator = "\n".into(); -// -// // let as_table = AsTable::new( &test_objects ); -// let got = AsTable::new( &test_objects ).table_to_string_with_format( &format ); -// let exp = r#">( id )|( created_at )|( file_ids )|( tools )< -// ───────────────────────────────────────────────────────────────────────────────────── -// >( 1 )|( 1627845583 )|( [ )|( )< -// >( )|( )|( "file1", )|( )< -// >( )|( )|( "file2", )|( )< -// >( )|( )|( ] )|( )< -// >( 2 )|( 13 )|( [ )|( [ )< -// >( )|( )|( "file3", )|( { )< -// >( )|( )|( "file4\nmore details", )|( "tool1": "value1", )< -// >( )|( )|( ] )|( }, )< -// >( )|( )|( )|( { )< -// >( )|( )|( )|( "tool2": "value2", )< -// >( )|( )|( )|( }, )< -// >( )|( )|( )|( ] )<"#; -// a_id!( got, exp ); -// -// } -// -// +#[ test ] +fn custom_format() +{ + // use the_module::TableFormatter; + let test_objects = test_object::test_objects_gen(); + + let mut format = output_format::Records::default(); + format.cell_prefix = "( ".into(); + format.cell_postfix = " )".into(); + format.cell_separator = "|".into(); + format.row_prefix = ">".into(); + format.row_postfix = "<".into(); + format.row_separator = "\n".into(); + + let printer = print::Printer::with_format( &format ); + let as_table = AsTable::new( &test_objects ); + let mut output = String::new(); + let mut context = print::Context::new( &mut output, printer ); + let result = the_module::TableFormatter::fmt( &as_table, &mut context ); + assert!( result.is_ok() ); + + println!( "\noutput\n{output}" ); + + let exp = r#" = 1 +>( id )|( 1 )< +>( created_at )|( 1627845583 )< +>( file_ids )|( [ )< +>( )|( "file1", )< +>( )|( "file2", )< +>( )|( ] )< +>( tools )|( )< + = 2 +>( id )|( 2 )< +>( created_at )|( 13 )< +>( file_ids )|( [ )< +>( )|( "file3", )< +>( )|( "file4\nmore details", )< +>( )|( ] )< +>( tools )|( [ )< +>( )|( { )< +>( )|( "tool1": "value1", )< +>( )|( }, )< +>( )|( { )< +>( )|( "tool2": "value2", )< +>( )|( }, )< +>( )|( ] )<"#; + a_id!( output.as_str(), exp ); + + // using table_to_string_with_format + + use the_module::TableFormatter; + + let mut format = output_format::Records::default(); + format.cell_prefix = "( ".into(); + format.cell_postfix = " )".into(); + format.cell_separator = "|".into(); + format.row_prefix = ">".into(); + format.row_postfix = "<".into(); + format.row_separator = "\n".into(); + + // let as_table = AsTable::new( &test_objects ); + let got = AsTable::new( &test_objects ).table_to_string_with_format( &format ); + let exp = r#" = 1 +>( id )|( 1 )< +>( created_at )|( 1627845583 )< +>( file_ids )|( [ )< +>( )|( "file1", )< +>( )|( "file2", )< +>( )|( ] )< +>( tools )|( )< + = 2 +>( id )|( 2 )< +>( created_at )|( 13 )< +>( file_ids )|( [ )< +>( )|( "file3", )< +>( )|( "file4\nmore details", )< +>( )|( ] )< +>( tools )|( [ )< +>( )|( { )< +>( )|( "tool1": "value1", )< +>( )|( }, )< +>( )|( { )< +>( )|( "tool2": "value2", )< +>( )|( }, )< +>( )|( ] )<"#; + a_id!( got, exp ); + +} + // + // #[ test ] // fn filter_col_none() // { // let test_objects = test_object::test_objects_gen(); // -// let mut format = output_format::Ordinary::default(); +// let mut format = output_format::Records::default(); // format.cell_prefix = "( ".into(); // format.cell_postfix = " )".into(); // format.cell_separator = "|".into(); @@ -211,7 +194,7 @@ fn basic() // { // let test_objects = test_object::test_objects_gen(); // -// let mut format = output_format::Ordinary::default(); +// let mut format = output_format::Records::default(); // format.cell_prefix = "( ".into(); // format.cell_postfix = " )".into(); // format.cell_separator = "|".into(); @@ -255,7 +238,7 @@ fn basic() // { // let test_objects = test_object::test_objects_gen(); // -// let mut format = output_format::Ordinary::default(); +// let mut format = output_format::Records::default(); // format.cell_prefix = "( ".into(); // format.cell_postfix = " )".into(); // format.cell_separator = "|".into(); @@ -287,7 +270,7 @@ fn basic() // { // let test_objects = test_object::test_objects_gen(); // -// let mut format = output_format::Ordinary::default(); +// let mut format = output_format::Records::default(); // format.cell_prefix = "( ".into(); // format.cell_postfix = " )".into(); // format.cell_separator = "|".into(); From c02bdca77880883589bc0a48d885f402fc3da18a Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 3 Sep 2024 08:00:35 +0300 Subject: [PATCH 7/9] format_tools : evolve it --- .../tests/inc/format_records_test.rs | 319 +++++++++--------- 1 file changed, 163 insertions(+), 156 deletions(-) diff --git a/module/core/format_tools/tests/inc/format_records_test.rs b/module/core/format_tools/tests/inc/format_records_test.rs index e93e8bbe81..8325dea020 100644 --- a/module/core/format_tools/tests/inc/format_records_test.rs +++ b/module/core/format_tools/tests/inc/format_records_test.rs @@ -5,16 +5,16 @@ use the_module:: { AsTable, WithRef, - // filter, + filter, print, output_format, }; -// use std:: -// { -// // collections::HashMap, -// // borrow::Cow, -// }; +use std:: +{ + // collections::HashMap, + borrow::Cow, +}; // @@ -154,159 +154,166 @@ fn custom_format() // -// #[ test ] -// fn filter_col_none() -// { -// let test_objects = test_object::test_objects_gen(); -// -// let mut format = output_format::Records::default(); -// format.cell_prefix = "( ".into(); -// format.cell_postfix = " )".into(); -// format.cell_separator = "|".into(); -// format.row_prefix = ">".into(); -// format.row_postfix = "<".into(); -// format.row_separator = "\n".into(); -// -// let mut printer = print::Printer::with_format( &format ); -// printer.filter_col = &filter::None; -// -// let as_table = AsTable::new( &test_objects ); -// let mut output = String::new(); -// let mut context = print::Context::new( &mut output, printer ); -// let result = the_module::TableFormatter::fmt( &as_table, &mut context ); -// assert!( result.is_ok() ); -// -// println!( "\noutput\n{output}" ); -// -// let exp = r#">< -// ── -// >< -// ><"#; -// -// a_id!( output.as_str(), exp ); -// -// } -// -// // -// -// #[ test ] -// fn filter_col_callback() -// { -// let test_objects = test_object::test_objects_gen(); -// -// let mut format = output_format::Records::default(); -// format.cell_prefix = "( ".into(); -// format.cell_postfix = " )".into(); -// format.cell_separator = "|".into(); -// format.row_prefix = ">".into(); -// format.row_postfix = "<".into(); -// format.row_separator = "\n".into(); -// -// let mut printer = print::Printer::with_format( &format ); -// printer.filter_col = &| title : &str | -// { -// title != "tools" -// }; -// -// let as_table = AsTable::new( &test_objects ); -// let mut output = String::new(); -// let mut context = print::Context::new( &mut output, printer ); -// let result = the_module::TableFormatter::fmt( &as_table, &mut context ); -// assert!( result.is_ok() ); -// -// println!( "\noutput\n{output}" ); -// -// let exp = r#">( id )|( created_at )|( file_ids )< -// ────────────────────────────────────────────────────── -// >( 1 )|( 1627845583 )|( [ )< -// >( )|( )|( "file1", )< -// >( )|( )|( "file2", )< -// >( )|( )|( ] )< -// >( 2 )|( 13 )|( [ )< -// >( )|( )|( "file3", )< -// >( )|( )|( "file4\nmore details", )< -// >( )|( )|( ] )<"#; -// -// a_id!( output.as_str(), exp ); -// -// } -// -// // -// -// #[ test ] -// fn filter_row_none() -// { -// let test_objects = test_object::test_objects_gen(); -// -// let mut format = output_format::Records::default(); -// format.cell_prefix = "( ".into(); -// format.cell_postfix = " )".into(); -// format.cell_separator = "|".into(); -// format.row_prefix = ">".into(); -// format.row_postfix = "<".into(); -// format.row_separator = "\n".into(); -// -// let mut printer = print::Printer::with_format( &format ); -// printer.filter_row = &filter::None; -// -// let as_table = AsTable::new( &test_objects ); -// let mut output = String::new(); -// let mut context = print::Context::new( &mut output, printer ); -// let result = the_module::TableFormatter::fmt( &as_table, &mut context ); -// assert!( result.is_ok() ); -// -// println!( "\noutput\n{output}" ); -// -// let exp = r#""#; -// -// a_id!( output.as_str(), exp ); -// -// } -// -// // -// -// #[ test ] -// fn filter_row_callback() -// { -// let test_objects = test_object::test_objects_gen(); -// -// let mut format = output_format::Records::default(); -// format.cell_prefix = "( ".into(); -// format.cell_postfix = " )".into(); -// format.cell_separator = "|".into(); -// format.row_prefix = ">".into(); -// format.row_postfix = "<".into(); -// format.row_separator = "\n".into(); -// -// let mut printer = print::Printer::with_format( &format ); -// printer.filter_row = &| _typ, irow, _row : &[ ( Cow< '_, str >, [ usize ; 2 ] ) ] | -// { -// irow != 1 -// }; -// -// let as_table = AsTable::new( &test_objects ); -// let mut output = String::new(); -// let mut context = print::Context::new( &mut output, printer ); -// let result = the_module::TableFormatter::fmt( &as_table, &mut context ); -// assert!( result.is_ok() ); -// -// println!( "\noutput\n{output}" ); +#[ test ] +fn filter_col_none() +{ + let test_objects = test_object::test_objects_gen(); + + let mut format = output_format::Records::default(); + format.cell_prefix = "( ".into(); + format.cell_postfix = " )".into(); + format.cell_separator = "|".into(); + format.row_prefix = ">".into(); + format.row_postfix = "<".into(); + format.row_separator = "\n".into(); + + let mut printer = print::Printer::with_format( &format ); + printer.filter_col = &filter::None; + + let as_table = AsTable::new( &test_objects ); + let mut output = String::new(); + let mut context = print::Context::new( &mut output, printer ); + let result = the_module::TableFormatter::fmt( &as_table, &mut context ); + assert!( result.is_ok() ); + println!( "\noutput\n{output}" ); + + let exp = r#" = 1 + + = 2 +"#; + + a_id!( output.as_str(), exp ); + +} + // -// let exp = r#">( id )|( created_at )|( file_ids )|( tools )< -// ───────────────────────────────────────────────────────────────────────────────────── -// >( 2 )|( 13 )|( [ )|( [ )< -// >( )|( )|( "file3", )|( { )< -// >( )|( )|( "file4\nmore details", )|( "tool1": "value1", )< -// >( )|( )|( ] )|( }, )< -// >( )|( )|( )|( { )< -// >( )|( )|( )|( "tool2": "value2", )< -// >( )|( )|( )|( }, )< -// >( )|( )|( )|( ] )<"#; + +#[ test ] +fn filter_col_callback() +{ + let test_objects = test_object::test_objects_gen(); + + let mut format = output_format::Records::default(); + format.cell_prefix = "( ".into(); + format.cell_postfix = " )".into(); + format.cell_separator = "|".into(); + format.row_prefix = ">".into(); + format.row_postfix = "<".into(); + format.row_separator = "\n".into(); + + let mut printer = print::Printer::with_format( &format ); + printer.filter_col = &| title : &str | + { + title != "tools" + }; + + let as_table = AsTable::new( &test_objects ); + let mut output = String::new(); + let mut context = print::Context::new( &mut output, printer ); + let result = the_module::TableFormatter::fmt( &as_table, &mut context ); + assert!( result.is_ok() ); + println!( "\noutput\n{output}" ); + + let exp = r#" = 1 +>( id )|( 1 )< +>( created_at )|( 1627845583 )< +>( file_ids )|( [ )< +>( )|( "file1", )< +>( )|( "file2", )< +>( )|( ] )< + = 2 +>( id )|( 2 )< +>( created_at )|( 13 )< +>( file_ids )|( [ )< +>( )|( "file3", )< +>( )|( "file4\nmore details", )< +>( )|( ] )<"#; + + a_id!( output.as_str(), exp ); + +} + // -// a_id!( output.as_str(), exp ); + +#[ test ] +fn filter_row_none() +{ + let test_objects = test_object::test_objects_gen(); + + let mut format = output_format::Records::default(); + format.cell_prefix = "( ".into(); + format.cell_postfix = " )".into(); + format.cell_separator = "|".into(); + format.row_prefix = ">".into(); + format.row_postfix = "<".into(); + format.row_separator = "\n".into(); + + let mut printer = print::Printer::with_format( &format ); + printer.filter_row = &filter::None; + + let as_table = AsTable::new( &test_objects ); + let mut output = String::new(); + let mut context = print::Context::new( &mut output, printer ); + let result = the_module::TableFormatter::fmt( &as_table, &mut context ); + assert!( result.is_ok() ); + + println!( "\noutput\n{output}" ); + + let exp = r#""#; + + a_id!( output.as_str(), exp ); + +} + // -// } + +#[ test ] +fn filter_row_callback() +{ + let test_objects = test_object::test_objects_gen(); + + let mut format = output_format::Records::default(); + format.cell_prefix = "( ".into(); + format.cell_postfix = " )".into(); + format.cell_separator = "|".into(); + format.row_prefix = ">".into(); + format.row_postfix = "<".into(); + format.row_separator = "\n".into(); + + let mut printer = print::Printer::with_format( &format ); + printer.filter_row = &| _typ, irow, _row : &[ ( Cow< '_, str >, [ usize ; 2 ] ) ] | + { + irow != 1 + }; + + let as_table = AsTable::new( &test_objects ); + let mut output = String::new(); + let mut context = print::Context::new( &mut output, printer ); + let result = the_module::TableFormatter::fmt( &as_table, &mut context ); + assert!( result.is_ok() ); + + println!( "\noutput\n{output}" ); + + let exp = r#" = 2 +>( id )|( 2 )< +>( created_at )|( 13 )< +>( file_ids )|( [ )< +>( )|( "file3", )< +>( )|( "file4\nmore details", )< +>( )|( ] )< +>( tools )|( [ )< +>( )|( { )< +>( )|( "tool1": "value1", )< +>( )|( }, )< +>( )|( { )< +>( )|( "tool2": "value2", )< +>( )|( }, )< +>( )|( ] )<"#; + + a_id!( output.as_str(), exp ); + +} + // -// // // xxx : enable \ No newline at end of file From d702b84bce7dc7589c256b5ed25e5bee0505b2bc Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 3 Sep 2024 09:21:12 +0300 Subject: [PATCH 8/9] format_tools : cleaning --- .../core/format_tools/src/format/md_math.rs | 15 +++- .../src/format/output_format/records.rs | 88 +++++++++---------- 2 files changed, 58 insertions(+), 45 deletions(-) diff --git a/module/core/format_tools/src/format/md_math.rs b/module/core/format_tools/src/format/md_math.rs index a53625fc21..d4de6ae6af 100644 --- a/module/core/format_tools/src/format/md_math.rs +++ b/module/core/format_tools/src/format/md_math.rs @@ -29,7 +29,20 @@ mod private /// # Returns /// /// A value of type `T` representing the flat offset. - fn md_offset( & self, md_index : [ T ; 3 ] ) -> T; + fn md_offset( & self, md_index : Self ) -> T; + } + + impl< T > MdOffset< T > for [ T ; 2 ] + where + T : Mul< T, Output = T > + Add< T, Output = T > + PartialOrd + Copy + fmt::Debug, + { + fn md_offset( & self, md_index : [ T ; 2 ] ) -> T + { + debug_assert!( md_index[ 0 ] < self[ 0 ], "md_index : {md_index:?} | md_size : {self:?}" ); + debug_assert!( md_index[ 1 ] < self[ 1 ], "md_index : {md_index:?} | md_size : {self:?}" ); + let m1 = self[ 0 ]; + md_index[ 0 ] + m1 * md_index[ 1 ] + } } impl< T > MdOffset< T > for [ T ; 3 ] diff --git a/module/core/format_tools/src/format/output_format/records.rs b/module/core/format_tools/src/format/output_format/records.rs index 0b894572ca..45a1206e41 100644 --- a/module/core/format_tools/src/format/output_format/records.rs +++ b/module/core/format_tools/src/format/output_format/records.rs @@ -59,28 +59,28 @@ pub struct Records pub cell_postfix : String, /// Separator used between table columns. pub cell_separator : String, - /// Horizontal line character. - pub h : char, - /// Vertical line character. - pub v : char, - /// Left T-junction character. - pub t_l : char, - /// Right T-junction character. - pub t_r : char, - /// Top T-junction character. - pub t_t : char, - /// Bottom T-junction character. - pub t_b : char, - /// Cross junction character. - pub cross : char, - /// Top-left corner character. - pub corner_lt : char, - /// Top-right corner character. - pub corner_rt : char, - /// Bottom-left corner character. - pub corner_lb : char, - /// Bottom-right corner character. - pub corner_rb : char, + // /// Horizontal line character. + // pub h : char, + // /// Vertical line character. + // pub v : char, + // /// Left T-junction character. + // pub t_l : char, + // /// Right T-junction character. + // pub t_r : char, + // /// Top T-junction character. + // pub t_t : char, + // /// Bottom T-junction character. + // pub t_b : char, + // /// Cross junction character. + // pub cross : char, + // /// Top-left corner character. + // pub corner_lt : char, + // /// Top-right corner character. + // pub corner_rt : char, + // /// Bottom-left corner character. + // pub corner_lb : char, + // /// Bottom-right corner character. + // pub corner_rb : char, } impl Records @@ -108,17 +108,17 @@ impl Default for Records let table_postfix = "".to_string(); let table_separator = "\n".to_string(); - let h = '─'; - let v = '|'; - let t_l = '├'; - let t_r = '┤'; - let t_t = '┬'; - let t_b = '┴'; - let cross = '┼'; - let corner_lt = '┌'; - let corner_rt = '┐'; - let corner_lb = '└'; - let corner_rb = '┘'; + // let h = '─'; + // let v = '|'; + // let t_l = '├'; + // let t_r = '┤'; + // let t_t = '┬'; + // let t_b = '┴'; + // let cross = '┼'; + // let corner_lt = '┌'; + // let corner_rt = '┐'; + // let corner_lb = '└'; + // let corner_rb = '┘'; Self { @@ -131,17 +131,17 @@ impl Default for Records cell_prefix, cell_postfix, cell_separator, - h, - v, - t_l, - t_r, - t_t, - t_b, - cross, - corner_lt, - corner_rt, - corner_lb, - corner_rb, + // h, + // v, + // t_l, + // t_r, + // t_t, + // t_b, + // cross, + // corner_lt, + // corner_rt, + // corner_lb, + // corner_rb, } } } From 596c0477669cf6dab9c3e6ed12dd6ae9054dd6c7 Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 3 Sep 2024 09:23:39 +0300 Subject: [PATCH 9/9] format_tools : cleaning --- module/core/format_tools/tests/inc/format_ordinary_test.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/core/format_tools/tests/inc/format_ordinary_test.rs b/module/core/format_tools/tests/inc/format_ordinary_test.rs index f0854cd6c0..5dbe2a95d2 100644 --- a/module/core/format_tools/tests/inc/format_ordinary_test.rs +++ b/module/core/format_tools/tests/inc/format_ordinary_test.rs @@ -324,3 +324,5 @@ fn filter_row_callback() } // + +// xxx : implement test for vector of vectors