【问题标题】:Filtering tab completion in input task implementation在输入任务实现中过滤选项卡完成
【发布时间】:2014-02-04 20:54:59
【问题描述】:

我目前正在为Gatling 实现一个 SBT 插件。 它的一项功能是在 SBT 的新浏览器选项卡中打开最后生成的报告。 由于每次运行都可以有不同的“模拟 ID”(基本上是一个简单的字符串),我想在模拟 ID 上提供选项卡补全。

一个例子:

运行 Gatling SBT 插件将在target/gatling 中生成多个文件夹(以simulationId + 报告生成日期命名),例如mysim-20140204234534myothersim-20140203124534yetanothersim-20140204234534

我们将任务称为lastReport。 如果有人开始输入lastReport my,我想过滤掉制表符补全,只建议mysimmyothersim

获取模拟 ID 是一件轻而易举的事,但如何帮助解析器过滤掉建议,使其只建议现有​​的模拟 ID?

总而言之,我想做testOnly 所做的事情,在某种程度上:我只想建议在我的上下文中有意义的事情。

提前感谢您的回答,

皮埃尔

编辑:由于我最近一次尝试后有点卡住,这是我的 inputTask 的代码,处于当前状态:

package io.gatling.sbt

import sbt._
import sbt.complete.{ DefaultParsers, Parser }

import io.gatling.sbt.Utils._

object GatlingTasks {

val lastReport = inputKey[Unit]("Open last report in browser")

val allSimulationIds = taskKey[Set[String]]("List of simulation ids found in reports folder")

val allReports = taskKey[List[Report]]("List of all reports by simulation id and timestamp")

def findAllReports(reportsFolder: File): List[Report] = {
    val allDirectories = (reportsFolder ** DirectoryFilter.&&(new PatternFilter(reportFolderRegex.pattern))).get
    allDirectories.map(file => (file, reportFolderRegex.findFirstMatchIn(file.getPath).get)).map {
        case (file, regexMatch) => Report(file, regexMatch.group(1), regexMatch.group(2))
    }.toList
}

def findAllSimulationIds(allReports: Seq[Report]): Set[String] = allReports.map(_.simulationId).distinct.toSet

def openLastReport(allReports: List[Report], allSimulationIds: Set[String]): Unit = {
    def simulationIdParser(allSimulationIds: Set[String]): Parser[Option[String]] =
        DefaultParsers.ID.examples(allSimulationIds, check = true).?

    def filterReportsIfSimulationIdSelected(allReports: List[Report], simulationId: Option[String]): List[Report] =
        simulationId match {
            case Some(id) => allReports.filter(_.simulationId == id)
            case None => allReports
        }

    Def.inputTaskDyn {
        val selectedSimulationId = simulationIdParser(allSimulationIds).parsed
        val filteredReports = filterReportsIfSimulationIdSelected(allReports, selectedSimulationId)
        val reportsSortedByDate = filteredReports.sorted.map(_.path)
        Def.task(reportsSortedByDate.headOption.foreach(file => openInBrowser((file / "index.html").toURI)))
    }
}

}

当然,openReport 是使用allReportsallSimulationIds 任务的结果调用的。 我想我已经接近正常的输入任务,但我仍然缺少一些东西......

【问题讨论】:

  • 当然,SBT 的文档始终是我的第一站 :) 我还研究了 testOnlytestQuick 实现,我发现我基本上是在寻找 Parserexamples 方法特征。但是,我没有设法让它工作,但我认为我正在做一些事情。我会回来分享我的解决方案。
  • 好的,我问是因为如果你有一个工作的解析器(或几乎工作),它会更容易提供帮助。如果您尝试过一些使用制表符完成的方法,那么描述它也会有所帮助。发布不起作用的代码是一个好的开始 - 在它起作用之前无需继续尝试!
  • 我在 OP 中添加了当前无法运行的代码。我觉得它接近一个可行的解决方案,但我总是被编译器咬住(inputTaskDyn 必须返回 Task 或者我得到 Illegal dynamic reference 错误)或者我的任务根本不起作用......看起来它永远不会进入inputTaskDyn 的正文。

标签: sbt tab-completion


【解决方案1】:
  1. Def.inputTaskDyn 返回一个InputTask[T] 类型的值并且不执行任何副作用。结果需要绑定到InputKey,例如lastReportopenLastReport 的返回类型是Unit,这意味着openLastReport 将构造一个将被丢弃的值,实际上没有做任何有用的事情。相反,有:

    def openLastReport(...): InputTask[...] = ...
    
    lastReport := openLastReport(...).evaluated
    

    (或者,openLastReport的实现可以内联到:=的右侧)

  2. 您可能不需要inputTaskDyn,而只需要inputTask。如果您需要返回任务,则只需要inputTaskDyn。否则,使用inputTask 并删除Def.task

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    • 2019-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多