Skip to content

Instantly share code, notes, and snippets.

@bmc
Created March 15, 2012 22:41
Show Gist options
  • Save bmc/2047420 to your computer and use it in GitHub Desktop.
Save bmc/2047420 to your computer and use it in GitHub Desktop.
Argot: New DSL possibility
package ThinkingAboutThisApproach {
object Types {
type Converter[T] = (String, ArgSpec) => Either[String, T]
}
import Types._
class ArgOption[T](val name: String, val desc: String, val cvt: Converter[T]) {
override def toString = "ArgOption<%s>" format name
override def hashCode = name.hashCode
override def equals(other: Any): Boolean = {
other match {
case that: ArgOption[_] => that.name == this.name
case _ => false
}
}
def get(p: ParsedParameters): Option[Either[String, T]] = {
p.options.get(this).map(e => e match {
case Right(v) => Right[String, T](v.asInstanceOf[T])
case Left(msg) => Left[String, T](msg)
})
}
}
object ArgOption {
def apply[T](name: String, desc: String)
(implicit cvt: Converter[T]): ArgOption[T] = {
new ArgOption[T](name, desc, cvt)
}
}
class Parameter[T](val name: String, val desc: String, val cvt: Converter[T]) {
override def toString = "Parameter<%s>" format name
override def hashCode = name.hashCode
override def equals(other: Any): Boolean = {
other match {
case that: Parameter[_] => that.name == this.name
case _ => false
}
}
def get(p: ParsedParameters): Option[Either[String, T]] = {
p.parameters.get(this).map(e => e match {
case Right(v) => Right[String, T](v.asInstanceOf[T])
case Left(msg) => Left[String, T](msg)
})
}
}
object Parameter {
def apply[T](name: String, desc: String)
(implicit cvt: Converter[T]): Parameter[T] = {
new Parameter[T](name, desc, cvt)
}
}
object Converters {
implicit def xToInt(s: String, a: ArgSpec): Either[String, Int] = {
try {
Right(s.toInt)
}
catch {
case e: NumberFormatException =>
Left(e.getClass.getName + " " + e.getMessage)
}
}
implicit def xToString(s: String, a: ArgSpec): Either[String, String] =
Right(s)
}
import scala.collection.immutable.{ListMap, ListSet}
class ArgSpec(val options: Seq[ArgOption[_]], val parameters: Seq[Parameter[_]]) {
private val optionMap = Map(options.map(opt => opt.name -> opt): _*)
private val paramMap = ListMap(parameters.map(p => p.name -> p): _*)
override def toString = {
val sb = new StringBuilder
sb append " options="
sb append options.toString
sb append " parameters="
sb append parameters.toString
sb.toString
}
}
case class ParsedParameters(options: Map[ArgOption[_], Either[String, _]],
parameters: Map[Parameter[_], Either[String, _]]) {
}
class ArgParser(val program: String, val spec: ArgSpec) {
def parse(argv: Array[String]): ParsedParameters = {
val opts = scala.collection.mutable.Map.empty[ArgOption[_], Either[String, _]]
spec.options.foreach(o => opts += (o -> o.cvt("1.0", spec)))
val params = scala.collection.mutable.Map.empty[Parameter[_], Either[String, _]]
spec.parameters.foreach(p => params += (p -> p.cvt("1", spec)))
new ParsedParameters(opts.toMap, params.toMap)
}
}
object ArgParser {
def apply(prog: String, spec: ArgSpec) = {
new ArgParser(prog, spec)
}
}
object Test {
def main(args: Array[String]): Unit = {
import Converters._
import java.io.File
val a = ArgOption[String]("-a", "string")
val i = ArgOption[Int]("-i", "int")
val f = ArgOption[Float]("-f", "float") {
(s, spec) =>
try {
Right(s.toFloat)
}
catch {
case e: NumberFormatException => Left(e.getMessage)
}
}
val p1 = Parameter[File]("input", "input_file") {
(s, spec) => Right(new File(s))
}
val p2 = Parameter[String]("foo", "foo thingie")
val spec = new ArgSpec(Seq(a, i, f), Seq(p1, p2))
val parsed = ArgParser("test", spec).parse(args)
for (opt <- Seq(a, i, f)) {
opt.get(parsed).foreach(_ match {
case Right(v) =>
println(opt.name + ": " + v + " (" + v.getClass.getName + ")")
case Left(msg) =>
println(opt.name + " (ERROR) " + msg)
})
}
for (p <- Seq(p1, p2)) {
p.get(parsed).foreach(_ match {
case Right(v) =>
println(p.name + ": " + v + " (" + v.getClass.getName + ")")
case Left(msg) =>
println(p.name + " (ERROR) " + msg)
})
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment