diff options
Diffstat (limited to 'src/cli.rs')
-rw-r--r-- | src/cli.rs | 91 |
1 files changed, 43 insertions, 48 deletions
@@ -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) } } |