| author | wenzelm | 
| Tue, 10 Dec 2024 21:06:04 +0100 | |
| changeset 81572 | 693a95492008 | 
| parent 81270 | b98595f82a88 | 
| child 81683 | b31d09029b94 | 
| permissions | -rw-r--r-- | 
| 6118 | 1 | (* Title: Pure/General/pretty.ML | 
| 8806 | 2 | Author: Lawrence C Paulson, Cambridge University Computer Laboratory | 
| 80892 | 3 | Author: Makarius | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 4 | |
| 80892 | 5 | Generic pretty printing. | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 6 | |
| 80892 | 7 | The object to be printed is given as a tree with blocks and breaks. A block | 
| 8 | causes alignment and may specify additional indentation and markup. A break | |
| 9 | inserts a newline if the text until the next break is too long to fit on the | |
| 10 | current line. After the newline, text is indented to the level of the | |
| 11 | enclosing block. Normally, if a block is broken then all enclosing blocks will | |
| 12 | also be broken. | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 13 | |
| 80892 | 14 | References: | 
| 15 | ||
| 16 | * L. C. Paulson, "ML for the Working Programmer" (1996), | |
| 17 | 2nd edition, Cambridge University Press. | |
| 18 | Section 8.10 "A pretty printer" | |
| 19 | https://www.cl.cam.ac.uk/~lp15/MLbook/PDF/chapter8.pdf | |
| 20 | ||
| 21 | * D. C. Oppen, "Pretty Printing", | |
| 22 | ACM Transactions on Programming Languages and Systems (1980), 465-483. | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 23 | *) | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 24 | |
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 25 | signature PRETTY = | 
| 14832 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 26 | sig | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 27 | type T | 
| 80810 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 28 | val to_ML: T -> ML_Pretty.pretty | 
| 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 29 | val from_ML: ML_Pretty.pretty -> T | 
| 80878 | 30 | val blk: int * T list -> T | 
| 31 | val block0: T list -> T | |
| 32 | val block1: T list -> T | |
| 33 | val block: T list -> T | |
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 34 |   type 'a block = {markup: 'a, open_block: bool, consistent: bool, indent: int}
 | 
| 80938 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 35 | val make_block: Markup.output block -> T list -> T | 
| 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 36 | val markup_block: Markup.T block -> T list -> T | 
| 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 37 | val markup: Markup.T -> T list -> T | 
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 38 | val markup_open: Markup.T -> T list -> T | 
| 80938 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 39 | val mark: Markup.T -> T -> T | 
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 40 | val mark_open: Markup.T -> T -> T | 
| 80938 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 41 | val markup_blocks: Markup.T list block -> T list -> T | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 42 | val str: string -> T | 
| 80813 
9dd4dcb08d37
clarified signature, following 1f718be3608b: Pretty.str is now value-oriented;
 wenzelm parents: 
80812diff
changeset | 43 | val dots: T | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 44 | val brk: int -> T | 
| 61862 
e2a9e46ac0fb
support pretty break indent, like underlying ML systems;
 wenzelm parents: 
56334diff
changeset | 45 | val brk_indent: int -> int -> T | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 46 | val fbrk: T | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 47 | val breaks: T list -> T list | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 48 | val fbreaks: T list -> T list | 
| 23645 | 49 | val strs: string list -> T | 
| 42266 | 50 | val mark_str: Markup.T * string -> T | 
| 51 | val marks_str: Markup.T list * string -> T | |
| 80873 | 52 | val mark_position: Position.T -> T -> T | 
| 53 | val mark_str_position: Position.T * string -> T | |
| 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: 
51511diff
changeset | 54 | val item: T list -> T | 
| 52693 | 55 | val text_fold: T list -> T | 
| 55763 | 56 | val keyword1: string -> T | 
| 57 | val keyword2: string -> T | |
| 50162 | 58 | val text: string -> T list | 
| 59 | val paragraph: T list -> T | |
| 60 | val para: string -> T | |
| 18802 | 61 | val quote: T -> T | 
| 55033 | 62 | val cartouche: T -> T | 
| 18802 | 63 | val separate: string -> T list -> T list | 
| 64 | val commas: T list -> T list | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 65 | val enclose: string -> string -> T list -> T | 
| 18802 | 66 | val enum: string -> string -> string -> T list -> T | 
| 30620 | 67 | val position: Position.T -> T | 
| 71465 
910a081cca74
more position information for oracles (e.g. "skip_proof" for 'sorry'), requires Proofterm.proofs := 1;
 wenzelm parents: 
