The clap crate implements built-in behaviour for the -h
option, but it doesn't seem to do the same for -?
. Is there a way to tell it to do so?

- 37,241
- 25
- 195
- 267

- 2,303
- 1
- 19
- 30
3 Answers
I had opened an issue at the clap repository. The author / main contributor has answered there. Here is a copy of the code, which answers the question:
extern crate clap;
use std::env;
use std::process;
use clap::{App, Arg};
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...
}

- 388,571
- 95
- 1,107
- 1,366

- 2,303
- 1
- 19
- 30
As of Clap 2.29.0, there's no built-in way to add multiple short names for the same option.
App::help_short
lets you override the default -h
option for help, but although the function accepts a string, it only cares about the first character (after stripping leading dashes). Arg::short
does the same.
You could define the -?
option as a separate option, and handle it yourself by calling App::print_help
. This will have the effect of displaying -?
separately in the help text, although you can hide the option.

- 60,274
- 7
- 180
- 155
-
Thanks for helping, but neither workarounds worked for me. The first one sounds like -h would not work anymore, which is not my intention. The second one doesn't work at all. I defined .arg(Arg::with_name("QUESTION_MARK").short("?") but later when I check if it the user entered a ? by calling value_of("QUESTION_MARK"), it returns None... And even if that would work, after calling .get_matches(), it seems it consumes App and returns clap::ArgMatches, which doesn't have a sort of print_help function, but only usage(), which is not what I was looking for. – Kağan Kayal Dec 11 '17 at 07:33
-
2@KağanKayal In that case, you might want to fill a new [issue](https://github.com/kbknapp/clap-rs/issues) on Clap's repository. Basically, what you're asking for is the ability to define *short* aliases (the `alias` functions on `Arg` only define aliases for the `--long` option syntax). – Francis Gagné Dec 12 '17 at 01:38
Tried to make this a comment, but it won't fit.
Another issue you're going to run into with this, at least on Unix-like systems, is that most shells assign a special meaning to '?'. I have a Rust program that just prints out the arguments it finds on the command line.
> $ cargo run one two three
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/cmdl one two three`
["target/debug/cmdl", "one", "two", "three"]
args len: 4
arg: target/debug/cmdl
arg: one
arg: two
arg: three
When I pass it -?
:
> $ cargo run -?
zsh: no matches found: -?
I can pass in -?
if I quote it and put --
in front of it:
> $ cargo run -- "-?"
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/cmdl '-?'`
["target/debug/cmdl", "-?"]
args len: 2
arg: target/debug/cmdl
arg: -?
It seems like that's a bit much to expect of someone looking for help but maybe it's friendlier on the OP's platform. I'm working on Mac OS X.
Update:
Most of the Bourne-based shells on Unix-like systems interpret ? as a globbing wildcard for matching a single character in file names. I don't know about fish but I've checked out /bin/sh, /bin/ksh, /bin/bash, and /bin/zsh below.
If you use -? as a command line option with these shells and there's a filename in the working directory that consists of a hyphen followed by a single character, your program will see the file name rather than the "-?" because the shell will do the substitution before the command line ever gets to your program.
Some of the shells (notably zsh) will stumble over -? before even checking files, as noted in my original message.
As shown below, if -? is enclosed in quotes, the shell won't mess with it but that's not something I'd expect most folks to know. I wouldn't even trust myself to remember that when I'm trying to find the help page for a program I'm not familiar with.
$ /bin/sh
$ ls
-a -bb -ccc a bb ccc
$ echo -?
-a
$ echo ?
a
$ echo ??
-a bb
$ echo "-?"
-?
$ /bin/ksh
$ ls
-a -bb -ccc a bb ccc
$ echo ?
a
$ echo -?
-a
$ echo ??
-a bb
$ echo "-?"
-?
$ /bin/bash
$ ls
-a -bb -ccc a bb ccc
$ echo ?
a
$ echo -?
-a
$ echo ??
-a bb
$ echo "-?"
-?
$ /bin/zsh
$ ls
-a -bb -ccc a bb ccc
$ echo ?
a
$ echo -?
-a
$ echo ??
-a bb
$ echo "-?"
-?

- 1,554
- 18
- 23
-
1 — Don't run it through `cargo`, which does its own command line handling. 2 — *most shells assign a special meaning* — running on bash: `./target/debug/echo -?` -> `["./target/debug/echo", "-?"]`. One shell does, one doesn't. You'll need to cite some statistics to claim "most". – Shepmaster Jan 16 '18 at 03:22
-
@Shepmaster: Thanks for calling me on my vague claim. I thought I remembered something about '?' being handled weirdly by the shells. I tried to use -? for help, like the OP, many years ago before eventually figuring out what I point out in my update and giving it up. The point is, -? is not a good option to use on Unix-like systems with shells in the Bourne family because of the potential inconsistent behavior due to file name matching. – Tom Barron Jan 16 '18 at 14:38
-
Using your set of shells and `echo -?` prints `-?` in each case on my machine, so your point is that if you have a file starting with a dash, then using `-?` can cause problems? – Shepmaster Jan 16 '18 at 15:07
-
Yes. If you have a file that matches -? (i.e., starts with dash and contains one other character), -? will return the file name, not '-?'. The program can't control the environment it runs in and -? behaves differently (at least in the set of shells we're talking about) depending on the contents of the current working directory. So using it as a command line option opens the door to obscure and weird bugs that are hard to figure out. – Tom Barron Jan 16 '18 at 18:10
-
Thanks for the interesting hints. I have no experiance with zsh. I use a mixture of bash, os-x and the windows 7 terminal. My anti-example is tar. This veteran understands -? and it doesn't understand -h and I grew up with that;-) My second example is python. It supports both. That shows to me that -? or -h is a preference of the developer. I would like to support both so that. – Kağan Kayal Jan 19 '18 at 12:41
-
Actually, to my understanding, the questionmark alone has a special meaning. 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 that there is 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. – Kağan Kayal Jan 19 '18 at 13:11
-
@KağanKayal: In bash on Mac OS X, if I do "touch -- -a; ls -?" I get the same output as "ls -a". (If you want to remove the '-a' file, you can do 'rm -- -a'.) – Tom Barron Jan 20 '18 at 17:25