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
|
||||
|
||||
// spell-checker:ignore (ToDO) istr chiter argptr ilen extendedbigdecimal extendedbigint numberparse
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
use std::io::{stdout, ErrorKind, Write};
|
||||
|
||||
use clap::{crate_version, App, AppSettings, Arg};
|
||||
use num_traits::Zero;
|
||||
use std::io::{stdout, ErrorKind, Write};
|
||||
|
||||
use uucore::error::FromIo;
|
||||
use uucore::error::UResult;
|
||||
|
||||
mod error;
|
||||
mod extendedbigdecimal;
|
||||
mod extendedbigint;
|
||||
mod number;
|
||||
mod numberparse;
|
||||
use crate::error::SeqError;
|
||||
use crate::extendedbigdecimal::ExtendedBigDecimal;
|
||||
use crate::extendedbigint::ExtendedBigInt;
|
||||
use crate::number::Number;
|
||||
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 OPT_SEPARATOR: &str = "separator";
|
||||
|
@ -54,47 +55,8 @@ type RangeInt = (ExtendedBigInt, ExtendedBigInt, ExtendedBigInt);
|
|||
/// The elements are (first, increment, last).
|
||||
type RangeFloat = (ExtendedBigDecimal, ExtendedBigDecimal, ExtendedBigDecimal);
|
||||
|
||||
/// Terminate the process with error code 1.
|
||||
///
|
||||
/// 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 {
|
||||
#[uucore_procs::gen_uumain]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let usage = usage();
|
||||
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 slice = numbers[0];
|
||||
slice.parse().unwrap_or_else(|e| exit_with_error(slice, e))
|
||||
match numbers[0].parse() {
|
||||
Ok(num) => num,
|
||||
Err(e) => return Err(SeqError::ParseError(numbers[0].to_string(), e).into()),
|
||||
}
|
||||
} else {
|
||||
PreciseNumber::one()
|
||||
};
|
||||
let increment = if numbers.len() > 2 {
|
||||
let slice = numbers[1];
|
||||
slice.parse().unwrap_or_else(|e| exit_with_error(slice, e))
|
||||
match numbers[1].parse() {
|
||||
Ok(num) => num,
|
||||
Err(e) => return Err(SeqError::ParseError(numbers[1].to_string(), e).into()),
|
||||
}
|
||||
} else {
|
||||
PreciseNumber::one()
|
||||
};
|
||||
if increment.is_zero() {
|
||||
show_error!(
|
||||
"invalid Zero increment value: '{}'\nTry '{} --help' for more information.",
|
||||
numbers[1],
|
||||
uucore::execution_phrase()
|
||||
);
|
||||
return 1;
|
||||
return Err(SeqError::ZeroIncrement(numbers[1].to_string()).into());
|
||||
}
|
||||
let last: PreciseNumber = {
|
||||
let slice = numbers[numbers.len() - 1];
|
||||
slice.parse().unwrap_or_else(|e| exit_with_error(slice, e))
|
||||
// We are guaranteed that `numbers.len()` is greater than zero
|
||||
// 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
|
||||
|
@ -164,9 +131,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
),
|
||||
};
|
||||
match result {
|
||||
Ok(_) => 0,
|
||||
Err(err) if err.kind() == ErrorKind::BrokenPipe => 0,
|
||||
Err(_) => 1,
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) if err.kind() == ErrorKind::BrokenPipe => Ok(()),
|
||||
Err(e) => Err(e.map_err_context(|| "write error".into())),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// spell-checker:ignore lmnop xlmnop
|
||||
use crate::common::util::*;
|
||||
use std::io::Read;
|
||||
|
||||
|
@ -676,3 +677,19 @@ fn test_rounding_end() {
|
|||
.stdout_is("1\n")
|
||||
.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