Kağan Kayal
Kağan Kayal

Reputation: 2463

Is there a way to make clap treat -? the same way as -h?

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?

Upvotes: 2

Views: 962

Answers (3)

Kağan Kayal
Kağan Kayal

Reputation: 2463

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...
}

Upvotes: 2

Tom Barron
Tom Barron

Reputation: 1594

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 "-?"
-?

Upvotes: -1

Francis Gagné
Francis Gagné

Reputation: 65832

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.

Upvotes: 0

Related Questions