如何动态调用SBT InputTask?

How to call SBT InputTask dynamically?

我想创建一个新的自定义 InputTask (testOnlyCustom)

因此:

If condition is true
  testOnlyCustom com.dummy.TestSuite calls
    pre and then
    testOnly com.dummy.TestSuite

If condition is false
  testOnlyCustom com.dummy.TestSuite calls
    testOnly com.dummy.TestSuite

虽然我能够通过 testCustom 引用 pretest(因此没有参数)来实现解决方案,但我无法解决问题testOnlyCustom,因为 InputTask 使用了

这是我的代码:

import sbt._
import sbt.Keys._
import sbt.Def._
import sbtsequential.Plugin._


object Simple extends sbt.Plugin {

  import SimpleKeys._

  object SimpleKeys {
    lazy val condition = SettingKey[Boolean]("mode", "The mode.")

    lazy val pre = TaskKey[Unit]("test-with-pre", "Do some pre step.")

    lazy val testWithPre = TaskKey[Unit]("test-with-pre", "Run pre task beforehand")
    lazy val testCustom = TaskKey[Unit]("test-custom", "Run pre (depending on condition) and then test.")

    lazy val testOnlyWithPre = InputKey[Unit]("test-only-with-pre", "Run selected tests (like test-only in SBT) with pre executed before.")
    lazy val testOnlyCustom = InputKey[Unit]("test-only-configured", "Run pre (depending on condition) and then call test-only.")
  }

  lazy val baseSettings: Seq[sbt.Def.Setting[_]] = Seq(

    // this is working
    testWithPre := test.value,
    testWithPre <<= testWithPre.dependsOn( pre ),

    testCustom := Def.taskDyn {
      val c = condition.value

      if (c) {
        testWithPre
      } else {
        test
      }
    }.value,


    //
    // this is the part, where my question focuses on
    //
    testOnlyWithPre := testOnly.evaluated,
    testOnlyWithPre <<= testOnlyWithPre.dependsOn( pre ),

    // is this the correct approach?
    testOnlyCustom := Def.inputTaskDyn {
      // ???????????????????????????????
      Def.task()
    }.evaluated
  )

  lazy val testSimpleSettings: Seq[sbt.Def.Setting[_]] = baseSettings
}
  1. inputTaskDyn 是正确的选择吗?它到底是做什么的?我刚刚选择了它,因为它似乎是 InputTasks 的动态版本。不幸的是,关于 inputTaskDyn.
  2. 的文档非常少
  3. 可以像我一样通过 dependsOn 强制执行 "sequential" 吗?我已经看到 SBT 0.13.8 包含 Def.sequantial。但是这个好像不适用于InputTasks?
  4. 如何将 InputTask 转换为 Task(与 taskDyn / inputTaskDyn 一起使用)但仍然坚持 evaluated 而不是使用显式解析器?或者有没有办法重用 testOnly 解析器?
  5. 有人可以详细说明 InputTask.evaluated.parsed 吗? InputTask.parse 到底做了什么?

如果有人能提供可行的解决方案那就太好了!

非常感谢

马丁

我能想到的最佳解决方案是

    testOnlyCustom := Def.inputTaskDyn {
      val args: Seq[String] = spaceDelimited("").parsed
      val c = condition.value

      if (c) {
        testOnlyWithPre.toTask(" " + args.head)
      } else {
        testOnly.toTask(" " + args.head)
      }
    }.evaluated

但是,这仍然迫使我使用新的解析器 (spaceDelimited),而且我无法(重新)使用 testOnly 解析器。

对如何重用解析器有什么想法吗?

补充评论

First, OlegYch_ 在 Freenode 上指出 # sbt 即将推出 SBT 0.13.9 可以通过

执行 Inputtasks
def runInputTask[T](key: InputKey[T], input: String, state: State): (State, T)

sbt.Extracted.scala.

其次,可以通过sbt.Defaults#inputTests.

重用testOnly解析器

仅作记录,SBT 1 等价物是

testOnlyWithPre := test.dependsOn(pre).value

testOnlyWithPre := testOnly.dependsOn(pre).evaluated