Skip to content

Positional is treated as a sub-command #1022

@gon1332

Description

@gon1332

CLI11: Version 2.4.1

I have this setup:

int main() {
    CLI::App cli{};
    cli.set_help_flag();
    cli.add_subcommand("foo", "Does foo")->parse_complete_callback([&](){std::cout << "=== Foo doing foo" << std::endl;});
    cli.add_subcommand("bar", "Does bar")->parse_complete_callback([&](){std::cout << "=== Bar doing bar" << std::endl;});
    auto *help_cmd = cli.add_subcommand("help", "Does help");
    std::string help_for_command;
    auto *help_opt = help_cmd->add_option("command", help_for_command, "Command to print help for")->expected(0, 1);
    help_cmd->parse_complete_callback([&]() {
            if (*help_opt) {
                std::cout << "Print help for " << help_for_command << std::endl;
            } else {
                CLI::Formatter fmt{};
                std::cout << fmt.make_help(&cli, "", CLI::AppFormatMode::Normal) << std::endl;
            }
    });

    std::cout << "=> " << std::flush;
    for (std::string line; std::getline(std::cin, line);) {
        try {
            cli.parse(line);
        } catch (const CLI::ParseError &e) {
            std::cout << e.what() << std::endl;
            std::cout << cli.help();
        }
        std::cout << "=> " << std::flush;
    }
}

Given the above setup, here are some behaviors that I expect:

Scenario 1
When help is called without arguments
Then the help string of all commands is printed

Scenario 2
When help is called with one argument
And   the argument is a registered (sub)command
Then the help string of this command is printed

Scenario 3
When help is called with one argument
And   the argument is not a registered (sub)command
Then the help string of all commands is printed

However, I get the below output for each scenario:

Scenario 1 🟢

=>help
 help
Usage: [SUBCOMMAND]

Subcommands:
  foo                         Does foo
  bar                         Does bar
  help                        Does help

=>

Scenario 2 🔴
Not only the positional is not recognised, it is executed as a sucommand.

=>help foo
 help foo
Usage: [SUBCOMMAND]

Subcommands:
  foo                         Does foo
  bar                         Does bar
  help                        Does help

=== Foo doing foo
=>
=>help help
 help help
Usage: [SUBCOMMAND]

Subcommands:
  foo                         Does foo
  bar                         Does bar
  help                        Does help

Usage: [SUBCOMMAND]

Subcommands:
  foo                         Does foo
  bar                         Does bar
  help                        Does help

=>

Scenario 3 🔴

=>help other
 help other
Usage: [SUBCOMMAND]

Subcommands:
  foo                         Does foo
  bar                         Does bar
  help                        Does help

The following argument was not expected: other
Does help
Usage: help [command]

Positionals:
  command TEXT                Command to print help for

I've tried using fallthrough(false) for help command, but with no luck.
How could I implement my use case?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions