Yaap version 1.0.0 swift 5.1 license MIT

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 类型定义,并按照它们在命令中声明的顺序解析。 它们也可以配置一个可选的 namedocumentation,这些信息将显示在帮助输出中。

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 设计的重大影响。