Skip to content
15 changes: 3 additions & 12 deletions module/core/format_tools/src/format/output_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,7 @@ mod private
InputExtract,
Context,
};
use core::
{
fmt,
};
use core::fmt;

//=

Expand Down Expand Up @@ -136,10 +133,7 @@ pub mod own
};

#[ doc( inline ) ]
pub use private::
{
vector_table_write,
};
pub use private::vector_table_write;

}

Expand All @@ -160,10 +154,7 @@ pub mod exposed
pub use super::super::output_format;

#[ doc( inline ) ]
pub use private::
{
TableOutputFormat,
};
pub use private::TableOutputFormat;

}

Expand Down
5 changes: 1 addition & 4 deletions module/core/format_tools/src/format/output_format/records.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ use print::
Context,
};
use std::borrow::Cow;
use core::
{
fmt,
};
use core::fmt;
use std::sync::OnceLock;

/// A struct representing the list of records( rows ) output format.
Expand Down
9 changes: 3 additions & 6 deletions module/core/format_tools/src/format/output_format/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ use print::
InputExtract,
Context,
};
use core::
{
fmt,
};
use core::fmt;
use std::sync::OnceLock;

/// A struct representing the classic table output format.
Expand Down Expand Up @@ -261,8 +258,8 @@ impl TableOutputFormat for Table

write!( c.buf, "{}", cell_prefix )?;

let lspaces = ( column_width - cell_wrapped_width ) / 2;
let rspaces = ( ( column_width - cell_wrapped_width ) as f32 / 2 as f32 ).round() as usize + cell_wrapped_width - slice_width;
let lspaces = column_width.saturating_sub( cell_wrapped_width ) / 2;
let rspaces = ( ( column_width.saturating_sub( cell_wrapped_width ) as f32 / 2 as f32 ) ).round() as usize + cell_wrapped_width.saturating_sub(slice_width);

if lspaces > 0
{
Expand Down
68 changes: 47 additions & 21 deletions module/core/format_tools/src/format/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ mod private
for line in lines( text )
{
height += 1;
let line_length = line.chars().count();
let line_length = line.as_bytes().len();
if line_length > width
{
width = line_length;
Expand Down Expand Up @@ -244,39 +244,65 @@ mod private
}
}

impl< 'a > Iterator for LinesWithLimit< 'a >
impl< 'a > Iterator for LinesWithLimit< 'a >
{
type Item = &'a str;

fn next( &mut self ) -> Option< Self::Item >
fn next( &mut self ) -> Option< Self::Item >
{
if self.cur.is_none() || self.cur.is_some_and( str::is_empty )
loop
{
self.cur = self.lines.next();
}

match self.cur
{
None => return None,

Some( cur ) =>
let s = match self.cur
{
if self.limit_width == 0
Some( st ) if !st.is_empty() => st,

_ =>
{
self.cur = None;
Some( cur )
let next_line = self.lines.next()?;
if next_line.is_empty()
{
self.cur = None;
return Some( "" );
}
else
{
self.cur = Some( next_line );
continue;
}
}
else
};

if self.limit_width == 0
{
self.cur = None;
return Some( s );
}

let mut boundary_byte_index = s.len();
let mut char_count = 0;
for ( byte_i, _ch ) in s.char_indices()
{
if char_count == self.limit_width
{
let (chunk, rest) = cur.split_at(self.limit_width.min(cur.len()));
self.cur = Some( rest );

Some(chunk)
boundary_byte_index = byte_i;
break;
}
char_count += 1;
}

let chunk = &s[ ..boundary_byte_index ];
let rest = &s[ boundary_byte_index.. ];

match rest.is_empty()
{
true => self.cur = None,
false => self.cur = Some( rest )
};

return Some( chunk );
}
}
}
}

}

Expand Down
51 changes: 51 additions & 0 deletions module/core/format_tools/tests/inc/format_records_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,57 @@ fn basic()

//

#[ test ]
fn unicode()
{
let test_objects = test_object::test_objects_gen_2_languages();

let as_table = AsTable::new( &test_objects );

let mut output = String::new();
let format = output_format::Records::default();
let printer = print::Printer::with_format( &format );
let mut context = print::Context::new( &mut output, printer );
let got = the_module::TableFormatter::fmt( &as_table, &mut context );
assert!( got.is_ok() );
println!( "{}", &output );

let exp = r#" = 1
│ id │ Доміно │
│ created_at │ 100 │
│ file_ids │ [ │
│ │ "файл1", │
│ │ "файл2", │
│ │ ] │
│ tools │ [ │
│ │ { │
│ │ "тулз1": "значення1", │
│ │ }, │
│ │ { │
│ │ "тулз2": "значення2", │
│ │ }, │
│ │ ] │
= 2
│ id │ File │
│ created_at │ 120 │
│ file_ids │ [ │
│ │ "file1", │
│ │ "file2", │
│ │ ] │
│ tools │ [ │
│ │ { │
│ │ "tools1": "value1", │
│ │ }, │
│ │ { │
│ │ "tools1": "value2", │
│ │ }, │
│ │ ] │"#;
a_id!( output.as_str(), exp );

}

