Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Printing help on bare command invocation #785

Closed
xpe opened this issue Dec 25, 2016 · 4 comments
Closed

Printing help on bare command invocation #785

xpe opened this issue Dec 25, 2016 · 4 comments

Comments

@xpe
Copy link

xpe commented Dec 25, 2016

Thanks for this great library!

I've spent some time looking for the easiest path to tell clap show a full help message on a bare command invocation. (This is the behavior with commands such as java and cloc.)

These commands don't work:

let mut app = App::new("name me").args_from_usage("<input_file> 'Sets the input file to use'");
let matches = app.get_matches(); // moves `app`
app.print_help(); // will not compile since `app` has been moved

I understand there are (at least) these options to make the API work as I intend:

  1. Clone app before passing it to get_matches.
  2. Find a function similar to get_matches that does not move app. (I'm not sure if one exists.)

I have a design question: What is the rationale for get_matches moving the app value? Perhaps a borrow would work out better?

P.S. For some context, feel free to see: http://stackoverflow.com/questions/40951538/method-call-on-clap-app-moving-ownership-more-than-once

@kbknapp
Copy link
Member

kbknapp commented Dec 27, 2016

Thanks!

You have a few options. You can either use AppSettings::ArgRequiredElseHelp or you can keep the move from happening by using App::get_matches_from_safe_borrow.

The downside with the second approach is it returns a Result, and you'll also have to provide the args to match against, either by providing your own arbitrary Vec, std::env::args or std::env::args_os (if you wish to support invalid UTF-8).

An example of the second version, should you choose that route would be:

let matches = // build app like normal
    .get_matches_from_safe_borrow(std::env:args_os())
    .unwrap_or_else(|e| e.exit())

The e.exit() portion does exactly what clap normally does, presenting an error message and gracefully exiting.

Hope this helps!

@EvanLuo42
Copy link

EvanLuo42 commented May 25, 2022

Thanks!

You have a few options. You can either use AppSettings::ArgRequiredElseHelp or you can keep the move from happening by using App::get_matches_from_safe_borrow.

The downside with the second approach is it returns a Result, and you'll also have to provide the args to match against, either by providing your own arbitrary Vec, std::env::args or std::env::args_os (if you wish to support invalid UTF-8).

An example of the second version, should you choose that route would be:

let matches = // build app like normal
    .get_matches_from_safe_borrow(std::env:args_os())
    .unwrap_or_else(|e| e.exit())

The e.exit() portion does exactly what clap normally does, presenting an error message and gracefully exiting.

Hope this helps!

I used this way to create matches. It's like:

let mut command = Command::new("ctool");
let matches = command.
    .try_get_matches_from(std::env::args_os())
    .unwrap_or_else(|e| e.exit());

And I want to use custom error, I did like this:

let action_undefined_error = command.error(
        clap::ErrorKind::InvalidValue,
        "The given action is not supported, please enter base64, hex, etc."
    );

But it still gave:
borrow of moved value: command E0382 value borrowed here after move Note: this function takes ownership of the receiver self, which moves command

How to solve this.

@epage
Copy link
Member

epage commented May 25, 2022

try_get_matches_from took ownership of command and then you are trying to use command again.

Options

  • Create a fn command() -> Command<'static> and write your errors as command().error(...). This will slow things down but in the error case so its unlikely anyone will notice
  • Use _mut variant for parsing, whether get_matches_mut or try_get_matches_from_mut.

@EvanLuo42
Copy link

try_get_matches_from took ownership of command and then you are trying to use command again.

Options

  • Create a fn command() -> Command<'static> and write your errors as command().error(...). This will slow things down but in the error case so its unlikely anyone will notice
  • Use _mut variant for parsing, whether get_matches_mut or try_get_matches_from_mut.

Thank you, it worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants