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

Allow final argument to be a command #278

Closed
Diggsey opened this issue Sep 24, 2015 · 10 comments
Closed

Allow final argument to be a command #278

Diggsey opened this issue Sep 24, 2015 · 10 comments
Labels
A-parsing Area: Parser's logic and needs it changed somehow.
Milestone

Comments

@Diggsey
Copy link

Diggsey commented Sep 24, 2015

AFAICT, it's not possible to define a CLI such as the following:
myprogram <arg> <command>

Here, command may include any number of arguments or flags, which clap should not attempt to interpret.

The first argument which does not begin with -, when all positional arguments have already been encountered, indicates the start of the command, and all subsequent arguments will be passed-through unchanged.

Alternatively, if -- occurred previously, and all positional arguments have already been encountered, then the next argument, regardless of whether it starts with -, indicates the start of the command.

eg.
myprogram a -t b - Error, -t is not recognised
myprogram -- a -t b - Valid, command is -t b
myprogram a - Error: no command present (if command is a required arg)
myprogram a b -t - Valid, command is b -t

@sru
Copy link
Contributor

sru commented Sep 25, 2015

@Diggsey is it possible to pass the command as one argument? i.e. using double quotes

Currently, Clap cannot allow the final argument to have the rest of argument to pass off as one argument.

We could also expose the arguments the are left over as extra.

@Diggsey
Copy link
Author

Diggsey commented Sep 25, 2015

Is it possible to pass the command as one argument? i.e. using double quotes

No, that would make escaping too painful, and I'm trying to mirror an existing CLI.

Currently, Clap cannot allow the final argument to have the rest of argument to pass off as one argument.

That's why I opened the issue... Or do you mean it can't add support for that for some reason? I had a brief look at the parsing code and it didn't seem particularly problematic to add support for this.

@sru
Copy link
Contributor

sru commented Sep 25, 2015

I see. No, I think it should be easy to add support for this.

@kbknapp
Copy link
Member

kbknapp commented Sep 25, 2015

This is already somewhat possible with --.

Example:

let m = App::new("test").arg_from_usage("<cmd>... 'some cmd'").get_matches();
if let Some(v) = m.values_of("cmd") {
    for cmd in v {
        println!("{}", cmd);
    }
}

Then running

$ test -- some -a -t cmd this that --long=this --testing
some
-a
-t
cmd
this
that
--long=this
--testing

@kbknapp
Copy link
Member

kbknapp commented Sep 29, 2015

@Diggsey is the current -- enough for your usage? If so, we can close this issue.

I am hesitant to add special case rules for this problem set which I would imagine is a rare case. Reason being, there may be cases when a user typos more positional than expected, and to have it automatically start parsing as a command could have very undesirable results.

I'm not saying we wouldn't add it, but that we'd need to discuss the implementation before-hand.

@kbknapp kbknapp added T: RFC / question S-waiting-on-decision Status: Waiting on a go/no-go before implementing A-parsing Area: Parser's logic and needs it changed somehow. labels Sep 29, 2015
@Diggsey
Copy link
Author

Diggsey commented Sep 29, 2015

is the current -- enough for your usage? If so, we can close this issue.

Not really - for the moment I've worked around it by detecting that case and intercepting it before I invoke clap.

there may be cases when a user typos more positional than expected, and to have it automatically start parsing as a command could have very undesirable results.

Presumably it would be opt-in: it would only start parsing as a command if the current subcommand expected to take a command as input.

@kbknapp
Copy link
Member

kbknapp commented Sep 29, 2015

Presumably it would be opt-in: it would only start parsing as a command if the current subcommand expected to take a command as input.

I'm OK with it being an opt-in setting. I'll set this for the 1.4.4 release, since it may take a little more time to implement.

@kbknapp kbknapp added T: new feature and removed T: RFC / question S-waiting-on-decision Status: Waiting on a go/no-go before implementing labels Sep 29, 2015
@kbknapp kbknapp added this to the 1.4.4 milestone Sep 29, 2015
@kbknapp
Copy link
Member

kbknapp commented Oct 1, 2015

Here's the implementation that #301 contains:

Using the AppSettings::TrailingVarArg setting enables:

  • Final positional argument "eats" all other arguments without the need for --
extern crate clap;

use clap::{App, AppSettings};

fn main() {
    let m = App::new("test")
        .setting(AppSettings::TrailingVarArg)
        .args_from_usage(
         "[arg1]         'some arg'
          [CMD]...       'arguments to pass to the CMD'")
        .get_matches();
    for a in m.values_of("CMD").unwrap() {
        println!("{}", a);
    }
}

Running with:

$ test some_arg cmd -H 20 --long value
cmd
-H
20
--long
value

The initial arg1 is just to show that it works even with other positional args defined.

@Diggsey @matklad

IF THIS DOES NOT SOLVE THIS ISSUE: let me know so that we can fix before the merge. One caveat, is I don't want to special case too heavily if there are things that can be done in downstream code.

@kbknapp kbknapp mentioned this issue Oct 1, 2015
@Diggsey
Copy link
Author

Diggsey commented Oct 1, 2015

@kbknapp Wow that looks perfect, thanks. Feel free to close this when those changes get merged in.

@kbknapp
Copy link
Member

kbknapp commented Oct 1, 2015

@Diggsey will do, let us know if you have any issues 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-parsing Area: Parser's logic and needs it changed somehow.
Projects
None yet
Development

No branches or pull requests

3 participants