All Downloads are FREE. Search and download functionalities are using the official Maven repository.

caseapp.core.parser.StandardArgument.scala Maven / Gradle / Ivy

There is a newer version: 2.1.0-M29
Show newest version
package caseapp.core.parser

import caseapp.core.argparser.{ArgParser, Consumed}
import caseapp.core.{Arg, Error}
import caseapp.core.util.NameOps.toNameOps
import dataclass.data
import caseapp.core.util.Formatter
import caseapp.Name

@data case class StandardArgument[H](
  arg: Arg,
  argParser: ArgParser[H],
  default: () => Option[H] // FIXME Couldn't this be Option[() => H]?
) extends Argument[H] {

  import StandardArgument._

  def withDefaultOrigin(origin: String): Argument[H] =
    this.withArg(arg.withDefaultOrigin(origin))

  def init: Option[H] =
    None

  def step(
    args: List[String],
    index: Int,
    d: Option[H],
    nameFormatter: Formatter[Name]
  ): Either[(Error, List[String]), Option[(Option[H], List[String])]] =
    args match {
      case Nil =>
        Right(None)

      case firstArg :: rem =>
        val matchedOpt = (Iterator(arg.name) ++ arg.extraNames.iterator)
          .map(n => n -> n(firstArg, nameFormatter))
          .collectFirst {
            case (n, Right(valueOpt)) => n -> valueOpt
          }

        matchedOpt match {
          case Some((name, valueOpt)) =>
            val (res, rem0) = valueOpt match {
              case Some(value) =>
                val res0 = argParser(d, index, 1, value)
                  .map(h => Some(Some(h)))
                (res0, rem)
              case None =>
                rem match {
                  case Nil =>
                    val res0 = argParser(d, index)
                      .map(h => Some(Some(h)))
                    (res0, Nil)
                  case th :: tRem =>
                    val (Consumed(usedArg), res) = argParser.optional(d, index, 2, th)
                    val res0                     = res.map(h => Some(Some(h)))
                    (res0, if (usedArg) tRem else rem)
                }
            }

            res
              .left
              .map { err =>
                (Error.ParsingArgument(name, err, nameFormatter), rem0)
              }
              .map(_.map((_, rem0)))

          case None =>
            Right(None)
        }
    }

  def get(d: Option[H], nameFormatter: Formatter[Name]): Either[Error, H] =
    d.orElse(default()).toRight {
      Error.RequiredOptionNotSpecified(
        arg.name.option(nameFormatter),
        arg.extraNames.map(_.option(nameFormatter))
      )
    }

  val args: Seq[Arg] =
    Seq(arg)

}

object StandardArgument {
  def apply[H: ArgParser](arg: Arg): StandardArgument[H] =
    StandardArgument[H](arg, ArgParser[H], () => None)

  implicit class StandardArgumentWithOps[H](private val standardArg: StandardArgument[H])
      extends AnyVal {
    def withArg(arg: Arg): StandardArgument[H] =
      standardArg.copy(arg = arg)
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy