我正在使用ArgumentParser
包进行命令行解析,并希望将其与Swift并发的async
API一起使用:
struct Foo: ParsableCommand {
@Argument(
help: "File to be parsed. If not present, parses stdin.",
transform: URL.init(fileURLWithPath:)
)
var file: URL?
mutating func run() async throws {
let handle: FileHandle
if let file {
handle = try .init(forReadingFrom: file)
} else {
handle = .standardInput
}
for try await line in handle.bytes.lines {
// do something with each line
}
try handle.close()
}
}
但是当我这样做的时候,我总是看到“用法”文本:
USAGE: foo [<file>]
ARGUMENTS:
<file> File to be parsed. If not present, parses stdin.
OPTIONS:
-h, --help Show help information.
我没有得到编译错误,但无论是否提供参数,我总是看到“USAGE”文本。
1条答案
按热度按时间bkkx9g8r1#
问题是将
ParsableCommand
与run() async throws
结合使用。使用
AsyncParsableCommand
代替。正如它的documentation所说:要在命令的
run()
方法实现中使用async
/await
代码,请执行以下步骤:1.对于命令行工具中的根命令,声明与
AsyncParsableCommand
的一致性,无论该命令是否使用异步代码。1.将
@main
属性应用于根命令。(注意:如果root命令位于main.Swift
文件中,请将该文件重命名为该命令的名称。)1.对于任何需要使用异步代码的命令,声明与
AsyncParsableCommand
的一致性,并将run()
方法标记为async
。对于不使用异步代码的子命令,不需要进行任何更改。不幸的是,虽然更广泛的documentation偶尔会提到支持
async
,但您必须深入研究代码示例(特别是count-lines
)或浏览整个类库才能偶然发现AsyncParsableCommand
。因此,使用
AsyncParsableCommand
和run
的async
再现:但是,不幸的是,如果您不小心将
run
的async
版本与ParsableCommand
一起使用,它编译时没有错误,但无论何时运行它都会产生“USAGE”文本,而没有任何关于 * 为什么 * 它不工作的诊断信息。简而言之,
ParsableCommand
需要run
的非async
副本。async
副本需要AsyncParsableCommand
。