当前位置: 首页 > 面试题库 >

SBT:将输入预先应用到inputKeys

洪楚
2023-03-14
问题内容

在SBT:我想以限定inputKey读取在命令行参数,轻微改变它们并 使用 该结果作为输入到其他inputKeys。

我试过了:

lazy val demo = inputKey[Unit]("A demo input task.")
lazy val root = (project in file(".")).settings(
  libraryDependencies += jUnitInterface
).settings(
  demo := {
    val args: Seq[String] = spaceDelimited("<arg>").parsed
    val one = (run in Compile).fullInput(args(0) + "foo").evaluated
  }
)

但是我得到了error: Illegal dynamic reference: args

我也尝试过:

demo := {
  val args: Seq[String] = spaceDelimited("<arg>").parsed
  System.setProperty("args0", args(0))
  val one = (run in Compile).fullInput(System.getProperty(args0) + "foo").evaluated
}

这根本不提供输入。我怀疑这是执行顺序的问题(我不需要时不设置属性,因为JVM可以随意移动行)。

因此,在绝望中,我什至尝试了残酷的行为:

demo := {
  val args: Seq[String] = spaceDelimited("<arg>").parsed
  try {
    System.setProperty("args0", args(0))
  } finally {
    val one = (run in Compile).fullInput(System.getProperty(args0) + "foo").evaluated
  }
}

强制命令。这只会引发NullPointerException。


问题答案:

正如Daniel C. Sobral所述,parsedevaluated是宏,在中定义InputWrapper

由于它们是在编译时执行的,并且参数是在运行时检索的,因此它们混合得不好。特别是,args的值仅在运行时才真正定义,并且不能由evaluated宏检索。

编辑: 与OP聊天之后,我确定他的目标是写作的捷径, myTask Foo bar 而不是 testOnly *Foo* -- --tests=*bar* ,我相应地更新了我的答案。

如前所述,由于您基本上希望编写一个“宏” myTask Foo bar而不是testOnly *Foo* -- --tests=*bar*,因此这是我的解决方案:

val filtersParser = {
    import complete.DefaultParsers._
    (token(Space) ~> token(StringBasic, "<classFilter>")) ~
        (token(Space) ~> token(StringBasic, "<methodFilter>"))
}

lazy val testFiltered = inputKey[Unit]("runs test methods matching *<methodFilter>* within classes matching *<classFilter>*")

testFiltered.in(Test) := Def.inputTaskDyn {
    val (classFilter, methodFilter) = filtersParser.parsed
    runTestsFiltered(classFilter, methodFilter)
}.evaluated

def runTestsFiltered(classFilter: String, methodFilter: String) = Def.taskDyn {
    (testOnly in Test).toTask(s" *$classFilter* -- --tests *$methodFilter*")
}

更详细

您需要一个自定义解析器来检索您期望的两个参数。这是通过以下代码实现的,该代码基本上定义了两个组,即“切分”两个空格而不记住它们,以及两个StringBasic参数,它们是解析器的结果(filtersParser类型为Parser[(String, String)]

val filtersParser = {
    import complete.DefaultParsers._
    (token(Space) ~> token(StringBasic, "<classFilter>")) ~
        (token(Space) ~> token(StringBasic, "<methodFilter>"))
}

然后,您需要一个输入任务来使用解析器的结果并将其转发到测试框架。这是在下一个代码段中完成的(如果比我更精通的人希望了解使用an的微妙之处inputTaskDyn,我很乐意为您提供启发:))。请注意任务范围的定义,该范围.in(Test)授予对测试依赖项的访问权限。

lazy val testFiltered = inputKey[Unit]("runs test methods matching *<methodFilter>* within classes matching *<classFilter>*")

testFiltered.in(Test) := Def.inputTaskDyn {
    val (classFilter, methodFilter) = filtersParser.parsed
    runTestsFiltered(classFilter, methodFilter)
}.evaluated

