プラグインによって、`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`)は末尾のスペースで失敗することに注意してください。そのため、空の `args` を処理するには、`toTask` 用に構築された文字列の右トリム(`.replaceAll("\s+$", "")`)が必要になる場合があります。
`Compile / actualRun` の実装は、Defaults.scala の `run` タスクの実装からコピーペーストされました。
これで、シェルから `run foo` を呼び出すと、渡された引数で `Compile / actualRun` が評価され、次に `openbrowser` タスクが評価されます。