2021-08-24 23:01:56 -05:00
#![ allow(clippy::type_complexity) ]
2021-07-15 10:33:02 -05:00
use std ::borrow ::Cow ;
2021-08-24 23:01:56 -05:00
use ansi_term ::Style ;
2022-08-28 15:48:47 -05:00
use regex ::Regex ;
lazy_static! {
// https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows
//
// For Control Sequence Introducer, or CSI, commands, the ESC [ is followed
// by any number (including none) of "parameter bytes" in the range
// 0x30– 0x3F (ASCII 0– 9:;<=>?), then by any number of "intermediate bytes"
// in the range 0x20– 0x2F (ASCII space and !"#$%&'()*+,-./), then finally
// by a single "final byte" in the range 0x40– 0x7E (ASCII @A– Z[\]^_`a– z{|}~)
//
// The lazy regex bellow doesn't cover all of that. It just works on ansi
// colors.
pub static ref ANSI_REGEX : Regex = Regex ::new ( " \x1b \\ [[ \\ d;]*m " ) . unwrap ( ) ;
}
/// An abstract way of getting the visual size of a string in a terminal
pub trait VisualSize {
fn size ( & self ) -> usize ;
}
impl VisualSize for & str {
fn size ( & self ) -> usize {
let s = ANSI_REGEX . replace_all ( self , " " ) ;
s . chars ( ) . count ( )
}
}
impl VisualSize for String {
fn size ( & self ) -> usize {
self . as_str ( ) . size ( )
}
}
2021-08-24 23:01:56 -05:00
2021-07-15 00:22:38 -05:00
fn lpad ( s : & str , len : usize ) -> String {
2022-08-28 15:48:47 -05:00
let padding = " " . repeat ( len . saturating_sub ( s . size ( ) ) ) ;
2021-07-15 00:22:38 -05:00
padding + s
}
fn rpad ( s : & str , len : usize ) -> String {
2022-08-28 15:48:47 -05:00
let padding = " " . repeat ( len . saturating_sub ( s . size ( ) ) ) ;
2021-07-15 00:22:38 -05:00
s . to_string ( ) + & padding
}
2021-07-15 10:33:02 -05:00
fn constrained_lines ( text : & str , width : usize ) -> Vec < Cow < '_ , str > > {
textwrap ::wrap ( text , width )
}
2021-07-15 00:22:38 -05:00
#[ derive(Copy, Clone) ]
pub enum Align {
Left ,
Right ,
}
use Align ::* ;
2021-08-24 23:01:56 -05:00
#[ derive(Clone) ]
2021-07-15 00:22:38 -05:00
pub struct Col {
min_width : usize ,
2021-07-15 10:33:02 -05:00
max_width : Option < usize > ,
2021-07-15 00:22:38 -05:00
align : Align ,
2021-08-24 23:01:56 -05:00
conditonal_styles : Vec < ( Style , fn ( & str ) -> bool ) > ,
2021-07-15 00:22:38 -05:00
}
impl Col {
2021-07-16 09:33:45 -05:00
pub fn new ( ) -> Col {
Col {
min_width : 0 ,
align : Align ::Left ,
max_width : None ,
2021-08-24 23:01:56 -05:00
conditonal_styles : Vec ::new ( ) ,
2021-07-16 09:33:45 -05:00
}
}
2022-07-21 08:35:45 -05:00
pub fn min_width ( self , size : usize ) -> Col {
2021-07-15 00:22:38 -05:00
Col {
min_width : size ,
2022-07-21 08:35:45 -05:00
.. self
2021-07-15 00:22:38 -05:00
}
}
pub fn and_alignment ( self , align : Align ) -> Col {
Col {
align ,
.. self
}
}
2021-07-15 10:33:02 -05:00
pub fn max_width ( self , size : usize ) -> Col {
Col {
max_width : Some ( size ) ,
.. self
}
}
2021-08-24 23:01:56 -05:00
pub fn color_if ( self , style : Style , f : fn ( & str ) -> bool ) -> Col {
let mut conditonal_styles = self . conditonal_styles ;
conditonal_styles . push ( ( style , f ) ) ;
Col {
conditonal_styles ,
.. self
}
}
2021-07-15 00:22:38 -05:00
}
2021-08-02 19:10:34 -05:00
impl Default for Col {
fn default ( ) -> Col {
Col ::new ( )
}
}
2021-07-15 00:22:38 -05:00
enum DataOrSep {
Data ( Vec < String > ) ,
Sep ( char ) ,
}
pub struct Tabulate {
cols : Vec < Col > ,
widths : Vec < usize > ,
data : Vec < DataOrSep > ,
}
impl Tabulate {
pub fn with_columns ( cols : Vec < Col > ) -> Tabulate {
Tabulate {
widths : cols . iter ( ) . map ( | c | c . min_width ) . collect ( ) ,
cols ,
data : Vec ::new ( ) ,
}
}
2022-07-21 08:35:45 -05:00
pub fn feed < T : AsRef < str > > ( & mut self , data : Vec < T > ) {
2021-07-15 09:40:37 -05:00
let mut lines : Vec < Vec < String > > = Vec ::new ( ) ;
2021-07-15 10:33:02 -05:00
for ( col , ( ( w , d ) , c ) ) in self . widths . iter_mut ( ) . zip ( data . iter ( ) ) . zip ( self . cols . iter ( ) ) . enumerate ( ) {
2022-07-21 08:35:45 -05:00
for ( r1 , dl ) in d . as_ref ( ) . split ( '\n' ) . enumerate ( ) {
2021-07-15 10:33:02 -05:00
for ( r2 , l ) in constrained_lines ( dl , c . max_width . unwrap_or ( usize ::MAX ) ) . into_iter ( ) . enumerate ( ) {
2022-08-28 15:48:47 -05:00
let width = l . as_ref ( ) . size ( ) ;
2021-07-15 09:40:37 -05:00
2022-08-28 15:48:47 -05:00
if width > * w {
* w = width ;
2021-07-15 09:40:37 -05:00
}
2021-07-15 10:33:02 -05:00
if let Some ( line ) = lines . get_mut ( r1 + r2 ) {
if let Some ( pos ) = line . get_mut ( col ) {
* pos = l . into ( ) ;
2021-07-15 09:40:37 -05:00
} else {
2021-07-15 10:33:02 -05:00
line . push ( l . into ( ) ) ;
}
} else {
lines . push ( {
2022-07-21 08:35:45 -05:00
let mut prev : Vec < _ > = if ( r1 + r2 ) = = 0 {
data [ .. col ] . iter ( ) . map ( | s | s . as_ref ( ) . to_string ( ) ) . collect ( )
2021-07-15 10:33:02 -05:00
} else {
( 0 .. col ) . map ( | _ | " " . into ( ) ) . collect ( )
} ;
2021-07-15 09:40:37 -05:00
2021-07-15 10:33:02 -05:00
prev . push ( l . into ( ) ) ;
2021-07-15 09:40:37 -05:00
2021-07-15 10:33:02 -05:00
prev
} ) ;
}
2021-07-15 09:40:37 -05:00
}
2021-07-15 00:22:38 -05:00
}
}
2021-07-15 09:40:37 -05:00
for line in lines {
self . data . push ( DataOrSep ::Data ( line ) ) ;
}
2021-07-15 00:22:38 -05:00
}
pub fn separator ( & mut self , c : char ) {
self . data . push ( DataOrSep ::Sep ( c ) ) ;
}
2021-08-25 14:43:50 -05:00
pub fn print ( self , color : bool ) -> String {
2021-07-15 00:22:38 -05:00
let widths = self . widths ;
let cols = self . cols ;
self . data . into_iter ( ) . map ( | row | match row {
DataOrSep ::Sep ( c ) = > {
2021-07-16 09:33:45 -05:00
if c = = ' ' {
" \n " . into ( )
} else {
c . to_string ( ) . repeat ( widths . iter ( ) . sum ::< usize > ( ) + widths . len ( ) - 1 ) + " \n "
}
2021-07-15 00:22:38 -05:00
} ,
DataOrSep ::Data ( d ) = > {
2021-08-24 23:01:56 -05:00
d . into_iter ( ) . zip ( widths . iter ( ) ) . zip ( cols . iter ( ) ) . map ( | ( ( d , & w ) , c ) | {
let style = c . conditonal_styles . iter ( ) . find ( | ( _s , f ) | {
f ( & d )
} ) . map ( | ( s , _f ) | s ) ;
let s = match c . align {
2021-07-15 00:22:38 -05:00
Left = > rpad ( & d , w ) ,
Right = > lpad ( & d , w ) ,
2021-08-24 23:01:56 -05:00
} ;
if let Some ( style ) = style {
2021-08-25 14:43:50 -05:00
if color {
style . paint ( s ) . to_string ( )
} else {
s
}
2021-08-24 23:01:56 -05:00
} else {
s
2021-07-15 00:22:38 -05:00
}
} ) . collect ::< Vec < _ > > ( ) . join ( " " ) . trim_end ( ) . to_string ( ) + " \n "
} ,
} ) . collect ::< Vec < _ > > ( ) . join ( " " )
}
}
#[ cfg(test) ]
mod tests {
use pretty_assertions ::assert_eq ;
2022-08-28 15:48:47 -05:00
use ansi_term ::Color ::Fixed ;
2021-07-15 00:22:38 -05:00
use super ::* ;
2021-12-13 14:20:56 -06:00
const LONG_NOTE : & str = " chatting with bob about upcoming task, district sharing of images, how the user settings currently works etc. Discussing the fingerprinting / cache busting issue with CKEDITOR, suggesting perhaps looking into forking the rubygem and seeing if we can work in our own changes, however hard that might be. " ;
2021-07-15 00:22:38 -05:00
2021-07-15 10:33:02 -05:00
#[ test ]
fn test_constrained_lines_long_text ( ) {
assert_eq! ( constrained_lines ( LONG_NOTE , 46 ) , vec! [
" chatting with bob about upcoming task, " ,
" district sharing of images, how the user " ,
" settings currently works etc. Discussing the " ,
" fingerprinting / cache busting issue with " ,
" CKEDITOR, suggesting perhaps looking into " ,
" forking the rubygem and seeing if we can work " ,
" in our own changes, however hard that might " ,
" be. " ,
] ) ;
}
#[ test ]
fn test_constrained_lines_nowrap ( ) {
assert_eq! ( constrained_lines ( LONG_NOTE , LONG_NOTE . len ( ) ) , vec! [
LONG_NOTE ,
] ) ;
}
2021-07-15 00:22:38 -05:00
#[ test ]
fn test_text_output ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
2022-07-21 08:35:45 -05:00
Col ::new ( ) . min_width ( " Fri Oct 03, 2008 " . len ( ) ) . and_alignment ( Left ) ,
Col ::new ( ) . min_width ( " 12:00:00 - 14:00:00 " . len ( ) ) . and_alignment ( Left ) ,
Col ::new ( ) . min_width ( " Duration " . len ( ) ) . and_alignment ( Right ) ,
Col ::new ( ) . min_width ( " Notes " . len ( ) ) . and_alignment ( Left ) ,
2021-07-15 00:22:38 -05:00
] ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " Day " , " Start End " , " Duration " , " Notes " ] ) ;
tabs . feed ( vec! [ " Fri Oct 03, 2008 " , " 12:00:00 - 14:00:00 " , " 2:00:00 " , " entry 1 " ] ) ;
tabs . feed ( vec! [ " " , " 16:00:00 - 18:00:00 " , " 2:00:00 " , " entry 2 " ] ) ;
tabs . feed ( vec! [ " " , " " , " 4:00:00 " , " " ] ) ;
tabs . feed ( vec! [ " Sun Oct 05, 2008 " , " 16:00:00 - 18:00:00 " , " 2:00:00 " , " entry 3 " ] ) ;
tabs . feed ( vec! [ " " , " 18:00:00 - " , " 2:00:00 " , " entry 4 " ] ) ;
tabs . feed ( vec! [ " " , " " , " 4:00:00 " , " " ] ) ;
2021-07-15 00:22:38 -05:00
tabs . separator ( '-' ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " Total " , " " , " 8:00:00 " , " " ] ) ;
2021-07-15 00:22:38 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & tabs . print ( false ) , " \
2021-07-15 00:22:38 -05:00
Day Start End Duration Notes
Fri Oct 03 , 2008 12 :00 :00 - 14 :00 :00 2 :00 :00 entry 1
16 :00 :00 - 18 :00 :00 2 :00 :00 entry 2
4 :00 :00
Sun Oct 05 , 2008 16 :00 :00 - 18 :00 :00 2 :00 :00 entry 3
18 :00 :00 - 2 :00 :00 entry 4
4 :00 :00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Total 8 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-07-15 00:22:38 -05:00
}
#[ test ]
fn test_text_output_long_duration ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
2022-07-21 08:35:45 -05:00
Col ::new ( ) . min_width ( " Fri Oct 03, 2008 " . len ( ) ) . and_alignment ( Left ) ,
Col ::new ( ) . min_width ( " 12:00:00 - 14:00:00 " . len ( ) ) . and_alignment ( Left ) ,
Col ::new ( ) . min_width ( " Duration " . len ( ) ) . and_alignment ( Right ) ,
Col ::new ( ) . min_width ( " Notes " . len ( ) ) . and_alignment ( Left ) ,
2021-07-15 00:22:38 -05:00
] ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " Day " , " Start End " , " Duration " , " Notes " ] ) ;
tabs . feed ( vec! [ " Wed Oct 01, 2008 " , " 12:00:00 - 14:00:00+2d " , " 50:00:00 " , " entry 1 " ] ) ;
tabs . feed ( vec! [ " " , " " , " 50:00:00 " , " " ] ) ;
tabs . feed ( vec! [ " Fri Oct 03, 2008 " , " 12:00:00 - 14:00:00 " , " 2:00:00 " , " entry 2 " ] ) ;
tabs . feed ( vec! [ " " , " " , " 2:00:00 " , " " ] ) ;
2021-07-15 00:22:38 -05:00
tabs . separator ( '-' ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " Total " , " " , " 52:00:00 " , " " ] ) ;
2021-07-15 00:22:38 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & tabs . print ( false ) , " \
2021-07-15 00:22:38 -05:00
Day Start End Duration Notes
Wed Oct 01 , 2008 12 :00 :00 - 14 :00 :00 + 2 d 50 :00 :00 entry 1
50 :00 :00
Fri Oct 03 , 2008 12 :00 :00 - 14 :00 :00 2 :00 :00 entry 2
2 :00 :00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Total 52 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-07-15 00:22:38 -05:00
}
#[ test ]
fn test_text_output_with_ids ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
2022-07-21 08:35:45 -05:00
Col ::new ( ) . min_width ( 3 ) . and_alignment ( Right ) ,
Col ::new ( ) . min_width ( " Fri Oct 03, 2008 " . len ( ) ) . and_alignment ( Left ) ,
Col ::new ( ) . min_width ( " 12:00:00 - 14:00:00 " . len ( ) ) . and_alignment ( Left ) ,
Col ::new ( ) . min_width ( " Duration " . len ( ) ) . and_alignment ( Right ) ,
Col ::new ( ) . min_width ( " Notes " . len ( ) ) . and_alignment ( Left ) ,
2021-07-15 00:22:38 -05:00
] ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " ID " , " Day " , " Start End " , " Duration " , " Notes " ] ) ;
tabs . feed ( vec! [ " 1 " , " Fri Oct 03, 2008 " , " 12:00:00 - 14:00:00 " , " 2:00:00 " , " entry 1 " ] ) ;
tabs . feed ( vec! [ " 2 " , " " , " 16:00:00 - 18:00:00 " , " 2:00:00 " , " entry 2 " ] ) ;
tabs . feed ( vec! [ " " , " " , " " , " 4:00:00 " , " " ] ) ;
tabs . feed ( vec! [ " 3 " , " Sun Oct 05, 2008 " , " 16:00:00 - 18:00:00 " , " 2:00:00 " , " entry 3 " ] ) ;
tabs . feed ( vec! [ " 4 " , " " , " 18:00:00 - " , " 2:00:00 " , " entry 4 " ] ) ;
tabs . feed ( vec! [ " " , " " , " " , " 4:00:00 " , " " ] ) ;
2021-07-15 00:22:38 -05:00
tabs . separator ( '-' ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " " , " Total " , " " , " 8:00:00 " ] ) ;
2021-07-15 00:22:38 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & tabs . print ( false ) , " ID Day Start End Duration Notes
2021-07-15 00:22:38 -05:00
1 Fri Oct 03 , 2008 12 :00 :00 - 14 :00 :00 2 :00 :00 entry 1
2 16 :00 :00 - 18 :00 :00 2 :00 :00 entry 2
4 :00 :00
3 Sun Oct 05 , 2008 16 :00 :00 - 18 :00 :00 2 :00 :00 entry 3
4 18 :00 :00 - 2 :00 :00 entry 4
4 :00 :00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Total 8 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-07-15 00:22:38 -05:00
}
#[ test ]
fn test_text_output_long_note_with_ids ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
2022-07-21 08:35:45 -05:00
Col ::new ( ) . min_width ( 2 ) . and_alignment ( Right ) ,
Col ::new ( ) . min_width ( " Fri Oct 03, 2008 " . len ( ) ) . and_alignment ( Left ) ,
Col ::new ( ) . min_width ( " 12:00:00 - 14:00:00 " . len ( ) ) . and_alignment ( Left ) ,
Col ::new ( ) . min_width ( " Duration " . len ( ) ) . and_alignment ( Right ) ,
Col ::new ( ) . min_width ( " Notes " . len ( ) ) . max_width ( 44 ) . and_alignment ( Left ) ,
2021-07-15 00:22:38 -05:00
] ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " ID " , " Day " , " Start End " , " Duration " , " Notes " ] ) ;
tabs . feed ( vec! [ " 60000 " , " Sun Oct 05, 2008 " , " 16:00:00 - 18:00:00 " , " 2:00:00 " , LONG_NOTE ] ) ;
tabs . feed ( vec! [ " " , " " , " " , " 2:00:00 " , " " ] ) ;
2021-07-15 00:22:38 -05:00
tabs . separator ( '-' ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " " , " Total " , " " , " 2:00:00 " ] ) ;
2021-07-15 00:22:38 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & tabs . print ( false ) , " ID Day Start End Duration Notes
2021-07-15 00:22:38 -05:00
60000 Sun Oct 05 , 2008 16 :00 :00 - 18 :00 :00 2 :00 :00 chatting with bob about upcoming task ,
district sharing of images , how the user
settings currently works etc . Discussing the
fingerprinting / cache busting issue with
CKEDITOR , suggesting perhaps looking into
forking the rubygem and seeing if we can
work in our own changes , however hard that
might be .
2 :00 :00
2021-07-15 10:33:02 -05:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2021-07-15 00:22:38 -05:00
Total 2 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-07-15 00:22:38 -05:00
}
#[ test ]
fn test_text_output_note_with_line_breaks ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
2022-07-21 08:35:45 -05:00
Col ::new ( ) . min_width ( " Fri Oct 03, 2008 " . len ( ) ) . and_alignment ( Left ) ,
Col ::new ( ) . min_width ( " 12:00:00 - 14:00:00 " . len ( ) ) . and_alignment ( Left ) ,
Col ::new ( ) . min_width ( " Duration " . len ( ) ) . and_alignment ( Right ) ,
Col ::new ( ) . min_width ( " Notes " . len ( ) ) . and_alignment ( Left ) ,
2021-07-15 00:22:38 -05:00
] ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " Day " , " Start End " , " Duration " , " Notes " ] ) ;
tabs . feed ( vec! [ " Sun Oct 05, 2008 " , " 16:00:00 - 18:00:00 " , " 2:00:00 " , " first line \n and a second line " ] ) ;
tabs . feed ( vec! [ " " , " " , " 2:00:00 " , " " ] ) ;
tabs . separator ( '-' ) ;
tabs . feed ( vec! [ " Total " , " " , " 2:00:00 " , " " ] ) ;
2021-07-15 00:22:38 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & tabs . print ( false ) , " \
2021-07-15 00:33:58 -05:00
Day Start End Duration Notes
Sun Oct 05 , 2008 16 :00 :00 - 18 :00 :00 2 :00 :00 first line
and a second line
2 :00 :00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Total 2 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-07-15 00:22:38 -05:00
}
#[ test ]
fn note_with_accents ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
2022-07-21 08:35:45 -05:00
Col ::new ( ) . min_width ( " Fri Oct 03, 2008 " . len ( ) ) . and_alignment ( Left ) ,
Col ::new ( ) . min_width ( " 12:00:00 - 14:00:00 " . len ( ) ) . and_alignment ( Left ) ,
Col ::new ( ) . min_width ( " Duration " . len ( ) ) . and_alignment ( Right ) ,
Col ::new ( ) . min_width ( " Notes " . len ( ) ) . and_alignment ( Left ) ,
2021-07-15 00:22:38 -05:00
] ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " Day " , " Start End " , " Duration " , " Notes " ] ) ;
tabs . feed ( vec! [ " Sun Oct 05, 2008 " , " 16:00:00 - 18:00:00 " , " 2:00:00 " , " quiúbole " ] ) ;
tabs . feed ( vec! [ " " , " " , " 2:00:00 " , " " ] ) ;
2021-07-15 00:22:38 -05:00
tabs . separator ( '-' ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " Total " , " " , " 2:00:00 " , " " ] ) ;
2021-07-15 00:22:38 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & tabs . print ( false ) , " \
2021-07-15 00:22:38 -05:00
Day Start End Duration Notes
Sun Oct 05 , 2008 16 :00 :00 - 18 :00 :00 2 :00 :00 quiúbole
2 :00 :00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Total 2 :00 :00
2022-07-19 05:38:37 -05:00
" );
2021-07-16 09:33:45 -05:00
}
#[ test ]
fn tabulate_a_blank_row ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
Col ::new ( )
] ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " Hola " ] ) ;
2021-07-16 09:33:45 -05:00
tabs . separator ( ' ' ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " adiós " ] ) ;
2021-07-16 09:33:45 -05:00
tabs . separator ( '-' ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " ta güeno " ] ) ;
2021-07-16 09:33:45 -05:00
2022-07-19 05:38:37 -05:00
assert_eq! ( & tabs . print ( false ) , " \
2021-07-16 09:33:45 -05:00
Hola
adiós
- - - - - - - -
ta güeno
2022-07-19 05:38:37 -05:00
" );
2021-07-15 00:22:38 -05:00
}
2021-08-24 23:01:56 -05:00
#[ test ]
fn add_a_color_condition ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
Col ::new ( ) . color_if ( Style ::new ( ) . dimmed ( ) , | val | {
val = = " key "
} ) ,
Col ::new ( ) ,
] ) ;
2022-07-21 08:35:45 -05:00
tabs . feed ( vec! [ " foo " , " key " ] ) ;
tabs . feed ( vec! [ " key " , " foo " ] ) ;
2021-08-24 23:01:56 -05:00
2021-08-25 14:43:50 -05:00
assert_eq! ( tabs . print ( true ) , format! ( " \
2021-08-24 23:01:56 -05:00
foo key
{ } foo
" , Style::new().dimmed().paint( " key " )));
}
2022-08-28 15:48:47 -05:00
#[ test ]
fn sizes_of_things ( ) {
assert_eq! ( " 🥦 " . size ( ) , 1 ) ;
assert_eq! ( " á " . size ( ) , 1 ) ;
assert_eq! ( Fixed ( 10 ) . paint ( " hola " ) . to_string ( ) . size ( ) , 4 ) ;
}
2021-07-15 00:22:38 -05:00
}