@@ -119,13 +119,19 @@ impl NBReader {
119119 /// - timeout:
120120 /// + `None`: read_until is blocking forever. This is probably not what you want
121121 /// + `Some(millis)`: after millis milliseconds a timeout error is raised
122- pub fn new < R : Read + Send + ' static > ( f : R , timeout : Option < u64 > ) -> NBReader {
122+ /// - strip_ansi_escape_codes: Whether to filter out escape codes, such as colors.
123+ pub fn new < R : Read + Send + ' static > (
124+ f : R ,
125+ timeout : Option < u64 > ,
126+ strip_ansi_escape_codes : bool
127+ ) -> NBReader {
123128 let ( tx, rx) = channel ( ) ;
124129
125130 // spawn a thread which reads one char and sends it to tx
126131 thread:: spawn ( move || -> Result < ( ) , Error > {
127132 let mut reader = BufReader :: new ( f) ;
128133 let mut byte = [ 0u8 ] ;
134+
129135 loop {
130136 match reader. read ( & mut byte) {
131137 Ok ( 0 ) => {
@@ -134,12 +140,21 @@ impl NBReader {
134140 break ;
135141 }
136142 Ok ( _) => {
137- tx. send ( Ok ( PipedChar :: Char ( byte[ 0 ] ) ) )
138- . map_err ( |_| Error :: MpscSendError ) ?;
143+ if strip_ansi_escape_codes && byte[ 0 ] == 27 {
144+ while let Ok ( _) = reader. read ( & mut byte) {
145+ if char:: from ( byte[ 0 ] ) . is_alphabetic ( ) {
146+ break ;
147+ }
148+ }
149+ }
150+ else {
151+ tx. send ( Ok ( PipedChar :: Char ( byte[ 0 ] ) ) )
152+ . map_err ( |_| Error :: MpscSendError ) ?;
153+ }
139154 }
140155 Err ( error) => {
141156 tx. send ( Err ( PipeError :: IO ( error) ) )
142- . map_err ( |_| Error :: MpscSendError ) ?;
157+ . map_err ( |_| Error :: MpscSendError ) ?;
143158 }
144159 }
145160 }
@@ -208,7 +223,7 @@ impl NBReader {
208223 /// // instead of a Cursor you would put your process output or file here
209224 /// let f = Cursor::new("Hello, miss!\n\
210225 /// What do you mean: 'miss'?");
211- /// let mut e = NBReader::new(f, None);
226+ /// let mut e = NBReader::new(f, None, false );
212227 ///
213228 /// let (first_line, _) = e.read_until(&ReadUntil::String('\n'.to_string())).unwrap();
214229 /// assert_eq!("Hello, miss!", &first_line);
@@ -230,6 +245,7 @@ impl NBReader {
230245
231246 loop {
232247 self . read_into_buffer ( ) ?;
248+
233249 if let Some ( tuple_pos) = find ( needle, & self . buffer , self . eof ) {
234250 let first = self . buffer . drain ( ..tuple_pos. 0 ) . collect ( ) ;
235251 let second = self . buffer . drain ( ..tuple_pos. 1 - tuple_pos. 0 ) . collect ( ) ;
@@ -287,7 +303,7 @@ mod tests {
287303 #[ test]
288304 fn test_expect_melon ( ) {
289305 let f = io:: Cursor :: new ( "a melon\r \n " ) ;
290- let mut r = NBReader :: new ( f, None ) ;
306+ let mut r = NBReader :: new ( f, None , false ) ;
291307 assert_eq ! (
292308 ( "a melon" . to_string( ) , "\r \n " . to_string( ) ) ,
293309 r. read_until( & ReadUntil :: String ( "\r \n " . to_string( ) ) )
@@ -304,7 +320,7 @@ mod tests {
304320 #[ test]
305321 fn test_regex ( ) {
306322 let f = io:: Cursor :: new ( "2014-03-15" ) ;
307- let mut r = NBReader :: new ( f, None ) ;
323+ let mut r = NBReader :: new ( f, None , false ) ;
308324 let re = Regex :: new ( r"^\d{4}-\d{2}-\d{2}$" ) . unwrap ( ) ;
309325 assert_eq ! (
310326 ( "" . to_string( ) , "2014-03-15" . to_string( ) ) ,
@@ -316,7 +332,7 @@ mod tests {
316332 #[ test]
317333 fn test_regex2 ( ) {
318334 let f = io:: Cursor :: new ( "2014-03-15" ) ;
319- let mut r = NBReader :: new ( f, None ) ;
335+ let mut r = NBReader :: new ( f, None , false ) ;
320336 let re = Regex :: new ( r"-\d{2}-" ) . unwrap ( ) ;
321337 assert_eq ! (
322338 ( "2014" . to_string( ) , "-03-" . to_string( ) ) ,
@@ -328,7 +344,7 @@ mod tests {
328344 #[ test]
329345 fn test_nbytes ( ) {
330346 let f = io:: Cursor :: new ( "abcdef" ) ;
331- let mut r = NBReader :: new ( f, None ) ;
347+ let mut r = NBReader :: new ( f, None , false ) ;
332348 assert_eq ! (
333349 ( "" . to_string( ) , "ab" . to_string( ) ) ,
334350 r. read_until( & ReadUntil :: NBytes ( 2 ) ) . expect( "2 bytes" )
@@ -346,7 +362,7 @@ mod tests {
346362 #[ test]
347363 fn test_any_with_multiple_possible_matches ( ) {
348364 let f = io:: Cursor :: new ( "zero one two three four five" ) ;
349- let mut r = NBReader :: new ( f, None ) ;
365+ let mut r = NBReader :: new ( f, None , false ) ;
350366
351367 let result = r
352368 . read_until ( & ReadUntil :: Any ( vec ! [
@@ -361,7 +377,7 @@ mod tests {
361377 #[ test]
362378 fn test_any_with_same_start_different_length ( ) {
363379 let f = io:: Cursor :: new ( "hi hello" ) ;
364- let mut r = NBReader :: new ( f, None ) ;
380+ let mut r = NBReader :: new ( f, None , false ) ;
365381
366382 let result = r
367383 . read_until ( & ReadUntil :: Any ( vec ! [
@@ -376,18 +392,29 @@ mod tests {
376392 #[ test]
377393 fn test_eof ( ) {
378394 let f = io:: Cursor :: new ( "lorem ipsum dolor sit amet" ) ;
379- let mut r = NBReader :: new ( f, None ) ;
395+ let mut r = NBReader :: new ( f, None , false ) ;
380396 r. read_until ( & ReadUntil :: NBytes ( 2 ) ) . expect ( "2 bytes" ) ;
381397 assert_eq ! (
382398 ( "" . to_string( ) , "rem ipsum dolor sit amet" . to_string( ) ) ,
383399 r. read_until( & ReadUntil :: EOF ) . expect( "reading until EOF" )
384400 ) ;
385401 }
386402
403+ #[ test]
404+ fn test_skip_ansi_codes ( ) {
405+ let f = io:: Cursor :: new ( "\x1b [31;1;4mHello\x1b [0m" ) ;
406+ let mut r = NBReader :: new ( f, None , true ) ;
407+ let bytes = r. read_until ( & ReadUntil :: String ( "Hello" . to_string ( ) ) ) . unwrap ( ) ;
408+ assert_eq ! ( bytes, ( "" . to_string( ) , "Hello" . to_string( ) ) ) ;
409+ assert_eq ! ( None , r. try_read( ) ) ;
410+
411+ }
412+
413+
387414 #[ test]
388415 fn test_try_read ( ) {
389416 let f = io:: Cursor :: new ( "lorem" ) ;
390- let mut r = NBReader :: new ( f, None ) ;
417+ let mut r = NBReader :: new ( f, None , false ) ;
391418 let bytes = r. read_until ( & ReadUntil :: NBytes ( 4 ) ) . unwrap ( ) ;
392419 assert ! ( bytes. 0 . is_empty( ) ) ;
393420 assert_eq ! ( bytes. 1 , "lore" ) ;
0 commit comments