These are chat archives for kbknapp/clap-rs

13th
Sep 2017
Jon Gjengset
@jonhoo
Sep 13 2017 15:30
Hey all \o/
I'm trying to do something that turns out to be a little finicky
Specifically, I'm writing a replacement for the time command, and I want my arguments to work similar to the following:
time [flags and options for time] command [ARGS]...

in particular, I'd like the following to be different:

time -x foo
time foo -x

the former should set the x flag in time, the second should include -x in ARGS. commandshould be "foo" in both cases

I can emulate this behavior by setting AllowExternalSubcommand, but that means command [ARGS]... doesn't appear in the usage string
but any attempt to use TrailingVarArg + allow_hyphen_values has failed me
Jon Gjengset
@jonhoo
Sep 13 2017 15:36
the closest I've gotten is to use TrailingVarArg + allow_hyphen_values and make command and args a single positional Arg with multiple(true)
but that again makes the usage string look weird
Jon Gjengset
@jonhoo
Sep 13 2017 16:19

while I'm here... I've also wanted the ability to have an option that takes an optional value combined with require_equals. Thus:

time -d

and

time -d foo

should both give the default value for d, whereas

time -d=x
time -d=x foo

should both give d = x. Is that possible?

Denis Lisov
@tanriol
Sep 13 2017 16:23
@jonhoo This one seems to work for the first part, no?
Jon Gjengset
@jonhoo
Sep 13 2017 16:34
@tanriol hmm, not quite. try either of the following:
#[test]
fn test_no_args() {
    let m = make_parser()
        .get_matches_from(vec!["time", "-x", "nop"]);

    assert_eq!(m.is_present("exclusive"), true);
    assert_eq!(m.value_of("cmd").unwrap(), "nop");
    assert_eq!(
        m.values_of("args").unwrap().count(),
        0);
}

#[test]
fn test_only_opt_arg() {
    let m = make_parser()
        .get_matches_from(vec!["time", "nop", "-x"]);

    assert_eq!(m.is_present("exclusive"), false);
    assert_eq!(m.value_of("cmd").unwrap(), "nop");
    assert_eq!(
        m.values_of("args").unwrap().collect::<Vec<_>>(),
        ["-x"]);
}
Kevin K.
@kbknapp
Sep 13 2017 16:44
I'm taking a look at it now too
Jon Gjengset
@jonhoo
Sep 13 2017 16:49
@kbknapp thanks! much appreciated :)
Jon Gjengset
@jonhoo
Sep 13 2017 17:01
you can see the workaround I'm currently using at https://github.com/jonhoo/tally/blob/master/src/main.rs#L94-L101
Kevin K.
@kbknapp
Sep 13 2017 17:23
In this case, it looks like the best option is to use that AllowExternalSubcommands. It may seem clunkier, but it's actually a much safer solution and catches any edge cases in a more clean manner
I've also used a custom usage string
Kevin K.
@kbknapp
Sep 13 2017 17:30
Also, it seems the require_equals(true).min_values(0) isn't working and is a bug! I can probably fix this pretty quick
Jon Gjengset
@jonhoo
Sep 13 2017 17:31
@kbknapp hmm, is there a way for me to also then hide the subcommands list in help?
because "cmd" isn't really a subcommand
in fact, why do I even then need to make a subcommand?
couldn't I just set TrailingVarArg for the whole App
oh, I guess it gives me automatic checking for the required command argument
Kevin K.
@kbknapp
Sep 13 2017 17:33
Yep! AppSettings::Hidden
Jon Gjengset
@jonhoo
Sep 13 2017 17:34
that still shows the SUBCOMMANDS list though
specifically, it shows help as a subcommand
Kevin K.
@kbknapp
Sep 13 2017 17:35
You could use TrailingVarArg to handle the whole thing, but since what you're probably doing is shelling out to another command anyway, it separates the parsing between the two commands (time and the external one) in a safer fashion
AppSettings::DisableHelpSubcommand
Jon Gjengset
@jonhoo
Sep 13 2017 17:37
now it shows:


SUBCOMMANDS:
:p
Kevin K.
@kbknapp
Sep 13 2017 17:38
haha :P Ok, then I'd either use a help template, or do the TrailingVarArg+custom usage string like you mentioned
with a template you can do away with the whole, AppSettings::Hidden part too
Jon Gjengset
@jonhoo
Sep 13 2017 17:40
hmm.. it's unfortunate to have to replicate the entire template though
I wonder why it doesn't detect that there aren't any subcommands...
Kevin K.
@kbknapp
Sep 13 2017 17:40
I agree
Jon Gjengset
@jonhoo
Sep 13 2017 17:40
seems like a bug, no?
Kevin K.
@kbknapp
Sep 13 2017 17:40
Technically there is one
but yes, I agree it's more of a logic bug
Jon Gjengset
@jonhoo
Sep 13 2017 17:41
true
Kevin K.
@kbknapp
Sep 13 2017 17:41
if all subcommands are hidden, the help sucommand probably shouldn't be displayed (nor SUBCOMMANDS: section)
Actually...this seems to work just fine :wink:
Jon Gjengset
@jonhoo
Sep 13 2017 17:43
ah, that's without the subcommand arg
Kevin K.
@kbknapp
Sep 13 2017 17:44
still using the external subcommand method, but no "dummy" subcommand
which also forgoes the SUBCOMMANDS: section
Jon Gjengset
@jonhoo
Sep 13 2017 17:44
yup
that's the solution I had earlier
.usage was what I needed :p
Kevin K.
@kbknapp
Sep 13 2017 17:44
ah, I must have misread that! Sorry haha
Jon Gjengset
@jonhoo
Sep 13 2017 17:44
no worries!
thanks for your help!
Kevin K.
@kbknapp
Sep 13 2017 17:45
No probs!
You could also add, after_help("ARGS: CMD the command to run ARGS... Args for CMD")
gitter didn't format that properaly
but basically emulate the "ARGS: section" but not actually adding those args
in order to match the usage string
Jon Gjengset
@jonhoo
Sep 13 2017 17:47
right
yeah, that's a good idea
Jon Gjengset
@jonhoo
Sep 13 2017 17:59
hmm.. if I set long_about, it never gets printed?
does setting usage or after_help impact that in any way?
Kevin K.
@kbknapp
Sep 13 2017 18:00
long_about only gets printed when one does --help
No, it shouldn't
Jon Gjengset
@jonhoo
Sep 13 2017 18:01
hmm, it doesn't get printed then either
ahh, --help and -h are different. I only realized that now. But it still doesn't print..
in fact, it never seems to get printed at all, even in this much shorter example: https://play.rust-lang.org/?gist=b339f356190a61dacadf2a5b885695ac&version=stable
Kevin K.
@kbknapp
Sep 13 2017 18:10
Yep I've confirmed, I'll fix it and release a new version
Jon Gjengset
@jonhoo
Sep 13 2017 18:19
:D
Kevin K.
@kbknapp
Sep 13 2017 18:25
Found the problem, and it's fixed. Just running tests now and I'll put in the PR
Jon Gjengset
@jonhoo
Sep 13 2017 18:30
Great!
Kevin K.
@kbknapp
Sep 13 2017 20:40
#1045
Jon Gjengset
@jonhoo
Sep 13 2017 21:51
@kbknapp how does the .min_values(0) change interact with default_value?
as in, if I have a default value set, can I figure out whether the user passed the option or not? and if they do, but without a value, does the empty value then overwrite the default?