@@ -814,6 +814,10 @@ pub(crate) fn char_width(_c: char) -> usize {
814814/// escapes code will still be honored. If truncation takes place
815815/// the tail string will be appended.
816816pub fn truncate_str < ' a > ( s : & ' a str , width : usize , tail : & str ) -> Cow < ' a , str > {
817+ if measure_text_width ( s) <= width {
818+ return Cow :: Borrowed ( s) ;
819+ }
820+
817821 #[ cfg( feature = "ansi-parsing" ) ]
818822 {
819823 use std:: cmp:: Ordering ;
@@ -825,12 +829,12 @@ pub fn truncate_str<'a>(s: &'a str, width: usize, tail: &str) -> Cow<'a, str> {
825829 match item {
826830 ( s, false ) => {
827831 if rv. is_none ( ) {
828- if str_width ( s) + length > width - str_width ( tail) {
832+ if str_width ( s) + length > width. saturating_sub ( str_width ( tail) ) {
829833 let ts = iter. current_slice ( ) ;
830834
831835 let mut s_byte = 0 ;
832836 let mut s_width = 0 ;
833- let rest_width = width - str_width ( tail) - length;
837+ let rest_width = width. saturating_sub ( str_width ( tail) ) . saturating_sub ( length) ;
834838 for c in s. chars ( ) {
835839 s_byte += c. len_utf8 ( ) ;
836840 s_width += char_width ( c) ;
@@ -869,15 +873,11 @@ pub fn truncate_str<'a>(s: &'a str, width: usize, tail: &str) -> Cow<'a, str> {
869873
870874 #[ cfg( not( feature = "ansi-parsing" ) ) ]
871875 {
872- if s. len ( ) <= width - tail. len ( ) {
873- Cow :: Borrowed ( s)
874- } else {
875- Cow :: Owned ( format ! (
876- "{}{}" ,
877- s. get( ..width - tail. len( ) ) . unwrap_or_default( ) ,
878- tail
879- ) )
880- }
876+ Cow :: Owned ( format ! (
877+ "{}{}" ,
878+ & s[ ..width. saturating_sub( tail. len( ) ) ] ,
879+ tail
880+ ) )
881881 }
882882}
883883
@@ -998,13 +998,23 @@ fn test_truncate_str() {
998998 & truncate_str( & s, 6 , "" ) ,
999999 & format!( "foo {}" , style( "バ" ) . red( ) . force_styling( true ) )
10001000 ) ;
1001+ let s = format ! ( "foo {}" , style( "バー" ) . red( ) . force_styling( true ) ) ;
1002+ assert_eq ! (
1003+ & truncate_str( & s, 2 , "!!!" ) ,
1004+ & format!( "!!!{}" , style( "" ) . red( ) . force_styling( true ) )
1005+ ) ;
10011006}
10021007
10031008#[ test]
10041009fn test_truncate_str_no_ansi ( ) {
1010+ assert_eq ! ( & truncate_str( "foo bar" , 7 , "!" ) , "foo bar" ) ;
10051011 assert_eq ! ( & truncate_str( "foo bar" , 5 , "" ) , "foo b" ) ;
10061012 assert_eq ! ( & truncate_str( "foo bar" , 5 , "!" ) , "foo !" ) ;
10071013 assert_eq ! ( & truncate_str( "foo bar baz" , 10 , "..." ) , "foo bar..." ) ;
1014+ assert_eq ! ( & truncate_str( "foo bar" , 0 , "" ) , "" ) ;
1015+ assert_eq ! ( & truncate_str( "foo bar" , 0 , "!" ) , "!" ) ;
1016+ assert_eq ! ( & truncate_str( "foo bar" , 2 , "!!!" ) , "!!!" ) ;
1017+ assert_eq ! ( & truncate_str( "ab" , 2 , "!!!" ) , "ab" ) ;
10081018}
10091019
10101020#[ test]
0 commit comments