mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
seq: return UResult from uumain() function (#2784)
This commit is contained in:
parent
3f18b98c9d
commit
8a55205521
3 changed files with 119 additions and 65 deletions
70
src/uu/seq/src/error.rs
Normal file
70
src/uu/seq/src/error.rs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// * This file is part of the uutils coreutils package.
|
||||||
|
// *
|
||||||
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
|
// * file that was distributed with this source code.
|
||||||
|
// spell-checker:ignore numberparse argtype
|
||||||
|
//! Errors returned by seq.
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use uucore::display::Quotable;
|
||||||
|
use uucore::error::UError;
|
||||||
|
|
||||||
|
use crate::numberparse::ParseNumberError;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SeqError {
|
||||||
|
/// An error parsing the input arguments.
|
||||||
|
///
|
||||||
|
/// The parameters are the [`String`] argument as read from the
|
||||||
|
/// command line and the underlying parsing error itself.
|
||||||
|
ParseError(String, ParseNumberError),
|
||||||
|
|
||||||
|
/// The increment argument was zero, which is not allowed.
|
||||||
|
///
|
||||||
|
/// The parameter is the increment argument as a [`String`] as read
|
||||||
|
/// from the command line.
|
||||||
|
ZeroIncrement(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SeqError {
|
||||||
|
/// The [`String`] argument as read from the command-line.
|
||||||
|
fn arg(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
SeqError::ParseError(s, _) => s,
|
||||||
|
SeqError::ZeroIncrement(s) => s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The type of argument that is causing the error.
|
||||||
|
fn argtype(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
SeqError::ParseError(_, e) => match e {
|
||||||
|
ParseNumberError::Float => "floating point",
|
||||||
|
ParseNumberError::Nan => "'not-a-number'",
|
||||||
|
ParseNumberError::Hex => "hexadecimal",
|
||||||
|
},
|
||||||
|
SeqError::ZeroIncrement(_) => "Zero increment",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl UError for SeqError {
|
||||||
|
/// Always return 1.
|
||||||
|
fn code(&self) -> i32 {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for SeqError {}
|
||||||
|
|
||||||
|
impl Display for SeqError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"invalid {} argument: {}\nTry '{} --help' for more information.",
|
||||||
|
self.argtype(),
|
||||||
|
self.arg().quote(),
|
||||||
|
uucore::execution_phrase(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,26 +1,27 @@
|
||||||
// TODO: Make -w flag work with decimals
|
// * This file is part of the uutils coreutils package.
|
||||||
|
// *
|
||||||
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
|
// * file that was distributed with this source code.
|
||||||
// TODO: Support -f flag
|
// TODO: Support -f flag
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) istr chiter argptr ilen extendedbigdecimal extendedbigint numberparse
|
// spell-checker:ignore (ToDO) istr chiter argptr ilen extendedbigdecimal extendedbigint numberparse
|
||||||
|
use std::io::{stdout, ErrorKind, Write};
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, AppSettings, Arg};
|
use clap::{crate_version, App, AppSettings, Arg};
|
||||||
use num_traits::Zero;
|
use num_traits::Zero;
|
||||||
use std::io::{stdout, ErrorKind, Write};
|
|
||||||
|
|
||||||
|
use uucore::error::FromIo;
|
||||||
|
use uucore::error::UResult;
|
||||||
|
|
||||||
|
mod error;
|
||||||
mod extendedbigdecimal;
|
mod extendedbigdecimal;
|
||||||
mod extendedbigint;
|
mod extendedbigint;
|
||||||
mod number;
|
mod number;
|
||||||
mod numberparse;
|
mod numberparse;
|
||||||
|
use crate::error::SeqError;
|
||||||
use crate::extendedbigdecimal::ExtendedBigDecimal;
|
use crate::extendedbigdecimal::ExtendedBigDecimal;
|
||||||
use crate::extendedbigint::ExtendedBigInt;
|
use crate::extendedbigint::ExtendedBigInt;
|
||||||
use crate::number::Number;
|
use crate::number::Number;
|
||||||
use crate::number::PreciseNumber;
|
use crate::number::PreciseNumber;
|
||||||
use crate::numberparse::ParseNumberError;
|
|
||||||
|
|
||||||
use uucore::display::Quotable;
|
|
||||||
|
|
||||||
static ABOUT: &str = "Display numbers from FIRST to LAST, in steps of INCREMENT.";
|
static ABOUT: &str = "Display numbers from FIRST to LAST, in steps of INCREMENT.";
|
||||||
static OPT_SEPARATOR: &str = "separator";
|
static OPT_SEPARATOR: &str = "separator";
|
||||||
|
@ -54,47 +55,8 @@ type RangeInt = (ExtendedBigInt, ExtendedBigInt, ExtendedBigInt);
|
||||||
/// The elements are (first, increment, last).
|
/// The elements are (first, increment, last).
|
||||||
type RangeFloat = (ExtendedBigDecimal, ExtendedBigDecimal, ExtendedBigDecimal);
|
type RangeFloat = (ExtendedBigDecimal, ExtendedBigDecimal, ExtendedBigDecimal);
|
||||||
|
|
||||||
/// Terminate the process with error code 1.
|
#[uucore_procs::gen_uumain]
|
||||||
///
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
/// Before terminating the process, this function prints an error
|
|
||||||
/// message that depends on `arg` and `e`.
|
|
||||||
///
|
|
||||||
/// Although the signature of this function states that it returns a
|
|
||||||
/// [`PreciseNumber`], it never reaches the return statement. It is just
|
|
||||||
/// there to make it easier to use this function when unwrapping the
|
|
||||||
/// result of calling [`str::parse`] when attempting to parse a
|
|
||||||
/// [`PreciseNumber`].
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```rust,ignore
|
|
||||||
/// let s = "1.2e-3";
|
|
||||||
/// s.parse::<PreciseNumber>.unwrap_or_else(|e| exit_with_error(s, e))
|
|
||||||
/// ```
|
|
||||||
fn exit_with_error(arg: &str, e: ParseNumberError) -> ! {
|
|
||||||
match e {
|
|
||||||
ParseNumberError::Float => crash!(
|
|
||||||
1,
|
|
||||||
"invalid floating point argument: {}\nTry '{} --help' for more information.",
|
|
||||||
arg.quote(),
|
|
||||||
uucore::execution_phrase()
|
|
||||||
),
|
|
||||||
ParseNumberError::Nan => crash!(
|
|
||||||
1,
|
|
||||||
"invalid 'not-a-number' argument: {}\nTry '{} --help' for more information.",
|
|
||||||
arg.quote(),
|
|
||||||
uucore::execution_phrase()
|
|
||||||
),
|
|
||||||
ParseNumberError::Hex => crash!(
|
|
||||||
1,
|
|
||||||
"invalid hexadecimal argument: {}\nTry '{} --help' for more information.",
|
|
||||||
arg.quote(),
|
|
||||||
uucore::execution_phrase()
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
|
||||||
let usage = usage();
|
let usage = usage();
|
||||||
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
|
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
|
||||||
|
|
||||||
|
@ -107,28 +69,33 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
};
|
};
|
||||||
|
|
||||||
let first = if numbers.len() > 1 {
|
let first = if numbers.len() > 1 {
|
||||||
let slice = numbers[0];
|
match numbers[0].parse() {
|
||||||
slice.parse().unwrap_or_else(|e| exit_with_error(slice, e))
|
Ok(num) => num,
|
||||||
|
Err(e) => return Err(SeqError::ParseError(numbers[0].to_string(), e).into()),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
PreciseNumber::one()
|
PreciseNumber::one()
|
||||||
};
|
};
|
||||||
let increment = if numbers.len() > 2 {
|
let increment = if numbers.len() > 2 {
|
||||||
let slice = numbers[1];
|
match numbers[1].parse() {
|
||||||
slice.parse().unwrap_or_else(|e| exit_with_error(slice, e))
|
Ok(num) => num,
|
||||||
|
Err(e) => return Err(SeqError::ParseError(numbers[1].to_string(), e).into()),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
PreciseNumber::one()
|
PreciseNumber::one()
|
||||||
};
|
};
|
||||||
if increment.is_zero() {
|
if increment.is_zero() {
|
||||||
show_error!(
|
return Err(SeqError::ZeroIncrement(numbers[1].to_string()).into());
|
||||||
"invalid Zero increment value: '{}'\nTry '{} --help' for more information.",
|
|
||||||
numbers[1],
|
|
||||||
uucore::execution_phrase()
|
|
||||||
);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
let last: PreciseNumber = {
|
let last: PreciseNumber = {
|
||||||
let slice = numbers[numbers.len() - 1];
|
// We are guaranteed that `numbers.len()` is greater than zero
|
||||||
slice.parse().unwrap_or_else(|e| exit_with_error(slice, e))
|
// and at most three because of the argument specification in
|
||||||
|
// `uu_app()`.
|
||||||
|
let n: usize = numbers.len();
|
||||||
|
match numbers[n - 1].parse() {
|
||||||
|
Ok(num) => num,
|
||||||
|
Err(e) => return Err(SeqError::ParseError(numbers[n - 1].to_string(), e).into()),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let padding = first
|
let padding = first
|
||||||
|
@ -164,9 +131,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => 0,
|
Ok(_) => Ok(()),
|
||||||
Err(err) if err.kind() == ErrorKind::BrokenPipe => 0,
|
Err(err) if err.kind() == ErrorKind::BrokenPipe => Ok(()),
|
||||||
Err(_) => 1,
|
Err(e) => Err(e.map_err_context(|| "write error".into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// spell-checker:ignore lmnop xlmnop
|
||||||
use crate::common::util::*;
|
use crate::common::util::*;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
|
@ -676,3 +677,19 @@ fn test_rounding_end() {
|
||||||
.stdout_is("1\n")
|
.stdout_is("1\n")
|
||||||
.no_stderr();
|
.no_stderr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_error_float() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("lmnop")
|
||||||
|
.fails()
|
||||||
|
.usage_error("invalid floating point argument: 'lmnop'");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_error_hex() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("0xlmnop")
|
||||||
|
.fails()
|
||||||
|
.usage_error("invalid hexadecimal argument: '0xlmnop'");
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue