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

Using -? for help in addition to -h #1127

Closed
kkayal opened this issue Dec 12, 2017 · 18 comments
Closed

Using -? for help in addition to -h #1127

kkayal opened this issue Dec 12, 2017 · 18 comments

Comments

@kkayal
Copy link

kkayal commented Dec 12, 2017

Rust Version

rustc 1.22.1 (05e2e1c41 2017-11-22)

Affected Version of clap

2.28.0

Expected Behavior Summary

The -h option has a good built-in behaviour. It is desireable that -? would do exactly the same.

Actual Behavior Summary

-? is not recognised as a built-in option as -h. Calling the hello world example with hello -? produces an error message:

error: Found argument '-?' which wasn't expected, or isn't valid in this context

USAGE:
    hello.exe [FLAGS] [OPTIONS] <INPUT> [SUBCOMMAND]

For more information try --help
error: process didn't exit successfully: `target\debug\hello.exe -?` (exit code: 1)

Steps to Reproduce the issue

Create a new minimal crate using the example code clap's own documentation, build the executable and run it with the -? option.

Sample Code or Link to Sample Code

https://docs.rs/clap/2.29.0/clap/index.html

Debug output

Not needed

@kbknapp
Copy link
Member

kbknapp commented Jan 9, 2018

There's no reason you can't use -? as the help short, by changing the default help short of -h. If you want to use both -h and -? that's also possible manually. However, I don't really want to add -? as a default alias to -h because there are people who use -? for other purposes.

@kkayal
Copy link
Author

kkayal commented Jan 11, 2018

