@@ -509,19 +509,36 @@ impl<'a> Pager<'a> {
509509 }
510510 }
511511
512+ /// Queue a line clear only when stdout is a tty; no-op otherwise so ANSI bytes
513+ /// don't leak into downstream pipes.
514+ fn clear_line ( & mut self ) -> std:: io:: Result < ( ) > {
515+ if self . stdout . is_tty ( ) {
516+ self . stdout . queue ( Clear ( ClearType :: CurrentLine ) ) ?;
517+ }
518+ Ok ( ( ) )
519+ }
520+
521+ /// Wrap `text` in the reverse-video attribute when stdout is a tty; return
522+ /// the plain text otherwise.
523+ fn highlight_text ( & self , text : & str ) -> String {
524+ if self . stdout . is_tty ( ) {
525+ format ! ( "{}{text}{}" , Attribute :: Reverse , Attribute :: Reset )
526+ } else {
527+ text. to_string ( )
528+ }
529+ }
530+
512531 fn handle_from_line ( & mut self ) -> UResult < ( ) > {
513532 if !self . read_until_line ( self . upper_mark ) ? {
514- write ! (
515- self . stdout,
516- "\r {}{} ({}){}" ,
517- Attribute :: Reverse ,
533+ let msg = format ! (
534+ "{} ({})" ,
518535 translate!(
519536 "more-error-cannot-seek-to-line" ,
520537 "line" => ( self . upper_mark + 1 )
521538 ) ,
522539 translate!( "more-press-return" ) ,
523- Attribute :: Reset ,
524- ) ?;
540+ ) ;
541+ write ! ( self . stdout , " \r {}" , self . highlight_text ( & msg ) ) ?;
525542 self . stdout . flush ( ) ?;
526543 self . wait_for_enter_key ( ) ?;
527544 self . upper_mark = 0 ;
@@ -576,14 +593,12 @@ impl<'a> Pager<'a> {
576593 self . upper_mark = line;
577594 } else {
578595 self . pattern = None ;
579- write ! (
580- self . stdout,
581- "\r {}{} ({}){}" ,
582- Attribute :: Reverse ,
596+ let msg = format ! (
597+ "{} ({})" ,
583598 translate!( "more-error-pattern-not-found" ) ,
584599 translate!( "more-press-return" ) ,
585- Attribute :: Reset ,
586- ) ?;
600+ ) ;
601+ write ! ( self . stdout , " \r {}" , self . highlight_text ( & msg ) ) ?;
587602 self . stdout . flush ( ) ?;
588603 self . wait_for_enter_key ( ) ?;
589604 }
@@ -610,7 +625,7 @@ impl<'a> Pager<'a> {
610625 }
611626
612627 fn display_multi_file_header ( & mut self ) -> UResult < ( ) > {
613- self . stdout . queue ( Clear ( ClearType :: CurrentLine ) ) ?;
628+ self . clear_line ( ) ?;
614629 self . stdout . write_all (
615630 MULTI_FILE_TOP_PROMPT
616631 . replace ( "{}" , self . file_name . unwrap_or_default ( ) )
@@ -629,6 +644,9 @@ impl<'a> Pager<'a> {
629644 }
630645
631646 fn update_display ( & mut self , options : & Options ) -> UResult < ( ) > {
647+ if !self . stdout . is_tty ( ) {
648+ return Ok ( ( ) ) ;
649+ }
632650 if options. print_over {
633651 self . stdout
634652 . execute ( MoveTo ( 0 , 0 ) ) ?
@@ -774,14 +792,14 @@ impl<'a> Pager<'a> {
774792
775793 fn draw ( & mut self , wrong_key : Option < char > ) -> UResult < ( ) > {
776794 self . draw_lines ( ) ?;
777- self . draw_status_bar ( wrong_key) ;
795+ self . draw_status_bar ( wrong_key) ? ;
778796 self . stdout . flush ( ) ?;
779797 Ok ( ( ) )
780798 }
781799
782800 fn draw_lines ( & mut self ) -> UResult < ( ) > {
783801 // Clear current prompt line
784- self . stdout . queue ( Clear ( ClearType :: CurrentLine ) ) ?;
802+ self . clear_line ( ) ?;
785803 // Reset squeezed lines counter
786804 self . lines_squeezed = 0 ;
787805 // Display lines until we've filled the screen
@@ -803,11 +821,8 @@ impl<'a> Pager<'a> {
803821 // Display the line
804822 let mut line = self . lines [ index] . clone ( ) ;
805823 if let Some ( pattern) = & self . pattern {
806- // Highlight the pattern in the line
807- line = line. replace (
808- pattern,
809- & format ! ( "{}{pattern}{}" , Attribute :: Reverse , Attribute :: Reset ) ,
810- ) ;
824+ let highlighted = self . highlight_text ( pattern) ;
825+ line = line. replace ( pattern, & highlighted) ;
811826 }
812827 self . stdout . write_all ( format ! ( "\r {line}\n " ) . as_bytes ( ) ) ?;
813828 lines_printed += 1 ;
@@ -833,7 +848,7 @@ impl<'a> Pager<'a> {
833848 }
834849 }
835850
836- fn draw_status_bar ( & mut self , wrong_key : Option < char > ) {
851+ fn draw_status_bar ( & mut self , wrong_key : Option < char > ) -> std :: io :: Result < ( ) > {
837852 // Calculate the index of the last visible line
838853 let lower_mark =
839854 ( self . upper_mark + self . content_rows ) . min ( self . lines . len ( ) . saturating_sub ( 1 ) ) ;
@@ -885,13 +900,9 @@ impl<'a> Pager<'a> {
885900 ( false , None ) => status,
886901 } ;
887902 // Draw the status bar at the bottom of the screen
888- write ! (
889- self . stdout,
890- "\r {}{banner}{}" ,
891- Attribute :: Reverse ,
892- Attribute :: Reset
893- )
894- . unwrap ( ) ;
903+ let styled = self . highlight_text ( & banner) ;
904+ write ! ( self . stdout, "\r {styled}" ) ?;
905+ Ok ( ( ) )
895906 }
896907}
897908
@@ -1075,7 +1086,7 @@ mod tests {
10751086 . from_line ( 3 )
10761087 . silent ( )
10771088 . build ( ) ;
1078- pager. draw_status_bar ( None ) ;
1089+ pager. draw_status_bar ( None ) . unwrap ( ) ;
10791090 let stdout = String :: from_utf8_lossy ( & pager. stdout ) ;
10801091 assert ! ( stdout. contains( & translate!( "more-help-message" ) ) ) ;
10811092 }
@@ -1182,15 +1193,15 @@ mod tests {
11821193 #[ test]
11831194 fn test_wrong_key ( ) {
11841195 let mut pager = TestPagerBuilder :: default ( ) . silent ( ) . build ( ) ;
1185- pager. draw_status_bar ( Some ( 'x' ) ) ;
1196+ pager. draw_status_bar ( Some ( 'x' ) ) . unwrap ( ) ;
11861197 let stdout = String :: from_utf8_lossy ( & pager. stdout ) ;
11871198 assert ! ( stdout. contains( & translate!(
11881199 "more-error-unknown-key" ,
11891200 "key" => "x"
11901201 ) ) ) ;
11911202
11921203 pager = TestPagerBuilder :: default ( ) . build ( ) ;
1193- pager. draw_status_bar ( Some ( 'x' ) ) ;
1204+ pager. draw_status_bar ( Some ( 'x' ) ) . unwrap ( ) ;
11941205 let stdout = String :: from_utf8_lossy ( & pager. stdout ) ;
11951206 assert ! ( stdout. contains( & BELL . to_string( ) ) ) ;
11961207 }
0 commit comments