Yaap 是另一个 (Swift) 命令行参数解析器,它将可执行命令表示为类型,并将参数表示为这些类型的属性。 它支持:
这是一个自包含的 rand
可执行程序的示例,它在可配置的区间内生成随机数到标准输出,包含 --help
文档、用法生成和 --version
打印等所有功能。
class RandomCommand: Command {
let name = "rand"
let documentation = "Generates a random number that lies in an interval."
@Argument(documentation: "Exclusive maximum value")
var maximum: Int
@Option(shorthand: "m", documentation: "Inclusive minimum value")
var minimum: Int = 0
let help = Help()
let version = Version("0.1.0")
func run(outputStream: inout TextOutputStream, errorStream: inout TextOutputStream) throws {
guard maximum > minimum else {
throw InvalidIntervalError(minimum: minimum, maximum: maximum)
}
outputStream.write(Int.random(in: minimum..<maximum).description)
outputStream.write("\n")
}
}
struct InvalidIntervalError: LocalizedError {
let minimum: Int
let maximum: Int
var errorDescription: String? {
return "invalid interval [\(minimum), \(maximum))"
}
}
RandomCommand().parseAndRun()
Yaap 可以作为 Swift Package Manager 依赖项安装。 这是依赖于最新稳定版本的声明:
let package = Package(
dependencies: [
.package(url: "https://github.com/hartbit/Yaap.git", from: "1.0.0")
]
)
在 Yaap 中,命令是一个独立的的操作,定义为遵循 Command
协议的类:参数(如果有)定义为属性,执行逻辑定义在 run(outputStream:errorStream)
函数中。 简单的程序只需要一个命令,但可以根据需要增加。
命令还必须定义一个 name
(可执行文件名),它将出现在用法描述中,以及一个可选的 documentation
属性,它将出现在帮助输出中。
class HelloWorldCommand: Command {
let name = "hello-world"
let description = "My first command"
func run(outputStream: inout TextOutputStream, errorStream: inout TextOutputStream) throws {
outputStream.write("Hello World")
}
}
命令可以使用 parseAndRun
函数解析命令行参数并运行自身。
let command = HelloWorldCommand()
command.parseAndRun()
run(outputStream:errorStream)
抛出的任何错误都将被捕获并报告给标准错误流。
强制参数使用泛型 Argument
类型定义,并按照它们在命令中声明的顺序解析。 它们也可以配置一个可选的 name
和 documentation
,这些信息将显示在帮助输出中。
class SplitCommand: Command {
let name = "split"
@Argument(documentation: "The string to split.")
var string: String
@Argument(name: "separator", documentation: "The seperator to split the string with.")
var sep: Character
func run(outputStream: inout TextOutputStream, errorStream: inout TextOutputStream) throws {
outputStream.write(string.split(separator: sep).joined(separator: "\n"))
outputStream.write("\n")
}
}
$ split "The Swift Programming Language" " "
The
Swift
Programming
Language
可选参数使用泛型 Option
类型定义,并且必须提供一个 defaultValue
。 它们使用 --option value
或 --option=value
语法解析,其中 option
是属性的名称,可以使用可选的 name
参数进行自定义。 还有一个可选的 shorthand
参数,允许使用 -o value
或 -o=value
的单字符语法解析它们。 同样,可以为帮助输出提供 documentation
。
class SplitCommand: Command {
let name = "split"
@Argument
var string: String
@Option(name: "separator", shorthand: "s", documentation: "The seperator to split the string with.")
var sep: Character = " "
func run(outputStream: inout TextOutputStream, errorStream: inout TextOutputStream) throws {
outputStream.write(string.split(separator: sep).joined(separator: "\n"))
outputStream.write("\n")
}
}
$ split a,b,c,d --separator ,
a
b
c
d
Yaap 自带一个内置的 Help
属性,它可以解析 --help/-h
参数并将命令的详细文档打印到标准输出。 可以使用不同的名称和简写语法配置它。 使用上面的 RandomCommand
示例:
class RandomCommand: Command {
let name = "rand"
let documentation = "Generates a random number that lies in an interval."
let help = Help()
@Argument(documentation: "Exclusive maximum value")
var maximum: Int
@Option(shorthand: "m", documentation: "Inclusive minimum value")
var minimum: Int = 0
func run(outputStream: inout TextOutputStream, errorStream: inout TextOutputStream) throws {
// ...
}
}
$ rand --help
OVERVIEW: Generates a random number that lies in an interval.
USAGE: rand [options] <maximum>
ARGUMENTS:
maximum Exclusive maximum value
OPTIONS:
--help, -h Display available options [default: false]
--minimum, -m Inclusive minimum value [default: 0]
Yaap 还有一个内置的 Version
属性,允许命令通过将其版本号打印到标准输出来响应 --version/-v
参数。 可以自定义该属性以响应不同的参数名称和可选的简写语法。
class MyCommand: Command {
let name = "program"
let version = Version("4.2", name: "ver", shorthand: nil)
func run(outputStream: inout TextOutputStream, errorStream: inout TextOutputStream) throws {
// ...
}
}
$ program --ver
4.2
我要感谢 SwiftCLI 对 Yaap 设计的重大影响。