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

Repeatable subcommands problem with programmatic configuration (was: How to run subcommands together) #1144

Closed
ErikDeveloperJava opened this issue Aug 12, 2020 · 10 comments

Comments

@ErikDeveloperJava
Copy link

I need to run subcommands together.
I have three main commands which starts so and which have their subcommands and options

  1. -i --instance ...
  2. -val --validate ...
  3. -g --generate ...
    and I need to that they will be together
    I tried to write with subcommands of picocli
    library but I had such problem. Picocli let me to run commands seperately but not together like this
    -i --instance ... -v --validate ... -g --generate
    Is it possible run these commands together using
    subcommands of Picocli?
@remkop
Copy link
Owner

remkop commented Aug 12, 2020

You may be looking for Repeatable Subcommands.

You enable this feature like this:

@Command(name = "myapp", subcommandsRepeatable = true)
...

The manual has more details and an example.
Does this meet your requirements?

@ErikDeveloperJava
Copy link
Author

I have just tried to add subcommandsRepeatable = true to my root command
and It works as I expected
thank you very much for aid

@remkop
Copy link
Owner

remkop commented Aug 12, 2020

Glad to hear that solved the issue!
Enjoy picocli!

Don't forget to give the project a star on GitHub and tell your friends! 😜

@remkop remkop closed this as completed Aug 12, 2020
@ErikDeveloperJava
Copy link
Author

Picocli doesn't understand subcommand of subcommand
I have such structure

  1. load commnad -l ...
  2. validate command -v .. and this has file validation sub command -fv
  3. generate command -g
    I wrote so
    CommandLine commandLine = new CommandLine(new MainCommand());
    commandLine
    .addSubcommand("-l",new LoadCommand())
    .addSubcommand("-g",new GenerateCommand())
    .addSubcommand("-v", new CommandLine(new ValidateCommand())
    .addSubcommand("-fv",new FileValidationCommand()));
    everything worked fine till ading -fv sub command for validation command
    now it says Unknown options: '-g',.. for all generation command options
    please help

@remkop
Copy link
Owner

remkop commented Aug 12, 2020

I was able to reproduce the issue.
There is a bug in the Repeatable Subcommands implementation that results in subcommands not being copied correctly...

Programmatic configuration does not work correctly, DON'T DO THIS:

        cmd
                .addSubcommand("-l",new LoadCommand())
                .addSubcommand("-g",new GenerateCommand())
                .addSubcommand("-v", new CommandLine(new ValidateCommand())
                        .addSubcommand("-fv",new FileValidationCommand()));

instead, do this:

@Command(name = "myapp", subcommandsRepeatable = true,
   // PLEASE USE DECLARATIVE CONFIGURATION
   // (also for sub-subcommands, see ValidateCommand below)
   subcommands = {
           LoadCommand.class,
           GenerateCommand.class,
           ValidateCommand.class,
   })
public class MainCommand implements Runnable {
...

Below is a full example. I need to investigate on how exactly to fix this, but this workaround should help.

package picocli.examples.issue1144;

import picocli.CommandLine;
import picocli.CommandLine.Command;

import java.util.Arrays;

@Command(name = "myapp", subcommandsRepeatable = true,
   // PLEASE USE DECLARATIVE CONFIGURATION
   // (also for sub-subcommands, see ValidateCommand below)
   subcommands = {
           LoadCommand.class,
           GenerateCommand.class,
           ValidateCommand.class,
   },
   mixinStandardHelpOptions = true, version = "myapp 0.1")
public class MainCommand implements Runnable {
    @Override
    public void run() {
        System.out.println("Executing MainCommand");
    }

    public static void main(String[] ignored) {
        //System.setProperty("picocli.trace", "DEBUG");
        CommandLine cmd = new CommandLine(new MainCommand());

        // There is a bug in the Repeatable Subcommands implementation
        // that results in subcommands not being copied correctly...
        // Programmatic configuration does not work correctly, DON'T DO THIS:
//        cmd
//                .addSubcommand("-l",new LoadCommand())
//                .addSubcommand("-g",new GenerateCommand())
//                .addSubcommand("-v", new CommandLine(new ValidateCommand())
//                        .addSubcommand("-fv",new FileValidationCommand()));

        String[][] all = {
                {"-l"},
                {"-l", "-g"},
                {"-l", "-g", "-v"},
                {"-l", "-g", "-v", "-fv"},
        };
        for (String[] args : all) {
            System.out.println(Arrays.toString(args));
            cmd.execute(args);
            System.out.println();
        }
    }
}
@Command(name = "-l")
class LoadCommand implements Runnable {
    @Override
    public void run() {
        System.out.println("Executing LoadCommand");
    }
}
@Command(name = "-g")
class GenerateCommand implements Runnable {
    @Override
    public void run() {
        System.out.println("Executing GenerateCommand");
    }
}
@Command(name = "-v", subcommands = {
        // ALSO USE DECLARATIVE CONFIGURATION HERE
        FileValidationCommand.class
})
class ValidateCommand implements Runnable {
    @Override
    public void run() {
        System.out.println("Executing ValidateCommand");
    }
}
@Command(name = "-fv")
class FileValidationCommand implements Runnable {
    @Override
    public void run() {
        System.out.println("Executing FileValidationCommand");
    }
}

@remkop remkop added this to the 4.6 milestone Aug 12, 2020
@ErikDeveloperJava
Copy link
Author

thank you for quick answer
This example works so
but When I added one option in FileValidationCommand
and run args so "-l","-v", "-fv","-m","1", "-g"
It didn't recognize -g option again
I need to add sub commands in generate command too yet
Is this a bug too?

@remkop
Copy link
Owner

remkop commented Aug 12, 2020

No, this is not a bug; this is the expected behaviour.

Please see repeatable subcommands specification, specifically Figure 2, and the explanation following that figure:

Note that it is not valid to specify a subcommand followed by its parent command.

One way to resolve this is to rethink/redesign your command hierarchy. Does -fv need to be a subcommand of -v?

Another idea is to look at Argument Groups. Could your commands be modeled as argument groups instead of subcommands? They do “look like” options a bit since they have a - dash prefix, but perhaps that is just my preconception.

@ErikDeveloperJava
Copy link
Author

thanks again
I will look at Argument Groups and if I have any question I will write you
thank you very much

@remkop
Copy link
Owner

remkop commented Aug 12, 2020

No worries!

Please star ⭐️ picocli on GitHub 😅
and tell your friends!

@remkop remkop changed the title How to run subcommands together Repeatable subcommands problem with programmatic configuration (was: How to run subcommands together) Aug 12, 2020
@remkop remkop modified the milestones: 4.5.2, 4.6 Oct 14, 2020
@remkop remkop modified the milestones: 4.6, 4.7 Nov 9, 2020
@remkop remkop added the status: duplicate 👨🏻‍🤝‍👨🏻 A duplicate of another issue label Dec 30, 2020
@remkop
Copy link
Owner

remkop commented Dec 30, 2020

Closing this one: the problem of combining repeatable subcommands with the programmatic API is already tracked in a separate ticket: #1010.

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

No branches or pull requests

2 participants