Search code examples
rustclap

Set default value for argument of type Vec<String> using Clap 4 Rust


In Clap 2, the following:

.arg(
   Arg::with_name("files")
   .value_name("FILE")
   .help("Input file(s)")
   .multiple(true)
   .default_value("-"),
)

will produce:

USAGE:
    catr [FLAGS] [FILE]...

FLAGS:
    -h, --help               Prints help information

I want to express this in Clap 4 using the derive API.

So, I've got the struct:

pub struct Config{ // Define a public struct called Config.
    /// The input files
    #[arg(default_value_t= vec!["-".to_string()])]
    files: Vec<String>,

When I cargo build, I get the following:

🕙[ 19:37:42 ] ❯ cargo build
   Compiling catr v0.1.0 (/home/david/Work/Bitbucket/OReilly/Books/cmdlinerust/ch03/catr)
error[E0277]: `Vec<std::string::String>` doesn't implement `std::fmt::Display`
  --> src/lib.rs:10:11
   |
10 |     #[arg(default_value_t=vec!["-".to_string()])]
   |           ^^^^^^^^^^^^^^^ `Vec<std::string::String>` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `Vec<std::string::String>`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
   = note: required for `Vec<std::string::String>` to implement `ToString`

As a Rust beginner, I understand that Vec<String> doesn't implement the Display trait but I don't think I can do that for Vec<String>.

Anyway, the question is how do I translate the code in Clap 2 to Clap 4 (I believe that because I have Vec<String> I don't have to explicitly specify the `multiple part)?


Solution

  • The solution is a single letter: default_values_t instead of default_value_t.

    #[arg(default_values_t = ["-".to_string()])]
    

    You also don't need vec! because it takes IntoIterator<Item = String>.