在编写SBT AutoPlugins时,在专用文件中写入任务

时间:2018-03-26 22:15:27

标签: scala sbt

我写了一个SBT自动插件MyPlugin.scala

package com.abhi

import sbt._
import sbt.Keys._

object MyPlugin extends AutoPlugin {
   object autoImport {
      val helloTask = taskKey[Unit]("says hello")
      val byeTask = taskKey[Unit]("bye task")
   }
   import autoImport._
   override lazy val projectSettings = Seq(
      helloTask := {
         val dir = sourceManaged.value
         val cp = (dependencyClasspath in Compile).value
         val r = (runner in Compile).value
         val s = streams.value
         val rd = (resourceDirectory in Compile).value         
         val sd = (sourceDirectory in Compile).value
         println(s"Here to say hello $dir $cp $r $s $rd $sd")
      },
      byeTask := {
         val dir = sourceManaged.value
         val cp = (dependencyClasspath in Compile).value
         val r = (runner in Compile).value
         val s = streams.value
         val rd = (resourceDirectory in Compile).value         
         val sd = (sourceDirectory in Compile).value         
         println(s"Here to say bye $dir $cp $r $s $rd $sd")
      }      
   )
}

这有效,我可以使用这个插件。但是helloTaskbyeTask的实现会有点长,所以我不想在MyPlugin.scala内编写实现。

相反,我想创建两个单独的文件HelloTask.scalaByeTask.scala,然后在那里编写相应的实现。

我查看了Custom Settings的SBT文档,所有示例都始终在插件本身内实现任务。

如何在helloTask文件之外编写byeTaskMyPlugin.scala的实现?还有如何在HelloTaskByeTask之间分享一些逻辑。

以下几行在两个任务之间是通用的,我只想写一次

val dir = sourceManaged.value
val cp = (dependencyClasspath in Compile).value
val r = (runner in Compile).value
val s = streams.value
val rd = (resourceDirectory in Compile).value         
val sd = (sourceDirectory in Compile).value

1 个答案:

答案 0 :(得分:2)

分离任务实施是一种常见的良好做法。它在Tasks documentation中提到。您可以使用Def.task宏编写实现:

def taskImpl(args: ...): Def.Initialize[Task[...]] = Def.task {
  ...
}

然后使用不同的参数设置不同的任务键:

override def projectSettings = Seq(
  taskA := taskImpl("A").value,
  taskB := taskImpl("B").value,
)

在你的情况下,你可以这样做:

def saySmthImpl(msg: String): Def.Initialize[Task[Unit]] = Def.task {
  val dir = sourceManaged.value
  val cp = (dependencyClasspath in Compile).value
  val r = (runner in Compile).value
  val s = streams.value
  val rd = (resourceDirectory in Compile).value
  val sd = (sourceDirectory in Compile).value
  println(s"$msg $dir $cp $r $s $rd $sd")
}

如果需要,您可以将此实现保留在单独的文件中。在插件定义中,您可以像这样使用它:

override def projectSettings = Seq(
  helloTask := saySmthImpl("Here to say hello").value,
  byeTask := saySmthImpl("Here to say bye").value,
)

您应该记住,使用.value访问其他设置或任务只能在某些范围内完成,例如Def.taskDef.setting或使用{{设置密钥时1}}。这限制了(或者更确切地说指示)在不同任务实现之间共享逻辑的方式。