From db0577c840425e699197c409b09674d5ce2039ac Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 8 Feb 2016 19:48:38 +1000 Subject: Add SBT tab completion for scala{,c,doc} Also refactor the partest parser to use the improved tab completion for test paths. --- project/PartestUtil.scala | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'project/PartestUtil.scala') diff --git a/project/PartestUtil.scala b/project/PartestUtil.scala index 7efe6185e5..0c0c677a6f 100644 --- a/project/PartestUtil.scala +++ b/project/PartestUtil.scala @@ -4,11 +4,25 @@ import sbt.complete._, Parser._, Parsers._ object PartestUtil { private case class TestFiles(srcPath: String, globalBase: File, testBase: File) { private val testCaseDir = new SimpleFileFilter(f => f.isDirectory && f.listFiles.nonEmpty && !(f.getParentFile / (f.name + ".res")).exists) - private def testCaseFinder = (testBase / srcPath).*(AllPassFilter).*(GlobFilter("*.scala") | GlobFilter("*.java") | GlobFilter("*.res") || testCaseDir) + private val testCaseFilter = GlobFilter("*.scala") | GlobFilter("*.java") | GlobFilter("*.res") || testCaseDir + private def testCaseFinder = (testBase / srcPath).*(AllPassFilter).*(testCaseFilter) private val basePaths = allTestCases.map(_._2.split('/').take(3).mkString("/") + "/").distinct def allTestCases = testCaseFinder.pair(relativeTo(globalBase)) def basePathExamples = new FixedSetExamples(basePaths) + private def equiv(f1: File, f2: File) = f1.getCanonicalFile == f2.getCanonicalFile + def parentChain(f: File): Iterator[File] = + if (f == null || !f.exists) Iterator() + else Iterator(f) ++ (if (f.getParentFile == null) Nil else parentChain(f.getParentFile)) + def isParentOf(parent: File, f2: File, maxDepth: Int) = + parentChain(f2).take(maxDepth).exists(p1 => equiv(p1, parent)) + def isTestCase(f: File) = { + val grandParent = if (f != null && f.getParentFile != null) f.getParentFile.getParentFile else null + grandParent != null && equiv(grandParent, testBase / srcPath) && testCaseFilter.accept(f) + } + def mayContainTestCase(f: File) = { + isParentOf(testBase / srcPath, f, 2) || isParentOf(f, testBase / srcPath, Int.MaxValue) + } } /** A parser for the custom `partest` command */ def partestParser(globalBase: File, testBase: File): Parser[String] = { @@ -28,11 +42,9 @@ object PartestUtil { if (_testFiles == null || _testFiles.srcPath != srcPath) _testFiles = new TestFiles(srcPath, globalBase, testBase) _testFiles } - val TestPathParser = token(NotSpace & not('-' ~> any.*, "File name cannot start with '-'."), TokenCompletions.fixed({ - (seen, level) => - val suggestions = testFiles.allTestCases.map(_._2).filter(_.startsWith(seen)).map(_.stripPrefix(seen)) - Completions.strict(suggestions.map(s => Completion.token(seen, s)).toSet) - })) + val TestPathParser = ParserUtil.FileParser( + new SimpleFileFilter(f => testFiles.isTestCase(f)), + new SimpleFileFilter(f => testFiles.mayContainTestCase(f)), globalBase) // allow `--grep "is unchecked" | --grep *t123*, in the spirit of ./bin/partest-ack // superset of the --grep built into partest itself. @@ -66,7 +78,7 @@ object PartestUtil { case Seq() => failure("no tests match pattern / glob") case x => success(x.mkString(" ")) } - ((token(grepOption <~ Space)) ~> token(globOrPattern, tokenCompletion)) + token(grepOption <~ Space) ~> token(globOrPattern, tokenCompletion) } val SrcPath = ((token(srcPathOption) <~ Space) ~ token(StringBasic.examples(Set("files", "pending", "scaladoc")))) map { @@ -74,9 +86,7 @@ object PartestUtil { srcPath = path opt + " " + path } - // allow the user to additional abitrary arguments, in case our parser is incomplete. - val WhatEver = token(NotSpace, _ => true).filter(x => !knownUnaryOptions.contains(x) && !Set(grepOption, srcPathOption).contains(x), x => x) - val P = oneOf(knownUnaryOptions.map(x => token(x))) | SrcPath | TestPathParser | Grep //| WhatEver - (Space ~> repsep(P, oneOrMore(Space))).map(_.mkString(" ")) + val P = oneOf(knownUnaryOptions.map(x => token(x))) | SrcPath | TestPathParser | Grep + (Space ~> repsep(P, oneOrMore(Space))).map(_.mkString(" ")).?.map(_.getOrElse("")) } } -- cgit v1.2.3