假設因為外掛程式,已經有一個名為 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 / actualRun
的 Compile / run
複製品
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
任務。