diff --git a/src/build/arg.rs b/src/build/arg.rs index 6d2c3787563..452880d2649 100644 --- a/src/build/arg.rs +++ b/src/build/arg.rs @@ -4633,6 +4633,12 @@ impl<'help> Arg<'help> { self.num_vals } + /// Get the delimiter between multiple values + #[inline] + pub fn get_value_delimiter(&self) -> Option { + self.val_delim + } + /// Get the index of this argument, if any #[inline] pub fn get_index(&self) -> Option { diff --git a/src/build/debug_asserts.rs b/src/build/debug_asserts.rs index 0e86473e955..e811db01e4c 100644 --- a/src/build/debug_asserts.rs +++ b/src/build/debug_asserts.rs @@ -1,5 +1,7 @@ use std::cmp::Ordering; +use os_str_bytes::RawOsStr; + use crate::build::arg::ArgProvider; use crate::mkeymap::KeyType; use crate::util::Id; @@ -686,7 +688,16 @@ fn assert_defaults<'d>( if let Some(validator) = arg.validator.as_ref() { let mut validator = validator.lock().unwrap(); - if let Err(err) = validator(default_s) { + if let Some(delim) = arg.get_value_delimiter() { + for part in default_s.split(delim) { + if let Err(err) = validator(part) { + panic!( + "Argument `{}`'s {}={} failed validation: {}", + arg.name, field, part, err + ); + } + } + } else if let Err(err) = validator(default_s) { panic!( "Argument `{}`'s {}={} failed validation: {}", arg.name, field, default_s, err @@ -697,7 +708,17 @@ fn assert_defaults<'d>( if let Some(validator) = arg.validator_os.as_ref() { let mut validator = validator.lock().unwrap(); - if let Err(err) = validator(default_os) { + if let Some(delim) = arg.get_value_delimiter() { + let default_os = RawOsStr::new(default_os); + for part in default_os.split(delim) { + if let Err(err) = validator(&part.to_os_str()) { + panic!( + "Argument `{}`'s {}={:?} failed validation: {}", + arg.name, field, part, err + ); + } + } + } else if let Err(err) = validator(default_os) { panic!( "Argument `{}`'s {}={:?} failed validation: {}", arg.name, field, default_os, err diff --git a/tests/builder/default_vals.rs b/tests/builder/default_vals.rs index 839024927f9..640a525eb84 100644 --- a/tests/builder/default_vals.rs +++ b/tests/builder/default_vals.rs @@ -648,15 +648,47 @@ fn default_values_are_possible_values() { #[cfg(debug_assertions)] #[test] -#[should_panic = "Argument `arg`'s default_value=value failed validation: invalid digit found in string"] -fn default_values_are_valid() { +#[should_panic = "Argument `arg`'s default_value=one failed validation: invalid digit found in string"] +fn invalid_default_values() { use clap::{Arg, Command}; let _ = Command::new("test") .arg( Arg::new("arg") .validator(|val| val.parse::().map_err(|e| e.to_string())) - .default_value("value"), + .default_value("one"), + ) + .try_get_matches(); +} + +#[test] +fn valid_delimited_default_values() { + use clap::{Arg, Command}; + + let _ = Command::new("test") + .arg( + Arg::new("arg") + .validator(|val| val.parse::().map_err(|e| e.to_string())) + .use_value_delimiter(true) + .require_value_delimiter(true) + .default_value("1,2,3"), + ) + .try_get_matches(); +} + +#[cfg(debug_assertions)] +#[test] +#[should_panic = "Argument `arg`'s default_value=one failed validation: invalid digit found in string"] +fn invalid_delimited_default_values() { + use clap::{Arg, Command}; + + let _ = Command::new("test") + .arg( + Arg::new("arg") + .validator(|val| val.parse::().map_err(|e| e.to_string())) + .use_value_delimiter(true) + .require_value_delimiter(true) + .default_value("one,two"), ) .try_get_matches(); }