Command Overview

本指引将通过如何创建 CLI 来向你介绍 Command (命令) 模块. 在示例中, 我们将实现 cowsay, 这是一个打印奶牛 ASCII 图片的命令.

tip

你可以通过 brew install cowsay 安装真实的 cowsay 程序.

  1. $ cowsay Hello
  2. -----
  3. < Hello >
  4. -----
  5. \ ^__^
  6. \ (oo\_______
  7. (__)\ )\/\
  8. ||----w |
  9. || ||

Command

第一步创建一个遵守 Command 协议的类型.

  1. /// Generates ASCII picture of a cow with a message.
  2. struct CowsayCommand: Command {
  3. ...
  4. }

现在让我们所需函数.

Arguments

命令可以有 0 或多个 CommandArgument (命令参数). 命令运行需要这些参数.

  1. /// Generates ASCII picture of a cow with a message.
  2. struct CowsayCommand: Command {
  3. /// See `Command`
  4. var arguments: [CommandArgument] {
  5. return [.argument(name: "message")]
  6. }
  7. ...
  8. }

在这里, 我们定义了一个参数, 奶牛会说的”消息”. 这是运行 cowsay 命令所需的.

Options

命令可以有 0 或多个 CommandOption (命令选项). 命令运行不需要这些选项, 选项可以使用 --- 语法传递.

  1. /// Generates ASCII picture of a cow with a message.
  2. struct CowsayCommand: Command {
  3. ...
  4. /// See `Command`
  5. var options: [CommandOption] {
  6. return [
  7. .value(name: "eyes", short: "e", default: "oo", help: ["Change cow's eyes"]),
  8. .value(name: "tongue", short: "t", default: " ", help: ["Change cow's tongue"]),
  9. ]
  10. }
  11. ...
  12. }

在这里, 我们定义了两个选项, eyetongue. 它们可以让用户选择改变奶牛的外观.

Help

接下来, 我们可以定义一个可选的帮助信息, 以便在用户输入 --help 时展示.

  1. /// Generates ASCII picture of a cow with a message.
  2. struct CowsayCommand: Command {
  3. ...
  4. /// See `Command`
  5. var help: [String] {
  6. return ["Generates ASCII picture of a cow with a message."]
  7. }
  8. ...
  9. }

让我们看看命令完成后它的表现:

  1. Usage: <executable> cowsay <message> [--eyes,-e] [--tongue,-t]
  2. Generates ASCII picture of a cow with a message.
  3. Arguments:
  4. message n/a
  5. Options:
  6. eyes Change cow's eyes
  7. tongue Change cow's tongue

Run

最后, 我们要编写我们的实现:

  1. /// Generates ASCII picture of a cow with a message.
  2. struct CowsayCommand: Command {
  3. ...
  4. /// See `Command`.
  5. func run(using context: CommandContext) throws -> Future {
  6. let message = try context.argument("message")
  7. /// We can use requireOption here since both options have default values
  8. let eyes = try context.requireOption("eyes")
  9. let tongue = try context.requireOption("tongue")
  10. let padding = String(repeating: "-", count: message.count)
  11. let text: String = """
  12. \(padding)
  13. < \(message) >
  14. \(padding)
  15. \\ ^__^
  16. \\ (\(eyes)\\_______
  17. (__)\\ )\\/\\
  18. \(tongue) ||----w |
  19. || ||
  20. """
  21. context.console.print(text)
  22. return .done(on: context.container)
  23. }
  24. }

CommandContext (命令内容) 让你可以访问所需的一切, 包括一个 容器. 现在我们有了一个完整的 命令, 下一步就是配置它.

Config

使用 CommandConfig (命令配置) 结构体向你的容器注册命令. 这通常在 configure.swift 中完成

  1. /// Create a `CommandConfig` with default commands.
  2. var commandConfig = CommandConfig.default()
  3. /// Add the `CowsayCommand`.
  4. commandConfig.use(CowsayCommand(), as: "cowsay")
  5. /// Register this `CommandConfig` to services.
  6. services.register(commandConfig)

使用 --help 查看你的指令是否正确配置.

  1. swift run Run cowsay --help

成了!

  1. $ swift run Run cowsay 'Good job!' -e ^^ -t U
  2. ---------
  3. < Good job! >
  4. ---------
  5. \ ^__^
  6. \ (^^\_______
  7. (__)\ )\/\
  8. U ||----w |
  9. || ||