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

Consider providing API for modifying the model at initialization #1259

Closed
remkop opened this issue Nov 13, 2020 · 4 comments · Fixed by #1266
Closed

Consider providing API for modifying the model at initialization #1259

remkop opened this issue Nov 13, 2020 · 4 comments · Fixed by #1266
Milestone

Comments

@remkop
Copy link
Owner

remkop commented Nov 13, 2020

This is a follow-up ticket from discussion on #1256 and #1217.

The use case raised by @MarkoMackic is as follows (Marko, please comment if I missed anything):

  • At model construction time, we want the ability to modify the model, based on some runtime environment information (system properties, environment variables, configuration files, etc.). One example is the ability to include or exclude some subcommand based on a system property.
  • We prefer to use the annotation API because of its ease of use, rather than constructing the model using the programmatic API.
  • We want to do this modification at model construction/initialization time, so that this modified model can be used by other components like generating man pages and generating shell completion scripts.

My initial reaction is that this is already possible with code like this:

static CommandLine createDynamicallyModifiedCommand() {
    CommandLine result = new CommandLine(new MyApp());
    if (someCondition()) { // could be a system property or something else
        result.getCommandSpec().subcommands().get("a")
                 .getCommandSpec().subcommands().get("b")
                 .removeSubcommand("c");
    }
    return result;
}

// runs MyApp
public static void main(String... args) {
    System.exit(createDynamicallyModifiedCommand().execute(args));
}

// generates man pages for MyApp
static class MyManPageGenerator implements Callable<Integer> {
        @Option(names = {"-d", "--outdir"}, defaultValue = ".", paramLabel = "<outdir>",
                description = {"Output directory to write the generated AsciiDoc files to. " +
                        "If not specified, files are written to the current directory."})
        File outdir;

        @Option(names = {"-v", "--verbose"},
                description = {
                        "Specify multiple -v options to increase verbosity.",
                        "For example, `-v -v -v` or `-vvv`"})
        boolean[] verbosity = new boolean[0];

    public Integer call() throws Exception {
        CommandSpec spec = createDynamicallyModifiedCommand().getCommandSpec();
        ManPageGenerator.generateManPage(outdir, null, verbosity, false, spec);
    }

    public static void main(String... args) throws Exception {
        new CommandLine(new MyManPageGenerator()).execute(args);
    }
}

@MarkoMackic can you clarify why the above is unsatisfactory and what you would like to see instead?

@MarkoMackic
Copy link
Contributor

So there is a single issue I see with this approach, the use case is possible, but it's centralized and not context aware ( e.g. all subcommands must be removed from root of command line ) , actually I though more about removing subcommands from a command that declares it. I'll do some initial implementation with preprocessors ( the preprocessor method will be called during model build time ), and than we'll have more concrete definition of how I picture it.

@MarkoMackic
Copy link
Contributor

Sorry for stalling on this, I'm currently busy, when I have spare time, I'll look into this.

@remkop
Copy link
Owner Author

remkop commented Nov 25, 2020

@MarkoMackic not at all, take your time!
From my point of view, people already have a way to achieve this, so we are simply considering if and how to fine-tune this. No rush!

@MarkoMackic
Copy link
Contributor

@remkop I finished inital proposal, now I need feedback. But you'll get the usecase from the tests.

@remkop remkop added this to the 4.6 milestone Dec 2, 2020
remkop added a commit that referenced this issue Dec 14, 2020
MarkoMackic pushed a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic pushed a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic added a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic added a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic added a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
MarkoMackic added a commit to MarkoMackic/picocli that referenced this issue Oct 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants