Tab completion of right side of setting in 'set' command no longer necessary with the new task syntax.

This commit is contained in:
Mark Harrah 2012-12-06 19:11:07 -05:00
parent 518bbc4077
commit f55c8ca15e
1 changed files with 3 additions and 78 deletions

View File

@ -143,21 +143,11 @@ private[sbt] object SettingCompletions
val function = "{(prev: " + typeString + ") => /*" + typeString + "*/ }"
token(OptSpace ~ function) ^^^ Nil
}
else if( assignNoInput(assign) )
else
{
val value = "/* value of type " + typeString + " */"
token(Space ~ value) ^^^ Nil
}
else
{
val open = token(OptSpace ~ '(')
val quietOptSpace = SpaceClass.*
val inputKeys = rep1sep(scopedKeyP, token(quietOptSpace ~ ',' ~ OptSpace))
val close = token(quietOptSpace ~ ')')
val method = token(Space ~ assignMethodName(sk.key))
val start = open ~> inputKeys <~ (close ~ method)
for(in <- start; _ <- initializeFunction(in, typeString,true)) yield in
}
}
/** For a setting definition `definingKey <<= (..., in, ...) { ... }`,
@ -166,20 +156,6 @@ private[sbt] object SettingCompletions
def keyFilter(definingKey: AttributeKey[_]): AttributeKey[_] => Boolean =
if(isSetting(definingKey)) isSetting _ else isTaskOrSetting _
/** Parser for the function literal part of an initialization expression given inputs `in` and
* the underlying type of the setting or task `typeString`.
* This parser is not useful for actually parsing; it mainly provides a completion suggestion
* that is a template for implementing the function. The parameter names are autogenerated mnemonics
* for the input keys they correspond to. If `withTypes` is true, explicit types will be given for the parameters. */
def initializeFunction(in: Seq[ScopedKey[_]], typeString: String, withTypes: Boolean): Parser[Seq[ScopedKey[_]]] =
{
val names = mnemonics(in.map(_.key))
val types = in.map(sk => keyTypeString(sk.key))
val params = if(withTypes) (names, types).zipped.map(_ + ": " + _) else names
val function = params.mkString("{(", ", ", ") => /* " + typeString + " */ }" )
token( OptSpace ~ function ) ^^^ in
}
/** Parser for a Scope for a `key` given the current project `context` and evaluated `settings`.
* The completions are restricted to be more useful. Currently, this parser will suggest
* only known axis values for configurations and tasks and only in that order.*/
@ -238,8 +214,7 @@ private[sbt] object SettingCompletions
def completeAssign(seen: String, level: Int, key: ScopedKey[_]): Seq[Completion] =
{
val allowed: Iterable[Assign.Value] =
if(isInputTask(key.key)) Assign.DefineDep :: Nil
else if(appendable(key.key)) Assign.values
if(appendable(key.key)) Assign.values
else assignNoAppend
val applicable = allowed.toSeq.flatMap { a =>
val s = a.toString
@ -291,36 +266,6 @@ private[sbt] object SettingCompletions
* This is intended to be an estimate of the Scala identifier that may be used to reference the keyword in the default sbt context. */
def configScalaID(c: String): String = Util.quoteIfKeyword(c.capitalize)
/** Returns unambiguous mnemonics for the provided sequence of `keys`.
* The key labels are first transformed to the shortest unambiguous prefix.
* Then, duplicate keys in the sequence are given a unique numeric suffix.
* The results are returned in the same order as the corresponding input keys. */
def mnemonics(keys: Seq[AttributeKey[_]]): Seq[String] =
{
val names = keys.map(key => keyScalaID(key.label))
val shortened = shortNames(names.toSet)
val repeated = collection.mutable.Map[String,Int]()
names.map { name =>
val base = shortened(name)
val occurs = repeated.getOrElse(base, 1)
repeated.put(base, occurs+1)
if(occurs > 1) base + occurs.toString else base
}
}
/** For a set of strings, generates a mapping from the original string to the shortest unambiguous prefix.
* For example, for `Set("blue", "black", "green"), this returns `Map("blue" -> "blu", "black" -> "bla", "green" -> "g")` */
def shortNames(names: Set[String]): Map[String,String] =
{
def loop(i:Int, current: Set[String]): Map[String,String] = {
val (unambiguous, ambiguous) = current.groupBy(_ charAt i).partition { case (_, v) => v.size <= 1 }
val thisLevel = unambiguous.values.flatten.map(s => (s, s.substring(0,i+1)))
val down = ambiguous.values.flatMap { (vs: Set[String]) => loop(i+1, vs) }
(thisLevel ++ down).toMap
}
loop(0, names)
}
/** Applies a function on the underlying manifest for T for `key` depending if it is for a `Setting[T]`, `Task[T]`, or `InputTask[T]`.*/
def keyType[S](key: AttributeKey[_])(onSetting: Manifest[_] => S, onTask: Manifest[_] => S, onInput: Manifest[_] => S)(implicit tm: Manifest[Task[_]], im: Manifest[InputTask[_]]): S =
{
@ -358,11 +303,6 @@ private[sbt] object SettingCompletions
appendableClasses.exists(_ isAssignableFrom underlying)
}
/** Name of the method to apply a function to several inputs depending on whether `key` is for a setting or task. */
def assignMethodName(key: AttributeKey[_]): String =
if(isSetting(key)) SettingAppName else TaskAppName
/** The simple name of the global scope axis, which can be used to reference it in the default setting context. */
final val GlobalID = Global.getClass.getSimpleName.stripSuffix("$")
@ -372,38 +312,23 @@ private[sbt] object SettingCompletions
/** Name of the method that modifies the scope of a key. */
final val InMethod = "in"
/** Name of the method that applies a function to several setting inputs (type Initialize[T]), producing a new setting.*/
final val SettingAppName = "apply"
/** Name of the method used to apply a function to several task inputs (type Initialize[Task[T]]), producing a new task*/
final val TaskAppName = "map"
/** Assignment methods that may be called on a setting or task. */
object Assign extends Enumeration {
val AppendValue = Value("+=")
val AppendValueDep = Value("<+=")
val AppendValues = Value("++=")
val AppendValuesDep = Value("<++=")
val Define = Value(":=")
val DefineDep = Value("<<=")
val Update = Value("~=")
}
import Assign._
/** Returns the description associated with the provided assignment method. */
def assignDescription(a: Assign.Value): String = a match {
case AppendValue => "append value"
case AppendValueDep => "append dependent value"
case AppendValues => "append values"
case AppendValuesDep => "append dependent values"
case Define => "define value, overwriting any existing value"
case DefineDep => "define dependent value, overwriting any existing value"
case Update => "transform existing value"
}
/** The assignment methods except for the ones that append. */
val assignNoAppend: Set[Assign.Value] = Set(Define, DefineDep, Update)
/** The assignment methods that do not accept an Initialize (that is, don't use values from other settings/tasks). */
val assignNoInput: Set[Assign.Value] = Set(AppendValue, AppendValues, Define, Update)
val assignNoAppend: Set[Assign.Value] = Set(Define, Update)
/** Class values to approximate which types can be appended*/
val appendableClasses = Seq(