mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
nl: implement TryFrom<&str> for NumberingStyle
This commit is contained in:
parent
6ffea22b57
commit
d5ab7bbacd
3 changed files with 77 additions and 56 deletions
|
@ -2,25 +2,6 @@
|
||||||
|
|
||||||
use crate::options;
|
use crate::options;
|
||||||
|
|
||||||
// parse_style parses a style string into a NumberingStyle.
|
|
||||||
fn parse_style(chars: &[char]) -> Result<crate::NumberingStyle, String> {
|
|
||||||
if chars.len() == 1 && chars[0] == 'a' {
|
|
||||||
Ok(crate::NumberingStyle::All)
|
|
||||||
} else if chars.len() == 1 && chars[0] == 't' {
|
|
||||||
Ok(crate::NumberingStyle::NonEmpty)
|
|
||||||
} else if chars.len() == 1 && chars[0] == 'n' {
|
|
||||||
Ok(crate::NumberingStyle::None)
|
|
||||||
} else if chars.len() > 1 && chars[0] == 'p' {
|
|
||||||
let s: String = chars[1..].iter().cloned().collect();
|
|
||||||
match regex::Regex::new(&s) {
|
|
||||||
Ok(re) => Ok(crate::NumberingStyle::Regex(Box::new(re))),
|
|
||||||
Err(_) => Err(String::from("Illegal regular expression")),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(String::from("Illegal style encountered"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse_options loads the options into the settings, returning an array of
|
// parse_options loads the options into the settings, returning an array of
|
||||||
// error messages.
|
// error messages.
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
|
@ -35,47 +16,32 @@ pub fn parse_options(settings: &mut crate::Settings, opts: &clap::ArgMatches) ->
|
||||||
.get_one::<String>(options::NUMBER_FORMAT)
|
.get_one::<String>(options::NUMBER_FORMAT)
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
match opts.get_one::<String>(options::BODY_NUMBERING) {
|
match opts
|
||||||
|
.get_one::<String>(options::HEADER_NUMBERING)
|
||||||
|
.map(String::as_str)
|
||||||
|
.map(TryInto::try_into)
|
||||||
|
{
|
||||||
None => {}
|
None => {}
|
||||||
Some(val) => {
|
Some(Ok(style)) => settings.header_numbering = style,
|
||||||
let chars: Vec<char> = val.chars().collect();
|
Some(Err(message)) => errs.push(message.to_string()),
|
||||||
match parse_style(&chars) {
|
|
||||||
Ok(s) => {
|
|
||||||
settings.body_numbering = s;
|
|
||||||
}
|
|
||||||
Err(message) => {
|
|
||||||
errs.push(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
match opts.get_one::<String>(options::FOOTER_NUMBERING) {
|
match opts
|
||||||
|
.get_one::<String>(options::BODY_NUMBERING)
|
||||||
|
.map(String::as_str)
|
||||||
|
.map(TryInto::try_into)
|
||||||
|
{
|
||||||
None => {}
|
None => {}
|
||||||
Some(val) => {
|
Some(Ok(style)) => settings.body_numbering = style,
|
||||||
let chars: Vec<char> = val.chars().collect();
|
Some(Err(message)) => errs.push(message.to_string()),
|
||||||
match parse_style(&chars) {
|
|
||||||
Ok(s) => {
|
|
||||||
settings.footer_numbering = s;
|
|
||||||
}
|
|
||||||
Err(message) => {
|
|
||||||
errs.push(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
match opts.get_one::<String>(options::HEADER_NUMBERING) {
|
match opts
|
||||||
|
.get_one::<String>(options::FOOTER_NUMBERING)
|
||||||
|
.map(String::as_str)
|
||||||
|
.map(TryInto::try_into)
|
||||||
|
{
|
||||||
None => {}
|
None => {}
|
||||||
Some(val) => {
|
Some(Ok(style)) => settings.footer_numbering = style,
|
||||||
let chars: Vec<char> = val.chars().collect();
|
Some(Err(message)) => errs.push(message.to_string()),
|
||||||
match parse_style(&chars) {
|
|
||||||
Ok(s) => {
|
|
||||||
settings.header_numbering = s;
|
|
||||||
}
|
|
||||||
Err(message) => {
|
|
||||||
errs.push(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
match opts.get_one::<usize>(options::NUMBER_WIDTH) {
|
match opts.get_one::<usize>(options::NUMBER_WIDTH) {
|
||||||
None => {}
|
None => {}
|
||||||
|
|
|
@ -71,6 +71,23 @@ enum NumberingStyle {
|
||||||
Regex(Box<regex::Regex>),
|
Regex(Box<regex::Regex>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&str> for NumberingStyle {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||||
|
match s {
|
||||||
|
"a" => Ok(Self::All),
|
||||||
|
"t" => Ok(Self::NonEmpty),
|
||||||
|
"n" => Ok(Self::None),
|
||||||
|
_ if s.starts_with('p') => match regex::Regex::new(&s[1..]) {
|
||||||
|
Ok(re) => Ok(Self::Regex(Box::new(re))),
|
||||||
|
Err(_) => Err(String::from("invalid regular expression")),
|
||||||
|
},
|
||||||
|
_ => Err(format!("invalid numbering style: '{s}'")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NumberFormat specifies how line numbers are output within their allocated
|
// NumberFormat specifies how line numbers are output within their allocated
|
||||||
// space. They are justified to the left or right, in the latter case with
|
// space. They are justified to the left or right, in the latter case with
|
||||||
// the option of having all unused space to its left turned into leading zeroes.
|
// the option of having all unused space to its left turned into leading zeroes.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// spell-checker:ignore iinvalid linvalid ninvalid vinvalid winvalid
|
// spell-checker:ignore binvalid finvalid hinvalid iinvalid linvalid ninvalid vinvalid winvalid
|
||||||
use crate::common::util::TestScenario;
|
use crate::common::util::TestScenario;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -426,3 +426,41 @@ fn test_numbering_matched_lines() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid_numbering() {
|
||||||
|
let invalid_args = [
|
||||||
|
"-hinvalid",
|
||||||
|
"--header-numbering=invalid",
|
||||||
|
"-binvalid",
|
||||||
|
"--body-numbering=invalid",
|
||||||
|
"-finvalid",
|
||||||
|
"--footer-numbering=invalid",
|
||||||
|
];
|
||||||
|
|
||||||
|
for invalid_arg in invalid_args {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg(invalid_arg)
|
||||||
|
.fails()
|
||||||
|
.stderr_contains("invalid numbering style: 'invalid'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid_regex_numbering() {
|
||||||
|
let invalid_args = [
|
||||||
|
"-hp[",
|
||||||
|
"--header-numbering=p[",
|
||||||
|
"-bp[",
|
||||||
|
"--body-numbering=p[",
|
||||||
|
"-fp[",
|
||||||
|
"--footer-numbering=p[",
|
||||||
|
];
|
||||||
|
|
||||||
|
for invalid_arg in invalid_args {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg(invalid_arg)
|
||||||
|
.fails()
|
||||||
|
.stderr_contains("invalid regular expression");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue