@@ -493,8 +493,67 @@ fn print_special_setting(setting: &PrintSetting, fd: i32) -> nix::Result<()> {
493493 Ok ( ( ) )
494494}
495495
496- fn print_terminal_size ( termios : & Termios , opts : & Options ) -> nix:: Result < ( ) > {
496+ struct WrappedPrinter {
497+ width : usize ,
498+ current : usize ,
499+ first_in_line : bool ,
500+ }
501+
502+ impl WrappedPrinter {
503+ fn new ( term_size : & Option < TermSize > ) -> Self {
504+ let columns = match term_size {
505+ Some ( term_size) => term_size. columns ,
506+ None => {
507+ const DEFAULT_TERM_WIDTH : u16 = 80 ;
508+
509+ std:: env:: var_os ( "COLUMNS" )
510+ . and_then ( |s| s. to_str ( ) ?. parse ( ) . ok ( ) )
511+ . filter ( |& c| c > 0 )
512+ . unwrap_or ( DEFAULT_TERM_WIDTH )
513+ }
514+ } ;
515+
516+ Self {
517+ width : columns. max ( 1 ) as usize ,
518+ current : 0 ,
519+ first_in_line : true ,
520+ }
521+ }
522+
523+ fn print ( & mut self , token : & str ) {
524+ let token_len = self . prefix ( ) . chars ( ) . count ( ) + token. chars ( ) . count ( ) ;
525+ if self . current > 0 && self . current + token_len > self . width {
526+ println ! ( ) ;
527+ self . current = 0 ;
528+ self . first_in_line = true ;
529+ }
530+
531+ print ! ( "{}{}" , self . prefix( ) , token) ;
532+ self . current += token_len;
533+ self . first_in_line = false ;
534+ }
535+
536+ fn prefix ( & self ) -> & str {
537+ if self . first_in_line { "" } else { " " }
538+ }
539+
540+ fn flush ( & mut self ) {
541+ if self . current > 0 {
542+ println ! ( ) ;
543+ self . current = 0 ;
544+ self . first_in_line = false ;
545+ }
546+ }
547+ }
548+
549+ fn print_terminal_size (
550+ termios : & Termios ,
551+ opts : & Options ,
552+ window_size : & Option < TermSize > ,
553+ term_size : & Option < TermSize > ,
554+ ) -> nix:: Result < ( ) > {
497555 let speed = cfgetospeed ( termios) ;
556+ let mut printer = WrappedPrinter :: new ( window_size) ;
498557
499558 // BSDs use a u32 for the baud rate, so we can simply print it.
500559 #[ cfg( any(
@@ -519,17 +578,15 @@ fn print_terminal_size(termios: &Termios, opts: &Options) -> nix::Result<()> {
519578 ) ) ) ]
520579 for ( text, baud_rate) in BAUD_RATES {
521580 if * baud_rate == speed {
522- print ! ( "{} " , translate!( "stty-output-speed" , "speed" => ( * text) ) ) ;
581+ printer . print ( & translate ! ( "stty-output-speed" , "speed" => ( * text) ) ) ;
523582 break ;
524583 }
525584 }
526585
527586 if opts. all {
528- let mut size = TermSize :: default ( ) ;
529- unsafe { tiocgwinsz ( opts. file . as_raw_fd ( ) , & raw mut size) ? } ;
530- print ! (
531- "{} " ,
532- translate!( "stty-output-rows-columns" , "rows" => size. rows, "columns" => size. columns)
587+ let term_size = term_size. as_ref ( ) . expect ( "terminal size should be set" ) ;
588+ printer. print (
589+ & translate ! ( "stty-output-rows-columns" , "rows" => term_size. rows, "columns" => term_size. columns) ,
533590 ) ;
534591 }
535592
@@ -539,10 +596,9 @@ fn print_terminal_size(termios: &Termios, opts: &Options) -> nix::Result<()> {
539596 // so we get the underlying libc::termios struct to get that information.
540597 let libc_termios: nix:: libc:: termios = termios. clone ( ) . into ( ) ;
541598 let line = libc_termios. c_line ;
542- print ! ( "{}" , translate!( "stty-output-line" , "line" => line) ) ;
599+ printer . print ( & translate ! ( "stty-output-line" , "line" => line) ) ;
543600 }
544-
545- println ! ( ) ;
601+ printer. flush ( ) ;
546602 Ok ( ( ) )
547603}
548604
@@ -710,39 +766,41 @@ fn control_char_to_string(cc: nix::libc::cc_t) -> nix::Result<String> {
710766 Ok ( format ! ( "{meta_prefix}{ctrl_prefix}{character}" ) )
711767}
712768
713- fn print_control_chars ( termios : & Termios , opts : & Options ) -> nix:: Result < ( ) > {
769+ fn print_control_chars (
770+ termios : & Termios ,
771+ opts : & Options ,
772+ term_size : & Option < TermSize > ,
773+ ) -> nix:: Result < ( ) > {
714774 if !opts. all {
715775 // Print only control chars that differ from sane defaults
716- let mut printed = false ;
776+ let mut printer = WrappedPrinter :: new ( term_size ) ;
717777 for ( text, cc_index) in CONTROL_CHARS {
718778 let current_val = termios. control_chars [ * cc_index as usize ] ;
719779 let sane_val = get_sane_control_char ( * cc_index) ;
720780
721781 if current_val != sane_val {
722- print ! ( "{text} = {}; " , control_char_to_string( current_val) ?) ;
723- printed = true ;
782+ printer. print ( & format ! (
783+ "{text} = {};" ,
784+ control_char_to_string( current_val) ?
785+ ) ) ;
724786 }
725787 }
726-
727- if printed {
728- println ! ( ) ;
729- }
788+ printer. flush ( ) ;
730789 return Ok ( ( ) ) ;
731790 }
732791
792+ let mut printer = WrappedPrinter :: new ( term_size) ;
733793 for ( text, cc_index) in CONTROL_CHARS {
734- print ! (
735- "{text} = {}; " ,
794+ printer . print ( & format ! (
795+ "{text} = {};" ,
736796 control_char_to_string( termios. control_chars[ * cc_index as usize ] ) ?
737- ) ;
797+ ) ) ;
738798 }
739- println ! (
740- "{}" ,
741- translate!( "stty-output-min-time" ,
799+ printer. print ( & translate ! ( "stty-output-min-time" ,
742800 "min" => termios. control_chars[ S :: VMIN as usize ] ,
743801 "time" => termios. control_chars[ S :: VTIME as usize ]
744- )
745- ) ;
802+ ) ) ;
803+ printer . flush ( ) ;
746804 Ok ( ( ) )
747805}
748806
@@ -764,18 +822,45 @@ fn print_settings(termios: &Termios, opts: &Options) -> nix::Result<()> {
764822 if opts. save {
765823 print_in_save_format ( termios) ;
766824 } else {
767- print_terminal_size ( termios, opts) ?;
768- print_control_chars ( termios, opts) ?;
769- print_flags ( termios, opts, CONTROL_FLAGS ) ;
770- print_flags ( termios, opts, INPUT_FLAGS ) ;
771- print_flags ( termios, opts, OUTPUT_FLAGS ) ;
772- print_flags ( termios, opts, LOCAL_FLAGS ) ;
825+ let device_fd = opts. file . as_raw_fd ( ) ;
826+ let term_size = {
827+ let mut term_size = TermSize :: default ( ) ;
828+ let term_size =
829+ unsafe { tiocgwinsz ( device_fd, & raw mut term_size) } . map ( |_| term_size) ;
830+ if opts. all {
831+ Some ( term_size?)
832+ } else {
833+ term_size. ok ( )
834+ }
835+ } ;
836+
837+ let stdout_fd = stdout ( ) . as_raw_fd ( ) ;
838+ let window_size = if device_fd != stdout_fd {
839+ let mut term_size = TermSize :: default ( ) ;
840+ & unsafe { tiocgwinsz ( stdout_fd, & raw mut term_size) }
841+ . map ( |_| term_size)
842+ . ok ( )
843+ } else {
844+ & term_size
845+ } ;
846+
847+ print_terminal_size ( termios, opts, & window_size, & term_size) ?;
848+ print_control_chars ( termios, opts, & window_size) ?;
849+ print_flags ( termios, opts, CONTROL_FLAGS , & window_size) ;
850+ print_flags ( termios, opts, INPUT_FLAGS , & window_size) ;
851+ print_flags ( termios, opts, OUTPUT_FLAGS , & window_size) ;
852+ print_flags ( termios, opts, LOCAL_FLAGS , & window_size) ;
773853 }
774854 Ok ( ( ) )
775855}
776856
777- fn print_flags < T : TermiosFlag > ( termios : & Termios , opts : & Options , flags : & [ Flag < T > ] ) {
778- let mut printed = false ;
857+ fn print_flags < T : TermiosFlag > (
858+ termios : & Termios ,
859+ opts : & Options ,
860+ flags : & [ Flag < T > ] ,
861+ term_size : & Option < TermSize > ,
862+ ) {
863+ let mut printer = WrappedPrinter :: new ( term_size) ;
779864 for & Flag {
780865 name,
781866 flag,
@@ -790,20 +875,17 @@ fn print_flags<T: TermiosFlag>(termios: &Termios, opts: &Options, flags: &[Flag<
790875 let val = flag. is_in ( termios, group) ;
791876 if group. is_some ( ) {
792877 if val && ( !sane || opts. all ) {
793- print ! ( "{name} " ) ;
794- printed = true ;
878+ printer. print ( name) ;
795879 }
796880 } else if opts. all || val != sane {
797881 if !val {
798- print ! ( "-" ) ;
882+ printer. print ( & format ! ( "-{name}" ) ) ;
883+ continue ;
799884 }
800- print ! ( "{name} " ) ;
801- printed = true ;
885+ printer. print ( name) ;
802886 }
803887 }
804- if printed {
805- println ! ( ) ;
806- }
888+ printer. flush ( ) ;
807889}
808890
809891/// Apply a single setting
0 commit comments