Reputation: 2542
I'm trying to have a base option parser with some default parameters.
In other projects i would like to extend the option parser with other parameters.
Something like:
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)
}
}
I'm a newbie at Scala
and I'm not sure how I can now use both of them on the same args
.
I'm using Scala
2.10 with scopt_2.10
v3.3.0.
Upvotes: 5
Views: 3376
Reputation: 4770
I've opened https://github.com/scopt/scopt/issues/132.
So far the best of what I've been able to come up with is combining two parsers.
case class OutputOpts(
val outputOption: Int = 1
)
trait OptsWithOutput {
def output: OutputOpts
}
The parser for this lives in the parent class.
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"))
}
A child class now can use this:
case class ChildOpts(
childThing: Int = 42,
output: OutputOpts = OutputOpts()
) extends OptsWithOutput
And its parser combines the two.
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"))
Note how we have to set errorOnUnknownArgument
to false
, which is definitely not ideal and causes warnings.
Upvotes: 3