SBT 插件 - 通过他们的 build.sbt 用户定义的命令配置

Posted

技术标签:

【中文标题】SBT 插件 - 通过他们的 build.sbt 用户定义的命令配置【英文标题】:SBT plugin - User defined configuration for Command via their build.sbt 【发布时间】:2013-06-06 23:33:09 【问题描述】:

我正在编写一个添加命令的 SBT 插件,并希望用户能够通过在 build.sbt 中设置变量来配置此命令。实现这一目标的最简单方法是什么?

这是插件外观的简化示例:

import sbt.Keys._
import sbt._

object MyPlugin extends Plugin 

  override lazy val settings = Seq(commands += Command.args("mycommand", "myarg")(myCommand))

  def myCommand = (state: State, args: Seq[String]) => 

    //Logic for command...

    state
  

我希望有人能够将以下内容添加到他们的 build.sbt 文件中:

newSetting := "light"

如何从上面的myCommand 命令中将其作为String 变量提供?

【问题讨论】:

【参考方案1】:

看看这里的例子:http://www.scala-sbt.org/release/docs/Extending/Plugins.html#example-plugin

在本例中,定义了一个任务和设置:

val newTask = TaskKey[Unit]("new-task")
val newSetting = SettingKey[String]("new-setting")

val newSettings = Seq(
  newSetting := "test",
  newTask <<= newSetting map  str => println(str) 
)

然后,您插件的用户可以在他们的 build.sbt 中为 newSetting 设置提供他们自己的值:

newSetting := "light"

编辑

这是另一个例子,更接近你的目标:

Build.scala

import sbt._                                                
import Keys._                                               

object HelloBuild extends Build                            

    val newSetting = SettingKey[String]("new-setting", "a new setting!")

    val myTask = TaskKey[State]("my-task")                  

    val mySettings = Seq(                                   
      newSetting := "default",                              
      myTask <<= (state, newSetting) map  (state, newSetting) =>  
        println("newSetting: " + newSetting)                
        state
      
    )

    lazy val root =
      Project(id = "hello",
              base = file("."),
              settings = Project.defaultSettings ++ mySettings)            

使用此配置,您可以在 sbt 提示符下运行my-task,您会看到newSetting: default 打印到控制台。

您可以在 build.sbt 中覆盖此设置:

newSetting := "modified"

现在,当您在 sbt 提示符下运行 my-task 时,您会看到 newSetting: modified 打印到控制台。

编辑 2

这是上述示例的独立版本:https://earldouglas.com/ext/***.com/questions/17038663/

【讨论】:

我试过这个,但没有太多的乐趣。 TBH,我不确定TaskKey 是什么,所以我认为我需要阅读更多内容。我已将问题编辑为更具体地说明我的用例,这是一个 SBT 插件,它添加了 SBT Command 并添加了我目前拥有的代码示例。如果您对我可能出错的地方有任何想法,请告诉我。 找到了一些相当不错的文档here,并且任务和命令看起来非常相似。 (也提到了here)我想明天我会尝试从使用Commands 迁移到使用Tasks。 我用一个更接近您正在寻找的示例更新了我的答案。 我已经在插件中实现了这个功能 - 感谢您的帮助。我稍后会在您的回答中添加更多关于我遇到的其他问题,如果可以的话? 没问题,请随时添加到我的答案中。【参考方案2】:

我接受了@James 的回答,因为它确实帮助了我。我不再使用命令来支持任务(请参阅this mailing list thread)。最后我的插件看起来像这样:

package packge.to.my.plugin

import sbt.Keys._
import sbt._

object MyPlugin extends Plugin 

  import MyKeys._

  object MyKeys 
    val myTask = TaskKey[Unit]("runme", "This means you can run 'runme' in the SBT console")
    val newSetting = SettingKey[String]("newSetting")
  

  override lazy val settings = Seq (
    newSetting := "light",
    myTask <<= (state, newSetting) map myCommand
  )

  def myCommand(state: State, newSetting: String) 
    //This code runs when the user types the "runme" command in the SBT console
    //newSetting is "light" here unless the user overrides in their build.sbt (see below)
    state.log.info(newSetting)
  

要覆盖使用此插件的项目的build.sbt 中的newSetting

import packge.to.my.plugin.MyKeys._

newSetting := "Something else"

缺少的导入语句让我卡了一段时间!

【讨论】:

您确定在.sbt 文件中允许导入吗? 是的,虽然它必须在文件的最顶部。

以上是关于SBT 插件 - 通过他们的 build.sbt 用户定义的命令配置的主要内容,如果未能解决你的问题,请参考以下文章

Sbt Plugin 添加依赖到 project/build.sbt

通过 SBT 中的系统属性指定 flywayUrl

play-sbt 2.5.6 插件给出未解决的依赖错误

在 build.sbt 和 project/plugins.sbt 中避免冗余/重用 ModuleID?

测试 sbt 插件

如何通知 SBT 使用插件的特定 scala 版本?