69345diff
changeset | 68 | val here: Position.T -> T list | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 69 | val list: string -> string -> T list -> T | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 70 | val str_list: string -> string -> string list -> T | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 71 | val big_list: string -> T list -> T | 
| 9730 | 72 | val indent: int -> T -> T | 
| 23645 | 73 | val unbreakable: T -> T | 
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 74 | type output_ops = | 
| 80855 
301612847ea3
further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
 wenzelm parents: 
80854diff
changeset | 75 |    {symbolic: bool,
 | 
| 
301612847ea3
further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
 wenzelm parents: 
80854diff
changeset | 76 | output: string -> Output.output * int, | 
| 80829 
bdae6195a287
clarified Pretty.markup_block: use value-oriented YXML.output_markup, with final re-interpretation via print_mode in output_tree;
 wenzelm parents: 
80825diff
changeset | 77 | markup: Markup.output -> Markup.output, | 
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 78 | indent: string -> int -> Output.output, | 
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 79 | margin: int} | 
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 80 | val output_ops: int option -> output_ops | 
| 80854 | 81 | val pure_output_ops: int option -> output_ops | 
| 80830 | 82 | val markup_output_ops: int option -> output_ops | 
| 80855 
301612847ea3
further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
 wenzelm parents: 
80854diff
changeset | 83 | val symbolic_output_ops: output_ops | 
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 84 | val symbolic_output: T -> Bytes.T | 
| 80844 | 85 | val symbolic_string_of: T -> string | 
| 86 | val unformatted_string_of: T -> string | |
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 87 | val output: output_ops -> T -> Bytes.T | 
| 80841 | 88 | val string_of_ops: output_ops -> T -> string | 
| 23645 | 89 | val string_of: T -> string | 
| 80863 | 90 | val pure_string_of: T -> string | 
| 49656 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 wenzelm parents: 
49565diff
changeset | 91 | val writeln: T -> unit | 
| 56334 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 92 | val markup_chunks: Markup.T -> T list -> T | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 93 | val chunks: T list -> T | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 94 | val chunks2: T list -> T | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 95 | val block_enclose: T * T -> T list -> T | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 96 | val writeln_chunks: T list -> unit | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 97 | val writeln_chunks2: T list -> unit | 
| 14832 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 98 | end; | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 99 | |
| 23617 | 100 | structure Pretty: PRETTY = | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 101 | struct | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 102 | |
| 80844 | 103 | (** Pretty.T **) | 
| 104 | ||
| 105 | (* abstype: ML_Pretty.pretty without (op =) *) | |
| 106 | ||
| 107 | abstype T = T of ML_Pretty.pretty | |
| 108 | with | |
| 109 | fun to_ML (T prt) = prt; | |
| 110 | val from_ML = T; | |
| 111 | end; | |
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 112 | |
| 62785 
70b9c7d4ed7f
more robust pretty printing: permissive treatment of bad values;
 wenzelm parents: 
62784diff
changeset | 113 | val force_nat = Integer.max 0; | 
| 80810 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 114 | val short_nat = FixedInt.fromInt o force_nat; | 
| 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 115 | val long_nat = force_nat o FixedInt.toInt; | 
| 62785 
70b9c7d4ed7f
more robust pretty printing: permissive treatment of bad values;
 wenzelm parents: 
62784diff
changeset | 116 | |
| 80810 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 117 | |
| 80878 | 118 | (* blocks *) | 
| 23645 | 119 | |
| 80938 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 120 | fun blk (indent, body) = | 
| 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 121 | from_ML (ML_Pretty.PrettyBlock (short_nat indent, false, [], map to_ML body)); | 
| 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 122 | |
| 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 123 | fun block0 body = blk (0, body); | 
| 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 124 | fun block1 body = blk (1, body); | 
| 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 125 | fun block body = blk (2, body); | 
| 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 126 | |
| 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 127 | |
| 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 128 | (* blocks with markup *) | 
| 
a119154a5f27
minor performance tuning: more direct blocks without markup;
 wenzelm parents: 
80937diff
changeset | 129 | |
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 130 | type 'a block = {markup: 'a, open_block: bool, consistent: bool, indent: int}
 | 
| 80878 | 131 | |
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 132 | fun make_block ({markup, open_block, consistent, indent}: Markup.output block) body =
 | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 133 | let | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 134 | val context = | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 135 | ML_Pretty.markup_context markup @ | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 136 | ML_Pretty.open_block_context open_block; | 
| 80937 | 137 | in from_ML (ML_Pretty.PrettyBlock (short_nat indent, consistent, context, map to_ML body)) end; | 
| 61864 | 138 | |
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 139 | fun markup_block ({markup, open_block, consistent, indent}: Markup.T block) body =
 | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 140 | make_block | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 141 |    {markup = YXML.output_markup markup,
 | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 142 | open_block = open_block, | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 143 | consistent = consistent, | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 144 | indent = indent} body; | 
