diff --git a/src/build/arg/mod.rs b/src/build/arg/mod.rs index 053cb2dd4a5d..4566877d71f4 100644 --- a/src/build/arg/mod.rs +++ b/src/build/arg/mod.rs @@ -5013,9 +5013,16 @@ impl<'help> Display for Arg<'help> { } else if let Some(s) = self.short { write!(f, "-{}", s)?; } + let is_optional_val = self.min_vals == Some(0); if !self.is_positional() && self.is_set(ArgSettings::TakesValue) { let sep = if self.is_set(ArgSettings::RequireEquals) { - "=" + if is_optional_val { + "[=" + } else { + "=" + } + } else if is_optional_val { + " [" } else { " " }; @@ -5024,6 +5031,9 @@ impl<'help> Display for Arg<'help> { if self.is_set(ArgSettings::TakesValue) || self.is_positional() { display_arg_val(self, |s, _| write!(f, "{}", s))?; } + if !self.is_positional() && self.is_set(ArgSettings::TakesValue) && is_optional_val { + write!(f, "]")?; + } Ok(()) } diff --git a/src/output/help.rs b/src/output/help.rs index 7544b0c18df3..f7e02db7e4f5 100644 --- a/src/output/help.rs +++ b/src/output/help.rs @@ -269,13 +269,11 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> { } } - /// Writes argument's long command to the wrapped stream. + /// Writes argument's long command and possible values to the wrapped stream. fn long(&mut self, arg: &Arg<'help>) -> io::Result<()> { debug!("Help::long"); - if arg.is_positional() { - return Ok(()); - } - if arg.is_set(ArgSettings::TakesValue) { + let is_optional_val = arg.min_vals == Some(0); + if !arg.is_positional() && arg.is_set(ArgSettings::TakesValue) { if let Some(l) = arg.long { if arg.short.is_some() { self.none(", ")?; @@ -284,7 +282,13 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> { } let sep = if arg.is_set(ArgSettings::RequireEquals) { - "=" + if is_optional_val { + "[=" + } else { + "=" + } + } else if is_optional_val { + " [" } else { " " }; @@ -295,12 +299,7 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> { } self.good(&format!("--{}", l))?; } - Ok(()) - } - /// Writes argument's possible values to the wrapped stream. - fn val(&mut self, arg: &Arg<'help>, next_line_help: bool, longest: usize) -> io::Result<()> { - debug!("Help::val: arg={}", arg.name); if arg.is_set(ArgSettings::TakesValue) || arg.is_positional() { display_arg_val( arg, @@ -308,13 +307,28 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> { )?; } - debug!("Help::val: Has switch..."); + if !arg.is_positional() && arg.is_set(ArgSettings::TakesValue) && is_optional_val { + self.none("]")?; + } + + Ok(()) + } + + /// Write alignment padding between arg's switches/values and its about message. + fn align_to_about( + &mut self, + arg: &Arg<'help>, + next_line_help: bool, + longest: usize, + ) -> io::Result<()> { + debug!("Help::align_to_about: arg={}", arg.name); + debug!("Help::align_to_about: Has switch..."); if self.use_long { - // long help prints messages on the next line so it don't need to align text - debug!("Help::val: printing long help so skip alignment"); + // long help prints messages on the next line so it doesn't need to align text + debug!("Help::align_to_about: printing long help so skip alignment"); } else if !arg.is_positional() { debug!("Yes"); - debug!("Help::val: nlh...{:?}", next_line_help); + debug!("Help::align_to_about: nlh...{:?}", next_line_help); if !next_line_help { let self_len = display_width(arg.to_string().as_str()); // subtract ourself @@ -439,7 +453,7 @@ impl<'help, 'app, 'parser, 'writer> Help<'help, 'app, 'parser, 'writer> { ) -> io::Result<()> { self.short(arg)?; self.long(arg)?; - self.val(arg, next_line_help, longest)?; + self.align_to_about(arg, next_line_help, longest)?; let about = if self.use_long { arg.long_help.unwrap_or_else(|| arg.help.unwrap_or("")) diff --git a/tests/builder/help.rs b/tests/builder/help.rs index 274dd66b1246..b4a0ce3f0f59 100644 --- a/tests/builder/help.rs +++ b/tests/builder/help.rs @@ -38,6 +38,8 @@ OPTIONS: --multvalsmo Tests multiple values, and mult occs -o, --option ... tests options -O, --option3 specific vals [possible values: fast, slow] + --optvaleq[=] Tests optional value, require = sign + --optvalnoeq [] Tests optional value -V, --version Print version information SUBCOMMANDS: diff --git a/tests/builder/utils.rs b/tests/builder/utils.rs index 094531362e6c..c54b5808ec1c 100644 --- a/tests/builder/utils.rs +++ b/tests/builder/utils.rs @@ -94,6 +94,15 @@ pub fn complex_app() -> App<'static> { arg!(--maxvals3 "Tests 3 max vals") .required(false) .max_values(3), + arg!(--optvaleq "Tests optional value, require = sign") + .required(false) + .min_values(0) + .number_of_values(1) + .require_equals(true), + arg!(--optvalnoeq "Tests optional value") + .required(false) + .min_values(0) + .number_of_values(1), ]) .subcommand( App::new("subcmd") diff --git a/tests/derive/options.rs b/tests/derive/options.rs index 0f21708b0b23..c0ab79e8a164 100644 --- a/tests/derive/options.rs +++ b/tests/derive/options.rs @@ -199,8 +199,8 @@ fn option_option_type_help() { arg: Option>, } let help = utils::get_help::(); - assert!(help.contains("--arg ")); - assert!(!help.contains("--arg ...")); + assert!(help.contains("--arg []")); + assert!(!help.contains("--arg []...")); } #[test]