mirror of https://github.com/KarolS/millfork.git
82 lines
2.4 KiB
Scala
82 lines
2.4 KiB
Scala
package millfork.cli
|
|
|
|
import fastparse.core.Parsed.Failure
|
|
|
|
import scala.collection.mutable
|
|
|
|
/**
|
|
* @author Karol Stasiak
|
|
*/
|
|
class CliParser[T] {
|
|
|
|
private val options = mutable.ArrayBuffer[CliOption[T, _]]()
|
|
private val mapFlags = mutable.Map[String, CliOption[T, _]]()
|
|
private val mapOptions = mutable.Map[String, CliOption[T, _]]()
|
|
private val _default = new UnknownParamOption[T]().action((p, _) => throw new IllegalArgumentException(s"Unknown option $p"))
|
|
private var _status: Option[CliStatus.Value] = None
|
|
options += _default
|
|
|
|
private def add[O <: CliOption[T, _]](o: O) = {
|
|
options += o
|
|
o.length match {
|
|
case 1 =>
|
|
o.names.foreach { n => mapFlags(n) = o }
|
|
case 2 =>
|
|
o.names.foreach { n => mapOptions(n) = o }
|
|
case _ => ()
|
|
}
|
|
o
|
|
}
|
|
|
|
def parse(context: T, args: List[String]): (CliStatus.Value, T) = {
|
|
val t = parseInner(context, args)
|
|
_status.getOrElse(if (options.forall(_.validate())) CliStatus.Ok else CliStatus.Failed) -> t
|
|
}
|
|
|
|
def assumeStatus(s: CliStatus.Value): Unit = {
|
|
_status = Some(s)
|
|
}
|
|
|
|
private def parseInner(context: T, args: List[String]): T = {
|
|
args match {
|
|
case k :: v :: xs if mapOptions.contains(k) =>
|
|
mapOptions(k) match {
|
|
case p: ParamOption[T] => parseInner(p.encounter(v, context), xs)
|
|
case _ => ???
|
|
}
|
|
case k :: xs if mapFlags.contains(k) =>
|
|
mapFlags(k) match {
|
|
case p: FlagOption[T] =>
|
|
parseInner(p.encounter(context), xs)
|
|
case p: BooleanOption[T] =>
|
|
parseInner(p.encounter(k, context), xs)
|
|
case p: NoMoreOptions[T] =>
|
|
p.encounter()
|
|
xs.foldLeft(context)((t, x) => _default.encounter(x, t))
|
|
case _ => ???
|
|
}
|
|
case x :: xs =>
|
|
parseInner(_default.encounter(x, context), xs)
|
|
case Nil => context
|
|
}
|
|
}
|
|
|
|
|
|
def fluff(text: String*): Unit = add(new Fluff[T](text))
|
|
|
|
def flag(names: String*): FlagOption[T] = add(new FlagOption[T](names))
|
|
|
|
def boolean(trueName: String, falseName: String): BooleanOption[T] = add(new BooleanOption[T](trueName, falseName))
|
|
|
|
def endOfFlags(names: String*): NoMoreOptions[T] = add(new NoMoreOptions[T](names))
|
|
|
|
def default: UnknownParamOption[T] = _default
|
|
|
|
def printHelp(firstTab: Int): List[String] = {
|
|
options.filterNot(_._hidden).toList.flatMap(_.toStrings(firstTab))
|
|
}
|
|
|
|
def parameter(names: String*): ParamOption[T] = add(new ParamOption[T](names))
|
|
|
|
}
|