我想使用scopt
声明必需的子命令(或类似但基于Scala的。)
例如,我希望有以下概要(例如,类似于man git
):
mycli [--version] [--help] <command> [<args>]
而<command>
必需是子命令之一,例如subA
和subB
。如下所示:
private val parser = new OptionParser[Config]("mycli") {
head(s"${BuildInfo.name} v${BuildInfo.version} is © 2014 by ${BuildInfo.organization}")
help("help") text("prints this usage text")
version("version") text("FIXME”)
cmd("command") required() action {(c, config) => c match {
case "subA" => config.copy(mode = "subA") children(
arg[String]("<files>...") unbounded() optional() action {(rs, config) => config.copy(files = config.files :+ rs) },
opt[Unit] ("with-optA") action {(_ , config) => config.copy(optA = true)},
opt[Unit] ("with-optB") action {(_ , config) => config.copy(optB = true)})
case "subB" => //...
case _ => // ERROR!
} }
}
任何提示?
提前感谢您的帮助!
答案 0 :(得分:3)
当然这有点棘手,它可以导致很多级别的儿童选择。
这是我的Config类:
case class Config(cmd:String="", subcmd:String="")
这是我的解析器:
val parser = new scopt.OptionParser[Config]("MyCLI") {
head("Foo")
cmd("cmdA") action { (_, c) => c.copy(cmd = "cmdA")
} children(
cmd("subA1") action { (_, c) => c.copy(subcmd = "subA1")},
cmd("subA2") action { (_, c) => c.copy(subcmd = "subA2")}
)
cmd("cmdB") action { (_, c) => c.copy(cmd = "cmdA")
} children(
cmd("subA1") action { (_, c) => c.copy(subcmd = "subA1")},
cmd("subA2") action { (_, c) => c.copy(subcmd = "subA2")}
)
checkConfig { c => c match {
case Config("", _) => failure("No command given.")
case Config(_, "") => failure("Must Choose a subcommand.")
case _ => success
}}
}
我希望这会有所帮助。我会用密封的特征和对象替换Config.cmd
。我没有这样做,所以这是可复制的。
每个子命令都可以拥有自己的子级,使用另一个命令,选项或参数。
对checkConfig
的调用非常重要,否则如果没有给出命令,应用程序将默默退出。