src/Pure/General/pretty.scala
changeset 38230 ed147003de4b
parent 37374 d66e6cc47fab
child 38414 49f1f657adc2
equal deleted inserted replaced
38229:61d0fe8b96ac 38230:ed147003de4b
    15   /* markup trees with physical blocks and breaks */
    15   /* markup trees with physical blocks and breaks */
    16 
    16 
    17   object Block
    17   object Block
    18   {
    18   {
    19     def apply(indent: Int, body: List[XML.Tree]): XML.Tree =
    19     def apply(indent: Int, body: List[XML.Tree]): XML.Tree =
    20       XML.Elem(Markup.BLOCK, List((Markup.INDENT, indent.toString)), body)
    20       XML.Elem(Markup(Markup.BLOCK, List((Markup.INDENT, indent.toString))), body)
    21 
    21 
    22     def unapply(tree: XML.Tree): Option[(Int, List[XML.Tree])] =
    22     def unapply(tree: XML.Tree): Option[(Int, List[XML.Tree])] =
    23       tree match {
    23       tree match {
    24         case XML.Elem(Markup.BLOCK, List((Markup.INDENT, indent)), body) =>
    24         case XML.Elem(Markup(Markup.BLOCK, List((Markup.INDENT, indent))), body) =>
    25           Markup.parse_int(indent) match {
    25           Markup.parse_int(indent) match {
    26             case Some(i) => Some((i, body))
    26             case Some(i) => Some((i, body))
    27             case None => None
    27             case None => None
    28           }
    28           }
    29         case _ => None
    29         case _ => None
    31   }
    31   }
    32 
    32 
    33   object Break
    33   object Break
    34   {
    34   {
    35     def apply(width: Int): XML.Tree =
    35     def apply(width: Int): XML.Tree =
    36       XML.Elem(Markup.BREAK, List((Markup.WIDTH, width.toString)),
    36       XML.Elem(Markup(Markup.BREAK, List((Markup.WIDTH, width.toString))),
    37         List(XML.Text(Symbol.spaces(width))))
    37         List(XML.Text(Symbol.spaces(width))))
    38 
    38 
    39     def unapply(tree: XML.Tree): Option[Int] =
    39     def unapply(tree: XML.Tree): Option[Int] =
    40       tree match {
    40       tree match {
    41         case XML.Elem(Markup.BREAK, List((Markup.WIDTH, width)), _) => Markup.parse_int(width)
    41         case XML.Elem(Markup(Markup.BREAK, List((Markup.WIDTH, width))), _) => Markup.parse_int(width)
    42         case _ => None
    42         case _ => None
    43       }
    43       }
    44   }
    44   }
    45 
    45 
    46   val FBreak = XML.Text("\n")
    46   val FBreak = XML.Text("\n")
    48 
    48 
    49   /* formatted output */
    49   /* formatted output */
    50 
    50 
    51   private def standard_format(tree: XML.Tree): List[XML.Tree] =
    51   private def standard_format(tree: XML.Tree): List[XML.Tree] =
    52     tree match {
    52     tree match {
    53       case XML.Elem(name, atts, body) => List(XML.Elem(name, atts, body.flatMap(standard_format)))
    53       case XML.Elem(markup, body) => List(XML.Elem(markup, body.flatMap(standard_format)))
    54       case XML.Text(text) =>
    54       case XML.Text(text) =>
    55         Library.separate(FBreak,
    55         Library.separate(FBreak,
    56           Library.chunks(text).toList.map((s: CharSequence) => XML.Text(s.toString)))
    56           Library.chunks(text).toList.map((s: CharSequence) => XML.Text(s.toString)))
    57     }
    57     }
    58 
    58 
    80     val breakgain = margin / 20
    80     val breakgain = margin / 20
    81     val emergencypos = margin / 2
    81     val emergencypos = margin / 2
    82 
    82 
    83     def content_length(tree: XML.Tree): Double =
    83     def content_length(tree: XML.Tree): Double =
    84       tree match {
    84       tree match {
    85         case XML.Elem(_, _, body) => (0.0 /: body)(_ + content_length(_))
    85         case XML.Elem(_, body) => (0.0 /: body)(_ + content_length(_))
    86         case XML.Text(s) => metric(s)
    86         case XML.Text(s) => metric(s)
    87       }
    87       }
    88 
    88 
    89     def breakdist(trees: List[XML.Tree], after: Double): Double =
    89     def breakdist(trees: List[XML.Tree], after: Double): Double =
    90       trees match {
    90       trees match {
   120           if (text.pos + wd <= (margin - breakdist(ts, after)).max(blockin + breakgain))
   120           if (text.pos + wd <= (margin - breakdist(ts, after)).max(blockin + breakgain))
   121             format(ts, blockin, after, text.blanks(wd))
   121             format(ts, blockin, after, text.blanks(wd))
   122           else format(ts, blockin, after, text.newline.blanks(blockin.toInt))
   122           else format(ts, blockin, after, text.newline.blanks(blockin.toInt))
   123         case FBreak :: ts => format(ts, blockin, after, text.newline.blanks(blockin.toInt))
   123         case FBreak :: ts => format(ts, blockin, after, text.newline.blanks(blockin.toInt))
   124 
   124 
   125         case XML.Elem(name, atts, body) :: ts =>
   125         case XML.Elem(markup, body) :: ts =>
   126           val btext = format(body, blockin, breakdist(ts, after), text.copy(tx = Nil))
   126           val btext = format(body, blockin, breakdist(ts, after), text.copy(tx = Nil))
   127           val ts1 = if (text.nl < btext.nl) forcenext(ts) else ts
   127           val ts1 = if (text.nl < btext.nl) forcenext(ts) else ts
   128           val btext1 = btext.copy(tx = XML.Elem(name, atts, btext.content) :: text.tx)
   128           val btext1 = btext.copy(tx = XML.Elem(markup, btext.content) :: text.tx)
   129           format(ts1, blockin, after, btext1)
   129           format(ts1, blockin, after, btext1)
   130         case XML.Text(s) :: ts => format(ts, blockin, after, text.string(s, metric(s)))
   130         case XML.Text(s) :: ts => format(ts, blockin, after, text.string(s, metric(s)))
   131       }
   131       }
   132     format(input.flatMap(standard_format), 0.0, 0.0, Text()).content
   132     format(input.flatMap(standard_format), 0.0, 0.0, Text()).content
   133   }
   133   }
   144     def fmt(tree: XML.Tree): List[XML.Tree] =
   144     def fmt(tree: XML.Tree): List[XML.Tree] =
   145       tree match {
   145       tree match {
   146         case Block(_, body) => body.flatMap(fmt)
   146         case Block(_, body) => body.flatMap(fmt)
   147         case Break(wd) => List(XML.Text(Symbol.spaces(wd)))
   147         case Break(wd) => List(XML.Text(Symbol.spaces(wd)))
   148         case FBreak => List(XML.Text(Symbol.space))
   148         case FBreak => List(XML.Text(Symbol.space))
   149         case XML.Elem(name, atts, body) => List(XML.Elem(name, atts, body.flatMap(fmt)))
   149         case XML.Elem(markup, body) => List(XML.Elem(markup, body.flatMap(fmt)))
   150         case XML.Text(_) => List(tree)
   150         case XML.Text(_) => List(tree)
   151       }
   151       }
   152     input.flatMap(standard_format).flatMap(fmt)
   152     input.flatMap(standard_format).flatMap(fmt)
   153   }
   153   }
   154 
   154