Transition to all camelCase key labels.

1. Hyphenated labels are still accepted when parsing scoped keys (so 'sbt test-only' still works)
   There is currently no timeline for removing this support for hyphenated keys.
2. Only camelCase is shown for tab completion.
3. AttributeKey.rawLabel provides the unnormalized label.
   This should only be used to implement support for accepting hyphenated keys as input for compatibility.
4. AttributeKey.normLabel provides the normalized label (hyphenated converted to camelCase)
This commit is contained in:
Mark Harrah 2012-11-13 14:52:33 -05:00
parent 49e7214fe3
commit a38bce8d41
7 changed files with 28 additions and 12 deletions

View File

@ -131,8 +131,9 @@ object Act
def key(index: KeyIndex, proj: Option[ResolvedReference], conf: Option[String], task: Option[AttributeKey[_]], keyMap: Map[String,AttributeKey[_]]): Parser[AttributeKey[_]] =
{
def dropHyphenated(keys: Set[String]): Set[String] = keys.filterNot(Util.hasHyphen)
def keyParser(keys: Set[String]): Parser[AttributeKey[_]] =
token(ID !!! "Expected key" examples keys) flatMap { keyString=>
token(ID !!! "Expected key" examples dropHyphenated(keys)) flatMap { keyString=>
getKey(keyMap, keyString, idFun)
}
keyParser(index.keys(proj, conf, task))
@ -155,9 +156,11 @@ object Act
def taskAxis(d: Option[String], tasks: Set[AttributeKey[_]], allKnown: Map[String, AttributeKey[_]]): Parser[ParsedAxis[AttributeKey[_]]] =
{
val knownKeys: Map[String, AttributeKey[_]] = tasks.toSeq.map(key => (key.label, key)).toMap
val valid = allKnown ++ knownKeys
val suggested = knownKeys.keySet
val taskSeq = tasks.toSeq
def taskKeys(f: AttributeKey[_] => String): Seq[(String, AttributeKey[_])] = taskSeq.map(key => (f(key), key))
val normKeys = taskKeys(_.label)
val valid = allKnown ++ normKeys ++ taskKeys(_.rawLabel)
val suggested = normKeys.map(_._1).toSet
val keyP = filterStrings(examples(ID, suggested, "key"), valid.keySet, "key") map valid
(token(value(keyP) | GlobalString ^^^ ParsedGlobal ) <~ token("::".id) ) ?? Omitted
}

View File

@ -125,9 +125,12 @@ object Index
settings.flatMap(s => if(s.key.key.isLocal) Nil else s.key +: s.dependencies).filter(!_.key.isLocal).toSet
def attributeKeys(settings: Settings[Scope]): Set[AttributeKey[_]] =
settings.data.values.flatMap(_.keys).toSet[AttributeKey[_]]
def stringToKeyMap(settings: Set[AttributeKey[_]]): Map[String, AttributeKey[_]] =
def stringToKeyMap(settings: Set[AttributeKey[_]]): Map[String, AttributeKey[_]] =
stringToKeyMap0(settings)(_.rawLabel) ++ stringToKeyMap0(settings)(_.label)
private[this] def stringToKeyMap0(settings: Set[AttributeKey[_]])(label: AttributeKey[_] => String): Map[String, AttributeKey[_]] =
{
val multiMap = settings.groupBy(_.label)
val multiMap = settings.groupBy(label)
val duplicates = multiMap collect { case (k, xs) if xs.size > 1 => (k, xs.map(_.manifest)) } collect { case (k, xs) if xs.size > 1 => (k, xs) }
if(duplicates.isEmpty)
multiMap.collect { case (k, v) if validID(k) => (k, v.head) } toMap;

View File

@ -62,7 +62,7 @@ trait ExtendableKeyIndex extends KeyIndex
// task axis <-> key
private final class AKeyIndex(val data: Relation[ Option[AttributeKey[_]], String])
{
def add(task: Option[AttributeKey[_]], key: AttributeKey[_]): AKeyIndex = new AKeyIndex(data + (task, key.label))
def add(task: Option[AttributeKey[_]], key: AttributeKey[_]): AKeyIndex = new AKeyIndex(data + (task, key.rawLabel) + (task, key.label))
def keys(task: Option[AttributeKey[_]]): Set[String] = data.forward(task)
def allKeys: Set[String] = data._2s.toSet
def tasks: Set[AttributeKey[_]] = data._1s.flatten.toSet

View File

@ -163,7 +163,7 @@ object BuiltinCommands
val extracted = Project.extract(s)
import extracted._
val index = structure.index
index.keyIndex.keys(Some(currentRef)).toSeq map index.keyMap
index.keyIndex.keys(Some(currentRef)).toSeq.map(index.keyMap).distinct
}
def sortByLabel(keys: Seq[AttributeKey[_]]): Seq[AttributeKey[_]] = keys.sortBy(_.label)

View File

@ -285,7 +285,7 @@ private[sbt] object SettingCompletions
/** Transforms the hypenated key label `k` into camel-case and quotes it with backticks if it is a Scala keyword.
* 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 keyScalaID(k: String): String = Util.quoteIfKeyword(Util.hypenToCamel(k))
def keyScalaID(k: String): String = Util.quoteIfKeyword(Util.hyphenToCamel(k))
/** Transforms the configuration name `c` so that the first letter is capitalized and the name is quoted with backticks if it is a Scala keyword.
* This is intended to be an estimate of the Scala identifier that may be used to reference the keyword in the default sbt context. */

View File

@ -11,6 +11,8 @@ import scala.reflect.Manifest
// a single AttributeKey instance cannot conform to AttributeKey[T] for different Ts
sealed trait AttributeKey[T] {
def manifest: Manifest[T]
@deprecated("Should only be used for compatibility during the transition from hyphenated labels to camelCase labels.", "0.13.0")
def rawLabel: String
def label: String
def description: Option[String]
def extend: Seq[AttributeKey[_]]
@ -48,13 +50,15 @@ object AttributeKey
private[this] def make[T](name: String, description0: Option[String], extend0: Seq[AttributeKey[_]], rank0: Int)(implicit mf: Manifest[T]): AttributeKey[T] = new SharedAttributeKey[T] {
def manifest = mf
def label = name
def rawLabel = name
val label = Util.hyphenToCamel(name)
def description = description0
def extend = extend0
def rank = rank0
}
private[sbt] def local[T](implicit mf: Manifest[T]): AttributeKey[T] = new AttributeKey[T] {
def manifest = mf
def rawLabel = LocalLabel
def label = LocalLabel
def description = None
def extend = Nil

View File

@ -26,8 +26,14 @@ object Util
def pairID[A,B] = (a: A, b: B) => (a,b)
private[this] lazy val Hypen = """-(\p{javaLowerCase})""".r
def hypenToCamel(s: String): String =
Hypen.replaceAllIn(s, _.group(1).toUpperCase)
def hasHyphen(s: String): Boolean = s.indexOf('-') >= 0
@deprecated("Use the properly spelled version: hyphenToCamel", "0.13.0")
def hypenToCamel(s: String): String = hyphenToCamel(s)
def hyphenToCamel(s: String): String =
if(hasHyphen(s))
Hypen.replaceAllIn(s, _.group(1).toUpperCase)
else
s
private[this] lazy val Camel = """(\p{javaLowerCase})(\p{javaUpperCase})""".r
def camelToHypen(s: String): String =