Can Clap treat an input with whitespaces as a singular argument?

Referring to clap, the console-parser.

Suppose I have a subcommand, "send", that expects an argument "message". A user may type in "send hello, world! Welcome".

Clap typically expects a singular input with no spaces since it splits at whitespaces. If delimiters are used, usually a comma is used instead of a space. Would a space be an invalid delimiter in this case?

I’ve never tried it but does AppSettings::DontDelimitTrailingValues work for this case.

From the docs

Disables the automatic delimiting of values when -- or AppSettings::TrailingVarArg was used.

NOTE: The same thing can be done manually by setting the final positional argument to Arg::use_delimiter(false). Using this setting is safer, because it's easier to locate when making changes.

I'm not quite sure if this is the case.

Normally, Clap (and every other argument-parsing library) uses everything the OS passed to the program arguments, i.e. std::env::args. The command line as already split be whitespaces by the moment Clap sees it - by the shell, not Clap. So, what you really want is:

  • either let Clap to collect trailing arguments into the vector, using TrailingVarArg config parameter, and then join this vector back,
  • or just call the program quoting the parameter with spaces, e.g. send "hello, world! Message", so that Clap will see it as a single argument.
6 Likes

Thanks for the help. Here's how to set it up (use multiple(true)):

        SubCommand::with_name("send")
            .arg(Arg::with_name("security_level").display_order(1).long("security").short("sl").required(false).takes_value(true).default_value("0").help("Sets the security level for the transmission. 0 is low, 4 is divine"))
            .arg(Arg::with_name("message").required(true).takes_value(true).display_order(2).multiple(true))

Where "message" is the block of text with whitespaces

Here's how to get "message" (use values_of, NOT value_of) :

let message = matches.values_of("message").unwrap().collect::<Vec<&str>>().join(" ");

It might not matter in this case, but I thought it would be good to mention that this solution doesn't retain
the amount of whitespace between words. Even if you run send a {multiple spaces} b the message will be a b. Retaining whitespace without quotes is probably not possible due to the explanation given by @Cerberuser

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.