mirror of
https://github.com/uutils/coreutils
synced 2024-11-16 09:48:03 +00:00
seq: use stdout.write_all() instead of print!()
Change from using `print!()` to using `stdout.write_all()` in order to allow the main function to handle broken pipe errors gracefully.
This commit is contained in:
parent
92a1f1422e
commit
96b8616a1a
2 changed files with 49 additions and 15 deletions
|
@ -12,7 +12,7 @@ use num_traits::One;
|
|||
use num_traits::Zero;
|
||||
use num_traits::{Num, ToPrimitive};
|
||||
use std::cmp;
|
||||
use std::io::{stdout, Write};
|
||||
use std::io::{stdout, ErrorKind, Write};
|
||||
use std::str::FromStr;
|
||||
use uucore::display::Quotable;
|
||||
|
||||
|
@ -192,7 +192,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
.num_digits()
|
||||
.max(increment.num_digits())
|
||||
.max(last.num_digits());
|
||||
match (first, last, increment) {
|
||||
let result = match (first, last, increment) {
|
||||
(Number::MinusZero, Number::BigInt(last), Number::BigInt(increment)) => print_seq_integers(
|
||||
(BigInt::zero(), increment, last),
|
||||
options.separator,
|
||||
|
@ -219,8 +219,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
options.widths,
|
||||
padding,
|
||||
),
|
||||
};
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
Err(err) if err.kind() == ErrorKind::BrokenPipe => 0,
|
||||
Err(_) => 1,
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
pub fn uu_app() -> App<'static, 'static> {
|
||||
|
@ -276,7 +280,9 @@ fn print_seq(
|
|||
terminator: String,
|
||||
pad: bool,
|
||||
padding: usize,
|
||||
) {
|
||||
) -> std::io::Result<()> {
|
||||
let stdout = stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
let (first, increment, last) = range;
|
||||
let mut i = 0isize;
|
||||
let mut value = first + i as f64 * increment;
|
||||
|
@ -286,20 +292,21 @@ fn print_seq(
|
|||
let before_dec = istr.find('.').unwrap_or(ilen);
|
||||
if pad && before_dec < padding {
|
||||
for _ in 0..(padding - before_dec) {
|
||||
print!("0");
|
||||
write!(stdout, "0")?;
|
||||
}
|
||||
}
|
||||
print!("{}", istr);
|
||||
write!(stdout, "{}", istr)?;
|
||||
i += 1;
|
||||
value = first + i as f64 * increment;
|
||||
if !done_printing(&value, &increment, &last) {
|
||||
print!("{}", separator);
|
||||
write!(stdout, "{}", separator)?;
|
||||
}
|
||||
}
|
||||
if (first >= last && increment < 0f64) || (first <= last && increment > 0f64) {
|
||||
print!("{}", terminator);
|
||||
write!(stdout, "{}", terminator)?;
|
||||
}
|
||||
crash_if_err!(1, stdout().flush());
|
||||
stdout.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Print an integer sequence.
|
||||
|
@ -323,31 +330,34 @@ fn print_seq_integers(
|
|||
pad: bool,
|
||||
padding: usize,
|
||||
is_first_minus_zero: bool,
|
||||
) {
|
||||
) -> std::io::Result<()> {
|
||||
let stdout = stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
let (first, increment, last) = range;
|
||||
let mut value = first;
|
||||
let mut is_first_iteration = true;
|
||||
while !done_printing(&value, &increment, &last) {
|
||||
if !is_first_iteration {
|
||||
print!("{}", separator);
|
||||
write!(stdout, "{}", separator)?;
|
||||
}
|
||||
let mut width = padding;
|
||||
if is_first_iteration && is_first_minus_zero {
|
||||
print!("-");
|
||||
write!(stdout, "-")?;
|
||||
width -= 1;
|
||||
}
|
||||
is_first_iteration = false;
|
||||
if pad {
|
||||
print!("{number:>0width$}", number = value, width = width);
|
||||
write!(stdout, "{number:>0width$}", number = value, width = width)?;
|
||||
} else {
|
||||
print!("{}", value);
|
||||
write!(stdout, "{}", value)?;
|
||||
}
|
||||
value += &increment;
|
||||
}
|
||||
|
||||
if !is_first_iteration {
|
||||
print!("{}", terminator);
|
||||
write!(stdout, "{}", terminator)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::common::util::*;
|
||||
use std::io::Read;
|
||||
|
||||
#[test]
|
||||
fn test_rejects_nan() {
|
||||
|
@ -176,3 +177,26 @@ fn test_width_negative_zero() {
|
|||
.stdout_is("-0\n01\n")
|
||||
.no_stderr();
|
||||
}
|
||||
|
||||
// TODO This is duplicated from `test_yes.rs`; refactor them.
|
||||
/// Run `seq`, capture some of the output, close the pipe, and verify it.
|
||||
fn run(args: &[&str], expected: &[u8]) {
|
||||
let mut cmd = new_ucmd!();
|
||||
let mut child = cmd.args(args).run_no_wait();
|
||||
let mut stdout = child.stdout.take().unwrap();
|
||||
let mut buf = vec![0; expected.len()];
|
||||
stdout.read_exact(&mut buf).unwrap();
|
||||
drop(stdout);
|
||||
assert!(child.wait().unwrap().success());
|
||||
assert_eq!(buf.as_slice(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_neg_inf() {
|
||||
run(&["--", "-inf", "0"], b"-inf\n-inf\n-inf\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inf() {
|
||||
run(&["inf"], b"1\n2\n3\n");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue