使用scopt声明所需的子命令

时间:2014-02-01 17:38:46

标签: scala command-line scopt

我想使用scopt声明必需的子命令(或类似但基于Scala的。)

例如,我希望有以下概要(例如,类似于man git):

mycli [--version] [--help] <command> [<args>]

<command> 必需是子命令之一,例如subAsubB。如下所示:

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! 
  } }
}

任何提示?

提前感谢您的帮助!

1 个答案:

答案 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的调用非常重要,否则如果没有给出命令,应用程序将默默退出。