如何在 SBT 的 onLoad 挂钩上应用设置更改? [英] How can I apply setting changes on onLoad hook in SBT?

查看:36
本文介绍了如何在 SBT 的 onLoad 挂钩上应用设置更改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 SBT 中有一些设置,我需要在加载的插件执行一些副作用后从中生成值.onLoad 钩子似乎是最好的地方.钩子接收一个 State,转换它并返回一个新的.使用 State 方法很容易调度命令,但更改设置似乎并不容易.

I have some settings in SBT that I need to generate values from after a loaded plugin has performed some side-effects. The onLoad hooks seem the best place to do that. The hook receives a State, transforms it and returns a new one. It's easy to schedule commands with State methods, but changing settings doesn't seem very easy.

我首先尝试了以下代码,该代码失败了,因为它似乎导致了对 onLoad 的递归调用,并且由于参与者名称重复(可能是递归的产物)而失败.

I first tried the following code, which fails because it seems to cause a recursive call to onLoad and a failure due to a duplicate actor name (probably a product of the recursion).

onLoad in Global := (onLoad in Global).value andThen { state =>
  val settings = generateMySettings
  Project.extract(state).append(settings, state)
}

我看到的另一种替代方法是直接在 State 本身中调用 putupdate 方法,但这看起来很丑陋且容易出错.有没有更好/更干净的方法?

The other alternative I see is calling the put or update methods in State itself directly, but that seems quite ugly and error prone. Is there a better/cleaner way?

推荐答案

有一个很好的例子说明如何在 github sbt repo 的 onLoad hook 中重新连接"项目设置:https://github.com/sbt/sbt-community-plugins/blob/master/project/Dependencies.scala

There is a good example of how to "rewire" project settings in onLoad hook at github sbt repo: https://github.com/sbt/sbt-community-plugins/blob/master/project/Dependencies.scala

我不确定为什么 onLoad 钩子可能会被执行多次,但解决您的问题的方法是简单地定义一个布尔标志属性,以便在标志尚未触发的情况下有条件地仅调用一次您的钩子.

I'm not sure why the onLoad hook might be executed more than one time, but the solution to your problem is to simply define a boolean flag attribute to conditionally call your hook only once if the flag wasn't triggered yet.

在上面提到的例子中,他们就是这样做的,

In the mentioned example they're doing it exactly like this,

trait GenerateMySettingsStartup extends Build {
  private lazy val generated =  AttributeKey[Boolean]("my-settings-generated")
  def generateCommandName = "generate-my-settings"

  private final def fixState(state: State): State = 
    if(state.get(generated) getOrElse false) {
      state
    } else {
      // >>> generate and append your settings here <<<
      state.put(generated, true)
    }

  private def initialize = Command.command(generateCommandName)(fixState(_))

  final def generateSettings: Seq[Setting[_]] = Seq(
    commands += initialize,
    // initialize onLoad task if not yet defined
    onLoad in Global <<= (onLoad in Global) ?? idFun[State],
    // append generateCommandName onLoad handler
    onLoad in Global <<= (onLoad in Global) apply ( _ andThen (generateCommandName :: _))
  )
}

然后只需将 GenerateMySettingsStartup#generateSettings 应用于您的项目设置.

then just apply GenerateMySettingsStartup#generateSettings to your project's settings.

附言不确定我是否理解正确,但在这里我认为 onLoad 钩子是通过 Command 定义的,因为它可以访问在某些范围内可能未定义的状态,只是一个疯狂的猜测,所以如果我的假设是错误的,请澄清我,谢谢!

P.S. Not sure if I've got it all right, but here I think the onLoad hook was defined through Command because it has access to a State which might not be defined at certain scopes, just a wild guess so clarify me if my assumption is wrong, thanks!

这篇关于如何在 SBT 的 onLoad 挂钩上应用设置更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