Apache Groovy 2.5中更新了用于快速简洁地构建命令行应用程序的CliBuilder
类。
这篇分为两部分的文章重点介绍了新功能。
第2部分将说明如何利用CliBuilder的基础库的某些高级功能。
以前的CliBuilder版本使用Apache Commons CLI作为基础解析器库。 从Groovy 2.5开始,有一个基于picocli解析器的CliBuilder的替代版本。
展望未来,建议应用程序显式导入groovy.cli.picocli.CliBuilder
或groovy.cli.commons.CliBuilder
。 groovy.util.CliBuilder
类已弃用,并委托Commons CLI版本以实现向后兼容。
新功能可能只会添加到picocli版本中,并且Groovy的未来版本中可能会删除groovy.util.CliBuilder
。 Commons CLI版本适用于依赖CliBuilder Commons CLI实现内部的应用程序,并且无法轻松迁移到picocli版本。
接下来,让我们看一下Groovy 2.5 CliBuilder中的一些新功能。
打字选项
选项可以是布尔标志,也可以采用一个或多个选项参数。 在以前的CliBuilder版本中,您必须指定args: 1
表示需要一个参数的选项,或args: '+'
表示接受多个参数的选项。
此版本的CliBuilder添加了对类型化选项的支持。 这在处理解析结果时很方便,但是此外,从类型推断参数的数量,因此,如果指定了type
,则可以省略args
。
例如:
def cli = new CliBuilder()
cli.a(type: String, 'a-arg')
cli.b(type: boolean, 'b-arg')
cli.c(type: Boolean, 'c-arg')
cli.d(type: int, 'd-arg')
cli.e(type: Long, 'e-arg')
cli.f(type: Float, 'f-arg')
cli.g(type: BigDecimal, 'g-arg')
cli.h(type: File, 'h-arg')
cli.i(type: RoundingMode, 'i-arg')
def argz = '''-a John -b -d 21 -e 1980 -f 3.5 -g 3.14159
-h cv.txt -i DOWN and some more'''.split()
def options = cli.parse(argz)
assert options.a == 'John'
assert options.b
assert !options.c
assert options.d == 21
assert options.e == 1980L
assert options.f == 3.5f
assert options.g == 3.14159
assert options.h == new File('cv.txt')
assert options.i == RoundingMode.DOWN
assert options.arguments() == ['and', 'some', 'more']
支持的类型
基于Commons CLI的CliBuilder支持原语,数值类型,文件,枚举和数组(使用StringGroovyMethods#asType(String,Class) )。 基于picocli的CliBuilder支持以上功能 。
添加更多类型
如果内置类型不能满足您的需求,则可以轻松注册自定义转换器。 指定convert
闭包以将String参数转换为任何其他类型。 例如:
import java.nio.file.Paths
import java.time.LocalTime
def cli = new CliBuilder()
cli.a(convert: { it.toUpperCase() }, 'a-arg') (1)
cli.p(convert: { Paths.get(it) }, 'p-arg') (2)
cli.t(convert: { LocalTime.parse(it) }, 't-arg') (3)
def options = cli.parse('-a abc -p /usr/home -t 15:31:59'.split())
assert options.a == 'ABC'
assert options.p.absolute && options.p.parent == Paths.get('/usr')
assert options.t.hour == 15 && options.t.minute == 31
- 将一个字符串转换为另一个
- 选项值将转换为
java.nio.file.Path
- 选项值转换为
java.time.LocalTime
注解
从此发行版开始,Groovy提供了用于处理命令行参数的注释API。
应用程序可以使用@groovy.cli.Option
命名字段或方法来命名选项,使用@groovy.cli.Unparsed
位置参数。 当解析器将命令行参数与选项名称或位置参数匹配时,该值将转换为正确的类型并注入到字段或方法中。
接口的注释方法
使用批注的一种方法是在接口的“类似getter的”方法(返回值的方法)上。 例如:
import groovy.cli.*
interface IHello {
@Option(shortName='h', description='display usage') Boolean help() (1)
@Option(shortName='u', description='user name') String user() (2)
@Unparsed(description = 'positional parameters') List remaining() (3)
}
- 如果在命令行上指定了
-h
或--help
则方法返回true
。 - 方法返回为
-u
或--user
选项指定的参数值。 - 该方法会将所有剩余参数作为列表返回。
如何使用此界面(使用picocli版本演示其用法帮助):
import groovy.cli.picocli.CliBuilder
def cli = new CliBuilder(name: 'groovy Greeter')
def argz = '--user abc'.split()
IHello hello = cli.parseFromSpec(IHello, argz)
assert hello.user() == 'abc'
hello = cli.parseFromSpec(GreeterI, ['--help', 'Some', 'Other', 'Args'] as String[])
assert hello.help()
cli.usage()
assert hello.remaining() == ['Some', 'Other', 'Args']
这将打印以下用法帮助消息:
Usage: groovy Greeter [-h] [-u=<user>] [<remaining>...]
[<remaining>...] positional parameters
-u, --user=<user> user name
-h, --help display usage
调用parseFromSpec
, CliBuilder
读取注释,解析命令行参数并返回接口的实例。 接口方法返回在命令行上匹配的选项值。
注释类的属性或设置器方法
使用批注的另一种方法是在类的属性或“类设定者”方法(具有单个参数的void
方法)上。 例如:
class Hello {
@Option(shortName='h', description='display usage') (1)
Boolean help
private String user
@Option(shortName='u', description='user name') (2)
void setUser(String user) {
this.user = user
}
String getUser() { user }
@Unparsed(description = 'positional parameters') (3)
List remaining
}
-
- 在
help
布尔属性设置为true
,如果-h
或--help
在命令行上指定。 - 使用
-u
或--user
选项参数值调用setUser
属性setter方法。 -
remaining
属性设置为包含剩余args(如果有)的新List
。
- 在
带注释的类可以如下使用:
String[] argz = ['--user', 'abc', 'foo']
def cli = new CliBuilder(usage: 'groovy Greeter [option]') (1)
Hello greeter = cli.parseFromInstance(new Hello(), argz) (2)
assert greeter.user == 'abc' (3)
assert greeter.remaining == ['foo'] (4)
-
- 创建一个
CliBuilder
实例。 - 从带注释的实例中提取选项,解析参数,然后填充并返回提供的实例。
- 验证是否已将字符串选项值分配给该属性。
- 验证剩余的参数属性。
- 创建一个
调用parseFromInstance
, CliBuilder
再次读取注释,解析命令行参数,最后返回实例。 带注释的字段和设置方法使用与关联选项匹配的值进行初始化。
脚本注释
Groovy 2.5还为Groovy脚本提供了新的注释。
@OptionField
等同于组合@groovy.transform.Field
和@Option
,而@UnparsedField
等同于组合@Field
和@Unparsed
。
使用这些批注将脚本变量转换为字段,以便CliBuilder可以填充变量。 例如:
import groovy.cli.OptionField
import groovy.cli.UnparsedField
@OptionField String user
@OptionField Boolean help
@UnparsedField List remaining
String[] argz = ['--user', 'abc', 'foo']
new CliBuilder().parseFromInstance(this, argz)
assert user == 'abc'
assert remaining == ['foo']
键入的位置参数
此版本的CliBuilder对强类型的位置参数提供了一些有限的支持。
如果所有位置参数都具有相同的类型,则@Unparsed
注释可以与String[]
以外的其他数组类型一起使用。 同样,在Commons CLI版本中使用StringGroovyMethods#asType(String,Class)完成类型转换,而CliBuilder的picocli版本支持这些类型的超集 。
此功能仅适用于注释API,不适用于动态API。 这是可以捕获强类型的位置参数的接口示例:
interface TypedPositionals {
@Unparsed Integer[] nums()
}
下面的代码演示了类型转换:
def argz = '12 34 56'.split()
def cli = new CliBuilder()
def options = cli.parseFromSpec(TypedPositionals, argz)
assert options.nums() == [12, 34, 56]
陷阱/不兼容
在某些方面,新版本的CliBuilder
与以前的版本或彼此不兼容。
属性
CliBuilder的Commons CLI版本和CliBuilder的早期版本公开了org.apache.commons.cli.Options
类型的options
属性,该属性可用于配置基础的Commons CLI解析器,而无需通过CliBuilder API。 此属性在picocli版本的CliBuilder中不可用。 读取或写入此属性的应用程序必须导入groovy.cli.commons.CliBuilder
或修改该应用程序。
此外,CliBuilder的picocli版本中不提供org.apache.commons.cli.HelpFormatter
类型的formatter
属性。 如果您的应用程序使用此属性,请考虑改为使用usageMessage
属性,或导入groovy.cli.commons.CliBuilder
。
Picocli和Commons CLI版本中的属性
picocli版本的CliBuilder具有parser
属性,该属性公开了picocli.CommandLine.Model.ParserSpec
对象,该对象可用于配置解析器行为。
Commons CLI版本的CliBuilder和早期版本的CliBuilder公开了类型为org.apache.commons.cli.CommandLineParser
的parser
属性。 picocli版本的CliBuilder中不提供此功能。
如果您的应用程序使用parser
属性来设置其他Commons CLI解析器,请考虑改为使用posix
属性,或导入groovy.cli.commons.CliBuilder
。
Commons CLI DefaultParser
识别以单连字符longOption
选项名称(例如-option
)和以双连字符--option
选项(例如--option
)。 这并不总是很明显,因为用法帮助消息仅显示longOption
选项名称的双连字符前缀。
为了向后兼容,CliBuilder的picocli版本具有acceptLongOptionsWithSingleHyphen
属性:如果解析器应识别带有单连字符和双连字符前缀的长选项名称,则将此属性设置为true
。 默认值为false
,因此只能识别带有双连字符前缀的长选项名称( --option
)。
等等,还有更多...
本文的第2部分介绍了如何利用CliBuilder的基础库的某些高级功能。 在这里,您可以使命令行应用程序真正发光。 敬请期待...
有关更多信息,请访问Groovy 网站和GitHub 项目 ,以及picocli 网站和picocli GitHub项目 。 如果您喜欢所看到的,请给项目加注星标!
翻译自: https://www.javacodegeeks.com/2018/06/groovy-clibuilder-renewal-part-1.html