package sbt.complete
sealed trait Completions
{
def get: Set[Completion]
final def x(o: Completions): Completions = flatMap(_ x o)
final def ++(o: Completions): Completions = Completions( get ++ o.get )
final def +:(o: Completion): Completions = Completions(get + o)
final def filter(f: Completion => Boolean): Completions = Completions(get filter f)
final def filterS(f: String => Boolean): Completions = filter(c => f(c.append))
override def toString = get.mkString("Completions(",",",")")
final def flatMap(f: Completion => Completions): Completions = Completions(get.flatMap(c => f(c).get))
final def map(f: Completion => Completion): Completions = Completions(get map f)
override final def hashCode = get.hashCode
override final def equals(o: Any) = o match { case c: Completions => get == c.get; case _ => false }
}
object Completions
{
def apply(cs: => Set[Completion]): Completions = new Completions {
lazy val get = cs
}
def strict(cs: Set[Completion]): Completions = apply(cs)
val nil: Completions = strict(Set.empty)
val empty: Completions = strict(Set.empty + Completion.empty)
def single(c: Completion): Completions = strict(Set.empty + c)
}
sealed trait Completion
{
def append: String
def display: String
def isEmpty: Boolean
def ++(o: Completion): Completion = Completion.concat(this, o)
final def x(o: Completions): Completions = if(Completion evaluatesRight this) o.map(this ++ _) else Completions.strict(Set.empty + this)
override final lazy val hashCode = Completion.hashCode(this)
override final def equals(o: Any) = o match { case c: Completion => Completion.equal(this, c); case _ => false }
}
final class DisplayOnly(val display: String) extends Completion
{
def isEmpty = display.isEmpty
def append = ""
override def toString = "{" + display + "}"
}
final class Token(prepend0: String, append0: String) extends Completion
{
lazy val prepend = prepend0
lazy val append = append0
def isEmpty = prepend.isEmpty && append.isEmpty
def display = prepend + append
override final def toString = "[" + prepend + "," + append +"]"
}
final class Suggestion(append0: String) extends Completion
{
lazy val append = append0
def isEmpty = append.isEmpty
def display = append
override def toString = append
}
object Completion
{
def concat(a: Completion, b: Completion): Completion =
(a,b) match
{
case (as: Suggestion, bs: Suggestion) => suggestion(as.append + bs.append)
case (at: Token, _) if at.append.isEmpty => b
case _ if a.isEmpty => b
case _ => a
}
def evaluatesRight(a: Completion): Boolean =
a match
{
case _: Suggestion => true
case at: Token if at.append.isEmpty => true
case _ => a.isEmpty
}
def equal(a: Completion, b: Completion): Boolean =
(a,b) match
{
case (as: Suggestion, bs: Suggestion) => as.append == bs.append
case (ad: DisplayOnly, bd: DisplayOnly) => ad.display == bd.display
case (at: Token, bt: Token) => at.prepend == bt.prepend && at.append == bt.append
case _ => false
}
def hashCode(a: Completion): Int =
a match
{
case as: Suggestion => (0, as.append).hashCode
case ad: DisplayOnly => (1, ad.display).hashCode
case at: Token => (2, at.prepend, at.append).hashCode
}
val empty: Completion = suggestStrict("")
def single(c: Char): Completion = suggestStrict(c.toString)
def displayOnly(value: => String): Completion = new DisplayOnly(value)
def displayStrict(value: String): Completion = displayOnly(value)
def token(prepend: => String, append: => String): Completion = new Token(prepend, append)
def tokenStrict(prepend: String, append: String): Completion = token(prepend, append)
def suggestion(value: => String): Completion = new Suggestion(value)
def suggestStrict(value: String): Completion = suggestion(value)
}