From 569e19d03c705f8e1c4e7a78d2f444bfda17313e Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Wed, 30 Nov 2016 02:33:05 -0500 Subject: [PATCH] Add build-level keys to the tab completion Fixes #2460 Fixes #2851 Ref #2707, #2708, #2469 Unlike the previous attempts at fixing the handling of build-level keys, this change does not change the main parsing logic, which uses `getKey` to retrieve the key from the key map. The fact that shell worked pre-0.13.11 means that the parsing was ok. What this changes is just the "example" keys supplied to the parser so the tab completion works. --- main/src/main/scala/sbt/internal/Act.scala | 11 ++++++- notes/0.13.14/buildlevelkey.md | 9 ++++++ .../sbt-test/actions/completions/build.sbt | 29 +++++++++++++++++++ .../completions/project/FooPlugin.scala | 15 ++++++++++ sbt/src/sbt-test/actions/completions/test | 1 + 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 notes/0.13.14/buildlevelkey.md create mode 100644 sbt/src/sbt-test/actions/completions/build.sbt create mode 100644 sbt/src/sbt-test/actions/completions/project/FooPlugin.scala create mode 100644 sbt/src/sbt-test/actions/completions/test diff --git a/main/src/main/scala/sbt/internal/Act.scala b/main/src/main/scala/sbt/internal/Act.scala index c8e3660c0..6be991063 100644 --- a/main/src/main/scala/sbt/internal/Act.scala +++ b/main/src/main/scala/sbt/internal/Act.scala @@ -134,7 +134,16 @@ object Act { token(ID !!! "Expected key" examples dropHyphenated(keys)) flatMap { keyString => getKey(keyMap, keyString, idFun) } - keyParser(index.keys(proj, conf, task)) + // Fixes sbt/sbt#2460 and sbt/sbt#2851 + // The parser already accepts build-level keys. + // This queries the key index so tab completion will list the build-level keys. + val buildKeys: Set[String] = + proj match { + case Some(ProjectRef(uri, id)) => index.keys(Some(BuildRef(uri)), conf, task) + case _ => Set() + } + val keys: Set[String] = index.keys(proj, conf, task) ++ buildKeys + keyParser(keys) } def getKey[T](keyMap: Map[String, AttributeKey[_]], keyString: String, f: AttributeKey[_] => T): Parser[T] = diff --git a/notes/0.13.14/buildlevelkey.md b/notes/0.13.14/buildlevelkey.md new file mode 100644 index 000000000..e5ee44518 --- /dev/null +++ b/notes/0.13.14/buildlevelkey.md @@ -0,0 +1,9 @@ +### Bug fixes + +- Fixes regressions in sbt 0.13.11 - 0.13.13 that processed build-level keys incorrectly. [#2851][2851]/[#2460][2460] by [@eed3si9n] + + [#2851]: https://github.com/sbt/sbt/issues/2851 + [#2460]: https://github.com/sbt/sbt/issues/2460 + [@eed3si9n]: https://github.com/eed3si9n + [@dwijnand]: https://github.com/dwijnand + [@Duhemm]: https://github.com/Duhemm diff --git a/sbt/src/sbt-test/actions/completions/build.sbt b/sbt/src/sbt-test/actions/completions/build.sbt new file mode 100644 index 000000000..072ab22e7 --- /dev/null +++ b/sbt/src/sbt-test/actions/completions/build.sbt @@ -0,0 +1,29 @@ +import complete.{ Completion, Completions, DefaultParsers, Parser } +import DefaultParsers._ +import Command.applyEffect +import CommandUtil._ + +lazy val root = (project in file(".")). + enablePlugins(FooPlugin). + settings( + commands += checkCompletionsCommand + ) + +// This checks the tab completion lists build-level keys +def checkCompletionsCommand = Command.make("checkCompletions")(completionsParser) +def completionsParser(state: State) = + { + val notQuoted = (NotQuoted ~ any.*) map { case (nq, s) => (nq +: s).mkString } + val quotedOrUnquotedSingleArgument = Space ~> (StringVerbatim | StringEscapable | notQuoted) + applyEffect(token(quotedOrUnquotedSingleArgument ?? "" examples ("", " ")))(runCompletions(state)) + } +def runCompletions(state: State)(input: String): State = { + val xs = Parser.completions(state.combinedParser, input, 9).get map { + c => if (c.isEmpty) input else input + c.append + } map { c => + c.replaceAll("\n", " ") + } + println(xs) + assert(xs == Set("myTask")) + state +} diff --git a/sbt/src/sbt-test/actions/completions/project/FooPlugin.scala b/sbt/src/sbt-test/actions/completions/project/FooPlugin.scala new file mode 100644 index 000000000..092417875 --- /dev/null +++ b/sbt/src/sbt-test/actions/completions/project/FooPlugin.scala @@ -0,0 +1,15 @@ +import sbt._ +import syntax._ + +object FooPlugin extends AutoPlugin { + override def trigger = noTrigger + object autoImport { + val myTask = taskKey[Unit]("My task") + } + + import autoImport._ + + override def buildSettings = super.buildSettings ++ Seq( + myTask := println("Called my task") + ) +} diff --git a/sbt/src/sbt-test/actions/completions/test b/sbt/src/sbt-test/actions/completions/test new file mode 100644 index 000000000..942db912e --- /dev/null +++ b/sbt/src/sbt-test/actions/completions/test @@ -0,0 +1 @@ +> checkCompletions my