clap icon indicating copy to clipboard operation
clap copied to clipboard

Question - how can I print the arguments given an opt instance?

Open epage opened this issue 3 years ago • 11 comments

Issue by avnerbarr Thursday Oct 15, 2020 at 13:51 GMT Originally opened as https://github.com/TeXitoi/structopt/issues/441


I want to get the string representation leading to a particular Opt instance (after I've modified it).

for instance

#[derive(StructOpt)]
struct Opt {
a : String,
b: String,
c: i32,
...
z : String
}

...
let opts = Opt::from_args();
...
if some condition occured, change opts and print the correct representation {
  let new_opts = Opt { z: "this_value_should_be_written", ..Opt::from_args() }; // change some values
  print(how do I print "new_opts" in such a way that is valid for the Opt parser for next run?)
}

epage avatar Dec 09 '21 16:12 epage

Comment by EverlastingBugstopper Monday Oct 19, 2020 at 18:05 GMT


you could add a debug derivation like so: #[derive(StructOpt, Debug)] and then print like println!("{:?}, new_opts); or even println!("{:#?}", new_opts);

epage avatar Dec 09 '21 16:12 epage

Comment by TeXitoi Tuesday Oct 20, 2020 at 09:16 GMT


AFAIK, that's not possible, and it will be a quite complicated feature, relying deeply in clap internal.

epage avatar Dec 09 '21 16:12 epage

Comment by therealbnut Tuesday Apr 06, 2021 at 00:32 GMT


Adding to this I want to use structopt for IPC with a forked child process, and so I'd like to be able to go from an Opt structure to a Vec/Iterator of argument strings.

ie.

enum Opt {
    #[structopt(short, long)]
    host_name: String,
}

// ["--host_name", "my-server"]
(Opt { host_name: "my-server".to_owned() }).args()

If this was possible then you could emit debugging info by doing:

println!("{:?}", op.args())

epage avatar Dec 09 '21 16:12 epage

Comment by Xaeroxe Monday Oct 04, 2021 at 16:29 GMT


@TeXitoi would you be open to a PR implementing this?

epage avatar Dec 09 '21 16:12 epage

Comment by TeXitoi Monday Oct 04, 2021 at 16:51 GMT


Better to propose to clapv3

epage avatar Dec 09 '21 16:12 epage

@epage This is currently possible with v3, right?

pksunkara avatar Dec 10 '21 01:12 pksunkara

I'm not aware of a way to convert a Parser to a valid args.

First, doing so would only work if all fields are Display (which will fail in common cases like Path). Ideally we would be instead generating OsStrings rather than Strings and there isn't anything like Display for OsStr though we could generate some specialization hacks to work in some cases.

Second, we'd have to examine all of the attributes to see what a valid command would look like.

  • The most obvious is dealing with if a short/long is needed and what that is.
  • An example of an easy to miss case is if they set require_equals.
  • A complicated case is when it comes to validation rules and defaulting. Once #3020 goes in, users can set requires that ignore defaults but we will have a hard time knowing in this what is a default to not put in the command line.

Of course, with all features, there is a question of how much correctness is needed so you aren't laying traps for people vs how much it gets in the way of progress.

epage avatar Dec 10 '21 19:12 epage

The shape I'd like to see this API take would be

  • clap exposes an additional derive trait, called something like IntoArgs (we can bikeshed the name)
  • That trait provides a method for generating an Iterator of OsStrings.
  • That Iterator can be fed into std::process::Command::args and if the target executable uses Parser::parse() on the same structure definition that we used IntoArgs on, then the transmission of the structure between programs is guaranteed to be correct.*

* Barring further manipulation of the Command which may invalidate the argument structure and ordering

It may be possible to lean on the serde data model for this. i.e. if the structure also implements serde::Serialize then clap only has to accept the serde data model, rather than requiring all of the members to implement some new trait that reverses FromStr. Display would be a poor choice for reversing FromStr because Display doesn't require a guarantee that it's compatible with FromStr. However it's worth noting that using the serde data model has a similar problem, unless clap also starts using serde for deserializing the arguments.

Xaeroxe avatar Jan 18 '22 18:01 Xaeroxe

Is it generally possible to generate a correct std::process::Command regardless of the OS, or is this complicated enough that Clap would have to target another library?

Kinrany avatar Sep 22 '22 22:09 Kinrany

"Regardless of OS" part is likely the easy part. The hard part is more in getting the data back out once it has been parsed as I outlined above.

epage avatar Sep 23 '22 00:09 epage