@@ -206,7 +206,6 @@ impl ANSICursorControl {
206206 pub fn sub ( & mut self ) {
207207 self . subn ( 1 )
208208 }
209- #[ allow( unused) ]
210209 pub fn subn ( & mut self , num : u16 ) {
211210 debug_assert ! ( self . len >= num) ;
212211 self . len -= num
@@ -282,29 +281,121 @@ impl<T> From<T> for ANSIColors
282281}
283282impl Display for ANSIColors {
284283 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
285- fn func ( a : u8 , b : u8 ) -> bool {
286- const EMPTY : ( u8 , u8 ) = ( 39 , 49 ) ;
287- ( a, b) == EMPTY || ( b, a) == EMPTY
288- }
289284 let len = self . colors . len ( ) ;
290- let res = if len != 0 {
291- let x = if self . colors [ len - 1 ] == 0
292- || ( len >= 2 && func (
293- self . colors [ len - 1 ] , self . colors [ len - 2 ] ) ) {
294- "0" . to_string ( )
285+ write ! ( f, "{}" , if len == 0 { String :: new( ) } else {
286+ let mut iter = self . colors. iter( ) ;
287+ let [ mut bnone, mut fnone] = [ false ; 2 ] ;
288+ let [ mut bgs, mut fgs] = [ [ 0u8 ; 5 ] ; 2 ] ;
289+ let [ mut bgc, mut fgc] = [ 0usize ; 2 ] ;
290+ macro_rules! err {
291+ ( ) => {
292+ panic!(
293+ "color format error: {:?}" , self . colors)
294+ } ;
295+ ( $( $x: expr ) , * ) => {
296+ panic!(
297+ "color format error: {:?} ({})" ,
298+ self . colors, format!( $( $x ) , * ) )
299+ } ;
300+ }
301+ macro_rules! next {
302+ ( ) => {
303+ iter. next( )
304+ . unwrap_or_else(
305+ || err!( "next to end" ) )
306+ } ;
307+ }
308+ // 将每种颜色情况分析 如果全部重置则重置为0
309+ loop {
310+ if let Some ( x) = iter. next( ) {
311+ match * x {
312+ 0 => [ bnone, fnone] = [ true ; 2 ] ,
313+ 39 => {
314+ fgc = 0 ;
315+ fnone = true ;
316+ } ,
317+ 49 => {
318+ bgc = 0 ;
319+ bnone = true ;
320+ } ,
321+ 38 => {
322+ fnone = false ;
323+ match * next!( )
324+ {
325+ y @ 2 => {
326+ fgs[ 0 ] = * x;
327+ fgs[ 1 ] = y;
328+ for i in 2 ..5 {
329+ fgs[ i] = * next!( ) ;
330+ }
331+ fgc = 5 ;
332+ } ,
333+ y @ 5 => {
334+ fgs[ 0 ] = * x;
335+ fgs[ 1 ] = y;
336+ fgs[ 2 ] = * next!( ) ;
337+ fgc = 3 ;
338+ } ,
339+ _ => err!( ) ,
340+ }
341+ } ,
342+ 48 => {
343+ bnone = false ;
344+ match * next!( )
345+ {
346+ y @ 2 => {
347+ bgs[ 0 ] = * x;
348+ bgs[ 1 ] = y;
349+ for i in 2 ..5 {
350+ bgs[ i] = * next!( ) ;
351+ }
352+ bgc = 5 ;
353+ } ,
354+ y @ 5 => {
355+ bgs[ 0 ] = * x;
356+ bgs[ 1 ] = y;
357+ bgs[ 2 ] = * next!( ) ;
358+ bgc = 3 ;
359+ } ,
360+ _ => err!( ) ,
361+ }
362+ } ,
363+ n @ ( 30 ..=37 | 90 ..=97 ) => {
364+ fnone = false ;
365+ fgs[ 0 ] = n;
366+ fgc = 1 ;
367+ } ,
368+ n @ ( 40 ..=47 | 100 ..=107 ) => {
369+ bnone = false ;
370+ bgs[ 0 ] = n;
371+ bgc = 1 ;
372+ } ,
373+ e => err!( "e:{}" , e) ,
374+ }
375+ } else {
376+ break ;
377+ }
378+ }
379+ macro_rules! join {
380+ ( $x: expr ) => {
381+ ( $x) . into_iter( ) . map( |x| format!( "{}" , x) ) . collect:: <Vec <_>>( ) . join( ";" )
382+ } ;
383+ }
384+ if bnone && fnone {
385+ format!( "{}[0m" , ESC )
386+ } else if bgc == 0 && fgc == 0 {
387+ format!( "" )
295388 } else {
296- self . colors . iter ( )
297- . map ( |x| x. to_string ( ) )
298- . collect :: < Vec < String > > ( ) . join ( ";" )
299- } ;
300- format ! ( "{ESC}[{}m" , x)
301- } else { /* empty */ "" . to_string ( ) } ;
302- write ! ( f, "{res}" )
389+ format!( "{}[{}m" , ESC ,
390+ join!( bgs[ 0 ..bgc] . into_iter( )
391+ . chain( fgs[ 0 ..fgc] . into_iter( ) ) ) )
392+ }
393+ } )
303394 }
304395}
305396#[ cfg( test) ]
306397mod ansi_colors_tests {
307- use super :: { ANSIColors , ESC } ;
398+ use super :: { ANSIColors , ESC , Color } ;
308399 #[ test]
309400 fn new ( ) {
310401 assert_eq ! ( ANSIColors :: new( ) , ANSIColors { colors: Vec :: new( ) } ) ;
@@ -323,8 +414,8 @@ mod ansi_colors_tests {
323414 #[ test]
324415 fn fmt ( ) {
325416 let mut a = ANSIColors :: new ( ) ;
326- a. add ( [ 1 , 2 , 4 ] ) ;
327- assert_eq ! ( format!( "{a}" ) , format!( "{ESC}[1;2;4m " ) ) ;
417+ a. add ( [ 31 , 42 , 36 ] ) ;
418+ assert_eq ! ( format!( "{a}" ) , format!( "{ESC}[42;36m " ) ) ;
328419 assert_eq ! ( format!( "{}" , ANSIColors :: new( ) ) , String :: new( ) ) ;
329420
330421 let mut a = ANSIColors :: new ( ) ;
@@ -334,8 +425,25 @@ mod ansi_colors_tests {
334425 a. add ( [ 39 , 49 ] ) ;
335426 assert_eq ! ( format!( "{a}" ) , format!( "{ESC}[0m" ) ) ;
336427 let mut a = ANSIColors :: new ( ) ;
337- a. add ( [ 8 , 39 , 49 ] ) ;
428+ a. add ( [ 32 , 39 , 49 ] ) ;
338429 assert_eq ! ( format!( "{a}" ) , format!( "{ESC}[0m" ) ) ;
430+ let mut a = ANSIColors :: new ( ) ;
431+ a. add ( Color :: Rgb ( [ 0 , 1 , 2 ] ) . to_ansi ( false ) ) ;
432+ assert_eq ! ( format!( "{a}" ) , format!( "{ESC}[38;2;0;1;2m" ) ) ;
433+
434+ let mut a = ANSIColors :: new ( ) ;
435+ a. add ( Color :: Rgb ( [ 255 , 39 , 0 ] ) . to_ansi ( false ) ) ;
436+ assert_eq ! ( format!( "{a}" ) , format!( "{ESC}[38;2;255;39;0m" ) ) ;
437+ a. add ( Color :: Rgb ( [ 255 , 39 , 0 ] ) . to_ansi ( true ) ) ;
438+ assert_eq ! ( format!( "{a}" ) , format!( "{ESC}[48;2;255;39;0;38;2;255;39;0m" ) ) ;
439+ a. add ( Color :: None . to_ansi ( false ) ) ;
440+ assert_eq ! ( format!( "{a}" ) , format!( "{ESC}[48;2;255;39;0m" ) ) ;
441+ a. add ( Color :: None . to_ansi ( true ) ) ;
442+ assert_eq ! ( format!( "{a}" ) , format!( "{ESC}[0m" ) ) ;
443+ a. add ( Color :: C256 ( 72 ) . to_ansi ( true ) ) ;
444+ assert_eq ! ( format!( "{a}" ) , format!( "{ESC}[48;5;72m" ) ) ;
445+ a. add ( Color :: C256 ( 12 ) . to_ansi ( true ) ) ;
446+ assert_eq ! ( format!( "{a}" ) , format!( "{ESC}[104m" ) ) ;
339447 }
340448}
341449
@@ -366,6 +474,10 @@ impl Color {
366474 /// let a = Color::Rgb([8, 18, 28]);
367475 /// assert_eq!(a.to_ansi(false), vec![38, 2, 8, 18, 28]);
368476 /// assert_eq!(a.to_ansi(true), vec![48, 2, 8, 18, 28]);
477+ ///
478+ /// let a = Color::Rgb([0; 3]);
479+ /// assert_eq!(a.to_ansi(false), vec![38, 2, 0, 0, 0]);
480+ /// assert_eq!(a.to_ansi(true), vec![48, 2, 0, 0, 0]);
369481 /// ```
370482 pub fn to_ansi ( & self , is_background : bool ) -> Vec < u8 > {
371483 let head = if is_background { 48 } else { 38 } ;
@@ -414,7 +526,7 @@ impl Color {
414526 Self :: Rgb ( color) => {
415527 type Num = i32 ;
416528 macro_rules! sum {
417- ( $a: expr $( , $x: expr) * ) => ( $a $( + $x) * ) ;
529+ ( $a: expr $( , $x: expr ) * ) => ( $a $( + $x ) * ) ;
418530 }
419531 macro_rules! fun {
420532 ( $self: ident, $other: ident
@@ -708,17 +820,20 @@ impl ScreenBuffer {
708820 /// You can use discontinuous output to avoid changing the color
709821 /// between multiple outputs that can affect the output effect.
710822 pub fn flush ( & self , is_continue : bool ) -> String {
711- let width: SizeType = self . size [ 0 ] ;
712- let line_size: usize = width as usize * (
713- UNIT_COLOR_CHARS * 2 + self . cfg . half . len_utf8 ( ) ) + 9 ;
714- let line_count = self . size [ 1 ] ;
715- let text_line_count = line_count >> 1 ;
716- let res_cap = line_size * ( text_line_count + 1 ) as usize ;
717- let mut downs = ANSICursorControl :: from ( 'B' ) ;
718- let mut skips = ANSICursorControl :: from ( 'C' ) ;
823+ let res_cap = self . get_output_string_size ( ) ;
719824 let mut res: String
720825 = String :: with_capacity ( res_cap) ;
721- let mut backs = ANSICursorControl :: from ( 'D' ) ;
826+ self . flush_to_string ( is_continue, & mut res) ;
827+ debug_assert_eq ! ( res. capacity( ) , res_cap) ;
828+ res
829+ }
830+ /// Same as `flush` , but output to the incoming string after clearing the incoming string
831+ pub fn flush_to_string ( & self , is_continue : bool , res : & mut String ) {
832+ let [ width, height] : Position = self . size ;
833+ let line_size: usize = self . get_output_string_line_size ( ) ;
834+ let mut downs: ANSICursorControl = ANSICursorControl :: from ( 'B' ) ;
835+ let mut skips: ANSICursorControl = ANSICursorControl :: from ( 'C' ) ;
836+ let mut backs: ANSICursorControl = ANSICursorControl :: from ( 'D' ) ;
722837 let mut line_buf: String = String :: with_capacity ( line_size) ;
723838
724839 macro_rules! add_empty_color {
@@ -734,7 +849,9 @@ impl ScreenBuffer {
734849 self . init_prev_color ( )
735850 }
736851
737- for line_num in ( 0 ..line_count) . step_by ( 2 ) {
852+ res. clear ( ) ; // 清空传入字符串
853+
854+ for line_num in ( 0 ..height) . step_by ( 2 ) {
738855 for column_num in 0 ..width {
739856 if let Some ( x) = self . get_pos_text ( [ column_num, line_num] ) {
740857 if ! skips. is_empty ( ) {
@@ -757,13 +874,22 @@ impl ScreenBuffer {
757874 downs. add ( ) ;
758875 res. push_str ( & line_buf) ;
759876 line_buf. clear ( ) ;
877+ debug_assert_eq ! ( line_buf. capacity( ) , line_size) ;
760878 }
761879 res. push_str ( & downs. to_string ( ) ) ;
762880 if ! is_continue {
763881 add_empty_color ! ( ) ;
764882 }
765- debug_assert_eq ! ( res. capacity( ) , res_cap) ;
766- res
883+ }
884+ /// Obtain the expected size of the string used for output. (Byte)
885+ pub fn get_output_string_size ( & self ) -> usize {
886+ let text_lines = ( self . size [ 1 ] >> 1 ) as usize ;
887+ self . get_output_string_line_size ( ) * text_lines
888+ }
889+ /// Obtain the expected size of a single line output string. (Byte)
890+ pub fn get_output_string_line_size ( & self ) -> usize {
891+ self . size [ 0 ] as usize * (
892+ UNIT_COLOR_CHARS * 2 + self . cfg . half . len_utf8 ( ) ) + 12
767893 }
768894 /// Get a borrow of the color buffer
769895 /// # Examples
@@ -855,6 +981,16 @@ impl<T> From<(Position, Config, T)> for ScreenBuffer
855981 /// assert_eq!(
856982 /// b, vec![Color::None, Color::C256(39), Color::None, Color::None]);
857983 /// ```
984+ /// ---
985+ /// From Buffer
986+ /// # Examples
987+ /// ```
988+ /// # use term_lattice::{ScreenBuffer,Color,Config};
989+ /// let a = ScreenBuffer::default();
990+ /// let b = ScreenBuffer::from((
991+ /// a.size(), a.cfg, a.get_colors_borrow().clone().into_iter()));
992+ /// assert_eq!(a, b);
993+ /// ```
858994 fn from ( value : ( Position , Config , T ) ) -> Self {
859995 let res = Self :: new_from_cfg ( value. 0 , value. 1 ) ;
860996 let mut i = 0 ;
@@ -918,32 +1054,36 @@ mod screen_buffer_test {
9181054 let mut cfg = Config :: new ( ) ;
9191055 cfg. default_color = Color :: C256 ( 15 ) ;
9201056 cfg. chromatic_aberration = 1 ;
921- let a = ScreenBuffer :: new_from_cfg ( [ n; 2 ] , cfg) ;
1057+ let buf = ScreenBuffer :: new_from_cfg ( [ n; 2 ] , cfg) ;
1058+ //let mut outstr: String = String::with_capacity(buf.get_output_string_size());
9221059 macro_rules! out {
9231060 ( $mode: expr) => {
924- print!( "\x1b [H\x1b [B {}" , a. flush( $mode) ) ;
1061+ print!( "\x1b [H\x1b [B {}" , buf. flush( $mode) ) ;
1062+ //buf.flush_to_string($mode, &mut outstr);
1063+ //print!("\x1b[H\x1b[B {outstr}");
9251064 } ;
9261065 }
9271066 for i in 0 ..n >> 1 {
9281067 for j in 0 ..n {
929- a. set ( [ j, i] , Color :: None ) ;
1068+ buf. set ( [ i, j] , Color :: None ) ;
1069+ buf. set ( [ j, i] , Color :: None ) ;
9301070 out ! ( true ) ;
9311071 }
9321072 }
9331073 for i in 0 ..n {
934- a . set ( [ i; 2 ] , Color :: C256 ( ( i & 0xff ) as u8 ) ) ;
1074+ buf . set ( [ i; 2 ] , Color :: C256 ( ( i & 0xff ) as u8 ) ) ;
9351075 out ! ( true ) ;
9361076 }
9371077 for i in 0 ..n {
938- a . set ( [ ( 12 + i) / 8 , i] , Color :: C256 ( ( i & 0xff ) as u8 ) ) ;
939- a . set ( [ i, ( 12 + i) / 8 ] , Color :: C256 ( ( i & 0xff ) as u8 ) ) ;
1078+ buf . set ( [ ( 12 + i) / 8 , i] , Color :: C256 ( ( i & 0xff ) as u8 ) ) ;
1079+ buf . set ( [ i, ( 12 + i) / 8 ] , Color :: C256 ( ( i & 0xff ) as u8 ) ) ;
9401080 out ! ( true ) ;
9411081 }
9421082 let mut i: f64 = 0.0 ;
9431083 let mut j = 0 ;
9441084 let n1 = ( n >> 1 ) as f64 ;
9451085 while i < 6.28 {
946- a . set (
1086+ buf . set (
9471087 [ ( ( i. cos ( ) * 0.5 ) * n1 + n1) as SizeType ,
9481088 ( ( i. sin ( ) * 0.5 ) * n1 + n1) as SizeType ] ,
9491089 Color :: C256 ( j) ) ;
@@ -953,18 +1093,40 @@ mod screen_buffer_test {
9531093 }
9541094 out ! ( false ) ;
9551095 println ! ( "\x1b [5A&&&" ) ;
956- a . init_rect_bg ( [ 0 , n - 10 ] , [ 3 , 2 ] ) ;
1096+ buf . init_rect_bg ( [ 0 , n - 10 ] , [ 3 , 2 ] ) ;
9571097 out ! ( false ) ;
958- a . fill_rect ( [ 8 , 7 ] , [ 22 ; 2 ] , Color :: C256 ( 84 ) ) ;
1098+ buf . fill_rect ( [ 8 , 7 ] , [ 22 ; 2 ] , Color :: C256 ( 84 ) ) ;
9591099 out ! ( false ) ;
960- //for i in (0..=255).step_by(4) {
961- // a.fill(Color::C256(i));
962- // out!(false);
963- //}
1100+ for i in 0 ..16 {
1101+ buf. fill ( Color :: C256 ( i) ) ;
1102+ out ! ( false ) ;
1103+ }
1104+ for i in ( 16 ..=255 ) . step_by ( 4 ) {
1105+ buf. fill ( Color :: C256 ( i) ) ;
1106+ out ! ( false ) ;
1107+ }
9641108 let s = ScreenBuffer :: new ( [ 0 , 0 ] ) . flush ( true ) ;
9651109 assert_eq ! ( s, String :: from( "" ) ) ;
9661110 }
9671111
1112+ #[ test]
1113+ fn example ( ) {
1114+ let n = 100 ;
1115+ let mut cfg = Config :: new ( ) ;
1116+ let text_lines = n as usize >> 1 ;
1117+ cfg. default_color = Color :: C256 ( 15 ) ;
1118+ cfg. default_color = Color :: Rgb ( [ 0 ; 3 ] ) ;
1119+ cfg. chromatic_aberration = 1 ;
1120+ let a = ScreenBuffer :: new_from_cfg ( [ n; 2 ] , cfg) ;
1121+
1122+ print ! ( "\x1b [s{}" , "\n " . repeat( text_lines + 1 ) ) ;
1123+
1124+ for i in 0 ..n {
1125+ a. set ( [ i; 2 ] , Color :: C256 ( ( i & 0xff ) as u8 ) ) ;
1126+ println ! ( "\x1b [u{}" , a. flush( false ) ) ;
1127+ }
1128+ }
1129+
9681130 #[ test]
9691131 fn incremental_flush ( ) {
9701132 let mut a = ScreenBuffer :: new ( [ 80 ; 2 ] ) ;
0 commit comments