| 61864 | 145 | |
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 146 | fun markup m = markup_block {markup = m, open_block = false, consistent = false, indent = 0};
 | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 147 | fun markup_open m = markup_block {markup = m, open_block = true, consistent = false, indent = 0};
 | 
| 80936 | 148 | |
| 149 | fun mark m prt = if m = Markup.empty then prt else markup m [prt]; | |
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 150 | fun mark_open m prt = if m = Markup.empty then prt else markup_open m [prt]; | 
| 23645 | 151 | |
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 152 | fun markup_blocks ({markup, open_block, consistent, indent}: Markup.T list block) body =
 | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 153 | if forall Markup.is_empty markup andalso not open_block andalso not consistent | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 154 | then blk (indent, body) | 
| 80942 
501ebf1fc308
minor performance tuning for blocks without markup;
 wenzelm parents: 
80938diff
changeset | 155 | else | 
| 
501ebf1fc308
minor performance tuning for blocks without markup;
 wenzelm parents: 
80938diff
changeset | 156 | let | 
| 
501ebf1fc308
minor performance tuning for blocks without markup;
 wenzelm parents: 
80938diff
changeset | 157 | val markups = filter_out Markup.is_empty markup; | 
| 
501ebf1fc308
minor performance tuning for blocks without markup;
 wenzelm parents: 
80938diff
changeset | 158 | val (ms, m) = if null markups then ([], Markup.empty) else split_last markups; | 
| 
501ebf1fc308
minor performance tuning for blocks without markup;
 wenzelm parents: 
80938diff
changeset | 159 | in | 
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 160 | fold_rev mark_open ms | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 161 | (markup_block | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 162 |           {markup = m, open_block = open_block, consistent = consistent, indent = indent} body)
 | 
| 80942 
501ebf1fc308
minor performance tuning for blocks without markup;
 wenzelm parents: 
80938diff
changeset | 163 | end; | 
| 80937 | 164 | |
| 80878 | 165 | |
| 166 | (* breaks *) | |
| 167 | ||
| 168 | fun brk_indent wd ind = from_ML (ML_Pretty.PrettyBreak (short_nat wd, short_nat ind)); | |
| 169 | fun brk wd = brk_indent wd 0; | |
| 170 | val fbrk = from_ML ML_Pretty.PrettyLineBreak; | |
| 171 | ||
| 172 | fun breaks prts = Library.separate (brk 1) prts; | |
| 173 | fun fbreaks prts = Library.separate fbrk prts; | |
| 174 | ||
| 175 | ||
| 176 | (* derived operations to create formatting expressions *) | |
| 177 | ||
| 178 | val str = from_ML o ML_Pretty.str; | |
| 179 | val dots = from_ML ML_Pretty.dots; | |
| 180 | ||
| 23645 | 181 | val strs = block o breaks o map str; | 
| 182 | ||
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 183 | fun mark_str (m, s) = mark_open m (str s); | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 184 | fun marks_str (ms, s) = fold_rev mark_open ms (str s); | 
| 42266 | 185 | |
| 80875 | 186 | val mark_position = mark o Position.markup; | 
| 187 | fun mark_str_position (pos, s) = mark_str (Position.markup pos, s); | |
| 80873 | 188 | |
| 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: 
51511diff
changeset | 189 | val item = markup Markup.item; | 
| 52693 | 190 | val text_fold = markup Markup.text_fold; | 
| 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: 
51511diff
changeset | 191 | |
| 55763 | 192 | fun keyword1 name = mark_str (Markup.keyword1, name); | 
| 193 | fun keyword2 name = mark_str (Markup.keyword2, name); | |
| 23645 | 194 | |
| 50162 | 195 | val text = breaks o map str o Symbol.explode_words; | 
| 50201 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
50162diff
changeset | 196 | val paragraph = markup Markup.paragraph; | 
| 50162 | 197 | val para = paragraph o text; | 
| 198 | ||
| 80328 | 199 | fun quote prt = block1 [str "\"", prt, str "\""]; | 
| 200 | fun cartouche prt = block1 [str Symbol.open_, prt, str Symbol.close]; | |
| 23645 | 201 | |
| 202 | fun separate sep prts = | |
| 203 | flat (Library.separate [str sep, brk 1] (map single prts)); | |
| 204 | ||
| 205 | val commas = separate ","; | |
| 206 | ||
| 207 | fun enclose lpar rpar prts = | |
| 208 | block (str lpar :: (prts @ [str rpar])); | |
| 209 | ||
| 210 | fun enum sep lpar rpar prts = enclose lpar rpar (separate sep prts); | |
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 211 | |
| 30620 | 212 | val position = | 
| 80504 | 213 |   enum "," "{" "}" o map (str o Properties.print_eq) o Position.properties_of;
 | 
| 30620 | 214 | |
| 71465 
910a081cca74
more position information for oracles (e.g. "skip_proof" for 'sorry'), requires Proofterm.proofs := 1;
 wenzelm parents: 
69345diff
changeset | 215 | fun here pos = | 
| 80873 | 216 | let val (s1, s2) = Position.here_strs pos | 
| 217 | in if s2 = "" then [] else [str s1, mark_str_position (pos, s2)] end; | |
| 71465 
910a081cca74
more position information for oracles (e.g. "skip_proof" for 'sorry'), requires Proofterm.proofs := 1;
 wenzelm parents: 
69345diff
changeset | 218 | |
| 23645 | 219 | val list = enum ","; | 
| 220 | fun str_list lpar rpar strs = list lpar rpar (map str strs); | |
| 221 | ||
| 222 | fun big_list name prts = block (fbreaks (str name :: prts)); | |
| 223 | ||
| 224 | fun indent 0 prt = prt | |
| 80328 | 225 | | indent n prt = block0 [str (Symbol.spaces n), prt]; | 
| 23645 | 226 | |
| 80810 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 227 | val unbreakable = | 
| 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 228 | let | 
| 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 229 | fun unbreak (ML_Pretty.PrettyBlock (ind, consistent, context, body)) = | 
| 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 230 | ML_Pretty.PrettyBlock (ind, consistent, context, map unbreak body) | 
| 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 231 | | unbreak (ML_Pretty.PrettyBreak (wd, _)) = | 
| 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 232 | ML_Pretty.str (Symbol.spaces (long_nat wd)) | 
| 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 233 | | unbreak prt = prt; | 
| 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 234 | in to_ML #> unbreak #> from_ML end; | 
| 23645 | 235 | |
| 236 | ||
| 237 | ||
| 238 | (** formatting **) | |
| 239 | ||
| 80861 
9de19e3a7231
dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
 wenzelm parents: 
80856diff
changeset | 240 | (* output operations *) | 
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 241 | |
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 242 | type output_ops = | 
| 80855 
301612847ea3
further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
 wenzelm parents: 
80854diff
changeset | 243 |  {symbolic: bool,
 | 
| 
301612847ea3
further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
 wenzelm parents: 
80854diff
changeset | 244 | output: string -> Output.output * int, | 
| 80829 
bdae6195a287
clarified Pretty.markup_block: use value-oriented YXML.output_markup, with final re-interpretation via print_mode in output_tree;
 wenzelm parents: 
80825diff
changeset | 245 | markup: Markup.output -> Markup.output, | 
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 246 | indent: string -> int -> Output.output, | 
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 247 | margin: int}; | 
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 248 | |
| 80861 
9de19e3a7231
dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
 wenzelm parents: 
80856diff
changeset | 249 | fun make_output_ops {symbolic, markup} opt_margin : output_ops =
 | 
| 80855 
301612847ea3
further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
 wenzelm parents: 
80854diff
changeset | 250 |  {symbolic = symbolic,
 | 
| 
301612847ea3
further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
 wenzelm parents: 
80854diff
changeset | 251 | output = fn s => (s, size s), | 
| 80854 | 252 | markup = markup, | 
| 80861 
9de19e3a7231
dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
 wenzelm parents: 
80856diff
changeset | 253 | indent = fn _ => Symbol.spaces, | 
| 80854 | 254 | margin = ML_Pretty.get_margin opt_margin}; | 
| 80849 
e3a419073736
drop pointless print_mode operations Output.output / Output.escape;
 wenzelm parents: 
80848diff
changeset | 255 | |
| 80861 
9de19e3a7231
dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
 wenzelm parents: 
80856diff
changeset | 256 | val pure_output_ops = make_output_ops {symbolic = false, markup = K Markup.no_output};
 | 
| 
9de19e3a7231
dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
 wenzelm parents: 
80856diff
changeset | 257 | val markup_output_ops = make_output_ops {symbolic = false, markup = I};
 | 
| 
9de19e3a7231
dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
 wenzelm parents: 
80856diff
changeset | 258 | val symbolic_output_ops = make_output_ops {symbolic = true, markup = I} NONE;
 | 
| 
9de19e3a7231
dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
 wenzelm parents: 
80856diff
changeset | 259 | |
| 
9de19e3a7231
dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
 wenzelm parents: 
80856diff
changeset | 260 | fun output_ops opt_margin = | 
| 80867 | 261 | if Print_Mode.PIDE_enabled () then symbolic_output_ops | 
| 80861 
9de19e3a7231
dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
 wenzelm parents: 
80856diff
changeset | 262 | else pure_output_ops opt_margin; | 
| 80829 
bdae6195a287
clarified Pretty.markup_block: use value-oriented YXML.output_markup, with final re-interpretation via print_mode in output_tree;
 wenzelm parents: 
80825diff
changeset | 263 | |
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 264 | fun output_newline (ops: output_ops) = #1 (#output ops "\n"); | 
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 265 | |
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 266 | fun output_spaces (ops: output_ops) = #output ops o Symbol.spaces; | 
| 80843 | 267 | fun output_spaces_buffer ops = Buffer.add o #1 o output_spaces ops; | 
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 268 | fun output_spaces_bytes ops = Bytes.add o #1 o output_spaces ops; | 
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 269 | |
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 270 | |
| 80844 | 271 | (* output tree *) | 
| 272 | ||
| 273 | datatype tree = | |
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 274 | Block of | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 275 |      {markup: Markup.output,
 | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 276 | open_block: bool, | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 277 | consistent: bool, | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 278 | indent: int, | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 279 | body: tree list, | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 280 | length: int} | 
| 80844 | 281 | | Break of bool * int * int (*mandatory flag, width if not taken, extra indentation if taken*) | 
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 282 | | Str of Output.output * int (*string output, length*) | 
| 81269 | 283 | | Raw of Output.output; (*raw output: no length, no indent*) | 
| 80844 | 284 | |
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 285 | fun tree_length (Block {length = len, ...}) = len
 | 
| 80844 | 286 | | tree_length (Break (_, wd, _)) = wd | 
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 287 | | tree_length (Str (_, len)) = len | 
| 81269 | 288 | | tree_length (Raw _) = 0; | 
| 80844 | 289 | |
| 290 | local | |
| 291 | ||
| 292 | fun block_length indent = | |
| 293 | let | |
| 80936 | 294 | fun block_len len body = | 
| 80844 | 295 | let | 
| 80936 | 296 | val (line, rest) = chop_prefix (fn Break (true, _, _) => false | _ => true) body; | 
| 80844 | 297 | val len' = Int.max (fold (Integer.add o tree_length) line 0, len); | 
| 298 | in | |
| 299 | (case rest of | |
| 300 | Break (true, _, ind) :: rest' => | |
| 301 | block_len len' (Break (false, indent + ind, 0) :: rest') | |
| 302 | | [] => len') | |
| 303 | end; | |
| 304 | in block_len 0 end; | |
| 305 | ||
| 306 | val fbreak = Break (true, 1, 0); | |
| 307 | ||
| 308 | in | |
| 309 | ||
| 310 | fun output_tree (ops: output_ops) make_length = | |
| 311 | let | |
| 81270 | 312 | fun tree (ML_Pretty.PrettyBlock (ind, consistent, context, body)) = | 
| 80844 | 313 | let | 
| 314 | val indent = long_nat ind; | |
| 81270 | 315 | val body' = map tree body; | 
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 316 | in | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 317 | Block | 
| 81266 | 318 |              {markup = #markup ops (ML_Pretty.markup_get context),
 | 
| 319 | open_block = ML_Pretty.open_block_detect context, | |
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 320 | consistent = consistent, | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 321 | indent = indent, | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 322 | body = body', | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 323 | length = if make_length then block_length indent body' else ~1} | 
| 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 324 | end | 
| 81270 | 325 | | tree (ML_Pretty.PrettyBreak (wd, ind)) = Break (false, long_nat wd, long_nat ind) | 
| 326 | | tree ML_Pretty.PrettyLineBreak = fbreak | |
| 327 | | tree (ML_Pretty.PrettyString s) = Str (#output ops s ||> force_nat) | |
| 328 | | tree (ML_Pretty.PrettyStringWithWidth (s, n)) = Str (s, long_nat n); | |
| 329 | in tree o to_ML end; | |
| 80844 | 330 | |
| 331 | end; | |
| 332 | ||
| 333 | ||
| 23645 | 334 | (* formatted output *) | 
| 335 | ||
| 336 | local | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 337 | |
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 338 | type text = {tx: Bytes.T, ind: Buffer.T, pos: int, nl: int};
 | 
| 17756 | 339 | |
| 340 | val empty: text = | |
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 341 |  {tx = Bytes.empty,
 | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 342 | ind = Buffer.empty, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 343 | pos = 0, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 344 | nl = 0}; | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 345 | |
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 346 | fun newline s {tx, ind = _, pos = _, nl} : text =
 | 
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 347 |  {tx = Bytes.add s tx,
 | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 348 | ind = Buffer.empty, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 349 | pos = 0, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 350 | nl = nl + 1}; | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 351 | |
| 17756 | 352 | fun string (s, len) {tx, ind, pos: int, nl} : text =
 | 
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 353 |  {tx = Bytes.add s tx,
 | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 354 | ind = Buffer.add s ind, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 355 | pos = pos + len, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 356 | nl = nl}; | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 357 | |
| 81269 | 358 | fun raw s {tx, ind, pos: int, nl} : text =
 | 
| 359 |  {tx = Bytes.add s tx,
 | |
| 360 | ind = ind, | |
| 361 | pos = pos, | |
| 362 | nl = nl}; | |
| 363 | ||
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 364 | (*Add the lengths of the expressions until the next Break; if no Break then | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 365 | include "after", to account for text following this block.*) | 
| 61864 | 366 | fun break_dist (Break _ :: _, _) = 0 | 
| 80936 | 367 | | break_dist (prt :: prts, after) = tree_length prt + break_dist (prts, after) | 
| 61864 | 368 | | break_dist ([], after) = after; | 
| 369 | ||
| 80936 | 370 | val force_break = fn Break (false, wd, ind) => Break (true, wd, ind) | prt => prt; | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 371 | |
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 372 | (*Search for the next break (at this or higher levels) and force it to occur.*) | 
| 61864 | 373 | fun force_next [] = [] | 
| 80936 | 374 | | force_next ((prt as Break _) :: prts) = force_break prt :: prts | 
| 375 | | force_next (prt :: prts) = prt :: force_next prts; | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 376 | |
| 23645 | 377 | in | 
| 19266 | 378 | |
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 379 | fun format_tree (ops: output_ops) input = | 
| 36745 | 380 | let | 
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 381 | val margin = #margin ops; | 
| 36745 | 382 | val breakgain = margin div 20; (*minimum added space required of a break*) | 
| 383 | val emergencypos = margin div 2; (*position too far to right*) | |
| 384 | ||
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 385 | val linebreak = newline (output_newline ops); | 
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 386 | val blanks = string o output_spaces ops; | 
| 80843 | 387 | val blanks_buffer = output_spaces_buffer ops; | 
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 388 | |
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 389 |     fun indentation (buf, len) {tx, ind, pos, nl} : text =
 | 
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 390 | let val s = Buffer.content buf in | 
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 391 |        {tx = Bytes.add (#indent ops s len) tx,
 | 
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 392 | ind = Buffer.add s ind, | 
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 393 | pos = pos + len, | 
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 394 | nl = nl} | 
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 395 | end; | 
| 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 396 | |
| 80936 | 397 | (*blockin is the indentation of the current block; | 
| 36745 | 398 | after is the width of the following context until next break.*) | 
| 399 | fun format ([], _, _) text = text | |
| 80936 | 400 |       | format (prt :: prts, block as (_, blockin), after) (text as {ind, pos, nl, ...}) =
 | 
| 401 | (case prt of | |
| 81268 | 402 |             Block {markup = (bg, en), open_block = true, body, ...} =>
 | 
| 81269 | 403 | format (Raw bg :: body @ Raw en :: prts, block, after) text | 
| 81268 | 404 |           | Block {markup = (bg, en), consistent, indent, body, length = blen, ...} =>
 | 
| 36745 | 405 | let | 
| 406 | val pos' = pos + indent; | |
| 407 | val pos'' = pos' mod emergencypos; | |
| 408 | val block' = | |
| 80843 | 409 | if pos' < emergencypos then (ind |> blanks_buffer indent, pos') | 
| 410 | else (blanks_buffer pos'' Buffer.empty, pos''); | |
| 80936 | 411 | val d = break_dist (prts, after) | 
| 81268 | 412 | val body' = body |> (consistent andalso pos + blen > margin - d) ? map force_break; | 
| 36745 | 413 | val btext: text = text | 
| 81269 | 414 | |> raw bg | 
| 81268 | 415 | |> format (body', block', d) | 
| 81269 | 416 | |> raw en; | 
| 36745 | 417 | (*if this block was broken then force the next break*) | 
| 80936 | 418 | val prts' = if nl < #nl btext then force_next prts else prts; | 
| 419 | in format (prts', block, after) btext end | |
| 61862 
e2a9e46ac0fb
support pretty break indent, like underlying ML systems;
 wenzelm parents: 
56334diff
changeset | 420 | | Break (force, wd, ind) => | 
| 36745 | 421 | (*no break if text to next break fits on this line | 
| 422 | or if breaking would add only breakgain to space*) | |
| 80936 | 423 | format (prts, block, after) | 
| 36745 | 424 | (if not force andalso | 
| 80936 | 425 | pos + wd <= Int.max (margin - break_dist (prts, after), blockin + breakgain) | 
| 61864 | 426 | then text |> blanks wd (*just insert wd blanks*) | 
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 427 | else text |> linebreak |> indentation block |> blanks ind) | 
| 81121 
7cacedbddba7
support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
 wenzelm parents: 
81120diff
changeset | 428 | | Str str => format (prts, block, after) (string str text) | 
| 81269 | 429 | | Raw s => format (prts, block, after) (raw s text)); | 
| 36745 | 430 | in | 
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 431 | #tx (format ([output_tree ops true input], (Buffer.empty, 0), 0) empty) | 
| 36745 | 432 | end; | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 433 | |
| 23645 | 434 | end; | 
| 14832 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 435 | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 436 | |
| 80844 | 437 | |
| 438 | (** no formatting **) | |
| 439 | ||
| 440 | (* symbolic output: XML markup for blocks/breaks + other markup *) | |
| 441 | ||
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 442 | val symbolic_output = | 
| 80829 
bdae6195a287
clarified Pretty.markup_block: use value-oriented YXML.output_markup, with final re-interpretation via print_mode in output_tree;
 wenzelm parents: 
80825diff
changeset | 443 | let | 
| 80855 
301612847ea3
further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
 wenzelm parents: 
80854diff
changeset | 444 | val ops = symbolic_output_ops; | 
| 18802 | 445 | |
| 81268 | 446 | fun markup_bytes m output_body = | 
| 80829 
bdae6195a287
clarified Pretty.markup_block: use value-oriented YXML.output_markup, with final re-interpretation via print_mode in output_tree;
 wenzelm parents: 
80825diff
changeset | 447 | let val (bg, en) = #markup ops (YXML.output_markup m) | 
| 81268 | 448 | in Bytes.add bg #> output_body #> Bytes.add en end; | 
| 80822 | 449 | |
| 81268 | 450 |     fun output (Block {markup = (bg, en), body = [], ...}) = Bytes.add bg #> Bytes.add en
 | 
| 451 |       | output (Block {markup = (bg, en), open_block = true, body, ...}) =
 | |
| 452 | Bytes.add bg #> fold output body #> Bytes.add en | |
| 453 |       | output (Block {markup = (bg, en), consistent, indent, body, ...}) =
 | |
| 81267 
d5ad89fda714
clarified symbolic output: avoid redundant "block" element for open_block = true;
 wenzelm parents: 
81266diff
changeset | 454 |           let val block_markup = Markup.block {consistent = consistent, indent = indent}
 | 
| 81268 | 455 | in Bytes.add bg #> markup_bytes block_markup (fold output body) #> Bytes.add en end | 
| 456 | | output (Break (false, wd, ind)) = | |
| 81120 | 457 |           markup_bytes (Markup.break {width = wd, indent = ind}) (output_spaces_bytes ops wd)
 | 
| 81268 | 458 | | output (Break (true, _, _)) = Bytes.add (output_newline ops) | 
| 459 | | output (Str (s, _)) = Bytes.add s | |
| 81269 | 460 | | output (Raw s) = Bytes.add s; | 
| 81268 | 461 | in Bytes.build o output o output_tree ops false end; | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 462 | |
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 463 | val symbolic_string_of = Bytes.content o symbolic_output; | 
| 80844 | 464 | |
| 465 | ||
| 466 | (* unformatted output: other markup only *) | |
| 467 | ||
| 80834 | 468 | fun unformatted ops = | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 469 | let | 
| 81268 | 470 |     fun output (Block ({markup = (bg, en), body, ...})) =
 | 
| 471 | Bytes.add bg #> fold output body #> Bytes.add en | |
| 472 | | output (Break (_, wd, _)) = output_spaces_bytes ops wd | |
| 473 | | output (Str (s, _)) = Bytes.add s | |
| 81269 | 474 | | output (Raw s) = Bytes.add s; | 
| 81268 | 475 | in Bytes.build o output o output_tree ops false end; | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 476 | |
| 80844 | 477 | fun unformatted_string_of prt = | 
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 478 | Bytes.content (unformatted (output_ops NONE) prt); | 
| 80844 | 479 | |
| 30624 
e755b8b76365
simplified datatype ML_Pretty.pretty: model Isabelle not Poly/ML;
 wenzelm parents: 
30620diff
changeset | 480 | |
| 36748 | 481 | (* output interfaces *) | 
| 30620 | 482 | |
| 80855 
301612847ea3
further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
 wenzelm parents: 
80854diff
changeset | 483 | fun output ops = if #symbolic ops then symbolic_output else format_tree ops; | 
| 23645 | 484 | |
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 485 | fun string_of_ops ops = Bytes.content o output ops; | 
| 80841 | 486 | fun string_of prt = string_of_ops (output_ops NONE) prt; | 
| 49656 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 wenzelm parents: 
49565diff
changeset | 487 | |
| 80863 | 488 | val pure_string_of = string_of_ops (pure_output_ops NONE); | 
| 489 | ||
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 490 | fun writeln prt = | 
| 80848 
df85df6315af
clarified signature: prefer explicit type Bytes.T;
 wenzelm parents: 
80846diff
changeset | 491 | Output.writelns (Bytes.contents (output (output_ops NONE) prt)); | 
| 80825 
b866d1510bd0
clarified signature: more explicit type output_ops: default via print_mode;
 wenzelm parents: 
80824diff
changeset | 492 | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 493 | |
| 56334 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 494 | (* chunks *) | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 495 | |
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 496 | fun markup_chunks m prts = markup m (fbreaks (map (text_fold o single) prts)); | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 497 | val chunks = markup_chunks Markup.empty; | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 498 | |
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 499 | fun chunks2 prts = | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 500 | (case try split_last prts of | 
| 80328 | 501 | NONE => block0 [] | 
| 56334 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 502 | | SOME (prefix, last) => | 
| 80328 | 503 | block0 (maps (fn prt => [text_fold [prt, fbrk], fbrk]) prefix @ [text_fold [last]])); | 
| 56334 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 504 | |
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 505 | fun block_enclose (prt1, prt2) prts = chunks [block (fbreaks (prt1 :: prts)), prt2]; | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 506 | |
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 507 | fun string_of_text_fold prt = string_of prt |> Markup.markup Markup.text_fold; | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 508 | |
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 509 | fun writeln_chunks prts = | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 510 | Output.writelns (Library.separate "\n" (map string_of_text_fold prts)); | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 511 | |
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 512 | fun writeln_chunks2 prts = | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 513 | (case try split_last prts of | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 514 | NONE => () | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 515 | | SOME (prefix, last) => | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 516 | (map (fn prt => Markup.markup Markup.text_fold (string_of prt ^ "\n") ^ "\n") prefix @ | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 517 | [string_of_text_fold last]) | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 518 | |> Output.writelns); | 
| 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 519 | |
| 80810 
1f718be3608b
clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
 wenzelm parents: 
80809diff
changeset | 520 | end; | 
| 56334 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55918diff
changeset | 521 | |
| 80844 | 522 | |
| 523 | ||
| 524 | (** back-patching **) | |
| 62899 
845ed4584e21
clarified bootstrap of @{make_string} -- avoid query on ML environment;
 wenzelm parents: 
62823diff
changeset | 525 | |
| 80809 
4a64fc4d1cde
clarified signature: type ML_Pretty.pretty coincides with PolyML.pretty;
 wenzelm parents: 
80805diff
changeset | 526 | structure ML_Pretty: ML_PRETTY = | 
| 62899 
845ed4584e21
clarified bootstrap of @{make_string} -- avoid query on ML environment;
 wenzelm parents: 
62823diff
changeset | 527 | struct | 
| 
845ed4584e21
clarified bootstrap of @{make_string} -- avoid query on ML environment;
 wenzelm parents: 
62823diff
changeset | 528 | open ML_Pretty; | 
| 80809 
4a64fc4d1cde
clarified signature: type ML_Pretty.pretty coincides with PolyML.pretty;
 wenzelm parents: 
80805diff
changeset | 529 | val string_of = Pretty.string_of o Pretty.from_ML; | 
| 62899 
845ed4584e21
clarified bootstrap of @{make_string} -- avoid query on ML environment;
 wenzelm parents: 
62823diff
changeset | 530 | end; | 
| 80812 | 531 | |
| 532 | ||
| 533 | ||
| 534 | (** toplevel pretty printing **) | |
| 535 | ||
| 536 | val _ = ML_system_pp (fn d => fn _ => ML_Pretty.prune (d + 1) o Pretty.to_ML o Pretty.quote); | |
| 537 | val _ = ML_system_pp (fn _ => fn _ => Pretty.to_ML o Pretty.position); | |
| 538 | val _ = ML_system_pp (fn _ => fn _ => Pretty.to_ML o Pretty.mark_str o Path.print_markup); | |
| 539 | ||
| 540 | val _ = | |
| 541 | ML_system_pp (fn _ => fn _ => fn t => | |
| 542 |     ML_Pretty.str ("<thread " ^ quote (Isabelle_Thread.print t) ^
 | |
| 543 | (if Isabelle_Thread.is_active t then "" else " (inactive)") ^ ">")); | |
| 544 | ||
| 545 | val _ = | |
| 546 | ML_system_pp (fn _ => fn _ => fn bytes => | |
| 547 | ML_Pretty.str | |
| 548 | (if Bytes.is_empty bytes then "Bytes.empty" | |
| 549 |       else "Bytes {size = " ^ string_of_int (Bytes.size bytes) ^ "}"));
 |