@@ -15,14 +15,15 @@ use nix::sys::termios::{
15
15
cfgetospeed, cfsetospeed, tcgetattr, tcsetattr,
16
16
} ;
17
17
use nix:: { ioctl_read_bad, ioctl_write_ptr_bad} ;
18
+ use std:: collections:: HashMap ;
18
19
use std:: fs:: File ;
19
20
use std:: io:: { self , Stdout , stdout} ;
20
21
use std:: os:: fd:: { AsFd , BorrowedFd } ;
21
22
use std:: os:: unix:: fs:: OpenOptionsExt ;
22
23
use std:: os:: unix:: io:: { AsRawFd , RawFd } ;
23
24
use uucore:: error:: { UResult , USimpleError } ;
24
25
use uucore:: format_usage;
25
- use uucore:: locale:: get_message;
26
+ use uucore:: locale:: { get_message, get_message_with_args } ;
26
27
27
28
#[ cfg( not( any(
28
29
target_os = "freebsd" ,
@@ -104,8 +105,8 @@ enum Device {
104
105
}
105
106
106
107
enum ControlCharMappingError {
107
- IntOutOfRange ,
108
- MultipleChars ,
108
+ IntOutOfRange ( String ) ,
109
+ MultipleChars ( String ) ,
109
110
}
110
111
111
112
enum SpecialSetting {
@@ -226,14 +227,14 @@ fn stty(opts: &Options) -> UResult<()> {
226
227
if opts. save && opts. all {
227
228
return Err ( USimpleError :: new (
228
229
1 ,
229
- "the options for verbose and stty-readable output styles are mutually exclusive",
230
+ get_message ( " stty-error-options- mutually- exclusive") ,
230
231
) ) ;
231
232
}
232
233
233
234
if opts. settings . is_some ( ) && ( opts. save || opts. all ) {
234
235
return Err ( USimpleError :: new (
235
236
1 ,
236
- "when specifying an output style, modes may not be set" ,
237
+ get_message ( "stty-error- output- style-no- modes" ) ,
237
238
) ) ;
238
239
}
239
240
@@ -248,18 +249,26 @@ fn stty(opts: &Options) -> UResult<()> {
248
249
if let Some ( mapping) = args_iter. next ( ) {
249
250
let cc_mapping = string_to_control_char ( mapping) . map_err ( |e| {
250
251
let message = match e {
251
- ControlCharMappingError :: IntOutOfRange => format ! (
252
- "invalid integer argument: '{mapping}': Value too large for defined data type"
252
+ ControlCharMappingError :: IntOutOfRange ( val) => get_message_with_args (
253
+ "stty-error-invalid-integer-argument-value-too-large" ,
254
+ HashMap :: from ( [ ( "value" . to_string ( ) , format ! ( "'{}'" , val) ) ] ) ,
255
+ ) ,
256
+ ControlCharMappingError :: MultipleChars ( val) => get_message_with_args (
257
+ "stty-error-invalid-integer-argument" ,
258
+ HashMap :: from ( [ ( "value" . to_string ( ) , format ! ( "'{}'" , val) ) ] ) ,
253
259
) ,
254
- ControlCharMappingError :: MultipleChars => {
255
- format ! ( "invalid integer argument: '{mapping}'" )
256
- }
257
260
} ;
258
261
USimpleError :: new ( 1 , message)
259
262
} ) ?;
260
263
valid_args. push ( ArgOptions :: Mapping ( ( char_index, cc_mapping) ) ) ;
261
264
} else {
262
- return Err ( USimpleError :: new ( 1 , format ! ( "missing argument to '{arg}'" ) ) ) ;
265
+ return Err ( USimpleError :: new (
266
+ 1 ,
267
+ get_message_with_args (
268
+ "stty-error-missing-argument" ,
269
+ HashMap :: from ( [ ( "arg" . to_string ( ) , arg. to_string ( ) ) ] ) ,
270
+ ) ,
271
+ ) ) ;
263
272
}
264
273
// ispeed/ospeed baud rate setting
265
274
} else if * arg == "ispeed" || * arg == "ospeed" {
@@ -268,11 +277,26 @@ fn stty(opts: &Options) -> UResult<()> {
268
277
if let Some ( baud_flag) = string_to_baud ( speed) {
269
278
valid_args. push ( ArgOptions :: Flags ( baud_flag) ) ;
270
279
} else {
271
- return Err ( USimpleError :: new ( 1 , format ! ( "invalid {arg} '{speed}'" ) ) ) ;
280
+ return Err ( USimpleError :: new (
281
+ 1 ,
282
+ get_message_with_args (
283
+ "stty-error-invalid-speed" ,
284
+ HashMap :: from ( [
285
+ ( "arg" . to_string ( ) , arg. to_string ( ) ) ,
286
+ ( "speed" . to_string ( ) , speed. to_string ( ) ) ,
287
+ ] ) ,
288
+ ) ,
289
+ ) ) ;
272
290
}
273
291
}
274
292
None => {
275
- return Err ( USimpleError :: new ( 1 , format ! ( "missing argument to '{arg}'" ) ) ) ;
293
+ return Err ( USimpleError :: new (
294
+ 1 ,
295
+ get_message_with_args (
296
+ "stty-error-missing-argument" ,
297
+ HashMap :: from ( [ ( "arg" . to_string ( ) , arg. to_string ( ) ) ] ) ,
298
+ ) ,
299
+ ) ) ;
276
300
}
277
301
}
278
302
// baud rate setting
@@ -288,7 +312,13 @@ fn stty(opts: &Options) -> UResult<()> {
288
312
AllFlags :: OutputFlags ( ( flag, remove) ) => check_flag_group ( flag, remove) ,
289
313
} ;
290
314
if remove_group {
291
- return Err ( USimpleError :: new ( 1 , format ! ( "invalid argument '{arg}'" ) ) ) ;
315
+ return Err ( USimpleError :: new (
316
+ 1 ,
317
+ get_message_with_args (
318
+ "stty-error-invalid-argument" ,
319
+ HashMap :: from ( [ ( "arg" . to_string ( ) , arg. to_string ( ) ) ] ) ,
320
+ ) ,
321
+ ) ) ;
292
322
}
293
323
valid_args. push ( flag. into ( ) ) ;
294
324
} else if * arg == "rows" {
@@ -298,11 +328,20 @@ fn stty(opts: &Options) -> UResult<()> {
298
328
} else {
299
329
return Err ( USimpleError :: new (
300
330
1 ,
301
- format ! ( "invalid integer argument: '{rows}'" ) ,
331
+ get_message_with_args (
332
+ "stty-error-invalid-integer-argument" ,
333
+ HashMap :: from ( [ ( "value" . to_string ( ) , format ! ( "'{}'" , rows) ) ] ) ,
334
+ ) ,
302
335
) ) ;
303
336
}
304
337
} else {
305
- return Err ( USimpleError :: new ( 1 , format ! ( "missing argument to '{arg}'" ) ) ) ;
338
+ return Err ( USimpleError :: new (
339
+ 1 ,
340
+ get_message_with_args (
341
+ "stty-error-missing-argument" ,
342
+ HashMap :: from ( [ ( "arg" . to_string ( ) , arg. to_string ( ) ) ] ) ,
343
+ ) ,
344
+ ) ) ;
306
345
}
307
346
} else if * arg == "columns" || * arg == "cols" {
308
347
if let Some ( cols) = args_iter. next ( ) {
@@ -311,17 +350,32 @@ fn stty(opts: &Options) -> UResult<()> {
311
350
} else {
312
351
return Err ( USimpleError :: new (
313
352
1 ,
314
- format ! ( "invalid integer argument: '{cols}'" ) ,
353
+ get_message_with_args (
354
+ "stty-error-invalid-integer-argument" ,
355
+ HashMap :: from ( [ ( "value" . to_string ( ) , format ! ( "'{}'" , cols) ) ] ) ,
356
+ ) ,
315
357
) ) ;
316
358
}
317
359
} else {
318
- return Err ( USimpleError :: new ( 1 , format ! ( "missing argument to '{arg}'" ) ) ) ;
360
+ return Err ( USimpleError :: new (
361
+ 1 ,
362
+ get_message_with_args (
363
+ "stty-error-missing-argument" ,
364
+ HashMap :: from ( [ ( "arg" . to_string ( ) , arg. to_string ( ) ) ] ) ,
365
+ ) ,
366
+ ) ) ;
319
367
}
320
368
} else if * arg == "size" {
321
369
valid_args. push ( ArgOptions :: Print ( PrintSetting :: Size ) ) ;
322
370
// not a valid option
323
371
} else {
324
- return Err ( USimpleError :: new ( 1 , format ! ( "invalid argument '{arg}'" ) ) ) ;
372
+ return Err ( USimpleError :: new (
373
+ 1 ,
374
+ get_message_with_args (
375
+ "stty-error-invalid-argument" ,
376
+ HashMap :: from ( [ ( "arg" . to_string ( ) , arg. to_string ( ) ) ] ) ,
377
+ ) ,
378
+ ) ) ;
325
379
}
326
380
}
327
381
@@ -391,7 +445,13 @@ fn print_terminal_size(termios: &Termios, opts: &Options) -> nix::Result<()> {
391
445
target_os = "netbsd" ,
392
446
target_os = "openbsd"
393
447
) ) ]
394
- print ! ( "speed {speed} baud; " ) ;
448
+ print ! (
449
+ "{} " ,
450
+ get_message_with_args(
451
+ "stty-output-speed" ,
452
+ HashMap :: from( [ ( "speed" . to_string( ) , speed. to_string( ) ) ] )
453
+ )
454
+ ) ;
395
455
396
456
// Other platforms need to use the baud rate enum, so printing the right value
397
457
// becomes slightly more complicated.
@@ -405,15 +465,30 @@ fn print_terminal_size(termios: &Termios, opts: &Options) -> nix::Result<()> {
405
465
) ) ) ]
406
466
for ( text, baud_rate) in BAUD_RATES {
407
467
if * baud_rate == speed {
408
- print ! ( "speed {text} baud; " ) ;
468
+ print ! (
469
+ "{} " ,
470
+ get_message_with_args(
471
+ "stty-output-speed" ,
472
+ HashMap :: from( [ ( "speed" . to_string( ) , text. to_string( ) ) ] )
473
+ )
474
+ ) ;
409
475
break ;
410
476
}
411
477
}
412
478
413
479
if opts. all {
414
480
let mut size = TermSize :: default ( ) ;
415
481
unsafe { tiocgwinsz ( opts. file . as_raw_fd ( ) , & raw mut size) ? } ;
416
- print ! ( "rows {}; columns {}; " , size. rows, size. columns) ;
482
+ print ! (
483
+ "{} " ,
484
+ get_message_with_args(
485
+ "stty-output-rows-columns" ,
486
+ HashMap :: from( [
487
+ ( "rows" . to_string( ) , size. rows. to_string( ) ) ,
488
+ ( "columns" . to_string( ) , size. columns. to_string( ) )
489
+ ] )
490
+ )
491
+ ) ;
417
492
}
418
493
419
494
#[ cfg( any( target_os = "linux" , target_os = "redox" ) ) ]
@@ -422,7 +497,13 @@ fn print_terminal_size(termios: &Termios, opts: &Options) -> nix::Result<()> {
422
497
// so we get the underlying libc::termios struct to get that information.
423
498
let libc_termios: nix:: libc:: termios = termios. clone ( ) . into ( ) ;
424
499
let line = libc_termios. c_line ;
425
- print ! ( "line = {line};" ) ;
500
+ print ! (
501
+ "{}" ,
502
+ get_message_with_args(
503
+ "stty-output-line" ,
504
+ HashMap :: from( [ ( "line" . to_string( ) , line. to_string( ) ) ] )
505
+ )
506
+ ) ;
426
507
}
427
508
428
509
println ! ( ) ;
@@ -498,7 +579,7 @@ fn string_to_flag(option: &str) -> Option<AllFlags> {
498
579
499
580
fn control_char_to_string ( cc : nix:: libc:: cc_t ) -> nix:: Result < String > {
500
581
if cc == 0 {
501
- return Ok ( "< undef>" . to_string ( ) ) ;
582
+ return Ok ( get_message ( "stty-output- undef" ) ) ;
502
583
}
503
584
504
585
let ( meta_prefix, code) = if cc >= 0x80 {
@@ -535,9 +616,20 @@ fn print_control_chars(termios: &Termios, opts: &Options) -> nix::Result<()> {
535
616
) ;
536
617
}
537
618
println ! (
538
- "min = {}; time = {};" ,
539
- termios. control_chars[ SpecialCharacterIndices :: VMIN as usize ] ,
540
- termios. control_chars[ SpecialCharacterIndices :: VTIME as usize ]
619
+ "{}" ,
620
+ get_message_with_args(
621
+ "stty-output-min-time" ,
622
+ HashMap :: from( [
623
+ (
624
+ "min" . to_string( ) ,
625
+ termios. control_chars[ SpecialCharacterIndices :: VMIN as usize ] . to_string( )
626
+ ) ,
627
+ (
628
+ "time" . to_string( ) ,
629
+ termios. control_chars[ SpecialCharacterIndices :: VTIME as usize ] . to_string( )
630
+ )
631
+ ] )
632
+ )
541
633
) ;
542
634
Ok ( ( ) )
543
635
}
@@ -682,14 +774,18 @@ fn string_to_control_char(s: &str) -> Result<u8, ControlCharMappingError> {
682
774
let ascii_num = if let Some ( hex) = s. strip_prefix ( "0x" ) {
683
775
u32:: from_str_radix ( hex, 16 ) . ok ( )
684
776
} else if let Some ( octal) = s. strip_prefix ( "0" ) {
685
- u32:: from_str_radix ( octal, 8 ) . ok ( )
777
+ if octal. is_empty ( ) {
778
+ Some ( 0 )
779
+ } else {
780
+ u32:: from_str_radix ( octal, 8 ) . ok ( )
781
+ }
686
782
} else {
687
783
s. parse :: < u32 > ( ) . ok ( )
688
784
} ;
689
785
690
786
if let Some ( val) = ascii_num {
691
787
if val > 255 {
692
- return Err ( ControlCharMappingError :: IntOutOfRange ) ;
788
+ return Err ( ControlCharMappingError :: IntOutOfRange ( s . to_string ( ) ) ) ;
693
789
} else {
694
790
return Ok ( val as u8 ) ;
695
791
}
@@ -706,7 +802,7 @@ fn string_to_control_char(s: &str) -> Result<u8, ControlCharMappingError> {
706
802
Ok ( ( c. to_ascii_uppercase ( ) as u8 ) . wrapping_sub ( b'@' ) )
707
803
}
708
804
( Some ( c) , None ) => Ok ( c as u8 ) ,
709
- ( Some ( _) , Some ( _) ) => Err ( ControlCharMappingError :: MultipleChars ) ,
805
+ ( Some ( _) , Some ( _) ) => Err ( ControlCharMappingError :: MultipleChars ( s . to_string ( ) ) ) ,
710
806
_ => unreachable ! ( "No arguments provided: must have been caught earlier" ) ,
711
807
}
712
808
}
@@ -721,14 +817,14 @@ pub fn uu_app() -> Command {
721
817
Arg :: new ( options:: ALL )
722
818
. short ( 'a' )
723
819
. long ( options:: ALL )
724
- . help ( "print all current settings in human-readable form" )
820
+ . help ( get_message ( "stty-option-all" ) )
725
821
. action ( ArgAction :: SetTrue ) ,
726
822
)
727
823
. arg (
728
824
Arg :: new ( options:: SAVE )
729
825
. short ( 'g' )
730
826
. long ( options:: SAVE )
731
- . help ( "print all current settings in a stty-readable form" )
827
+ . help ( get_message ( " stty-option-save" ) )
732
828
. action ( ArgAction :: SetTrue ) ,
733
829
)
734
830
. arg (
@@ -737,13 +833,13 @@ pub fn uu_app() -> Command {
737
833
. long ( options:: FILE )
738
834
. value_hint ( clap:: ValueHint :: FilePath )
739
835
. value_name ( "DEVICE" )
740
- . help ( "open and use the specified DEVICE instead of stdin" ) ,
836
+ . help ( get_message ( "stty-option-file" ) ) ,
741
837
)
742
838
. arg (
743
839
Arg :: new ( options:: SETTINGS )
744
840
. action ( ArgAction :: Append )
745
841
. allow_hyphen_values ( true )
746
- . help ( " settings to change" ) ,
842
+ . help ( get_message ( "stty-option- settings" ) ) ,
747
843
)
748
844
}
749
845
0 commit comments