Skip to content
This repository has been archived by the owner on Jan 1, 2022. It is now read-only.

Parse arguments before or after subcommands ambivalently #245

Open
2 tasks done
epage opened this issue Dec 6, 2021 · 1 comment
Open
2 tasks done

Parse arguments before or after subcommands ambivalently #245

epage opened this issue Dec 6, 2021 · 1 comment

Comments

@epage
Copy link
Owner

epage commented Dec 6, 2021

Issue by 9999years
Thursday Dec 02, 2021 at 21:14 GMT
Originally opened as clap-rs/clap#3056


Please complete the following tasks

  • I have searched the discussions
  • I have searched the existing issues

Clap Version

2.34, but I don't think this is a feature in 3.0 either.

Describe your use case

I'd like to be able to pass args at any position before or after subcommands. This is a quality-of-live improvement for users of command-line tools.

Consider the following App:

use clap::{App, Arg, Subcommand};
App::new("prog")
    .arg(Arg::with_name("a").short("a"))
    .subcommand(SubCommand::with_name("cmd").arg(Arg::with_name("b").short("b")))

prog -a cmd -b will parse, but prog -a -b cmd and prog cmd -a -b will not. In my opinion, this makes the command-line interface more cumbersome:

  • In the shell, it's harder to work on a previous command by hitting ^P and adding options to the end -- you have to know what level the option can be set at and insert it at the correct place in the command line
  • Requiring arguments at a certain position doesn't enable a compelling use-case -- I don't like the idea of a CLI where prog -a cmd and prog cmd -a mean different things

Describe the solution you'd like

Adding a clap::AppSettings variant seems like the natural way to alter parsing behavior:

App::new("prog")
    .setting(AppSettings::ArgsBeforeOrAfterSubcommands)
    // ...

Alternatives, if applicable

A more granular API could use an ArgSettings instead:

App::new("prog")
    .arg(Arg::with_name("a").short("a").set(ArgSettings::BeforeOrAfterSubcommands))

Additional Context

I'm not familiar with clap's implementation, and it occurs to me that the parser might be structured such that it would be difficult or resource-intensive to alter the parser to recognize subcommand args before the subcommand token itself.

The parser would have to know about and check all the subcommand-args before parsing, or otherwise determine which subcommand is going to be used -- which I think may be tricky, because determining if bar is a subcommand in prog --foo bar would require knowing if --foo takes a value or not.

This change would also make certain patterns that are currently allowed ambiguous, such as having a top-level argument and a subcommand argument with the same name (and impossible to parse if, for example, one takes a value and the other doesn't).

My immediate questions about this feature request are:

  • Would it be possible to add this to clap?
  • Would this feature be allowed in clap, in light of the above complications?
  • Should I work on a PR to implement this functionality?
@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by epage
Thursday Dec 02, 2021 at 21:26 GMT


While not quite what you are asking for,

  • Clap does have Arg::global for saying a top-level argument can exist within subcommands
  • You could skip clap's built-in subcommand support and define all of your arguments at the top level and have a positional argument that is your "subcommand". You could even get some validation working with required_if, conflicts_with, etc. In clap3 we also expose a App::error for custom validation to report errors like clap does.

(leaving it to others to weigh in on whether this is desirable or not)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant