PicoCLI:依赖性和排他性参数混合

PicoCLI: Dependent and Exclusive Arguments mixed

我正在尝试使用 PicoCLI 实现如下目标:

我不知道我是否可以使用 PicoCLI 工具进行此设置,或者我是否可以在使用自定义代码解析后进行检查。

对于这种情况,选项 A 在需要选项 A 的 ArgGroup 中,但选项 A-* 不是。 选项 B 在不同的 ArgGroup 中。我试图设置一些独占的东西,但我不知道如何 ArgGroup/Exclusive 东西按预期工作...

有什么提示吗?

总结这些选项需要具备的关系:

  1. -B-A1-A2-A3 需要 -A 选项
  2. -B 不允许任何-A1-A2-A3选项
  3. -A1-A2-A3 选项允许彼此
  4. -A选项允许(但不要求)-B-A1-A2-A3 选项

单独的 picocli 注释不足以以声明的方式表达所有这些关系,一些自定义验证是必要的。

所以我们不妨简化并创建一个参数组,因为我们不能同时表达要求 2(-B 与 -A1、-A2、-A3 互斥)与要求 1 和 3(- B、-A1、-A2、-A3都需要-A,-A1、-A2、-A3相互允许。

[-A [-B] [-A1] [-A2] [-A3]] 这样的单个组将负责一些验证:除了要求 2 之外的所有内容(-B 与 -A1、-A2、-A3 互斥)。对于要求 2,我们需要在应用程序中编写一些自定义验证代码(下面的示例)。

对于您的用例,拥有一个能够准确反映选项之间关系的自定义概要可能会很有用。像这样:

Usage: app [-hV] [-A [-B]]
       app [-hV] [-A [-A1] [-A2] [-A3]]

实现此目的的示例代码:

import picocli.CommandLine;
import picocli.CommandLine.*;
import picocli.CommandLine.Model.CommandSpec;

@Command(name = "app", mixinStandardHelpOptions = true,
        synopsisHeading = "",
        customSynopsis = {
            "Usage: app [-hV] [-A [-B]]",
            "       app [-hV] [-A [-A1] [-A2] [-A3]]",
        })
public class App implements Runnable {
    static class MyGroup {
        @Option(names = "-A", required = true) boolean a;
        @Option(names = "-B") boolean b;
        @Option(names = "-A1") boolean a1;
        @Option(names = "-A2") boolean a2;
        @Option(names = "-A3") boolean a3;

        boolean isInvalid() {
            return b && (a1 || a2 || a3);
        }
    }

    @ArgGroup(exclusive = false)
    MyGroup myGroup;

    @Spec CommandSpec spec;

    public void run() {
        if (myGroup != null && myGroup.isInvalid()) {
            String msg = "Option -B is mutually exclusive with -A1, -A2 and -A3";
            throw new ParameterException(spec.commandLine(), msg);
        }
        System.out.printf("OK: %s%n", spec.commandLine().getParseResult().originalArgs());
    }

    public static void main(String[] args) {
        //new CommandLine(new App()).usage(System.out);

        //test: these are all valid
        new CommandLine(new App()).execute();
        new CommandLine(new App()).execute("-A -B".split(" "));

        // requires validation in the application to disallow
        new CommandLine(new App()).execute("-A -B -A1".split(" "));

        // picocli validates this, gives: "Error: Missing required argument(s): -A"
        new CommandLine(new App()).execute("-B -A1".split(" "));
    }
}