Ver*_*tex 3 java command-line-interface picocli
由于子命令支持(和基于注释的声明),我从 Apache Commons CLI 切换到 Picocli。
考虑一个像 这样的命令行工具git,带有像 这样的子命令push。Git 有一个主开关--verbose或-v用于在所有子命令中启用详细模式。如何实现在任何子命令之前执行的主开关?
这是我的测试
@CommandLine.Command(name = "push",
description = "Update remote refs along with associated objects")
class PushCommand implements Callable<Void> {
@Override
public Void call() throws Exception {
System.out.println("#PushCommand.call");
return null;
}
}
@CommandLine.Command(description = "Version control", subcommands = {PushCommand.class})
public class GitApp implements Callable<Void> {
@CommandLine.Option(names = {"-h", "--help"}, usageHelp = true, description = "Display this help message.")
private boolean usageHelpRequested;
@CommandLine.Option(names = {"-v", "--verbose"}, description = "Verbose mode. Helpful for troubleshooting.")
private boolean verboseMode;
public static void main(String[] args) {
GitApp app = new GitApp();
CommandLine.call(app, "--verbose", "push");
System.out.println("#GitApp.main after. verbose: " + (app.verboseMode));
}
@Override
public Void call() throws Exception {
System.out.println("#GitApp.call");
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
输出是
#PushCommand.call
#GitApp.main after. verbose: true
Run Code Online (Sandbox Code Playgroud)
我希望GitApp.call在子命令被调用之前被调用。但只有子命令被调用。
CommandLine.call(和)方法CommandLine.run仅根据设计调用最后一个子命令,因此您在原始帖子中看到的是预期的行为。
和方法实际上是一个快捷方式call。run以下两行是等效的:
CommandLine.run(callable, args); // internally uses RunLast, equivalent to:
new CommandLine(callable).parseWithHandler(new RunLast(), args);
Run Code Online (Sandbox Code Playgroud)
更新:从 picocli 4.0 开始,上述方法已被弃用,并替换为
new CommandLine(myapp).execute(args). “处理程序”现在称为“执行策略”(下面的示例)。
还有一个RunAll处理程序运行所有匹配的命令。以下main方法给出了所需的行为:
public static void main(String[] args) {
args = new String[] { "--verbose", "push" };
GitApp app = new GitApp();
// before picocli 4.0:
new CommandLine(app).parseWithHandler(new RunAll(), args);
// from picocli 4.0:
//new CommandLine(app).setExecutionStrategy(new RunAll()).execute(args);
System.out.println("#GitApp.main after. verbose: " + (app.verboseMode));
}
Run Code Online (Sandbox Code Playgroud)
输出:
#GitApp.call
#PushCommand.call
#GitApp.main after. verbose: true
Run Code Online (Sandbox Code Playgroud)
您可能还对注释感兴趣@ParentCommand。这告诉 picocli 将父命令的实例注入子命令中。然后,您的子命令可以调用父命令上的方法,例如检查是否verbose为 true。例如:
更新:从 picocli 4.0 开始,使用
setExecutionStrategy方法来指定RunAll. 以下示例已更新为使用新的 picocli 4.0+ API。
import picocli.CommandLine;
import picocli.CommandLine.*;
@Command(name = "push",
description = "Update remote refs along with associated objects")
class PushCommand implements Runnable {
@ParentCommand // picocli injects the parent instance
private GitApp parentCommand;
public void run() {
System.out.printf("#PushCommand.call: parent.verbose=%s%n",
parentCommand.verboseMode); // use parent instance
}
}
@Command(description = "Version control",
mixinStandardHelpOptions = true, // auto-include --help and --version
subcommands = {PushCommand.class,
HelpCommand.class}) // built-in help subcommand
public class GitApp implements Runnable {
@Option(names = {"-v", "--verbose"},
description = "Verbose mode. Helpful for troubleshooting.")
boolean verboseMode;
public void run() {
System.out.println("#GitApp.call");
}
public static void main(String[] args) {
args = new String[] { "--verbose", "push" };
GitApp app = new GitApp();
int exitCode = new CommandLine(app)
.setExecutionStrategy(new RunAll())
.execute(args);
System.out.println("#GitApp.main after. verbose: " + (app.verboseMode));
System.exit(exitCode);
}
}
Run Code Online (Sandbox Code Playgroud)
其他小的编辑:通过导入内部类使注释更加紧凑。您可能还喜欢有助于减少样板代码的mixinStandardHelpOptions属性和内置子命令。help
| 归档时间: |
|
| 查看次数: |
3454 次 |
| 最近记录: |