src/Pure/General/pretty.scala
changeset 75393 87ebf5a50283
parent 73359 d8a0e996614b
child 75958 97445e208419
equal deleted inserted replaced
75388:b3ca4a6ed74b 75393:87ebf5a50283
     7 package isabelle
     7 package isabelle
     8 
     8 
     9 import scala.annotation.tailrec
     9 import scala.annotation.tailrec
    10 
    10 
    11 
    11 
    12 object Pretty
    12 object Pretty {
    13 {
       
    14   /* XML constructors */
    13   /* XML constructors */
    15 
    14 
    16   val space: XML.Body = List(XML.Text(Symbol.space))
    15   val space: XML.Body = List(XML.Text(Symbol.space))
    17   def spaces(n: Int): XML.Body =
    16   def spaces(n: Int): XML.Body =
    18     if (n == 0) Nil
    17     if (n == 0) Nil
    34   def separate(ts: List[XML.Tree]): XML.Body = Library.separate(Separator, ts.map(List(_))).flatten
    33   def separate(ts: List[XML.Tree]): XML.Body = Library.separate(Separator, ts.map(List(_))).flatten
    35 
    34 
    36 
    35 
    37   /* text metric -- standardized to width of space */
    36   /* text metric -- standardized to width of space */
    38 
    37 
    39   abstract class Metric
    38   abstract class Metric {
    40   {
       
    41     val unit: Double
    39     val unit: Double
    42     def apply(s: String): Double
    40     def apply(s: String): Double
    43   }
    41   }
    44 
    42 
    45   object Default_Metric extends Metric
    43   object Default_Metric extends Metric {
    46   {
       
    47     val unit = 1.0
    44     val unit = 1.0
    48     def apply(s: String): Double = s.length.toDouble
    45     def apply(s: String): Double = s.length.toDouble
    49   }
    46   }
    50 
    47 
    51 
    48 
    55 
    52 
    56   private sealed abstract class Tree { def length: Double }
    53   private sealed abstract class Tree { def length: Double }
    57   private case class Block(
    54   private case class Block(
    58     markup: Option[(Markup, Option[XML.Body])],
    55     markup: Option[(Markup, Option[XML.Body])],
    59     consistent: Boolean, indent: Int, body: List[Tree], length: Double) extends Tree
    56     consistent: Boolean, indent: Int, body: List[Tree], length: Double) extends Tree
    60   private case class Break(force: Boolean, width: Int, indent: Int) extends Tree
    57   private case class Break(force: Boolean, width: Int, indent: Int) extends Tree {
    61   { def length: Double = width.toDouble }
    58     def length: Double = width.toDouble
       
    59   }
    62   private case class Str(string: String, length: Double) extends Tree
    60   private case class Str(string: String, length: Double) extends Tree
    63 
    61 
    64   private val FBreak = Break(true, 1, 0)
    62   private val FBreak = Break(true, 1, 0)
    65 
    63 
    66   private def make_block(
    64   private def make_block(
    67       markup: Option[(Markup, Option[XML.Body])],
    65     markup: Option[(Markup, Option[XML.Body])],
    68       consistent: Boolean,
    66     consistent: Boolean,
    69       indent: Int,
    67     indent: Int,
    70       body: List[Tree]): Tree =
    68     body: List[Tree]
    71   {
    69   ): Tree = {
    72     val indent1 = force_nat(indent)
    70     val indent1 = force_nat(indent)
    73 
    71 
    74     @tailrec def body_length(prts: List[Tree], len: Double): Double =
    72     @tailrec def body_length(prts: List[Tree], len: Double): Double = {
    75     {
       
    76       val (line, rest) =
    73       val (line, rest) =
    77         Library.take_prefix[Tree]({ case Break(true, _, _) => false case _ => true }, prts)
    74         Library.take_prefix[Tree]({ case Break(true, _, _) => false case _ => true }, prts)
    78       val len1 = (line.foldLeft(0.0) { case (l, t) => l + t.length }) max len
    75       val len1 = (line.foldLeft(0.0) { case (l, t) => l + t.length }) max len
    79       (rest: @unchecked) match {
    76       (rest: @unchecked) match {
    80         case Break(true, _, ind) :: rest1 =>
    77         case Break(true, _, ind) :: rest1 =>
    86   }
    83   }
    87 
    84 
    88 
    85 
    89   /* formatted output */
    86   /* formatted output */
    90 
    87 
    91   private sealed case class Text(tx: XML.Body = Nil, pos: Double = 0.0, nl: Int = 0)
    88   private sealed case class Text(tx: XML.Body = Nil, pos: Double = 0.0, nl: Int = 0) {
    92   {
       
    93     def newline: Text = copy(tx = fbrk :: tx, pos = 0.0, nl = nl + 1)
    89     def newline: Text = copy(tx = fbrk :: tx, pos = 0.0, nl = nl + 1)
    94     def string(s: String, len: Double): Text =
    90     def string(s: String, len: Double): Text =
    95       copy(tx = if (s == "") tx else XML.Text(s) :: tx, pos = pos + len)
    91       copy(tx = if (s == "") tx else XML.Text(s) :: tx, pos = pos + len)
    96     def blanks(wd: Int): Text = string(Symbol.spaces(wd), wd.toDouble)
    92     def blanks(wd: Int): Text = string(Symbol.spaces(wd), wd.toDouble)
    97     def content: XML.Body = tx.reverse
    93     def content: XML.Body = tx.reverse
   119   val default_breakgain: Double = default_margin / 20
   115   val default_breakgain: Double = default_margin / 20
   120 
   116 
   121   def formatted(input: XML.Body,
   117   def formatted(input: XML.Body,
   122     margin: Double = default_margin,
   118     margin: Double = default_margin,
   123     breakgain: Double = default_breakgain,
   119     breakgain: Double = default_breakgain,
   124     metric: Metric = Default_Metric): XML.Body =
   120     metric: Metric = Default_Metric
   125   {
   121   ): XML.Body = {
   126     val emergencypos = (margin / 2).round.toInt
   122     val emergencypos = (margin / 2).round.toInt
   127 
   123 
   128     def make_tree(inp: XML.Body): List[Tree] =
   124     def make_tree(inp: XML.Body): List[Tree] =
   129       inp flatMap {
   125       inp flatMap {
   130         case XML.Wrapped_Elem(markup, body1, body2) =>
   126         case XML.Wrapped_Elem(markup, body1, body2) =>