@@ -492,8 +492,67 @@ fn print_special_setting(setting: &PrintSetting, fd: i32) -> nix::Result<()> {
492492 Ok ( ( ) )
493493}
494494
495- fn print_terminal_size ( termios : & Termios , opts : & Options ) -> nix:: Result < ( ) > {
495+ struct WrappedPrinter {
496+ width : usize ,
497+ current : usize ,
498+ first_in_line : bool ,
499+ }
500+
501+ impl WrappedPrinter {
502+ fn new ( term_size : & Option < TermSize > ) -> Self {
503+ let columns = match term_size {
504+ Some ( term_size) => term_size. columns ,
505+ None => {
506+ const DEFAULT_TERM_WIDTH : u16 = 80 ;
507+
508+ std:: env:: var_os ( "COLUMNS" )
509+ . and_then ( |s| s. to_str ( ) ?. parse ( ) . ok ( ) )
510+ . filter ( |& c| c > 0 )
511+ . unwrap_or ( DEFAULT_TERM_WIDTH )
512+ }
513+ } ;
514+
515+ Self {
516+ width : columns. max ( 1 ) as usize ,
517+ current : 0 ,
518+ first_in_line : true ,
519+ }
520+ }
521+
522+ fn print ( & mut self , token : & str ) {
523+ let token_len = self . prefix ( ) . chars ( ) . count ( ) + token. chars ( ) . count ( ) ;
524+ if self . current > 0 && self . current + token_len > self . width {
525+ println ! ( ) ;
526+ self . current = 0 ;
527+ self . first_in_line = true ;
528+ }
529+
530+ print ! ( "{}{}" , self . prefix( ) , token) ;
531+ self . current += token_len;
532+ self . first_in_line = false ;
533+ }
534+
535+ fn prefix ( & self ) -> & str {
536+ if self . first_in_line { "" } else { " " }
537+ }
538+
539+ fn flush ( & mut self ) {
540+ if self . current > 0 {
541+ println ! ( ) ;
542+ self . current = 0 ;
543+ self . first_in_line = false ;
544+ }
545+ }
546+ }
547+
548+ fn print_terminal_size (
549+ termios : & Termios ,
550+ opts : & Options ,
551+ window_size : & Option < TermSize > ,
552+ term_size : & Option < TermSize > ,
553+ ) -> nix:: Result < ( ) > {
496554 let speed = cfgetospeed ( termios) ;
555+ let mut printer = WrappedPrinter :: new ( window_size) ;
497556
498557 // BSDs use a u32 for the baud rate, so we can simply print it.
499558 #[ cfg( any(
@@ -518,17 +577,15 @@ fn print_terminal_size(termios: &Termios, opts: &Options) -> nix::Result<()> {
518577 ) ) ) ]
519578 for ( text, baud_rate) in BAUD_RATES {
520579 if * baud_rate == speed {
521- print ! ( "{} " , translate!( "stty-output-speed" , "speed" => ( * text) ) ) ;
580+ printer . print ( & translate ! ( "stty-output-speed" , "speed" => ( * text) ) ) ;
522581 break ;
523582 }
524583 }
525584
526585 if opts. all {
527- let mut size = TermSize :: default ( ) ;
528- unsafe { tiocgwinsz ( opts. file . as_raw_fd ( ) , & raw mut size) ? } ;
529- print ! (
530- "{} " ,
531- translate!( "stty-output-rows-columns" , "rows" => size. rows, "columns" => size. columns)
586+ let term_size = term_size. as_ref ( ) . expect ( "terminal size should be set" ) ;
587+ printer. print (
588+ & translate ! ( "stty-output-rows-columns" , "rows" => term_size. rows, "columns" => term_size. columns) ,
532589 ) ;
533590 }
534591
@@ -538,10 +595,9 @@ fn print_terminal_size(termios: &Termios, opts: &Options) -> nix::Result<()> {
538595 // so we get the underlying libc::termios struct to get that information.
539596 let libc_termios: nix:: libc:: termios = termios. clone ( ) . into ( ) ;
540597 let line = libc_termios. c_line ;
541- print ! ( "{}" , translate!( "stty-output-line" , "line" => line) ) ;
598+ printer . print ( & translate ! ( "stty-output-line" , "line" => line) ) ;
542599 }
543-
544- println ! ( ) ;
600+ printer. flush ( ) ;
545601 Ok ( ( ) )
546602}
547603
@@ -647,39 +703,41 @@ fn control_char_to_string(cc: nix::libc::cc_t) -> nix::Result<String> {
647703 Ok ( format ! ( "{meta_prefix}{ctrl_prefix}{character}" ) )
648704}
649705
650- fn print_control_chars ( termios : & Termios , opts : & Options ) -> nix:: Result < ( ) > {
706+ fn print_control_chars (
707+ termios : & Termios ,
708+ opts : & Options ,
709+ term_size : & Option < TermSize > ,
710+ ) -> nix:: Result < ( ) > {
651711 if !opts. all {
652712 // Print only control chars that differ from sane defaults
653- let mut printed = false ;
713+ let mut printer = WrappedPrinter :: new ( term_size ) ;
654714 for ( text, cc_index) in CONTROL_CHARS {
655715 let current_val = termios. control_chars [ * cc_index as usize ] ;
656716 let sane_val = get_sane_control_char ( * cc_index) ;
657717
658718 if current_val != sane_val {
659- print ! ( "{text} = {}; " , control_char_to_string( current_val) ?) ;
660- printed = true ;
719+ printer. print ( & format ! (
720+ "{text} = {};" ,
721+ control_char_to_string( current_val) ?
722+ ) ) ;
661723 }
662724 }
663-
664- if printed {
665- println ! ( ) ;
666- }
725+ printer. flush ( ) ;
667726 return Ok ( ( ) ) ;
668727 }
669728
729+ let mut printer = WrappedPrinter :: new ( term_size) ;
670730 for ( text, cc_index) in CONTROL_CHARS {
671- print ! (
672- "{text} = {}; " ,
731+ printer . print ( & format ! (
732+ "{text} = {};" ,
673733 control_char_to_string( termios. control_chars[ * cc_index as usize ] ) ?
674- ) ;
734+ ) ) ;
675735 }
676- println ! (
677- "{}" ,
678- translate!( "stty-output-min-time" ,
736+ printer. print ( & translate ! ( "stty-output-min-time" ,
679737 "min" => termios. control_chars[ S :: VMIN as usize ] ,
680738 "time" => termios. control_chars[ S :: VTIME as usize ]
681- )
682- ) ;
739+ ) ) ;
740+ printer . flush ( ) ;
683741 Ok ( ( ) )
684742}
685743
@@ -701,18 +759,45 @@ fn print_settings(termios: &Termios, opts: &Options) -> nix::Result<()> {
701759 if opts. save {
702760 print_in_save_format ( termios) ;
703761 } else {
704- print_terminal_size ( termios, opts) ?;
705- print_control_chars ( termios, opts) ?;
706- print_flags ( termios, opts, CONTROL_FLAGS ) ;
707- print_flags ( termios, opts, INPUT_FLAGS ) ;
708- print_flags ( termios, opts, OUTPUT_FLAGS ) ;
709- print_flags ( termios, opts, LOCAL_FLAGS ) ;
762+ let device_fd = opts. file . as_raw_fd ( ) ;
763+ let term_size = {
764+ let mut term_size = TermSize :: default ( ) ;
765+ let term_size =
766+ unsafe { tiocgwinsz ( device_fd, & raw mut term_size) } . map ( |_| term_size) ;
767+ if opts. all {
768+ Some ( term_size?)
769+ } else {
770+ term_size. ok ( )
771+ }
772+ } ;
773+
774+ let stdout_fd = stdout ( ) . as_raw_fd ( ) ;
775+ let window_size = if device_fd != stdout_fd {
776+ let mut term_size = TermSize :: default ( ) ;
777+ & unsafe { tiocgwinsz ( stdout_fd, & raw mut term_size) }
778+ . map ( |_| term_size)
779+ . ok ( )
780+ } else {
781+ & term_size
782+ } ;
783+
784+ print_terminal_size ( termios, opts, & window_size, & term_size) ?;
785+ print_control_chars ( termios, opts, & window_size) ?;
786+ print_flags ( termios, opts, CONTROL_FLAGS , & window_size) ;
787+ print_flags ( termios, opts, INPUT_FLAGS , & window_size) ;
788+ print_flags ( termios, opts, OUTPUT_FLAGS , & window_size) ;
789+ print_flags ( termios, opts, LOCAL_FLAGS , & window_size) ;
710790 }
711791 Ok ( ( ) )
712792}
713793
714- fn print_flags < T : TermiosFlag > ( termios : & Termios , opts : & Options , flags : & [ Flag < T > ] ) {
715- let mut printed = false ;
794+ fn print_flags < T : TermiosFlag > (
795+ termios : & Termios ,
796+ opts : & Options ,
797+ flags : & [ Flag < T > ] ,
798+ term_size : & Option < TermSize > ,
799+ ) {
800+ let mut printer = WrappedPrinter :: new ( term_size) ;
716801 for & Flag {
717802 name,
718803 flag,
@@ -727,20 +812,17 @@ fn print_flags<T: TermiosFlag>(termios: &Termios, opts: &Options, flags: &[Flag<
727812 let val = flag. is_in ( termios, group) ;
728813 if group. is_some ( ) {
729814 if val && ( !sane || opts. all ) {
730- print ! ( "{name} " ) ;
731- printed = true ;
815+ printer. print ( name) ;
732816 }
733817 } else if opts. all || val != sane {
734818 if !val {
735- print ! ( "-" ) ;
819+ printer. print ( & format ! ( "-{name}" ) ) ;
820+ continue ;
736821 }
737- print ! ( "{name} " ) ;
738- printed = true ;
822+ printer. print ( name) ;
739823 }
740824 }
741- if printed {
742- println ! ( ) ;
743- }
825+ printer. flush ( ) ;
744826}
745827
746828/// Apply a single setting
0 commit comments