Commander

Commander

Build Status

Commander 是一个小型 Swift 框架,允许你以可组合的方式创建美观的命令行界面。

用法

简单的 Hello World
import Commander

let main = command { (filename:String) in
  print("Reading file \(filename)...")
}

main.run()
类型安全的参数处理

传递给命令函数的闭包接受任何符合 ArgumentConvertible 的参数,Commander 将自动将参数转换为这些类型。如果无法转换,用户将收到一条友好的错误消息,告知他们参数与期望的类型不匹配。

StringIntDoubleFloat 已扩展为符合 ArgumentConvertible,你可以轻松扩展任何其他类或结构,以便将其用作命令的参数。

command { (hostname:String, port:Int) in
  print("Connecting to \(hostname) on port \(port)...")
}
分组命令

你可以将一组命令组合在一起。

Group {
  $0.command("login") { (name:String) in
    print("Hello \(name)")
  }

  $0.command("logout") {
    print("Goodbye.")
  }
}

用法

$ auth
Usage:

    $ auth COMMAND

Commands:

    + login
    + logout

$ auth login Kyle
Hello Kyle
$ auth logout
Goodbye.

描述参数

你可以描述命令的位置参数和选项,以自动生成帮助信息。这通过传入这些参数的描述符来完成。

例如,对于带有描述的固定位置参数,你可以使用

command(
    Argument<String>("name", description: "Your name"),
    Argument<String>("surname", description: "Your surname"),
    Argument<Int>("count", description: "Number of times to print")
) { name, surname, count in
    for _ in 0..<count {
        print("Hello \(name) \(surname)")
    }
   }.run()

请记住,你必须传递 3 个必需的参数。

另一个例子,描述一个接受两个(可选)选项的命令,--name--count,其中 name 的默认值为 world,count 的默认值为 1

command(
  Option("name", default: "world"),
  Option("count", default: 1, description: "The number of times to print.")
) { name, count in
  for _ in 0..<count {
    print("Hello \(name)")
  }
}
$ hello --help
Usage:

    $ hello

Options:
    --name
    --count - The number of times to print.

$ hello
Hello world

$ hello --name Kyle
Hello Kyle

$ hello --name Kyle --count 4
Hello Kyle
Hello Kyle
Hello Kyle
Hello Kyle
描述符的类型

注意:*重要的是在选项和标志之后描述你的参数,以便解析器可以区分 --option value--flag argument。*

使用参数解析器

注意:*ArgumentParser 本身是 ArgumentConvertible,因此你也可以获取原始参数解析器来执行任何自定义解析。*

command { (name:String, parser:ArgumentParser) in
  if parser.hasOption("verbose") {
    print("Verbose mode enabled")
  }

  print("Hello \(name)")
}
$ tool Kyle --verbose
Verbose mode enabled
Hello Kyle

使用 Commander 的工具示例

安装

你可以通过多种方式安装 Commander,例如使用 SPM (Swift Package Manager)、Conche、CocoaPods 或 CocoaPods-Rome

框架和 rpath

重要的是要注意,Commander(以及任何其他依赖项)的 .framework 或动态库文件必须在运行时对你的命令行工具可用。除非你正在使用 SPM。

应用程序将在它们的 rpath 中查找,其中包含期望找到 .framework 的路径。

使用 Swift 脚本,你可以使用 -F 标志来设置框架搜索路径,如下所示

#!/usr/bin/env xcrun swift -F Rome

import Commander

对于编译后的 Swift 代码,你需要添加一个指向你的依赖框架的 rpath,如下所示

$ install_name_tool -add_rpath "@executable_path/../Frameworks/"  "bin/querykit"

其中相对于可执行路径的 "../Frameworks" 用于查找框架,而 bin/querykit 是可执行文件。

在其他系统上安装可执行文件时,重要的是复制框架和二进制文件。

架构

CommandType

CommandType 是命令背后的核心协议,它是一个对象或结构,具有一个接受 ArgumentParserrun 方法。

command 函数和 Group 都返回一个符合 CommandType 的命令,它们可以轻松互换。

protocol CommandType {
  func run(parser:ArgumentParser) throws
}
ArgumentConvertible

便捷的 command 函数为你的命令接受一个闭包,该闭包接受符合 ArgumentConvertible 协议的参数。这使 Commander 可以轻松地将参数转换为你想用于命令的类型。

protocol ArgumentConvertible {
  init(parser: ArgumentParser) throws
}
ArgumentParser

ArgumentParser 是一个允许你提取选项、标志和位置参数的对象。

许可证

Commander 在 BSD 许可证下可用。有关更多信息,请参阅 LICENSE 文件