代码的最后一部分只是将参数转发给预先存在的testOnly任务:

def runTestsFiltered(classFilter: String, methodFilter: String) = Def.taskDyn {
    (testOnly in Test).toTask(s" *$classFilter* -- --tests *$methodFilter*")
}

先前的答案

但是,您应该能够通过将定义和用法拆分为两个任务来解决它:

import sbt._
import complete.DefaultParsers._

lazy val loadArgTask = inputKey[Unit]("loads and transforms argument")

lazy val runStuff = taskKey[Unit]("Runs some stuff")

lazy val loadArgIntoPropertyTask: Def.Initialize[InputTask[Unit]] = Def.inputTask {
    val myArg = (token(Space) ~> token(StringBasic, "<myArg>")).parsed
    System.setProperty("myArg", myArg + "foo")
}

loadArgTask <<= loadArgIntoPropertyTask

runStuff := {
    println(System.getProperty("myArg"))
}

可以如下使用

> loadArgTask orange
[success] Total time: 0 s, completed [...]
> runStuff
orangefoo
[success] Total time: 0 s, completed [...]


 类似资料:
  • 问题内容: 我正在尝试像这样使用AngularJS和UI Bootstrap 设置: .html .js 目前,我已经能够使用所选名称更新模型,但是我的目标是通过传递整个对象。有一种干净的方法可以仅使用输入来执行此操作吗? 问题答案: 当然可以:-) 从预输入指令http://angular-ui.github.io/bootstrap/使用作为AngularJS相同的超灵活的语法选择指令进行。所

  • 我使用高斯朴素贝叶斯(Gaussian Naive Bayes)从熊猫(Pandas)数据帧中训练模型,但使用precision\u recall\u曲线时出现错误。文档中说precision\u recall\u曲线将预测的概率作为输入(至少在我读到的时候),因此我希望下面的方法能够起作用(xtrain和xtest分别是736行和184行的熊猫数据帧;ytrain/ytest分别是736行和18

  • 我希望使用预先设计的URL功能,允许我的无服务器应用程序的用户上传图像。看完之后,这听起来是一个完美的解决方案,但是我有一个关于安全性的问题。 通过使用预先设计的URL方法,上传发生在客户端而不是服务器端,对此我唯一的担忧是,尽管我的应用程序要求在上传发生前进行身份验证,但这并不能防止用户上传恶意文件,因为他们可以绕过客户端检查来确定文件是否是图像。 有人对这件事有任何澄清吗? 谢谢

  • 问题内容: 我正在为业余时间使用的聊天应用程序编写JS,并且需要具有根据用户提交的数据而变化的HTML标识符。从概念上讲,这通常有些不稳定,以至于我什至都不会尝试,但是这次我没有太多选择。然后,我需要做的是转义HTML ID,以确保它不会允许XSS或破坏HTML。 这是代码: 避免上述任何问题的最佳逃脱途径是什么?如您所见,现在我正在使用内置函数,但不确定将其与其他替代方案相比有多好。在输入到文本

  • 我已经和它斗争了好几天了,但还是没有运气:(尝试添加一些“解析器”等,但我没有任何正确的前进方向。看起来没有org.scala-sbt#sbt;0.12.3,但我可以使用我的浏览器访问http://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt/0.12.3/ivys/ivys/ivy.xml(所以工件是可用的)。 我是在代理服务

  • 问题内容: 如何将字形图标添加到文本类型输入框?例如,我想在用户名输入中包含“ icon-user”, 问题答案: 没有引导程序: 我们将稍后介绍Bootstrap,但这是基本的CSS概念,您可以自己做。正如猎物所指出的那样,您可以通过将CSS绝对放置在输入元素内部的图标来使用CSS。然后在任一侧添加填充,以使文本不会与图标重叠。 因此,对于以下HTML: 您可以使用以下CSS左右对齐字形: De