Расширение Scopt OptionParser в Scala

Я пытаюсь иметь парсер базовых опций с некоторыми параметрами по умолчанию.

В других проектах я хотел бы расширить парсер опций другими параметрами.

Что-то вроде:

case class Config(foo: String = null)

trait DefaultParser { self: OptionParser[Config] =>
  opt[String]('f', "foo") action { (x, c) =>
    c.copy(foo = x)
  }
}

case class MyConfig(bar: String = "hello world")

trait MyParser { self: OptionParser[MyConfig] =>
  opt[String]('b', "bar") action { (x, c) =>
    c.copy(bar = x)
  }
}

Я новичок в Scala и я не уверен, как теперь я могу использовать оба из них на одном args,

я использую Scala 2.10 с scopt_2.10 v3.3.0.

1 ответ

Я открыл https://github.com/scopt/scopt/issues/132.

Пока что лучшее из того, что я смог придумать, это объединение двух парсеров.

case class OutputOpts(
  val outputOption: Int = 1
)

trait OptsWithOutput {
  def output: OutputOpts
}

Парсер для этого живет в родительском классе.

def parseOutputOpts(args: Array[String]): OutputOpts = {
  val parser = new scopt.OptionParser[OutputOpts]("scopt") {
    override def errorOnUnknownArgument = false

    opt[Int]("outputOption") action { (x, c) =>
      c.copy(outputOption = x)
    } text ("some output option")
  }

  parser.parse(args, OutputOpts())
    .getOrElse(throw new Exception("Error parsing output cli args"))
}

Дочерний класс теперь может использовать это:

case class ChildOpts(
  childThing: Int = 42,
  output: OutputOpts = OutputOpts()
) extends OptsWithOutput

И его парсер сочетает в себе два.

val opts = ChildOpts(output = super.parseOutputOpts(args))

val parser = new scopt.OptionParser[ChildOpts]("scopt") {
  override def errorOnUnknownArgument = false

  opt[Int]("childThing") action { (x, c) =>
    c.copy(childThing = x)
  } text ("some child thing")
}

parser.parse(args, opts).getOrElse(throw new Exception("failed"))

Обратите внимание, как мы должны установить errorOnUnknownArgument в false, что, безусловно, не идеально и вызывает предупреждения.

Другие вопросы по тегам