假设已经有了一个名为 openbrowser
的任务用于打开浏览器(由于插件的缘故)。以下是我们在输入任务后排序任务的方法。
lazy val runopen = inputKey[Unit]("run and then open the browser")
lazy val openbrowser = taskKey[Unit]("open the browser")
lazy val root = (project in file("."))
.settings(
runopen := (Def.inputTaskDyn {
import sbt.complete.Parsers.spaceDelimited
val args = spaceDelimited("<args>").parsed
Def.taskDyn {
(Compile / run).toTask(" " + args.mkString(" ")).value
openbrowser
}
}).evaluated,
openbrowser := {
println("open browser!")
}
)
尝试重新连接 Compile / run
会很复杂。由于对内部 Compile / run
的引用已经在延续任务中,简单地将 runopen
重新连接到 Compile / run
会创建一个循环引用。为了打破循环,我们将引入 Compile / run
的克隆,称为 Compile / actualRun
lazy val actualRun = inputKey[Unit]("The actual run task")
lazy val openbrowser = taskKey[Unit]("open the browser")
lazy val root = (project in file("."))
.settings(
Compile / run := (Def.inputTaskDyn {
import sbt.complete.Parsers.spaceDelimited
val args = spaceDelimited("<args>").parsed
Def.taskDyn {
(Compile / actualRun).toTask(" " + args.mkString(" ")).value
openbrowser
}
}).evaluated,
Comile / actualRun := Defaults.runTask(
Runtime / fullClasspath,
Compile / run / mainClass,
Compile / run / runner
).evaluated,
openbrowser := {
println("open browser!")
}
)
* 请注意,某些任务(例如 testOnly
)会在结尾处出现空格,因此可能需要对为 toTask
构建的字符串进行右修剪(.replaceAll("\s+$", "")
)来处理空 args
。
Compile / actualRun
的实现是从 Defaults.scala
中 run
任务的实现复制粘贴的。
现在,我们可以从 shell 中调用 run foo
,它会使用传递的参数评估 Compile / actualRun
,然后评估 openbrowser
任务。