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 ;
2021-07-15 00:22:38 -05:00
fn lpad ( s : & str , len : usize ) -> String {
let padding = " " . repeat ( len . saturating_sub ( s . chars ( ) . count ( ) ) ) ;
padding + s
}
fn rpad ( s : & str , len : usize ) -> String {
let padding = " " . repeat ( len . saturating_sub ( s . chars ( ) . count ( ) ) ) ;
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
}
}
2021-07-15 00:22:38 -05:00
pub fn min_width ( size : usize ) -> Col {
Col {
min_width : size ,
align : Align ::Left ,
2021-07-15 10:33:02 -05:00
max_width : None ,
2021-08-24 23:01:56 -05:00
conditonal_styles : Vec ::new ( ) ,
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 ( ) ,
}
}
pub fn feed ( & mut self , data : Vec < String > ) {
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 ( ) {
2021-08-02 19:10:34 -05:00
for ( r1 , dl ) in d . 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 ( ) {
let count = l . chars ( ) . count ( ) ;
2021-07-15 09:40:37 -05:00
2021-07-15 10:33:02 -05:00
if count > * w {
* w = count ;
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 ( {
let mut prev = if ( r1 + r2 ) = = 0 {
data [ .. col ] . to_vec ( )
} 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 ;
2021-08-03 20:56:40 -05:00
use crate ::test_utils ::Ps ;
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! [
2021-07-15 00:33:58 -05:00
Col ::min_width ( " Fri Oct 03, 2008 " . len ( ) ) . and_alignment ( Left ) ,
Col ::min_width ( " 12:00:00 - 14:00:00 " . len ( ) ) . and_alignment ( Left ) ,
2021-07-15 00:22:38 -05:00
Col ::min_width ( " Duration " . len ( ) ) . and_alignment ( Right ) ,
Col ::min_width ( " Notes " . len ( ) ) . and_alignment ( Left ) ,
] ) ;
tabs . feed ( vec! [ " Day " . into ( ) , " Start End " . into ( ) , " Duration " . into ( ) , " Notes " . into ( ) ] ) ;
tabs . feed ( vec! [ " Fri Oct 03, 2008 " . into ( ) , " 12:00:00 - 14:00:00 " . into ( ) , " 2:00:00 " . into ( ) , " entry 1 " . into ( ) ] ) ;
tabs . feed ( vec! [ " " . into ( ) , " 16:00:00 - 18:00:00 " . into ( ) , " 2:00:00 " . into ( ) , " entry 2 " . into ( ) ] ) ;
tabs . feed ( vec! [ " " . into ( ) , " " . into ( ) , " 4:00:00 " . into ( ) , " " . into ( ) ] ) ;
tabs . feed ( vec! [ " Sun Oct 05, 2008 " . into ( ) , " 16:00:00 - 18:00:00 " . into ( ) , " 2:00:00 " . into ( ) , " entry 3 " . into ( ) ] ) ;
tabs . feed ( vec! [ " " . into ( ) , " 18:00:00 - " . into ( ) , " 2:00:00 " . into ( ) , " entry 4 " . into ( ) ] ) ;
tabs . feed ( vec! [ " " . into ( ) , " " . into ( ) , " 4:00:00 " . into ( ) , " " . into ( ) ] ) ;
tabs . separator ( '-' ) ;
tabs . feed ( vec! [ " Total " . into ( ) , " " . into ( ) , " 8:00:00 " . into ( ) , " " . into ( ) ] ) ;
2021-08-25 14:43:50 -05:00
assert_eq! ( Ps ( & tabs . print ( false ) ) , Ps ( " \
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
" ));
}
#[ test ]
fn test_text_output_long_duration ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
Col ::min_width ( " Fri Oct 03, 2008 " . len ( ) ) . and_alignment ( Left ) ,
Col ::min_width ( " 12:00:00 - 14:00:00 " . len ( ) ) . and_alignment ( Left ) ,
Col ::min_width ( " Duration " . len ( ) ) . and_alignment ( Right ) ,
Col ::min_width ( " Notes " . len ( ) ) . and_alignment ( Left ) ,
] ) ;
tabs . feed ( vec! [ " Day " . into ( ) , " Start End " . into ( ) , " Duration " . into ( ) , " Notes " . into ( ) ] ) ;
tabs . feed ( vec! [ " Wed Oct 01, 2008 " . into ( ) , " 12:00:00 - 14:00:00+2d " . into ( ) , " 50:00:00 " . into ( ) , " entry 1 " . into ( ) ] ) ;
tabs . feed ( vec! [ " " . into ( ) , " " . into ( ) , " 50:00:00 " . into ( ) , " " . into ( ) ] ) ;
tabs . feed ( vec! [ " Fri Oct 03, 2008 " . into ( ) , " 12:00:00 - 14:00:00 " . into ( ) , " 2:00:00 " . into ( ) , " entry 2 " . into ( ) ] ) ;
tabs . feed ( vec! [ " " . into ( ) , " " . into ( ) , " 2:00:00 " . into ( ) , " " . into ( ) ] ) ;
tabs . separator ( '-' ) ;
tabs . feed ( vec! [ " Total " . into ( ) , " " . into ( ) , " 52:00:00 " . into ( ) , " " . into ( ) ] ) ;
2021-08-25 14:43:50 -05:00
assert_eq! ( Ps ( & tabs . print ( false ) ) , Ps ( " \
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
" ));
}
#[ test ]
fn test_text_output_with_ids ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
Col ::min_width ( 3 ) . and_alignment ( Right ) ,
Col ::min_width ( " Fri Oct 03, 2008 " . len ( ) ) . and_alignment ( Left ) ,
Col ::min_width ( " 12:00:00 - 14:00:00 " . len ( ) ) . and_alignment ( Left ) ,
Col ::min_width ( " Duration " . len ( ) ) . and_alignment ( Right ) ,
Col ::min_width ( " Notes " . len ( ) ) . and_alignment ( Left ) ,
] ) ;
tabs . feed ( vec! [ " ID " . into ( ) , " Day " . into ( ) , " Start End " . into ( ) , " Duration " . into ( ) , " Notes " . into ( ) ] ) ;
tabs . feed ( vec! [ " 1 " . into ( ) , " Fri Oct 03, 2008 " . into ( ) , " 12:00:00 - 14:00:00 " . into ( ) , " 2:00:00 " . into ( ) , " entry 1 " . into ( ) ] ) ;
tabs . feed ( vec! [ " 2 " . into ( ) , " " . into ( ) , " 16:00:00 - 18:00:00 " . into ( ) , " 2:00:00 " . into ( ) , " entry 2 " . into ( ) ] ) ;
tabs . feed ( vec! [ " " . into ( ) , " " . into ( ) , " " . into ( ) , " 4:00:00 " . into ( ) , " " . into ( ) ] ) ;
tabs . feed ( vec! [ " 3 " . into ( ) , " Sun Oct 05, 2008 " . into ( ) , " 16:00:00 - 18:00:00 " . into ( ) , " 2:00:00 " . into ( ) , " entry 3 " . into ( ) ] ) ;
tabs . feed ( vec! [ " 4 " . into ( ) , " " . into ( ) , " 18:00:00 - " . into ( ) , " 2:00:00 " . into ( ) , " entry 4 " . into ( ) ] ) ;
tabs . feed ( vec! [ " " . into ( ) , " " . into ( ) , " " . into ( ) , " 4:00:00 " . into ( ) , " " . into ( ) ] ) ;
tabs . separator ( '-' ) ;
tabs . feed ( vec! [ " " . into ( ) , " Total " . into ( ) , " " . into ( ) , " 8:00:00 " . into ( ) ] ) ;
2021-08-25 14:43:50 -05:00
assert_eq! ( Ps ( & tabs . print ( false ) ) , Ps ( " 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
" ));
}
#[ test ]
fn test_text_output_long_note_with_ids ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
2021-07-15 00:33:58 -05:00
Col ::min_width ( 2 ) . and_alignment ( Right ) ,
Col ::min_width ( " Fri Oct 03, 2008 " . len ( ) ) . and_alignment ( Left ) ,
Col ::min_width ( " 12:00:00 - 14:00:00 " . len ( ) ) . and_alignment ( Left ) ,
2021-07-15 00:22:38 -05:00
Col ::min_width ( " Duration " . len ( ) ) . and_alignment ( Right ) ,
2021-07-15 10:33:02 -05:00
Col ::min_width ( " Notes " . len ( ) ) . max_width ( 44 ) . and_alignment ( Left ) ,
2021-07-15 00:22:38 -05:00
] ) ;
tabs . feed ( vec! [ " ID " . into ( ) , " Day " . into ( ) , " Start End " . into ( ) , " Duration " . into ( ) , " Notes " . into ( ) ] ) ;
tabs . feed ( vec! [ " 60000 " . into ( ) , " Sun Oct 05, 2008 " . into ( ) , " 16:00:00 - 18:00:00 " . into ( ) , " 2:00:00 " . into ( ) , LONG_NOTE . into ( ) ] ) ;
2021-07-15 00:33:58 -05:00
tabs . feed ( vec! [ " " . into ( ) , " " . into ( ) , " " . into ( ) , " 2:00:00 " . into ( ) , " " . into ( ) ] ) ;
2021-07-15 00:22:38 -05:00
tabs . separator ( '-' ) ;
2021-07-15 00:33:58 -05:00
tabs . feed ( vec! [ " " . into ( ) , " Total " . into ( ) , " " . into ( ) , " 2:00:00 " . into ( ) ] ) ;
2021-07-15 00:22:38 -05:00
2021-08-25 14:43:50 -05:00
assert_eq! ( Ps ( & tabs . print ( false ) ) , Ps ( " 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
" ));
}
#[ test ]
fn test_text_output_note_with_line_breaks ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
2021-07-15 00:33:58 -05:00
Col ::min_width ( " Fri Oct 03, 2008 " . len ( ) ) . and_alignment ( Left ) ,
Col ::min_width ( " 12:00:00 - 14:00:00 " . len ( ) ) . and_alignment ( Left ) ,
2021-07-15 00:22:38 -05:00
Col ::min_width ( " Duration " . len ( ) ) . and_alignment ( Right ) ,
Col ::min_width ( " Notes " . len ( ) ) . and_alignment ( Left ) ,
] ) ;
tabs . feed ( vec! [ " Day " . into ( ) , " Start End " . into ( ) , " Duration " . into ( ) , " Notes " . into ( ) ] ) ;
tabs . feed ( vec! [ " Sun Oct 05, 2008 " . into ( ) , " 16:00:00 - 18:00:00 " . into ( ) , " 2:00:00 " . into ( ) , " first line \n and a second line " . into ( ) ] ) ;
tabs . feed ( vec! [ " " . into ( ) , " " . into ( ) , " 2:00:00 " . into ( ) , " " . into ( ) ] ) ;
tabs . separator ( '-' ) ;
tabs . feed ( vec! [ " Total " . into ( ) , " " . into ( ) , " 2:00:00 " . into ( ) , " " . into ( ) ] ) ;
2021-08-25 14:43:50 -05:00
assert_eq! ( Ps ( & tabs . print ( false ) ) , Ps ( " \
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
2021-07-15 00:22:38 -05:00
" ));
}
#[ test ]
fn note_with_accents ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
Col ::min_width ( " Fri Oct 03, 2008 " . len ( ) ) . and_alignment ( Left ) ,
Col ::min_width ( " 12:00:00 - 14:00:00 " . len ( ) ) . and_alignment ( Left ) ,
Col ::min_width ( " Duration " . len ( ) ) . and_alignment ( Right ) ,
Col ::min_width ( " Notes " . len ( ) ) . and_alignment ( Left ) ,
] ) ;
tabs . feed ( vec! [ " Day " . into ( ) , " Start End " . into ( ) , " Duration " . into ( ) , " Notes " . into ( ) ] ) ;
tabs . feed ( vec! [ " Sun Oct 05, 2008 " . into ( ) , " 16:00:00 - 18:00:00 " . into ( ) , " 2:00:00 " . into ( ) , " quiúbole " . into ( ) ] ) ;
tabs . feed ( vec! [ " " . into ( ) , " " . into ( ) , " 2:00:00 " . into ( ) , " " . into ( ) ] ) ;
tabs . separator ( '-' ) ;
tabs . feed ( vec! [ " Total " . into ( ) , " " . into ( ) , " 2:00:00 " . into ( ) , " " . into ( ) ] ) ;
2021-08-25 14:43:50 -05:00
assert_eq! ( Ps ( & tabs . print ( false ) ) , Ps ( " \
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
2021-07-16 09:33:45 -05:00
" ));
}
#[ test ]
fn tabulate_a_blank_row ( ) {
let mut tabs = Tabulate ::with_columns ( vec! [
Col ::new ( )
] ) ;
tabs . feed ( vec! [ " Hola " . into ( ) ] ) ;
tabs . separator ( ' ' ) ;
tabs . feed ( vec! [ " adiós " . into ( ) ] ) ;
tabs . separator ( '-' ) ;
tabs . feed ( vec! [ " ta güeno " . into ( ) ] ) ;
2021-08-25 14:43:50 -05:00
assert_eq! ( Ps ( & tabs . print ( false ) ) , Ps ( " \
2021-07-16 09:33:45 -05:00
Hola
adiós
- - - - - - - -
ta güeno
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 ( ) ,
] ) ;
tabs . feed ( vec! [ " foo " . into ( ) , " key " . into ( ) ] ) ;
tabs . feed ( vec! [ " key " . into ( ) , " foo " . into ( ) ] ) ;
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 " )));
}
2021-07-15 00:22:38 -05:00
}