aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/util
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-03-20 17:39:32 +0100
committerMartin Odersky <odersky@gmail.com>2013-03-20 17:39:32 +0100
commit5ac2104e688409e24785cfe62cdc7e8ef0bc6428 (patch)
tree0d48205fa5b50c25e240d77d4fb0e26c4b6c9b36 /src/dotty/tools/dotc/util
parent53e0a8a9227820e47e33f1e0b1d91819aec917c4 (diff)
downloaddotty-5ac2104e688409e24785cfe62cdc7e8ef0bc6428.tar.gz
dotty-5ac2104e688409e24785cfe62cdc7e8ef0bc6428.tar.bz2
dotty-5ac2104e688409e24785cfe62cdc7e8ef0bc6428.zip
Pretty-printing improvements.
Diffstat (limited to 'src/dotty/tools/dotc/util')
-rw-r--r--src/dotty/tools/dotc/util/Text.scala108
1 files changed, 69 insertions, 39 deletions
diff --git a/src/dotty/tools/dotc/util/Text.scala b/src/dotty/tools/dotc/util/Text.scala
index a63f36b83..251274371 100644
--- a/src/dotty/tools/dotc/util/Text.scala
+++ b/src/dotty/tools/dotc/util/Text.scala
@@ -4,33 +4,40 @@ import language.implicitConversions
object Texts {
- class Text {
+ abstract class Text {
protected def indentMargin = 2
- protected def pageWidth = 80
def relems: List[Text]
def isEmpty: Boolean = this match {
case Str(s) => s.isEmpty
case Fluid(relems) => relems forall (_.isEmpty)
- case Rigid(relems) => relems.isEmpty
+ case Vertical(relems) => relems.isEmpty
}
- def isRigid = isInstanceOf[Rigid]
+ def isVertical = isInstanceOf[Vertical]
+ def isClosed = isVertical || isInstanceOf[Closed]
+ def isFluid = isInstanceOf[Fluid]
+ def isSplittable = isFluid && !isClosed
- def fitsIn(width: Int): Boolean = this match {
+ def close = new Closed(relems)
+
+ def remaining(width: Int): Int = this match {
case Str(s) =>
- s.length <= width
- case Fluid(Str(s) :: prevs) =>
- s.length < width && Fluid(prevs).fitsIn(width - s.length)
- case Rigid(_) =>
- false
+ width - s.length
+ case Fluid(Nil) =>
+ width
+ case Fluid(last :: prevs) =>
+ val r = last remaining width
+ if (r < 0) r else Fluid(prevs) remaining r
+ case Vertical(_) =>
+ -1
}
- def lastLineWidth: Int = this match {
- case Str(s) => s.length
- case _ => relems.head.lastLineWidth
+ def lastLine: String = this match {
+ case Str(s) => s
+ case _ => relems.head.lastLine
}
def appendToLastLine(that: Text): Text = that match {
@@ -44,80 +51,103 @@ object Texts {
}
private def appendIndented(that: Text)(width: Int): Text =
- Rigid(that.layout(width - indentMargin).indented :: this.relems)
+ Vertical(that.layout(width - indentMargin).indented :: this.relems)
- private def append(width: Int)(that: Text): Text =
+ private def append(width: Int)(that: Text): Text = {
if (this.isEmpty) that.layout(width)
else if (that.isEmpty) this
- else if (that.isRigid) appendIndented(that)(width)
- else if (this.isRigid) Fluid(that.layout(width) :: this.relems)
- else if (that.fitsIn(width - this.lastLineWidth)) appendToLastLine(that)
+ else if (that.isVertical) appendIndented(that)(width)
+ else if (this.isVertical) Fluid(that.layout(width) :: this.relems)
+ else if (that.remaining(width - lastLine.length) >= 0) appendToLastLine(that)
+ else if (that.isSplittable) (this /: that.relems.reverse)(_.append(width)(_))
else appendIndented(that)(width)
+ }
def layout(width: Int): Text = this match {
case Str(_) =>
this
case Fluid(relems) =>
((Str(""): Text) /: relems.reverse)(_.append(width)(_))
- case Rigid(relems) =>
- Rigid(relems map (_ layout width))
+ case Vertical(relems) =>
+ Vertical(relems map (_ layout width))
+ }
+
+ def map(f: String => String): Text = this match {
+ case Str(s) => Str(f(s))
+ case Fluid(relems) => Fluid(relems map (_ map f))
+ case Vertical(relems) => Vertical(relems map (_ map f))
+ }
+
+ def stripPrefix(pre: String): Text = this match {
+ case Str(s) =>
+ if (s.startsWith(pre)) s drop pre.length else s
+ case Fluid(relems) =>
+ val elems = relems.reverse
+ val head = elems.head.stripPrefix(pre)
+ if (head eq elems.head) this else Fluid((head :: elems.tail).reverse)
+ case Vertical(relems) =>
+ val elems = relems.reverse
+ val head = elems.head.stripPrefix(pre)
+ if (head eq elems.head) this else Vertical((head :: elems.tail).reverse)
}
private def indented: Text = this match {
case Str(s) => Str((" " * indentMargin) + s)
case Fluid(relems) => Fluid(relems map (_.indented))
- case Rigid(relems) => Rigid(relems map (_.indented))
+ case Vertical(relems) => Vertical(relems map (_.indented))
}
def print(sb: StringBuilder): Unit = this match {
case Str(s) =>
sb.append(s)
- case txt: CompoundText =>
+ case _ =>
var follow = false
- for (elem <- txt.relems.reverse) {
+ for (elem <- relems.reverse) {
if (follow) sb.append("\n")
elem.print(sb)
follow = true
}
}
- def show: String =
- layout(pageWidth).showRaw
-
- def showRaw: String = {
+ def mkString(width: Int): String = {
val sb = new StringBuilder
- print(sb)
+ layout(width).print(sb)
sb.toString
}
- def +++ (that: Text) =
+ def ~ (that: Text) =
if (this.isEmpty) that
else if (that.isEmpty) this
else Fluid(that :: this :: Nil)
+ def ~~ (that: Text) =
+ if (this.isEmpty) that
+ else if (that.isEmpty) this
+ else Fluid(that :: Str(" ") :: this :: Nil)
+
def over (that: Text) =
- if (this.isRigid) Rigid(that :: this.relems)
- else Rigid(that :: this :: Nil)
+ if (this.isVertical) Vertical(that :: this.relems)
+ else Vertical(that :: this :: Nil)
}
object Text {
- def apply(xs: Traversable[Text], sep: String): Text = {
+ def apply(): Text = Str("")
+ def apply(xs: Traversable[Text], sep: String = " "): Text = {
val ys = xs filterNot (_.isEmpty)
if (ys.isEmpty) Str("")
- else ys reduce (_ +++ sep +++ _)
+ else ys reduce (_ ~ sep ~ _)
}
- }
-
- abstract class CompoundText extends Text {
- def relems: List[Text]
+ def lines(xs: Traversable[Text]) = Vertical(xs.toList.reverse)
}
case class Str(s: String) extends Text {
override def relems: List[Text] = List(this)
}
- case class Rigid(relems: List[Text]) extends CompoundText
- case class Fluid(relems: List[Text]) extends CompoundText
+ case class Vertical(relems: List[Text]) extends Text
+ case class Fluid(relems: List[Text]) extends Text
+
+ class Closed(relems: List[Text]) extends Fluid(relems)
implicit def stringToText(s: String): Text = Str(s)
} \ No newline at end of file