运行 Shell 命令 | 解析命令行参数 | 处理文件和目录
Moderator 是一个简单的 Swift 库,用于解析命令行参数。
另请参阅为什么创建 Moderator。
import Moderator
import FileSmith
let arguments = Moderator(description: "Automatically add code to Swift Package Manager projects to run unit tests on Linux.")
let overwrite = arguments.add(.option("o","overwrite", description: "Replace <test directory>/LinuxMain.swift if it already exists."))
let testdirarg = arguments.add(Argument<String?>
.optionWithValue("testdir", name: "test directory", description: "The path to the directory with the unit tests.")
.default("Tests"))
_ = arguments.add(Argument<String?>
.singleArgument(name: "directory", description: "The project root directory.")
.default("./")
.map { (projectpath: String) in
let projectdir = try Directory(open: projectpath)
try projectdir.verifyContains("Package.swift")
Directory.current = projectdir
})
do {
try arguments.parse()
let testdir = try Directory(open: testdirarg.value)
if !overwrite.value && testdir.contains("LinuxMain.swift") {
throw ArgumentError(errormessage: "\(testdir.path)/LinuxMain.swift already exists. Use -o/--overwrite to replace it.")
}
...
} catch {
WritableFile.stderror.print(error)
exit(Int32(error._code))
}
自动生成的帮助文本
Automatically add code to Swift Package Manager projects to run unit tests on Linux.
Usage: linuxmain-generator
-o,--overwrite:
Replace <test directory>/LinuxMain.swift if it already exists.
--testdir <test directory>:
The path to the directory with the unit tests. Default = 'Tests'.
<directory>:
The project root directory. Default = './'.
Moderator 的工作原理是拥有一个单独的 Moderator 对象,您可以向其添加单独的参数解析器。当您开始解析时,它会按照添加的顺序遍历每个参数解析器。每个解析器都从命令行获取字符串参数数组,找到它负责的参数,处理它们,并在出现任何错误时抛出错误,从数组中删除参数,返回其输出(对于某些解析器,如果未找到参数,则可能为 nil),并将修改后的数组传递给下一个解析器。
这保持了代码的简洁,并且每个解析器只需要处理它自己的参数。内置解析器可以很容易地进行自定义,并且您可以从头开始创建自己的解析器。
func option(_ names: String..., description: String? = nil) -> Argument<Bool>
处理像 -h
和 --help
这样的选项参数。如果该参数存在,则返回 true,否则返回 false。
func optionWithValue(_ names: String..., name valuename: String? = nil, description: String? = nil)
-> Argument<String?>
处理带有值的选项参数,例如 --help <topic>
。它将该值作为字符串返回,如果该选项不存在,则返回 nil。
func singleArgument(name: String, description: String? = nil) -> Argument<String?>
返回下一个参数,如果没有更多参数或下一个参数是选项,则返回 nil。必须在任何选项解析器之后添加。
可以用于返回 optionals 的解析器,用默认值替换 nil。
可以用于返回 optionals 的解析器,在 nil 时抛出错误。
获取任何参数解析器的输出,并将其转换为其他内容。
通过重复一个可选的解析器直到它返回 nil 来查找一个参数的多个出现。
let m = Moderator()
let options = m.add(Argument<String?>.optionWithValue("b").repeat())
let multiple = m.add(Argument<String?>.singleArgument(name: "multiple").repeat())
try m.parse(["-b", "b1", "-b", "b2", "-b", "b3", "one", "two", "three"])
options.value
现在是 ["b1", "b2", "b3"]
,multiple.value
是 ["one", "two", "three"]
。
计算选项参数出现的次数。
let m = Moderator()
let option = m.add(Argument<Bool>.option("b").count())
try m.parse(["-b", "-b", "some", "other", "-b", "arguments"])
option.value
返回 3
如果内置的解析器和自定义不够用,您可以轻松创建自己的解析器。例如,这是 singleArgument 解析器的实现
extension Argument {
public static func singleArgument (name: String, description: String? = nil) -> Argument<String?> {
return Argument<String?>(usage: description.map { ("<"+name+">", $0) }) { args in
let index = args.first == "--" ? args.index(after: args.startIndex) : args.startIndex
guard index != args.endIndex, !isOption(index: index, args: args) else { return (nil, args) }
var args = args
return (args.remove(at: index), args)
}
}
}
在 Argument 初始化程序中,您返回一个元组,其中包含解析器的输出和没有处理的参数的参数数组。
将 .Package(url: "https://github.com/kareman/Moderator", "0.5.0")
添加到您的 Package.swift
import PackageDescription
let package = Package(
name: "somename",
dependencies: [
.Package(url: "https://github.com/kareman/Moderator", "0.5.0")
]
)
并运行 swift build
。
将 github "kareman/Moderator"
添加到您的 Cartfile,然后运行 carthage update
并将生成的框架添加到应用程序的 "Embedded Binaries" 部分。 有关更多说明,请参见Carthage 的 README。
将 Moderator
添加到您的 Podfile
。
pod "Moderator", git: "https://github.com/kareman/Moderator.git"
然后运行 pod install
安装它。
根据 MIT 许可证(MIT)发布,https://open-source.org.cn/licenses/MIT
Kåre Morstøl, NotTooBad Software