使用 Picocli 创建 Java 命令行程序

使用 Picocli 创建 Java 命令行程序

Hello World 程序(快速入门)

创建maven项目,使用依赖

<dependency>
    <groupId>info.picocli</groupId>
    <artifactId>picocli</artifactId>
    <version>4.7.0</version>
</dependency>

在命令类名上添加 @Command 注释,可以通过namedescription 指明相关属性。

@CommandLine.Command(name = "hello", description = "say hello")
public class HelloWorldCommand{
}

要能够使用命令,首先要在主程序中添加main方法,并在main方法中调用CommandLine.run(Runnable, String[]) 方法,第一个是传入我们的命令类,因此需要继承Runnable类,并在run()方法中编写需要执行的代码;第二个则传入主函数接收到的参数args。

@CommandLine.Command(name = "hello", description = "say hello")
public class HelloWorldCommand implements Runnable{

    public static void main(String[] args) {
        CommandLine.run(new HelloWorldCommand(), args);
    }

    @Override
    public void run() {
        System.out.println("Hello Word Command");
    }
}

运行主函数,会打印出 Hello Word Command

具体使用

这里我们以实现类似git命令的效果为例

先创建一个GitCommand.class

@CommandLine.Command
public class GitCommand implements Runnable{
    public static void main(String[] args) {
        CommandLine.run(GitCommand, args);
    }

    @Override
    public void run() {
        System.out.println("常见的git命令");
    }

}

添加子命令

在子命令类上添加@Command注释

@Command注释中添加subcommands属性,在属性中写明子类。

@Command(
  subcommands = {
      GitAddCommand.class,
      GitCommitCommand.class
  }
)

这里创建GitAddCommand.class以及GitCommitCommand.class两个子命令类。子命令类也要加上@Command注释。

@Command(
  name = "add"
)
public class GitAddCommand implements Runnable {
    @Override
    public void run() {
        System.out.println("提交文件到暂存区");
    }
}
@Command(
  name = "commit"
)
public class GitCommitCommand implements Runnable {
    @Override
    public void run() {
        System.out.println("将缓存区的文件提交到仓库");
    }
}

在方法上添加@Command注释

@Command(name = "add")
public void addCommand() {
    System.out.println("提交文件到暂存区");
}

@Command(name = "commit")
public void commitCommand() {
    System.out.println("将缓存区的文件提交到仓库");
}

以编程方式添加子命令

CommandLine commandLine = new CommandLine(new GitCommand());
commandLine.addSubcommand("add", new GitAddCommand());
commandLine.addSubcommand("commit", new GitCommitCommand());

不再使用CommandLine.run(),而是使用commandLine.parseWithHandler();

commandLine.parseWithHandler(new RunLast(), args);

parseWithHandler会解析命令行参数,处理错误等,RunLast()会确保只有在参数正确解析后才会执行run()方法。

添加选项

无参数选项

想要实现的效果:在add中添加一个选项,在add后输入这个选项则添加所有文件,没有这个选项则添加部分文件

使用@Option

@Option(names = {"-A", "--all"})
private boolean allFiles;

@Override
public void run() {
    if (allFiles) {
        System.out.println("添加所有文件到暂存区");
    } else {
        System.out.println("添加某些文件到暂存区");
    }
}

只要在add命令后添加-A或者--all 即可打印"添加所有文件到暂存区"

add -A(-all)

有一个参数选项

想要实现的效果:在commit中添加一个备注选项,在输入该选项后并输入参数

@Option(names = {"-m", "--message"})
private String message;

@Override
public void run() {
    System.out.println("将缓存区的文件提交到仓库");
    if (message != null) {
        System.out.println("备注内容是" + message);
    }
}

命令示例:

commit -m xxx

有多个参数选项

想要实现的效果:在commit中添加一个备注选项,在输入该选项后并输入一些参数

@Option(names = {"-m", "--message"})
private String[] messages;

@Override
public void run() {
    System.out.println("将缓存区的文件提交到仓库");
    if (messages != null) {
        System.out.println("备注内容是");
        for (String message : messages) {
            System.out.println(message);
        }
    }
}

命令示例:

commit -m xxx -m xxx

可以使用split属性,就不需要写多个-m了

@Option(names = {"-m", "--message"}, split = ",")
private String[] messages;

命令示例:

commit -m xxx,xxx,xxx

必须选项

required属性赋值为true,则在输入命令时必须带上该选项

@Option(names = {"-m", "--message"}, required = true)
private String[] messages;

在使用commit时,如果不带-m,则会报错

管理位置参数

捕获位置参数

位置参数可以捕获特定位置的参数,比如,我想在add命令中增加一个功能,如果在add命令后继续输入某文件的位置,则会将这些文件添加到暂存区

使用@Parameters注释

@Parameters
private List<Path> files;

@Override
public void run() {
    if (allFiles) {
        System.out.println("添加所有文件到暂存区");
    }

    if (files != null) {
        files.forEach(path -> System.out.println("添加文件 " + path + " 到暂存区"));
    }
}

命令示例:

add file1 file2...
posted @ 2024-09-11 09:50  forest-pan  阅读(13)  评论(0编辑  收藏  举报