You have to have a Parser, which will parse the input given to the task. Once you have the input, you can convert (runMain in Compile).toTask
, and feed the input to the task.
TL;DR; build.sbt
import sbt.complete._
import complete.DefaultParsers._
lazy val myRunTask = inputKey[Unit]("Runs actual tests")
lazy val FullQualifiedClassName =
(charClass(c => isScalaIDChar(c) || (c == '.'), "class name")).+.string
def commaDelimited(display: String) =
token(Space) ~> repsep(token(FullQualifiedClassName, display), token(","))
lazy val testClassArgs: Parser[Seq[String]] =
commaDelimited("<full qualified test class name>").map {
xs: Seq[String] => xs.map(e => s" -s $e ")
}
myRunTask := Def.inputTaskDyn {
val classes = testClassArgs.parsed
runMainInCompile(classes)
}.evaluated
def runMainInCompile(classes: Seq[String]) = Def.taskDyn {
(runMain in Compile).toTask(s" org.scalatest.tools.Runner -P1 -C reporter.TestReporter -o ${classes.mkString}")
}
Parser
Let's start with a parser. The parser must take a space, followed by your classes separated by comma.
Let's first defined a parser, which parses full qualified class name:
lazy val FullQualifiedClassName =
(charClass(c => isScalaIDChar(c) || (c == '.'), "class name")).+.string
Once we have the parser, we can combine it together with another parser. We need to create a parser, which takes comma separated full qualified class names:
def commaDelimited(display: String) =
token(Space) ~> repsep(token(FullQualifiedClassName, display), token(","))
The ~>
operator means that the input on the left of it will be discarded. The value returned from the parser is a Seq[String]
of the full qualified class names.
Judging from your question, you want your classes to be prefixed with -s
. You could do it later, but just to show one more feature of parsers, I'll just do it here.
You can take an output of a parser and convert it to another output, using map
.
lazy val testClassArgs: Parser[Seq[String]] =
commaDelimited("<full qualified test class name>").map {
xs: Seq[String] => xs.map(e => s" -s $e ")
}
OK, we're almost there.
Run InputTask with arguments combined with a static string
We can define a new input task key. I'll chose myRunTask
, because otherwise it will collide with runTask
, which already exists.
Let's define a method which takes a sequence of classes (already prefixed with -s
) as an argument, and which returns a Task
obtained from an InputTask
.
def runMainInCompile(classes: Seq[String]) = Def.taskDyn {
(runMain in Compile).toTask(s" org.scalatest.tools.Runner -P1 -C reporter.TestReporter -o ${classes.mkString}")
}
Now let's combine all elements in one task:
myRunTask := Def.inputTaskDyn {
val classes = testClassArgs.parsed
runMainInCompile(classes)
}.evaluated