diff --git a/src/app/macros.rs b/src/app/macros.rs index ded81276..b9694665 100644 --- a/src/app/macros.rs +++ b/src/app/macros.rs @@ -114,7 +114,7 @@ macro_rules! _handle_group_reqs{ debugln!("macro=_handle_group_reqs!;"); for grp in $me.groups.values() { let mut found = false; - for name in grp.args.iter() { + for name in &grp.args { if name == &$arg.name() { vec_remove!($me.required, name); if let Some(ref reqs) = grp.requires { diff --git a/src/app/parser.rs b/src/app/parser.rs index 1c2ef458..c2ae89c7 100644 --- a/src/app/parser.rs +++ b/src/app/parser.rs @@ -96,7 +96,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b { Parser { meta: AppMeta::with_name(n), ..Default::default() } } - pub fn help_short<'z>(&mut self, s: &'z str) { + pub fn help_short(&mut self, s: &str) { self.help_short = s.trim_left_matches(|c| c == '-') .chars() .nth(0); @@ -116,7 +116,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b { panic!("Non-unique argument name: {} is already in use", a.name); } if let Some(grp) = a.group { - let ag = self.groups.entry(grp).or_insert(ArgGroup::with_name(grp)); + let ag = self.groups.entry(grp).or_insert_with(|| ArgGroup::with_name(grp)); ag.args.push(a.name); } if let Some(s) = a.short { @@ -288,7 +288,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b { c_opt.push(f); } let mut tmp_p = vec![]; - for p in c_pos.iter() { + for p in &c_pos { if let Some(p) = self.positionals.values().filter(|pos| &pos.name == p).next() { if let Some(ref rl) = p.requires { for r in rl { @@ -426,11 +426,11 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b { } pub fn propogate_globals(&mut self) { - for sc in self.subcommands.iter_mut() { + for sc in &mut self.subcommands { // We have to create a new scope in order to tell rustc the borrow of `sc` is // done and to recursively call this method { - for a in self.global_args.iter() { + for a in &self.global_args { sc.0.add_arg(a); } } @@ -621,7 +621,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b { } let reqs = self.get_required_from(&hs, Some(matcher)); - for s in reqs.iter() { + for s in &reqs { write!(&mut mid_string, " {}", s).expect(INTERNAL_ERROR_MSG); } } @@ -1281,7 +1281,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b { } fn validate_required(&self, matcher: &ArgMatcher) -> ClapResult<()> { - 'outer: for name in self.required.iter() { + 'outer: for name in &self.required { if matcher.contains(name) { continue 'outer; } diff --git a/src/args/arg_matches.rs b/src/args/arg_matches.rs index ddefbce0..1e73f10c 100644 --- a/src/args/arg_matches.rs +++ b/src/args/arg_matches.rs @@ -92,26 +92,27 @@ impl<'a> ArgMatches<'a> { #[doc(hidden)] pub fn new() -> Self { ArgMatches { ..Default::default() } } - /// Gets the value of a specific option or positional argument (i.e. an argument that takes - /// an additional value at runtime). If the option wasn't present at runtime - /// it returns `None`. - /// - /// *NOTE:* If getting a value for an option or positional argument that allows multiples, - /// prefer `values_of()` as `value_of()` will only return the _*first*_ value. - /// - /// # Examples - /// - /// ```no_run - /// # use clap::{App, Arg}; - /// # let matches = App::new("myapp") - /// # .arg(Arg::with_name("output") - /// # .takes_value(true)) - /// # .get_matches(); - /// if let Some(o) = matches.value_of("output") { - /// println!("Value for output: {}", o); - /// } - /// ``` pub fn value_of>(&self, name: S) -> Option<&str> { + /*! + Gets the value of a specific option or positional argument (i.e. an argument that takes + an additional value at runtime). If the option wasn't present at runtime + it returns `None`. + + *NOTE:* If getting a value for an option or positional argument that allows multiples, + prefer `values_of()` as `value_of()` will only return the _*first*_ value. + + # Examples + + ```no_run + # use clap::{App, Arg}; + let m = App::new("myapp") + .arg(Arg::with_name("output") + .takes_value(true)) + .get_matches_from(vec!["myapp", "something"]); + + assert_eq!(m.value_of("output"), Some("something")); + ``` + */ if let Some(ref arg) = self.args.get(name.as_ref()) { if let Some(v) = arg.vals.values().nth(0) { return Some(v.to_str().expect(INVALID_UTF8)); @@ -121,6 +122,27 @@ impl<'a> ArgMatches<'a> { } pub fn lossy_value_of>(&'a self, name: S) -> Option> { + /*! + Gets the lossy value of a specific argument If the option wasn't present at runtime + it returns `None`. A lossy value is one which contains invalid UTF-8 code points, those + invalid points will be replaced with `\u{FFFD}` + + *NOTE:* If getting a value for an option or positional argument that allows multiples, + prefer `lossy_values_of()` as `lossy_value_of()` will only return the _*first*_ value. + + # Examples + + ```no_run + # use clap::{App, Arg}; + use std::ffi::OsString; + let m = App::new("utf8") + .arg(Arg::from_usage(" 'some arg'")) + .get_matches_from(vec![OsString::from("myprog"), + // "Hi {0xe9}!" + OsString::from_vec(vec![b'H', b'i', b' ', 0xe9, b'!'])]); + assert_eq!(&*m.lossy_value_of("arg").unwrap(), "Hi \u{FFFD}!"); + ``` + */ if let Some(arg) = self.args.get(name.as_ref()) { if let Some(v) = arg.vals.values().nth(0) { return Some(v.to_string_lossy()); @@ -130,7 +152,35 @@ impl<'a> ArgMatches<'a> { } pub fn os_value_of>(&self, name: S) -> Option<&OsStr> { - self.args.get(name.as_ref()).map(|arg| arg.vals.values().nth(0).map(|v| v.as_os_str())).unwrap_or(None) + /*! + Gets the OS version of a string value of a specific argument If the option wasn't present at + runtime it returns `None`. An OS value on Unix-like systems is any series of bytes, regardless + of whether or not they contain valid UTF-8 code points. Since `String`s in Rust are + garunteed to be valid UTF-8, a valid filename as an argument value on Linux (for example) may + contain invalid UTF-8 code points. This would cause a `panic!` or only the abiltiy to get a + lossy version of the file name (i.e. one where the invalid code points were replaced with + `\u{FFFD}`). This method returns an `OsString` which allows one to represent those strings + which rightfully contain invalid UTF-8. + + *NOTE:* If getting a value for an option or positional argument that allows multiples, + prefer `os_values_of()` as `os_value_of()` will only return the _*first*_ value. + + # Examples + + ```no_run + # use clap::{App, Arg}; + use std::ffi::OsString; + use std::os::unix::ffi::OsStrExt; + + let m = App::new("utf8") + .arg(Arg::from_usage(" 'some arg'")) + .get_matches_from(vec![OsString::from("myprog"), + // "Hi {0xe9}!" + OsString::from_vec(vec![b'H', b'i', b' ', 0xe9, b'!'])]); + assert_eq!(&*m.os_value_of("arg").unwrap().as_bytes(), &[b'H', b'i', b' ', 0xe9, b'!']); + ``` + */ + self.args.get(name.as_ref()).map_or(None, |arg| arg.vals.values().nth(0).map(|v| v.as_os_str())) } /// Gets the values of a specific option or positional argument in a vector (i.e. an argument @@ -154,14 +204,35 @@ impl<'a> ArgMatches<'a> { /// ``` pub fn values_of>(&'a self, name: S) -> Option> { if let Some(ref arg) = self.args.get(name.as_ref()) { - fn to_str_slice<'a>(o: &'a OsString) -> &'a str { o.to_str().expect(INVALID_UTF8) } - let to_str_slice: fn(&'a OsString) -> &'a str = to_str_slice; // coerce to fn pointer + fn to_str_slice(o: &OsString) -> &str { o.to_str().expect(INVALID_UTF8) } + let to_str_slice: fn(&OsString) -> &str = to_str_slice; // coerce to fn pointer return Some(Values { iter: arg.vals.values().map(to_str_slice) }); } None } pub fn lossy_values_of>(&'a self, name: S) -> Option> { + /*! + Gets the lossy values of a specific argument If the option wasn't present at runtime + it returns `None`. A lossy value is one which contains invalid UTF-8 code points, those + invalid points will be replaced with `\u{FFFD}` + + # Examples + + ```no_run + # use clap::{App, Arg}; + use std::ffi::OsString; + let m = App::new("utf8") + .arg(Arg::from_usage(" 'some arg'")) + .get_matches_from(vec![OsString::from("myprog"), + // "Hi {0xe9}!" + OsString::from_vec(vec![b'H', b'i', b' ', 0xe9, b'!'])]); + let itr = m.lossy_values_of("arg").unwrap(); + assert_eq!(&*itr.next().unwrap(), "Hi"); + assert_eq!(&*itr.next().unwrap(), "\u{FFFD}!"); + assert_eq!(itr.next(), None); + ``` + */ if let Some(ref arg) = self.args.get(name.as_ref()) { return Some(arg.vals.values() .map(|v| v.to_string_lossy().into_owned()) @@ -171,7 +242,37 @@ impl<'a> ArgMatches<'a> { } pub fn os_values_of>(&'a self, name: S) -> Option> { - fn to_str_slice<'a>(o: &'a OsString) -> &'a OsStr { &*o } + /*! + Gets the OS version of a string value of a specific argument If the option wasn't present at + runtime it returns `None`. An OS value on Unix-like systems is any series of bytes, regardless + of whether or not they contain valid UTF-8 code points. Since `String`s in Rust are + garunteed to be valid UTF-8, a valid filename as an argument value on Linux (for example) may + contain invalid UTF-8 code points. This would cause a `panic!` or only the abiltiy to get a + lossy version of the file name (i.e. one where the invalid code points were replaced with + `\u{FFFD}`). This method returns an `OsString` which allows one to represent those strings + which rightfully contain invalid UTF-8. + + # Examples + + ```no_run + # use clap::{App, Arg}; + use std::ffi::OsString; + + let m = App::new("utf8") + .arg(Arg::from_usage(" 'some arg'")) + .get_matches_from(vec![OsString::from("myprog"), + // "Hi" + OsString::from_vec(vec![b'H', b'i']), + // "{0xe9}!" + OsString::from_vec(vec![0xe9, b'!'])]); + + let itr = m.os_values_of("arg").unwrap(); + assert_eq!(itr.next(), Some(&*OsString::from("Hi"))); + assert_eq!(itr.next(), Some(&*OsString::from_vec(vec![0xe9, b'!']))); + assert_eq!(itr.next(), None); + ``` + */ + fn to_str_slice(o: &OsString) -> &OsStr { &*o } let to_str_slice: fn(&'a OsString) -> &'a OsStr = to_str_slice; // coerce to fn pointer if let Some(ref arg) = self.args.get(name.as_ref()) { return Some(OsValues { iter: arg.vals.values().map(to_str_slice) }); @@ -219,7 +320,7 @@ impl<'a> ArgMatches<'a> { /// } /// ``` pub fn occurrences_of>(&self, name: S) -> u8 { - self.args.get(name.as_ref()).map(|a| a.occurs).unwrap_or(0) + self.args.get(name.as_ref()).map_or(0, |a| a.occurs) } /// Returns the `ArgMatches` for a particular subcommand or None if the subcommand wasn't @@ -279,7 +380,7 @@ impl<'a> ArgMatches<'a> { /// } /// ``` pub fn subcommand(&self) -> (&str, Option<&ArgMatches<'a>>) { - self.subcommand.as_ref().map(|sc| (&sc.name[..], Some(&sc.matches))).unwrap_or(("", None)) + self.subcommand.as_ref().map_or(("",None), |sc| (&sc.name[..], Some(&sc.matches))) } /// Returns a string slice of the usage statement for the `App` (or `SubCommand`) @@ -294,7 +395,7 @@ impl<'a> ArgMatches<'a> { /// println!("{}",app_matches.usage()); /// ``` pub fn usage(&self) -> &str { - self.usage.as_ref().map(|u| &u[..]).unwrap_or("") + self.usage.as_ref().map_or("", |u| &u[..]) } } @@ -334,18 +435,11 @@ impl<'a, V> Iterator for Iter<'a, V> { #[inline] fn next(&mut self) -> Option<&'a V> { while self.front < self.back { - match self.iter.next() { - Some(elem) => { - match elem.as_ref() { - Some(x) => { - // let index = self.front; - self.front += 1; - return Some(x); - }, - None => {}, - } + if let Some(elem) = self.iter.next() { + if let Some(x) = elem.as_ref() { + self.front += 1; + return Some(x); } - _ => () } self.front += 1; } @@ -362,17 +456,11 @@ impl<'a, V> DoubleEndedIterator for Iter<'a, V> { #[inline] fn next_back(&mut self) -> Option<&'a V> { while self.front < self.back { - match self.iter.next_back() { - Some(elem) => { - match elem.as_ref() { - Some(x) => { - self.back -= 1; - return Some(x); - }, - None => {}, - } + if let Some(elem) = self.iter.next_back() { + if let Some(x) = elem.as_ref() { + self.back -= 1; + return Some(x); } - _ => () } self.back -= 1; } diff --git a/src/lib.rs b/src/lib.rs index 648ca42f..469ae832 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -648,20 +648,17 @@ #![cfg_attr(feature = "lints", deny(warnings))] #![cfg_attr(not(any(feature = "lints", feature = "nightly")), deny(unstable_features))] #![deny( - // missing_docs, + missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts, trivial_numeric_casts, - // unsafe_code, unused_import_braces, unused_qualifications)] // clippy false positives, or ones we're ok with... -#![cfg_attr(feature = "lints", allow(explicit_iter_loop))] -#![cfg_attr(feature = "lints", allow(should_implement_trait))] #![cfg_attr(feature = "lints", allow(cyclomatic_complexity))] // Only while bitflats uses "_first" inside it's macros -#![cfg_attr(feature = "lints", allow(used_underscore_binding))] + #![cfg_attr(feature = "lints", allow(used_underscore_binding))] #[cfg(feature = "suggestions")] extern crate strsim; diff --git a/src/osstringext.rs b/src/osstringext.rs index c38936c9..284cac83 100644 --- a/src/osstringext.rs +++ b/src/osstringext.rs @@ -13,13 +13,11 @@ pub trait OsStrExt2 { impl OsStrExt2 for OsStr { fn starts_with(&self, s: &[u8]) -> bool { - let mut i = 0; let sab = self.as_bytes(); - for b in s { + for (i, b) in s.iter().enumerate() { if *b != sab[i] { return false; } - i += 1; } - return true; + true } fn is_empty(&self) -> bool { @@ -34,19 +32,15 @@ impl OsStrExt2 for OsStr { } fn split_at_byte(&self, byte: u8) -> (&OsStr, &OsStr) { - let mut i = 0; - for b in self.as_bytes() { + for (i, b) in self.as_bytes().iter().enumerate() { if b == &byte { return (OsStr::from_bytes(&self.as_bytes()[..i]), OsStr::from_bytes(&self.as_bytes()[i+1..])); } - i += 1; } (&*self, OsStr::from_bytes(&self.as_bytes()[self.len()..self.len()])) } fn trim_left_matches(&self, byte: u8) -> &OsStr { - let mut i = 0; - for b in self.as_bytes() { + for (i, b) in self.as_bytes().iter().enumerate() { if b != &byte { return OsStr::from_bytes(&self.as_bytes()[i..]); } - i += 1; } &*self }