From 39a858de7a65b70ae35ce460e7746cae5e4d3fc4 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 10 Feb 2016 12:26:41 +1000 Subject: Fix SBT tab completion of scala command `scala -deprecation` (without a trailing script argument) wasn't allowed. Now it is. I also supported trailing whitespace on all commands. Also fixed: a bug with completion of `scalac ./san`. It was completing as though the `./` had not been typed, which threw the suggestion off by a few characters. --- project/ParserUtil.scala | 24 +++++++++++------------- project/PartestUtil.scala | 2 +- project/ScalaOptionParser.scala | 9 +++++---- 3 files changed, 17 insertions(+), 18 deletions(-) (limited to 'project') diff --git a/project/ParserUtil.scala b/project/ParserUtil.scala index f6658b146b..cdaf8831a5 100644 --- a/project/ParserUtil.scala +++ b/project/ParserUtil.scala @@ -9,41 +9,39 @@ object ParserUtil { p.map(x => x._1 + x._2) } - def EitherOr(a: Parser[String], b: Parser[String]): Parser[String] = { - a.flatMap[String] { - case "" => b - case x: String => - concat(Space.string ~ b).map[String]((s: String) => x + s) - } - } def Opt(a: Parser[String]) = a.?.map(_.getOrElse("")) val StringBasicNotStartingWithDash = notStartingWith(StringBasic, '-') val IsDirectoryFilter = new SimpleFileFilter(_.isDirectory) val JarOrDirectoryParser = FileParser(GlobFilter("*.jar") || IsDirectoryFilter) - def FileParser(filter: FileFilter, dirFilter: FileFilter = AllPassFilter, base: File = file(".")) = { + def FileParser(fileFilter: FileFilter, dirFilter: FileFilter = AllPassFilter, base: File = file(".")) = { def matching(prefix: String): List[String] = { val preFile = file(prefix) val cwd = base val parent = Option(preFile.getParentFile).getOrElse(cwd) if (preFile.exists) { if (preFile.isDirectory) { - preFile.*(IsDirectoryFilter.&&(dirFilter) || filter).get.map(_.getPath).toList + preFile.*(IsDirectoryFilter.&&(dirFilter) || fileFilter).get.map(_.getPath).toList } else { - List(preFile).filter(filter.accept).map(_.getPath) + List(preFile).filter(fileFilter.accept).map(_.getPath) } } else if (parent != null) { def ensureSuffix(s: String, suffix: String) = if (s.endsWith(suffix)) s else s + suffix - def pathOf(f: File): String = if (f.isDirectory && !filter.accept(f)) ensureSuffix(f.getPath, "/") else f.getPath - parent.*(GlobFilter(preFile.name + "*") && ((IsDirectoryFilter && dirFilter) || filter)).get.map(x => pathOf(if (parent == cwd) x.relativeTo(cwd).get else x)).toList + def pathOf(f: File): String = { + val f1 = if (preFile.getParentFile == null) f.relativeTo(cwd).getOrElse(f) else f + if (f1.isDirectory && !fileFilter.accept(f1)) ensureSuffix(f1.getPath, "/") else f1.getPath + } + val childFilter = GlobFilter(preFile.name + "*") && ((IsDirectoryFilter && dirFilter) || fileFilter) + val children = parent.*(childFilter).get + children.map(pathOf).toList } else Nil } def displayPath = Completions.single(Completion.displayOnly("")) token(StringBasic, TokenCompletions.fixed((seen, level) => if (seen.isEmpty) displayPath else matching(seen) match { case Nil => displayPath case x :: Nil => - if (filter.accept(file(x))) + if (fileFilter.accept(file(x))) Completions.strict(Set(Completion.tokenDisplay(x.stripPrefix(seen), x))) else Completions.strict(Set(Completion.suggestion(x.stripPrefix(seen)))) diff --git a/project/PartestUtil.scala b/project/PartestUtil.scala index 0c0c677a6f..4b18c94b47 100644 --- a/project/PartestUtil.scala +++ b/project/PartestUtil.scala @@ -87,6 +87,6 @@ object PartestUtil { opt + " " + path } val P = oneOf(knownUnaryOptions.map(x => token(x))) | SrcPath | TestPathParser | Grep - (Space ~> repsep(P, oneOrMore(Space))).map(_.mkString(" ")).?.map(_.getOrElse("")) + (Space ~> repsep(P, oneOrMore(Space))).map(_.mkString(" ")).?.map(_.getOrElse("")) <~ OptSpace } } diff --git a/project/ScalaOptionParser.scala b/project/ScalaOptionParser.scala index a11bd93d82..da8a3bf460 100644 --- a/project/ScalaOptionParser.scala +++ b/project/ScalaOptionParser.scala @@ -63,19 +63,20 @@ object ScalaOptionParser { ++ scaladocPathSettingNames.map(PathSetting) ++ scaladocMultiStringSettingNames.map(MultiStringSetting) ) - val ScalaDocOpt = sourceFile | ScalaOpt | ScalaDocExtraSettings + val ScalaDocOpt = ScalacOpt | ScalaDocExtraSettings - entryPoint match { + val P = entryPoint match { case "scala" => val runnable = token(StringBasicNotStartingWithDash, TokenCompletions.displayOnly("")).filter(!_.startsWith("-"), x => x) val runnableAndArgs = concat(runnable ~ Opt(concat(Space.string ~ repsep(token(StringBasic, TokenCompletions.displayOnly("")), Space).map(_.mkString(" "))))) - val options = repsep(ScalaOpt, Space).map(_.mkString(" ")) - Opt(Space ~> EitherOr(options, runnableAndArgs)) + val options = rep1sep(ScalaOpt, Space).map(_.mkString(" ")) + Opt(Space ~> (options | concat(concat(options ~ Space.string) ~ runnableAndArgs) | runnableAndArgs)) case "scaladoc" => Opt(Space ~> Opt(repsep(ScalaDocOpt, Space).map(_.mkString(" ")))) case "scalac" => Opt(Space ~> repsep(ScalacOpt, Space).map(_.mkString(" "))) } + P <~ token(OptSpace) } // TODO retrieve this data programatically, ala https://github.com/scala/scala-tool-support/blob/master/bash-completion/src/main/scala/BashCompletion.scala -- cgit v1.2.3