Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How does one inherit or reuse options? #132

Closed
dblock opened this issue Mar 19, 2017 · 7 comments
Closed

How does one inherit or reuse options? #132

dblock opened this issue Mar 19, 2017 · 7 comments

Comments

@dblock
Copy link

dblock commented Mar 19, 2017

Forgive a scala noob, this is probably trivial and is basically the unanswered SO http://stackoverflow.com/questions/34026943/extending-scopt-optionparser-in-scala.

I have some base options:

trait BaseOpts {
  def reticulate: Boolean
}

case class Opts(
  reticulate = true
) extends BaseOpts

abstract class Job {

  def parseOpts(args: Array[String]): Opts = {
    val parser = new scopt.OptionParser[Opts]("scopt") {
      head("scopt", "3.x")
      opt[String]("reticulate") action { (x, c) =>
        c.copy(reticulate = x)
      } text ("reticulate splines")
    }

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

I'd like to extend Job along with Opts.

case class SplineOpts(
  maxSplines:   Int = 10000
) extends Opts(reticulate = true);

object SplineJob extends Job {
  override def parseOpts(args: Array[String]): SplineOpts = {
  }
}

So far I'm stuck here, this signature below is String, SplineOpts -> Opts, which is wrong, I want SplineOpts.

    val parser = new scopt.OptionParser[SplineOpts]("scopt") {
      opt[String]("maxSplines") action { (x, c) =>
        c.copy(maxSplines = x.toInt)
      } text ("max number of splines")
    }

Maybe there's an overall better strategy for adding more options than a base and parsing them?

@dblock dblock changed the title How does one inherit options? How does one inherit or reuse options? Mar 19, 2017
@dblock
Copy link
Author

dblock commented Mar 24, 2017

I was able to combine two parsers into one set of options, see http://stackoverflow.com/a/43001193/123094, but that is far from ideal. I'd like to be able to actually inherit a parser from another or combine them in some way that produces a single case class set of options.

@aappddeevv
Copy link

aappddeevv commented Dec 11, 2017

@i think the final parser needs to be a union of all the types that would eventually be parsed so you could split the "config" type up (an abstract type) if you want to but they need to come together at some point in the lowest level class.

You could then just compose things based on passing around the parser instance and importing the dsl functions to "add" a component's options prior to the actual parsing.

// Unit signals we are mutating
def addOptions(op: scopt.OptionParser[FinalType]): Unit = {
  import op._
  cmd("blah")
  note("blah")
  ...
}

Having said that you could also probably pull the option processing out of the class entirely.

@dportabella
Copy link

any idea of how to solve this issue?

@aappddeevv
Copy link

aappddeevv commented Mar 1, 2018

just do as described above, there are a couple methods. The parser object has a DSL that mutates internal structures so write a function that takes the parser object and import those DSL functions. The rest of the function uses those DSL functions to “add” your reusable parser options. There are a couple of other issues that covers this as well. Because of the dsl design, you do not declare options outside the context of a parser object.

@dportabella
Copy link

is it possible to have a minimal complete working example, please?

@eed3si9n
Copy link
Member

Released scopt 4.0.0-RC2 with more composable OParser. See http://eed3si9n.com/scopt4 for details.

2m pushed a commit to 2m/scopt that referenced this issue Feb 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants