| author | steckerm | 
| Sat, 20 Sep 2014 10:42:08 +0200 | |
| changeset 58401 | b8ca69d9897b | 
| parent 55551 | 4a5f65df29fa | 
| child 61862 | e2a9e46ac0fb | 
| permissions | -rw-r--r-- | 
| 36683 | 1 | /* Title: Pure/General/pretty.scala | 
| 2 | Author: Makarius | |
| 3 | ||
| 36687 | 4 | Generic pretty printing module. | 
| 36683 | 5 | */ | 
| 6 | ||
| 7 | package isabelle | |
| 8 | ||
| 9 | ||
| 10 | object Pretty | |
| 11 | {
 | |
| 48704 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 12 | /* spaces */ | 
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 13 | |
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 14 | val space = " " | 
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 15 | |
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 16 | private val static_spaces = space * 4000 | 
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 17 | |
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 18 | def spaces(k: Int): String = | 
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 19 |   {
 | 
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 20 | require(k >= 0) | 
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 21 | if (k < static_spaces.length) static_spaces.substring(0, k) | 
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 22 | else space * k | 
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 23 | } | 
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 24 | |
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 25 | |
| 51492 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 26 | /* text metric -- standardized to width of space */ | 
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 27 | |
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 28 | abstract class Metric | 
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 29 |   {
 | 
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 30 | val unit: Double | 
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 31 | def apply(s: String): Double | 
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 32 | } | 
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 33 | |
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 34 | object Metric_Default extends Metric | 
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 35 |   {
 | 
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 36 | val unit = 1.0 | 
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 37 | def apply(s: String): Double = s.length.toDouble | 
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 38 | } | 
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 39 | |
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 40 | |
| 36687 | 41 | /* markup trees with physical blocks and breaks */ | 
| 42 | ||
| 38573 | 43 | def block(body: XML.Body): XML.Tree = Block(2, body) | 
| 44 | ||
| 36683 | 45 | object Block | 
| 46 |   {
 | |
| 38573 | 47 | def apply(i: Int, body: XML.Body): XML.Tree = | 
| 55551 | 48 | XML.Elem(Markup.Block(i), body) | 
| 36683 | 49 | |
| 38573 | 50 | def unapply(tree: XML.Tree): Option[(Int, XML.Body)] = | 
| 36683 | 51 |       tree match {
 | 
| 55551 | 52 | case XML.Elem(Markup.Block(i), body) => Some((i, body)) | 
| 36683 | 53 | case _ => None | 
| 54 | } | |
| 55 | } | |
| 56 | ||
| 57 | object Break | |
| 58 |   {
 | |
| 38414 
49f1f657adc2
more basic Markup.parse_int/print_int (using signed_string_of_int) (ML);
 wenzelm parents: 
38230diff
changeset | 59 | def apply(w: Int): XML.Tree = | 
| 55551 | 60 | XML.Elem(Markup.Break(w), List(XML.Text(spaces(w)))) | 
| 36683 | 61 | |
| 62 | def unapply(tree: XML.Tree): Option[Int] = | |
| 63 |       tree match {
 | |
| 55551 | 64 | case XML.Elem(Markup.Break(w), _) => Some(w) | 
| 36683 | 65 | case _ => None | 
| 66 | } | |
| 67 | } | |
| 68 | ||
| 36689 
379f5b1e7f91
replaced slightly odd fbreak markup by plain "\n", which also coincides with regular linebreaks produced outside the ML pretty engine;
 wenzelm parents: 
36687diff
changeset | 69 |   val FBreak = XML.Text("\n")
 | 
| 36687 | 70 | |
| 51570 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 71 | def item(body: XML.Body): XML.Tree = | 
| 51574 
2b58d7b139d6
ghost bullet via markup, which is painted as bar under text (normally space);
 wenzelm parents: 
51570diff
changeset | 72 | Block(2, XML.elem(Markup.BULLET, List(XML.Text(space))) :: XML.Text(space) :: body) | 
| 51570 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 73 | |
| 50201 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49843diff
changeset | 74 | val Separator = List(XML.elem(Markup.SEPARATOR, List(XML.Text(space))), FBreak) | 
| 49843 
afddf4e26fac
further refinement of jEdit line range, avoiding lack of final \n;
 wenzelm parents: 
49827diff
changeset | 75 | def separate(ts: List[XML.Tree]): XML.Body = Library.separate(Separator, ts.map(List(_))).flatten | 
| 49473 | 76 | |
| 36687 | 77 | |
| 51570 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 78 | /* standard form */ | 
| 36687 | 79 | |
| 51570 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 80 | def standard_form(body: XML.Body): XML.Body = | 
| 49468 | 81 |     body flatMap {
 | 
| 49650 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 wenzelm parents: 
49473diff
changeset | 82 | case XML.Wrapped_Elem(markup, body1, body2) => | 
| 51570 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 83 | List(XML.Wrapped_Elem(markup, body1, standard_form(body2))) | 
| 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 84 | case XML.Elem(markup, body) => | 
| 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 85 | if (markup.name == Markup.ITEM) List(item(standard_form(body))) | 
| 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 86 | else List(XML.Elem(markup, standard_form(body))) | 
| 48996 | 87 | case XML.Text(text) => Library.separate(FBreak, split_lines(text).map(XML.Text)) | 
| 36689 
379f5b1e7f91
replaced slightly odd fbreak markup by plain "\n", which also coincides with regular linebreaks produced outside the ML pretty engine;
 wenzelm parents: 
36687diff
changeset | 88 | } | 
| 
379f5b1e7f91
replaced slightly odd fbreak markup by plain "\n", which also coincides with regular linebreaks produced outside the ML pretty engine;
 wenzelm parents: 
36687diff
changeset | 89 | |
| 51570 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 90 | |
| 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 91 | /* formatted output */ | 
| 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 92 | |
| 51493 
59d8a1031c00
allow fractional pretty margin -- avoid premature rounding;
 wenzelm parents: 
51492diff
changeset | 93 | private val margin_default = 76.0 | 
| 36820 | 94 | |
| 51493 
59d8a1031c00
allow fractional pretty margin -- avoid premature rounding;
 wenzelm parents: 
51492diff
changeset | 95 | def formatted(input: XML.Body, margin: Double = margin_default, | 
| 51492 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 96 | metric: Metric = Metric_Default): XML.Body = | 
| 36687 | 97 |   {
 | 
| 51568 | 98 | sealed case class Text(tx: XML.Body = Nil, pos: Double = 0.0, nl: Int = 0) | 
| 51470 
a981a5c8a505
proper metric for blanks -- NB: 70f7483df9cb discontinues coincidence of char_width with space width;
 wenzelm parents: 
51469diff
changeset | 99 |     {
 | 
| 
a981a5c8a505
proper metric for blanks -- NB: 70f7483df9cb discontinues coincidence of char_width with space width;
 wenzelm parents: 
51469diff
changeset | 100 | def newline: Text = copy(tx = FBreak :: tx, pos = 0.0, nl = nl + 1) | 
| 51492 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 101 | def string(s: String): Text = copy(tx = XML.Text(s) :: tx, pos = pos + metric(s)) | 
| 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 102 | def blanks(wd: Int): Text = string(spaces(wd)) | 
| 51470 
a981a5c8a505
proper metric for blanks -- NB: 70f7483df9cb discontinues coincidence of char_width with space width;
 wenzelm parents: 
51469diff
changeset | 103 | def content: XML.Body = tx.reverse | 
| 
a981a5c8a505
proper metric for blanks -- NB: 70f7483df9cb discontinues coincidence of char_width with space width;
 wenzelm parents: 
51469diff
changeset | 104 | } | 
| 
a981a5c8a505
proper metric for blanks -- NB: 70f7483df9cb discontinues coincidence of char_width with space width;
 wenzelm parents: 
51469diff
changeset | 105 | |
| 36687 | 106 | val breakgain = margin / 20 | 
| 51569 
4e084727faae
maintain integer indentation during formatting -- it needs to be implemented by repeated spaces eventually;
 wenzelm parents: 
51568diff
changeset | 107 | val emergencypos = (margin / 2).round.toInt | 
| 36687 | 108 | |
| 36817 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 109 | def content_length(tree: XML.Tree): Double = | 
| 49651 | 110 | XML.traverse_text(List(tree))(0.0)(_ + metric(_)) | 
| 36817 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 111 | |
| 38573 | 112 | def breakdist(trees: XML.Body, after: Double): Double = | 
| 36817 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 113 |       trees match {
 | 
| 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 114 | case Break(_) :: _ => 0.0 | 
| 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 115 | case FBreak :: _ => 0.0 | 
| 36818 | 116 | case t :: ts => content_length(t) + breakdist(ts, after) | 
| 36817 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 117 | case Nil => after | 
| 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 118 | } | 
| 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 119 | |
| 38573 | 120 | def forcenext(trees: XML.Body): XML.Body = | 
| 36817 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 121 |       trees match {
 | 
| 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 122 | case Nil => Nil | 
| 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 123 | case FBreak :: _ => trees | 
| 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 124 | case Break(_) :: ts => FBreak :: ts | 
| 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 125 | case t :: ts => t :: forcenext(ts) | 
| 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 126 | } | 
| 
ed97e877ff2d
more precise pretty printing based on actual font metrics;
 wenzelm parents: 
36763diff
changeset | 127 | |
| 51569 
4e084727faae
maintain integer indentation during formatting -- it needs to be implemented by repeated spaces eventually;
 wenzelm parents: 
51568diff
changeset | 128 | def format(trees: XML.Body, blockin: Int, after: Double, text: Text): Text = | 
| 36687 | 129 |       trees match {
 | 
| 130 | case Nil => text | |
| 131 | ||
| 132 | case Block(indent, body) :: ts => | |
| 51569 
4e084727faae
maintain integer indentation during formatting -- it needs to be implemented by repeated spaces eventually;
 wenzelm parents: 
51568diff
changeset | 133 | val pos1 = (text.pos + indent).ceil.toInt | 
| 36687 | 134 | val pos2 = pos1 % emergencypos | 
| 135 | val blockin1 = | |
| 136 | if (pos1 < emergencypos) pos1 | |
| 137 | else pos2 | |
| 138 | val btext = format(body, blockin1, breakdist(ts, after), text) | |
| 139 | val ts1 = if (text.nl < btext.nl) forcenext(ts) else ts | |
| 140 | format(ts1, blockin, after, btext) | |
| 141 | ||
| 142 | case Break(wd) :: ts => | |
| 51568 | 143 | if (text.pos + wd <= ((margin - breakdist(ts, after)) max (blockin + breakgain))) | 
| 36687 | 144 | format(ts, blockin, after, text.blanks(wd)) | 
| 51569 
4e084727faae
maintain integer indentation during formatting -- it needs to be implemented by repeated spaces eventually;
 wenzelm parents: 
51568diff
changeset | 145 | else format(ts, blockin, after, text.newline.blanks(blockin)) | 
| 
4e084727faae
maintain integer indentation during formatting -- it needs to be implemented by repeated spaces eventually;
 wenzelm parents: 
51568diff
changeset | 146 | case FBreak :: ts => format(ts, blockin, after, text.newline.blanks(blockin)) | 
| 36687 | 147 | |
| 49650 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 wenzelm parents: 
49473diff
changeset | 148 | case XML.Wrapped_Elem(markup, body1, body2) :: ts => | 
| 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 wenzelm parents: 
49473diff
changeset | 149 | val btext = format(body2, blockin, breakdist(ts, after), text.copy(tx = Nil)) | 
| 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 wenzelm parents: 
49473diff
changeset | 150 | val ts1 = if (text.nl < btext.nl) forcenext(ts) else ts | 
| 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 wenzelm parents: 
49473diff
changeset | 151 | val btext1 = btext.copy(tx = XML.Wrapped_Elem(markup, body1, btext.content) :: text.tx) | 
| 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 wenzelm parents: 
49473diff
changeset | 152 | format(ts1, blockin, after, btext1) | 
| 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 wenzelm parents: 
49473diff
changeset | 153 | |
| 38230 
ed147003de4b
simplified type XML.Tree: embed Markup directly, avoid slightly odd triple;
 wenzelm parents: 
37374diff
changeset | 154 | case XML.Elem(markup, body) :: ts => | 
| 36734 
d9b10c173330
Pretty.formatted operates directly on XML trees, treating XML.Elem like a pro-forma block of indentation 0, like the ML version;
 wenzelm parents: 
36689diff
changeset | 155 | val btext = format(body, blockin, breakdist(ts, after), text.copy(tx = Nil)) | 
| 
d9b10c173330
Pretty.formatted operates directly on XML trees, treating XML.Elem like a pro-forma block of indentation 0, like the ML version;
 wenzelm parents: 
36689diff
changeset | 156 | val ts1 = if (text.nl < btext.nl) forcenext(ts) else ts | 
| 38230 
ed147003de4b
simplified type XML.Tree: embed Markup directly, avoid slightly odd triple;
 wenzelm parents: 
37374diff
changeset | 157 | val btext1 = btext.copy(tx = XML.Elem(markup, btext.content) :: text.tx) | 
| 36734 
d9b10c173330
Pretty.formatted operates directly on XML trees, treating XML.Elem like a pro-forma block of indentation 0, like the ML version;
 wenzelm parents: 
36689diff
changeset | 158 | format(ts1, blockin, after, btext1) | 
| 49650 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 wenzelm parents: 
49473diff
changeset | 159 | |
| 51492 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 160 | case XML.Text(s) :: ts => format(ts, blockin, after, text.string(s)) | 
| 36687 | 161 | } | 
| 49650 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 wenzelm parents: 
49473diff
changeset | 162 | |
| 51570 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 163 | format(standard_form(input), 0, 0.0, Text()).content | 
| 36687 | 164 | } | 
| 36734 
d9b10c173330
Pretty.formatted operates directly on XML trees, treating XML.Elem like a pro-forma block of indentation 0, like the ML version;
 wenzelm parents: 
36689diff
changeset | 165 | |
| 51493 
59d8a1031c00
allow fractional pretty margin -- avoid premature rounding;
 wenzelm parents: 
51492diff
changeset | 166 | def string_of(input: XML.Body, margin: Double = margin_default, | 
| 51492 
eaa1c4cc1106
more explicit Pretty.Metric, with clear distinction of unit (space width) vs. average char width (for visual adjustments) -- NB: Pretty formatting works via full space characters (despite a981a5c8a505 and 70f7483df9cb);
 wenzelm parents: 
51470diff
changeset | 167 | metric: Metric = Metric_Default): String = | 
| 49416 
1053a564dd25
some actual rich text markup via XML.content_markup;
 wenzelm parents: 
49414diff
changeset | 168 | XML.content(formatted(input, margin, metric)) | 
| 36736 | 169 | |
| 170 | ||
| 171 | /* unformatted output */ | |
| 172 | ||
| 38573 | 173 | def unformatted(input: XML.Body): XML.Body = | 
| 36736 | 174 |   {
 | 
| 38573 | 175 | def fmt(tree: XML.Tree): XML.Body = | 
| 36736 | 176 |       tree match {
 | 
| 177 | case Block(_, body) => body.flatMap(fmt) | |
| 48704 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 178 | case Break(wd) => List(XML.Text(spaces(wd))) | 
| 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 wenzelm parents: 
45666diff
changeset | 179 | case FBreak => List(XML.Text(space)) | 
| 49650 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 wenzelm parents: 
49473diff
changeset | 180 | case XML.Wrapped_Elem(markup, body1, body2) => | 
| 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 wenzelm parents: 
49473diff
changeset | 181 | List(XML.Wrapped_Elem(markup, body1, body2.flatMap(fmt))) | 
| 38230 
ed147003de4b
simplified type XML.Tree: embed Markup directly, avoid slightly odd triple;
 wenzelm parents: 
37374diff
changeset | 182 | case XML.Elem(markup, body) => List(XML.Elem(markup, body.flatMap(fmt))) | 
| 36736 | 183 | case XML.Text(_) => List(tree) | 
| 184 | } | |
| 51570 
3633828d80fc
basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
 wenzelm parents: 
51569diff
changeset | 185 | standard_form(input).flatMap(fmt) | 
| 36736 | 186 | } | 
| 187 | ||
| 49416 
1053a564dd25
some actual rich text markup via XML.content_markup;
 wenzelm parents: 
49414diff
changeset | 188 | def str_of(input: XML.Body): String = XML.content(unformatted(input)) | 
| 36683 | 189 | } |