Thanks, but I was unable to add -? as a new option properly. Maybe I miss something else.
I took the quick example from documentation, replaced the argument "config" with the following:

                      ...
                      .about("Does awesome things")
                      .arg(Arg::with_name("question_mark")
                           .short("?")
                           .help("Shows a short help message"))
                      .arg(Arg::with_name("INPUT")
                      ...

when I compile this as foo.rs and execute foo -? I get the following error message:

error: The following required arguments were not provided:
    <INPUT>

USAGE:
    foo <INPUT> -?

For more information try --help

When I type foo -h, I get no errors, just the expected help message. So it seems the -h has higher priority than the mandatory <INPUT>, which is good, but is it possible to give -? the same privilege as the -h option?

Second question: Assuming the above can be solved, how would I connect the -? option with the print_help function?

@kbknapp
Copy link
Member

kbknapp commented Jan 15, 2018

Which shell are you using? In ZSH ? is used to match a single character and thus you have to do $ program -\?

For example on my machine:

extern crate clap;

use clap::App;

fn main() {
    let matches = App::new("prog")
        .help_short("?")
        .get_matches();
}

Then:

$ prog -\?
prog 

USAGE:
    prog

FLAGS:
    -?, --help       Prints help information
    -V, --version    Prints version information

It's the same if you simply want to add a flag which prints the help too (as in your example).

@kkayal
Copy link
Author

kkayal commented Jan 19, 2018

Thanks, I just tried .help_short("?"). It works as desired, but unfortunately, the -h option becomes an invalid one.

I have no experience with zsh. I use bash as well as the standard os-x and windows 7 terminals. My examples are tar and python. tar understands -? and it doesn't even understand -h. Python supports both. That shows to me that -? or -h is just a preference of the developer. I would like to be able to support both.

In case a shell such as zsh gives the -? a special meaning, that is fair enough, but I am sure the ones that I use would not prevent me from using -? directly.

Actually, bash has the same special meaning for ? For example if I have a file called abc and then do ls a?c I get abc as expected. But this doesn't mean it has a special meaning for -? When I type ls -? it returns invalid option. In other words bash passes -? very well to ls. It is just ls, which doesn't understand the -? option.

@kbknapp
Copy link
Member

kbknapp commented Jan 23, 2018

If you want to use both -h and -?

extern crate clap;

use std::env;
use std::process;

use clap::{Arg, App};

fn main() {

	// We build the App instance and save it, so we can
	// use it later if needed
    let mut app = App::new("prog")
		.arg(Arg::with_name("help")
			.short("?")
			.help("Also prints the help message"));

	// We call this method which will do all the
	//parsing, but not consume our App instance
	let res = app.get_matches_from_safe_borrow(env::args_os());

	// This calls all the normal clap error messages
	// if one should exist
	let matches = res.unwrap_or_else(|e| e.exit());

	// Now we check for ?
	if matches.is_present("help") {
		let _ = app.print_help();
                println!(""); // adds a newline
		process::exit(0);
	}

	// Now we can use matches like normal...
}
kevin@beefcake: ~/Projects/prog 
➜ ./target/debug/prog -h
prog 

USAGE:
    prog [FLAGS]

FLAGS:
    -h, --help       Prints help information
    -?               Also prints the help message
    -V, --version    Prints version information

kevin@beefcake: ~/Projects/fake 
➜ ./target/debug/prog -\?
prog 

USAGE:
    prog [FLAGS]

FLAGS:
    -h, --help       Prints help information
    -?               Also prints the help message
    -V, --version    Prints version information

@kkayal
Copy link
Author

kkayal commented Jan 23, 2018

Thanks! This is exactly what I was looking for.

@SUPERCILEX
Copy link
Contributor

@epage is there documentation on how to do this with modern clap (derive specifically)?

@epage
Copy link
Member

epage commented Aug 5, 2022

As of clap v3, there are two ways of doing this

  1. Modify the existing help item
#[derive(Parser)]
#[clap(mut_arg("help", |arg| arg.short_alias('?')))]
struct Cli {
   ...
}

(You'd just as easily use short_visible_alias or short, depending on your need)

  1. Supplying your own help item
#[derive(Parser)]
struct Cli {
    #[clap(short, long, short_alias = '?', action = ArgAction::Help, help = "Print help information")]
    help: bool,
}

@SUPERCILEX
Copy link
Contributor

That's perfect, thank you!

@SUPERCILEX
Copy link
Contributor

@epage How do you do this in v4?

@epage
Copy link
Member

epage commented Sep 30, 2022

#[derive(Parser)]
#[command(disable_help_flag = true)]
struct Cli {
    #[arg(short, long, short_alias = '?', action = ArgAction::Help, help = "Print help information")]
    help: bool,
}

@SUPERCILEX
Copy link
Contributor

Thanks! Needs global = true as well, but that seems to work.

@SUPERCILEX
Copy link
Contributor

Also needs to be Option<bool>

@fpagliughi
Copy link

It would be awesome for this information to make it into the docs/tutorial/examples for both the Derive and Builder patterns. My company standardized on '-?' for help and '-v' for version. So I've spent the last few hours trying to figure how to upgrade all my clap 2.34 apps to v4.0.

I was pulling my hair out until I stumbled on this.

@epage
Copy link
Member

epage commented Jan 3, 2023

Trying to think of the best way to integrate this into the docs

  • This seems too specialized/advanced to be in the tutorial.
  • I'd prefer the examples not to be inundated with a small example for each person's topic of interest. One way we solve this is by covering multiple topics under a reproduction of a real world program people are likely familiar with, like git or pacman.

@LeoniePhiline
Copy link

This seems too specialized/advanced to be in the tutorial.

Maybe it's not actually that specialized.

Whenever someone creates an #[arg(short, long)] for a struct member starting with h, they will stumble upon this.

I suppose args starting with h are going to be quite common, and it took me far too long to figure out how to fix it in clap 4.

A certainly common example: Args to connect to a database:

use clap::{arg, Parser};

#[derive(Debug, Parser)]
#[command(author, version, about)]
pub struct Args {
    /// Database host
    #[arg(short, long)]
    pub host: String, // <-- Will cause trouble

    /// Database port
    #[arg(short = 'P', long, default_value_t = 3306)]
    pub port: usize,

    /// Database user
    #[arg(short, long)]
    pub user: String,

    /// Database password. Pass "-" to read from stdin.
    #[arg(short, long)]
    pub password: String,

    /// Database name
    #[arg(short, long)]
    pub database: String,
}

In the end, I opted to go for #[arg(short = 'H', long)] on the host, but I wasted time trying to go with -?/--help or just --help for help.

This used to be easier, especially when using clap_derive.

@epage
Copy link
Member

epage commented Feb 9, 2023

Maybe it's not actually that specialized.

For a tutorial, yes it is. This is where we are showing people how to create an argument in the first place; we shouldn't be covering all the various special cases. There are other places this might fit, like the cookbook, but its a problem of finding the right way to include it so it is discoverable without contributing to the docs being overwhelming. We could have a cookbook item just about this but its better when we can (1) have a concrete example we are mimicing (I want to do "X" like git does) and (2) when that concrete example is able to pull its weight by showing several things (e.g. git) or a complex interaction (e.g. the REPL example)

Whenever someone creates an #[arg(short, long)] for a struct member starting with h, they will stumble upon this.

While I am sympathetic to the struggles of figuring out how to do it, I feel like this use case is a good example for why I think the current behavior is important. Besides anything else I get into below, making -h anything but help should be the exception case with a very deliberate decision. The default behavior should be to steer people away from doing it so they fall into a pit of success for their UI design. Granted, how they get there is a mountain of success because we can't automatically report this problem at compile time and have to wait until test-time at best and runtime at worst.

This used to be easier, especially when using clap_derive.

I assume you are referring to clap automatically disabling -h for help when the user uses it. That came with its own implementation complexity which got pushed onto users as some unpredictable behavior and doubled the time it took for clap to run in the benchmark I used when releasing clap v4.

@fpagliughi
Copy link

fpagliughi commented Feb 10, 2023

I hold to my initial request 😃

The behavior for this changed in recent versions, and for people upgrading that need to maintain backward compatibility for their apps, it can be a little frustrating how to do it with the new versions. The new way is certainly more flexible, so documenting it would also help explain the new power at hand.

If the vagueness of the existing docs are a subtle way to guide users to a default, uniform behavior, then keep in mind the huge number of different areas this library may be used in. I use this a lot for networking and MQTT utilities, and in that space, -h <hostname> is universally used to indicate the network host name of the server/broker.

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

6 participants