Port util-complete

This commit is contained in:
Eugene Yokota 2021-12-20 02:56:09 -05:00
parent 50b062b795
commit cd43045444
7 changed files with 47 additions and 78 deletions

View File

@ -185,6 +185,8 @@ lazy val sbtRoot: Project = (project in file("."))
collectionProj,
coreMacrosProj,
utilLogging,
utilControl,
completeProj,
)
.settings(
minimalSettings,

View File

@ -238,17 +238,9 @@ abstract class JLine extends LineReader {
@deprecated("Use LineReader apis", "1.4.0")
private[sbt] object JLine {
@deprecated("For binary compatibility only", "1.4.0")
protected[this] val originalIn = new FileInputStream(FileDescriptor.in)
@deprecated("Handled by Terminal.fixTerminalProperty", "1.4.0")
private[sbt] def fixTerminalProperty(): Unit = ()
@deprecated("For binary compatibility only", "1.4.0")
private[sbt] def makeInputStream(injectThreadSleep: Boolean): InputStream =
if (injectThreadSleep) new InputStreamWrapper(originalIn, 2.milliseconds)
else originalIn
// When calling this, ensure that enableEcho has been or will be called.
// TerminalFactory.get will initialize the terminal to disable echo.
@deprecated("Don't use jline.Terminal directly", "1.4.0")
@ -258,11 +250,11 @@ private[sbt] object JLine {
* For accessing the JLine Terminal object. This ensures synchronized access as well as
* re-enabling echo after getting the Terminal.
*/
@deprecated(
"Don't use jline.Terminal directly. Use Terminal.get.withCanonicalIn instead.",
"1.4.0"
)
def usingTerminal[T](f: jline.Terminal => T): T = f(Terminal.get.toJLine)
// @deprecated(
// "Don't use jline.Terminal directly. Use Terminal.get.withCanonicalIn instead.",
// "1.4.0"
// )
// def usingTerminal[T](f: jline.Terminal => T): T = f(Terminal.get.toJLine)
@deprecated("unused", "1.4.0")
def createReader(): ConsoleReader = createReader(None, Terminal.wrappedSystemIn)
@ -298,31 +290,6 @@ private[sbt] object JLine {
val HandleCONT = LineReader.HandleCONT
}
@deprecated("For binary compatibility only", "1.4.0")
private[sbt] class InputStreamWrapper(is: InputStream, val poll: Duration)
extends FilterInputStream(is) {
@tailrec final override def read(): Int =
if (is.available() != 0) is.read()
else {
Thread.sleep(poll.toMillis)
read()
}
@tailrec final override def read(b: Array[Byte]): Int =
if (is.available() != 0) is.read(b)
else {
Thread.sleep(poll.toMillis)
read(b)
}
@tailrec final override def read(b: Array[Byte], off: Int, len: Int): Int =
if (is.available() != 0) is.read(b, off, len)
else {
Thread.sleep(poll.toMillis)
read(b, off, len)
}
}
final class FullReader(
historyPath: Option[File],
complete: Parser[_],

View File

@ -158,14 +158,4 @@ object Completion {
def tokenDisplay(append: String, display: String): Completion = new Token(display, append)
def suggestion(value: String): Completion = new Suggestion(value)
@deprecated("No longer used. for binary compatibility", "1.1.0")
private[complete] def displayOnly(value: => String): Completion = new DisplayOnly(value)
@deprecated("No longer used. for binary compatibility", "1.1.0")
private[complete] def token(prepend: => String, append: => String): Completion =
new Token(prepend + append, append)
@deprecated("No longer used. for binary compatibility", "1.1.0")
private[complete] def suggestion(value: => String): Completion = new Suggestion(value)
}

View File

@ -270,16 +270,18 @@ object Parser extends ParserMain {
}
def choiceParser[A, B](a: Parser[A], b: Parser[B]): Parser[Either[A, B]] =
if (a.valid)
if (b.valid) new HetParser(a, b) else a.map(left.fn)
else
b.map(right.fn)
if a.valid then
if b.valid then new HetParser(a, b)
else a.map(left[A])
else b.map(right[B])
def opt[T](a: Parser[T]): Parser[Option[T]] =
if (a.valid) new Optional(a) else success(None)
if a.valid then new Optional(a)
else success(None)
def onFailure[T](delegate: Parser[T], msg: String): Parser[T] =
if (delegate.valid) new OnFailure(delegate, msg) else failure(msg)
if delegate.valid then new OnFailure(delegate, msg)
else failure(msg)
def trapAndFail[T](delegate: Parser[T]): Parser[T] =
delegate.ifValid(new TrapAndFail(delegate))
@ -437,8 +439,9 @@ trait ParserMain {
/** Presents a single Char `ch` as a Parser that only parses that exact character. */
implicit def literal(ch: Char): Parser[Char] = new ValidParser[Char] {
def result = None
def resultEmpty = mkFailure("Expected '" + ch + "'")
def derive(c: Char) = if (c == ch) success(ch) else new Invalid(resultEmpty)
private[this] lazy val fail = mkFailure("Expected '" + ch + "'")
def resultEmpty = fail
def derive(c: Char) = if (c == ch) success(ch) else new Invalid(fail)
def completions(level: Int) = Completions.single(Completion.suggestion(ch.toString))
override def toString = "'" + ch + "'"
}
@ -640,7 +643,7 @@ trait ParserMain {
def seq0[T](p: Seq[Parser[T]], errors: => Seq[String]): Parser[Seq[T]] = {
val (newErrors, valid) = separate(p) {
case Invalid(f) => Left(f.errors _): Either[() => Seq[String], Parser[T]]
case Invalid(f) => Left(() => f.errors): Either[() => Seq[String], Parser[T]]
case ok => Right(ok): Either[() => Seq[String], Parser[T]]
}
def combinedErrors = errors ++ newErrors.flatMap(_())
@ -944,11 +947,12 @@ private final class StringLiteral(str: String, start: Int) extends ValidParser[S
assert(0 <= start && start < str.length)
def failMsg = "Expected '" + str + "'"
private[this] lazy val fail = mkFailure(failMsg)
def resultEmpty = mkFailure(failMsg)
def result = None
def derive(c: Char) =
if (str.charAt(start) == c) stringLiteral(str, start + 1) else new Invalid(resultEmpty)
if (str.charAt(start) == c) stringLiteral(str, start + 1) else new Invalid(fail)
def completions(level: Int) = Completions.single(Completion.suggestion(str.substring(start)))
override def toString = "\"" + str + "\""
@ -956,16 +960,17 @@ private final class StringLiteral(str: String, start: Int) extends ValidParser[S
private final class CharacterClass(f: Char => Boolean, label: String) extends ValidParser[Char] {
def result = None
def resultEmpty = mkFailure("Expected " + label)
def derive(c: Char) = if (f(c)) success(c) else Invalid(resultEmpty)
private[this] def fail: Failure = mkFailure("Expected " + label)
def resultEmpty = fail
def derive(c: Char) = if (f(c)) success(c) else Invalid(fail)
def completions(level: Int) = Completions.empty
override def toString = "class(" + label + ")"
}
private final class Optional[T](delegate: Parser[T]) extends ValidParser[Option[T]] {
def result = delegate.result map some.fn
private final class Optional[A](delegate: Parser[A]) extends ValidParser[Option[A]] {
def result = delegate.result.map(some[A])
def resultEmpty = Value(None)
def derive(c: Char) = (delegate derive c).map(some.fn)
def derive(c: Char) = (delegate derive c).map(some[A])
def completions(level: Int) = Completion.empty +: delegate.completions(level)
override def toString = delegate.toString + "?"
}

View File

@ -125,7 +125,8 @@ trait Parsers {
def isOpType(cat: Int) = cat match {
case MATH_SYMBOL | OTHER_SYMBOL | DASH_PUNCTUATION | OTHER_PUNCTUATION | MODIFIER_SYMBOL |
CURRENCY_SYMBOL =>
true; case _ => false
true
case _ => false
}
/** Returns true if `c` is a dash `-`, a letter, digit, or an underscore `_`. */
@ -182,18 +183,14 @@ trait Parsers {
/** Matches any character except a double quote or whitespace. */
lazy val NotDQuoteSpaceClass =
charClass(
{ c: Char =>
(c != DQuoteChar) && !c.isWhitespace
},
(c: Char) => { (c != DQuoteChar) && !c.isWhitespace },
"non-double-quote-space character"
)
/** Matches any character except a double quote or backslash. */
lazy val NotDQuoteBackslashClass =
charClass(
{ c: Char =>
(c != DQuoteChar) && (c != BackslashChar)
},
(c: Char) => { (c != DQuoteChar) && (c != BackslashChar) },
"non-double-quote-backslash character"
)

View File

@ -8,6 +8,8 @@
package sbt.internal.util
package complete
import scala.collection.StringOps
object JLineTest {
import DefaultParsers._
@ -153,12 +155,12 @@ object ParserExample {
val an = repeat(a, min = n, max = n)
val ann = aqn ~ an
def r = apply(ann)("a" * (n * 2)).resultEmpty
def r = apply(ann)(new StringOps("a") * (n * 2)).resultEmpty
println(r.isValid)
}
def run2(n: Int): Unit = {
val ab = "ab".?.*
val r = apply(ab)("a" * n).resultEmpty
val r = apply(ab)(new StringOps("a") * n).resultEmpty
println(r)
}
}

View File

@ -17,15 +17,21 @@ trait TypeFunctions:
sealed trait ConstK[A] { type l[L[x]] = A }
sealed trait Compose[A[_], B[_]] { type Apply[T] = A[B[T]] }
sealed trait [A[_], B[_]] { type l[T] = A[B[T]] }
*/
private type AnyLeft[T] = Left[T, Nothing]
private type AnyRight[T] = Right[Nothing, T]
final val left: [A] => A => Left[A, Nothing] = [A] => (a: A) => Left(a)
final val right: [A] => A => Right[Nothing, A] = [A] => (a: A) => Right(a)
final val some: [A] => A => Some[A] = [A] => (a: A) => Some(a)
// Id ~> Left[*, Nothing] =
// λ[Id ~> AnyLeft](Left(_)).setToString("TypeFunctions.left")
// final val right: Id ~> Right[Nothing, *] =
// λ[Id ~> AnyRight](Right(_)).setToString("TypeFunctions.right")
// final val some: Id ~> Some[*] = λ[Id ~> Some](Some(_)).setToString("TypeFunctions.some")
final val left: Id ~> Left[*, Nothing] =
λ[Id ~> AnyLeft](Left(_)).setToString("TypeFunctions.left")
final val right: Id ~> Right[Nothing, *] =
λ[Id ~> AnyRight](Right(_)).setToString("TypeFunctions.right")
final val some: Id ~> Some[*] = λ[Id ~> Some](Some(_)).setToString("TypeFunctions.some")
*/
final def idFun[A]: A => A = ((a: A) => a) // .setToString("TypeFunctions.id")
final def const[A, B](b: B): A => B = ((_: A) => b) // .setToString(s"TypeFunctions.const($b)")
/*