//

#[ test ]
fn custom_format()
{
Expand Down
62 changes: 62 additions & 0 deletions module/core/format_tools/tests/inc/format_table_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,4 +470,66 @@ fn max_width() -> usize
}

0
}

#[ test ]
fn ukrainian_chars()
{
let test_objects = test_object::test_objects_gen_with_unicode();
let as_table = AsTable::new( &test_objects );

let mut output = String::new();
let mut context = print::Context::new( &mut output, Default::default() );
let got = the_module::TableFormatter::fmt( &as_table, &mut context );
assert!( got.is_ok() );
println!( "{}", &output );

let exp = r#"│ id │ created_at │ file_ids │ tools │
───────────────────────────────────────────────────────────────────────────────────────────────────────
│ Доміно │ 100 │ [ │ │
│ │ │ "файл1", │ │
│ │ │ "файл2", │ │
│ │ │ ] │ │
│ Інший юнікод │ 120 │ [] │ [ │
│ │ │ │ { │
│ │ │ │ "тулз1": "значення1", │
│ │ │ │ }, │
│ │ │ │ { │
│ │ │ │ "тулз2": "значення2", │
│ │ │ │ }, │
│ │ │ │ ] │"#;
a_id!( output.as_str(), exp );
}

#[ test ]
fn ukrainian_and_english_chars()
{
let test_objects = test_object::test_objects_gen_2_languages();
let as_table = AsTable::new( &test_objects );

let mut output = String::new();
let mut context = print::Context::new( &mut output, Default::default() );
let got = the_module::TableFormatter::fmt( &as_table, &mut context );
assert!( got.is_ok() );
println!( "{}", &output );

let exp = r#"│ id │ created_at │ file_ids │ tools │
────────────────────────────────────────────────────────────────────────────────────────────
│ Доміно │ 100 │ [ │ [ │
│ │ │ "файл1", │ { │
│ │ │ "файл2", │ "тулз1": "значення1", │
│ │ │ ] │ }, │
│ │ │ │ { │
│ │ │ │ "тулз2": "значення2", │
│ │ │ │ }, │
│ │ │ │ ] │
│ File │ 120 │ [ │ [ │
│ │ │ "file1", │ { │
│ │ │ "file2", │ "tools1": "value1", │
│ │ │ ] │ }, │
│ │ │ │ { │
│ │ │ │ "tools1": "value2", │
│ │ │ │ }, │
│ │ │ │ ] │"#;
a_id!( output.as_str(), exp );
}
77 changes: 75 additions & 2 deletions module/core/format_tools/tests/inc/test_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,83 @@ pub fn test_objects_gen_with_unicode() -> Vec< TestObject >
[
TestObject
{
id : "Юнікод".to_string(),
id : "Доміно".to_string(),
created_at : 100,
file_ids : vec![],
file_ids : vec![ "файл1".to_string(), "файл2".to_string() ],
tools : None,
},
TestObject
{
id : "Інший юнікод".to_string(),
created_at : 120,
file_ids : vec![],
tools : Some
(
vec!
[
{
let mut map = HashMap::new();
map.insert( "тулз1".to_string(), "значення1".to_string() );
map
},
{
let mut map = HashMap::new();
map.insert( "тулз2".to_string(), "значення2".to_string() );
map
}
]
),
}
]
}

pub fn test_objects_gen_2_languages() -> Vec< TestObject >
{
vec!
[
TestObject
{
id : "Доміно".to_string(),
created_at : 100,
file_ids : vec![ "файл1".to_string(), "файл2".to_string() ],
tools : Some
(
vec!
[
{
let mut map = HashMap::new();
map.insert( "тулз1".to_string(), "значення1".to_string() );
map
},
{
let mut map = HashMap::new();
map.insert( "тулз2".to_string(), "значення2".to_string() );
map
}
]
),
},
TestObject
{
id : "File".to_string(),
created_at : 120,
file_ids : vec![ "file1".to_string(), "file2".to_string() ],
tools : Some
(
vec!
[
{
let mut map = HashMap::new();
map.insert( "tools1".to_string(), "value1".to_string() );
map
},
{
let mut map = HashMap::new();
map.insert( "tools1".to_string(), "value2".to_string() );
map
}
]
),
}
]
}
Loading