src/Pure/General/pretty.scala
changeset 81710 c914db7419a3
parent 81698 17f1a78af3f5
child 81718 289ded3c342f
equal deleted inserted replaced
81709:0b088316b8a3 81710:c914db7419a3
    61   private def force_nat(i: Int): Int = i max 0
    61   private def force_nat(i: Int): Int = i max 0
    62 
    62 
    63   type Markup_Body = (Markup, Option[XML.Body])
    63   type Markup_Body = (Markup, Option[XML.Body])
    64   val no_markup: Markup_Body = (Markup.Empty, None)
    64   val no_markup: Markup_Body = (Markup.Empty, None)
    65   val item_markup: Markup_Body = (Markup.Expression.item, None)
    65   val item_markup: Markup_Body = (Markup.Expression.item, None)
    66 
       
    67   def markup_elem(markup: Markup_Body, body: XML.Body): XML.Elem =
       
    68     markup match {
       
    69       case (m, None) => XML.Elem(m, body)
       
    70       case (m1, Some(m2)) => XML.Wrapped_Elem(m1, m2, body)
       
    71     }
       
    72 
    66 
    73   private sealed abstract class Tree { def length: Double }
    67   private sealed abstract class Tree { def length: Double }
    74   private case object End extends Tree {
    68   private case object End extends Tree {
    75     override def length: Double = 0.0
    69     override def length: Double = 0.0
    76   }
    70   }
   129     output_content(pure, unbreakable(input))
   123     output_content(pure, unbreakable(input))
   130 
   124 
   131 
   125 
   132   /* formatting */
   126   /* formatting */
   133 
   127 
   134   private type State = List[(Markup_Body, List[XML.Tree])]
   128   private sealed abstract class Tree_Buffer { def result: XML.Tree }
   135   private val init_state: State = List((no_markup, Nil))
   129   private case class Elem_Buffer(markup: Markup_Body, body: XML.Body) extends Tree_Buffer {
       
   130     def result: XML.Elem =
       
   131       markup match {
       
   132         case (m, None) => XML.Elem(m, body)
       
   133         case (m1, Some(m2)) => XML.Wrapped_Elem(m1, m2, body)
       
   134       }
       
   135   }
       
   136   private case class Text_Buffer(buffer: List[String]) extends Tree_Buffer {
       
   137     def result: XML.Text = XML.Text(buffer.reverse.mkString)
       
   138 
       
   139     def add(s: String): Text_Buffer =
       
   140       if (s.isEmpty) this else copy(buffer = s :: buffer)
       
   141   }
       
   142 
       
   143   private case class Result_Buffer(
       
   144     markup: Markup_Body = no_markup,
       
   145     buffer: List[Tree_Buffer] = Nil
       
   146   ) {
       
   147     def result_body: XML.Body = buffer.foldLeft[XML.Body](Nil)((res, t) => t.result :: res)
       
   148     def result_elem: Elem_Buffer = Elem_Buffer(markup, result_body)
       
   149 
       
   150     def add(elem: Elem_Buffer): Result_Buffer = copy(buffer = elem :: buffer)
       
   151 
       
   152     def string(s: String): Result_Buffer =
       
   153       if (s.isEmpty) this
       
   154       else {
       
   155         buffer match {
       
   156           case (text: Text_Buffer) :: ts => copy(buffer = text.add(s) :: ts)
       
   157           case _ => copy(buffer = Text_Buffer(List(s)) :: buffer)
       
   158         }
       
   159       }
       
   160   }
       
   161 
       
   162   private type State = List[Result_Buffer]
       
   163   private val init_state: State = List(Result_Buffer())
   136 
   164 
   137   private sealed case class Text(
   165   private sealed case class Text(
   138     state: State = init_state,
   166     state: State = init_state,
   139     pos: Double = 0.0,
   167     pos: Double = 0.0,
   140     nl: Int = 0
   168     nl: Int = 0
   141   ) {
   169   ) {
   142     def add(t: XML.Tree, len: Double = 0.0): Text =
   170     def add(elem: Elem_Buffer): Text =
   143       (state: @unchecked) match {
   171       (state: @unchecked) match {
   144         case (m, ts) :: rest => copy(state = (m, t :: ts) :: rest, pos = pos + len)
   172         case res :: rest => copy(state = res.add(elem) :: rest)
   145       }
   173       }
   146 
   174 
   147     def push(m: Markup_Body): Text =
   175     def push(m: Markup_Body): Text =
   148       copy(state = (m, Nil) :: state)
   176       copy(state = Result_Buffer(markup = m) :: state)
   149 
   177 
   150     def pop: Text =
   178     def pop: Text =
   151       (state: @unchecked) match {
   179       (state: @unchecked) match {
   152         case (m1, ts1) :: (m2, ts2) :: rest =>
   180         case res1 :: res2 :: rest => copy(state = res2.add(res1.result_elem) :: rest)
   153           copy(state = (m2, markup_elem(m1, ts1.reverse) :: ts2) :: rest)
       
   154       }
   181       }
   155 
   182 
   156     def result: XML.Body =
   183     def result: XML.Body =
   157       (state: @unchecked) match {
   184       (state: @unchecked) match {
   158         case List((m, ts)) if m == no_markup => ts.reverse
   185         case List(res) if res.markup == no_markup => res.result_body
   159       }
   186       }
   160 
   187 
   161     def reset: Text = copy(state = init_state)
   188     def reset: Text = copy(state = init_state)
   162     def restore(other: Text): Text = copy(state = other.state)
   189     def restore(other: Text): Text = copy(state = other.state)
   163 
   190 
   164     def newline: Text = add(fbrk).copy(pos = 0.0, nl = nl + 1)
       
   165 
       
   166     def string(s: String, len: Double): Text =
   191     def string(s: String, len: Double): Text =
   167       if (s.isEmpty) copy(pos = pos + len)
   192       (state: @unchecked) match {
   168       else add(XML.Text(s), len = len)
   193         case res :: rest => copy(state = res.string(s) :: rest, pos = pos + len)
   169 
   194       }
   170     def blanks(wd: Int): Text = string(Symbol.spaces(wd), wd.toDouble)
   195     def blanks(wd: Int): Text = string(Symbol.spaces(wd), wd.toDouble)
       
   196     def newline: Text = string("\n", 0.0).copy(pos = 0.0, nl = nl + 1)
   171   }
   197   }
   172 
   198 
   173   private def break_dist(trees: List[Tree], after: Double): Double =
   199   private def break_dist(trees: List[Tree], after: Double): Double =
   174     trees match {
   200     trees match {
   175       case (_: Break) :: _ => 0.0
   201       case (_: Break) :: _ => 0.0
   233             else block.body
   259             else block.body
   234           val btext1 =
   260           val btext1 =
   235             if (block.markup == no_markup) format(body1, before1, after1, text)
   261             if (block.markup == no_markup) format(body1, before1, after1, text)
   236             else {
   262             else {
   237               val btext = format(body1, before1, after1, text.reset)
   263               val btext = format(body1, before1, after1, text.reset)
   238               val elem = markup_elem(block.markup, btext.result)
   264               val elem = Elem_Buffer(block.markup, btext.result)
   239               btext.restore(text.add(elem))
   265               btext.restore(text.add(elem))
   240             }
   266             }
   241           val ts1 = if (text.nl < btext1.nl) force_next(ts) else ts
   267           val ts1 = if (text.nl < btext1.nl) force_next(ts) else ts
   242           format(ts1, before, after, btext1)
   268           format(ts1, before, after, btext1)
   243         case Break(force, wd, ind) :: ts =>
   269         case Break(force, wd, ind) :: ts =>