summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToby Vincent <tobyv13@gmail.com>2022-12-04 00:02:00 -0600
committerToby Vincent <tobyv13@gmail.com>2022-12-04 00:02:00 -0600
commit9b70a213e7379c80e137b381f5f31145cef561d1 (patch)
treed35cc112de41d37bb1efd7abb3875439381a3f8d
parent1939e8d2e2411497291b419abd0a85a2b4808834 (diff)
refactor: improve arg parsingHEADmain
-rw-r--r--src/cli.rs91
-rw-r--r--src/lib.rs8
2 files changed, 47 insertions, 52 deletions
diff --git a/src/cli.rs b/src/cli.rs
index 8c72155..968c33f 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -27,7 +27,14 @@ impl Cli {
fn parse_arg(mut self, opt: String) -> Result<Self> {
match opt.as_str() {
"-" => self.files.push(Input::Stdin),
- o if o.starts_with('-') => self.opts.parse_opt(o)?,
+ s if s.starts_with("--") => {
+ self.opts.try_set_opt(s)?;
+ }
+ s if s.starts_with('-') => {
+ s.chars()
+ .skip(1)
+ .try_fold(&mut self.opts, Opts::try_set_opt)?;
+ }
s => self.files.push(s.into()),
};
Ok(self)
@@ -47,30 +54,14 @@ pub struct Opts {
}
impl Opts {
- fn parse_opt(&mut self, s: &str) -> Result<()> {
- if s.starts_with("--") {
- self.parse_long(s)
- } else if s.starts_with('-') {
- self.parse_short(s)
- } else {
- Err(Error::Opts(format!("`{}` is not an option.", s)))
- }
- }
-
- fn parse_short(&mut self, short: &str) -> Result<()> {
- short
- .trim_start_matches('-')
- .chars()
- .map(Into::into)
- .try_for_each(|opt| self.set_opt(opt))
- }
-
- fn parse_long(&mut self, long: &str) -> Result<()> {
- let opt = long.trim_start_matches('-').into();
- self.set_opt(opt)
+ fn try_set_opt<T>(&mut self, t: T) -> Result<&mut Self>
+ where
+ T: TryInto<Opt, Error = Error>,
+ {
+ t.try_into().map(|opt| self.set_opt(opt))
}
- fn set_opt(&mut self, opt: Opt) -> Result<()> {
+ pub fn set_opt(&mut self, opt: Opt) -> &mut Self {
match opt {
Opt::ShowAll => {
self.show_ends = true;
@@ -94,14 +85,13 @@ impl Opts {
Opt::ShowNonprinting => self.show_nonprinting = true,
Opt::Help => self.help = true,
Opt::Version => self.version = true,
- Opt::Unknown(s) => return Err(Error::Opts(s)),
};
- Ok(())
+ self
}
}
#[derive(Debug)]
-enum Opt {
+pub enum Opt {
/// -A, --show-all
///
/// equivalent to -vET
@@ -161,14 +151,13 @@ enum Opt {
///
/// output version information and exit
Version,
-
- /// unrecognized option
- Unknown(String),
}
-impl From<char> for Opt {
- fn from(value: char) -> Self {
- match value {
+impl TryFrom<char> for Opt {
+ type Error = Error;
+
+ fn try_from(value: char) -> Result<Self> {
+ let opt = match value {
'A' => Self::ShowAll,
'b' => Self::NumberNonblank,
'e' => Self::ShowEndsNonprinting,
@@ -179,24 +168,30 @@ impl From<char> for Opt {
'T' => Self::ShowTabs,
'u' => Self::Ignored,
'v' => Self::ShowNonprinting,
- s => Self::Unknown(s.into()),
- }
+ s => return Err(Error::Opts(s.into())),
+ };
+
+ Ok(opt)
}
}
-impl From<&str> for Opt {
- fn from(value: &str) -> Self {
- match value {
- "show-all" => Self::ShowAll,
- "number-nonblank" => Self::NumberNonblank,
- "show-ends" => Self::ShowEnds,
- "number" => Self::Number,
- "squeeze-blank" => Self::SqueezeBlank,
- "show-tabs" => Self::ShowTabs,
- "show-nonprinting" => Self::ShowNonprinting,
- "help" => Self::Help,
- "version" => Self::Version,
- s => Self::Unknown(s.into()),
- }
+impl TryFrom<&str> for Opt {
+ type Error = Error;
+
+ fn try_from(value: &str) -> Result<Self> {
+ let opt = match value {
+ "--show-all" => Self::ShowAll,
+ "--number-nonblank" => Self::NumberNonblank,
+ "--show-ends" => Self::ShowEnds,
+ "--number" => Self::Number,
+ "--squeeze-blank" => Self::SqueezeBlank,
+ "--show-tabs" => Self::ShowTabs,
+ "--show-nonprinting" => Self::ShowNonprinting,
+ "--help" => Self::Help,
+ "--version" => Self::Version,
+ s => return Err(Error::Opts(s.into())),
+ };
+
+ Ok(opt)
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 92c8b3a..1d05eaf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -103,6 +103,8 @@ fn process_nonprinting(mut c: u8) -> Vec<u8> {
#[cfg(test)]
mod test {
+ use crate::cli::Opt;
+
use super::*;
use std::process::{Command, Stdio};
@@ -132,10 +134,8 @@ mod test {
let cat_output = cat_child.wait_with_output().unwrap();
let cat_result = String::from_utf8(cat_output.stdout).unwrap();
- let opts = Opts {
- show_nonprinting: true,
- ..Default::default()
- };
+ let mut opts = Opts::default();
+ opts.set_opt(Opt::ShowNonprinting);
let mut writer = Vec::new();