26 val add_mode: string -> ops -> unit |
26 val add_mode: string -> ops -> unit |
27 val get_mode: unit -> ops |
27 val get_mode: unit -> ops |
28 type T |
28 type T |
29 val to_ML: T -> ML_Pretty.pretty |
29 val to_ML: T -> ML_Pretty.pretty |
30 val from_ML: ML_Pretty.pretty -> T |
30 val from_ML: ML_Pretty.pretty -> T |
31 val make_block: {markup: Markup.output, consistent: bool, indent: int} -> |
31 val make_block: {markup: Markup.output, consistent: bool, indent: int} -> T list -> T |
32 T list -> T |
|
33 val markup_block: {markup: Markup.T, consistent: bool, indent: int} -> T list -> T |
32 val markup_block: {markup: Markup.T, consistent: bool, indent: int} -> T list -> T |
34 val str: string -> T |
33 val str: string -> T |
35 val dots: T |
34 val dots: T |
36 val brk: int -> T |
35 val brk: int -> T |
37 val brk_indent: int -> int -> T |
36 val brk_indent: int -> int -> T |
73 markup: Markup.output -> Markup.output, |
72 markup: Markup.output -> Markup.output, |
74 indent: string -> int -> Output.output, |
73 indent: string -> int -> Output.output, |
75 margin: int} |
74 margin: int} |
76 val output_ops: int option -> output_ops |
75 val output_ops: int option -> output_ops |
77 val markup_output_ops: int option -> output_ops |
76 val markup_output_ops: int option -> output_ops |
|
77 val symbolic_output: T -> Output.output list |
|
78 val symbolic_string_of: T -> string |
|
79 val unformatted_string_of: T -> string |
78 val regularN: string |
80 val regularN: string |
79 val symbolicN: string |
81 val symbolicN: string |
80 val output_buffer: output_ops -> T -> Buffer.T |
82 val output_buffer: output_ops -> T -> Buffer.T |
81 val output: output_ops -> T -> Output.output list |
83 val output: output_ops -> T -> Output.output list |
82 val string_of_ops: output_ops -> T -> string |
84 val string_of_ops: output_ops -> T -> string |
83 val string_of: T -> string |
85 val string_of: T -> string |
84 val writeln: T -> unit |
86 val writeln: T -> unit |
85 val symbolic_output: T -> Output.output list |
|
86 val symbolic_string_of: T -> string |
|
87 val unformatted_string_of: T -> string |
|
88 val markup_chunks: Markup.T -> T list -> T |
87 val markup_chunks: Markup.T -> T list -> T |
89 val chunks: T list -> T |
88 val chunks: T list -> T |
90 val chunks2: T list -> T |
89 val chunks2: T list -> T |
91 val block_enclose: T * T -> T list -> T |
90 val block_enclose: T * T -> T list -> T |
92 val writeln_chunks: T list -> unit |
91 val writeln_chunks: T list -> unit |
116 (Library.get_first (Symtab.lookup (Synchronized.value modes)) (print_mode_value ())); |
115 (Library.get_first (Symtab.lookup (Synchronized.value modes)) (print_mode_value ())); |
117 end; |
116 end; |
118 |
117 |
119 |
118 |
120 |
119 |
121 (** printing items: compound phrases, strings, and breaks **) |
120 (** Pretty.T **) |
|
121 |
|
122 (* abstype: ML_Pretty.pretty without (op =) *) |
|
123 |
|
124 abstype T = T of ML_Pretty.pretty |
|
125 with |
|
126 fun to_ML (T prt) = prt; |
|
127 val from_ML = T; |
|
128 end; |
122 |
129 |
123 val force_nat = Integer.max 0; |
130 val force_nat = Integer.max 0; |
124 val short_nat = FixedInt.fromInt o force_nat; |
131 val short_nat = FixedInt.fromInt o force_nat; |
125 val long_nat = force_nat o FixedInt.toInt; |
132 val long_nat = force_nat o FixedInt.toInt; |
126 |
133 |
127 datatype tree = |
134 |
128 Block of Markup.output * bool * int * tree list * int |
135 (* primitives *) |
129 (*markup output, consistent, indentation, body, length*) |
|
130 | Break of bool * int * int (*mandatory flag, width if not taken, extra indentation if taken*) |
|
131 | Str of Output.output * int; (*string output, length*) |
|
132 |
|
133 fun tree_length (Block (_, _, _, _, len)) = len |
|
134 | tree_length (Break (_, wd, _)) = wd |
|
135 | tree_length (Str (_, len)) = len; |
|
136 |
|
137 abstype T = T of ML_Pretty.pretty |
|
138 with |
|
139 |
|
140 fun to_ML (T prt) = prt; |
|
141 val from_ML = T; |
|
142 |
136 |
143 fun make_block {markup = (bg, en), consistent, indent} body = |
137 fun make_block {markup = (bg, en), consistent, indent} body = |
144 let |
138 let |
145 val context = |
139 val context = |
146 (if bg = "" then [] else [ML_Pretty.ContextProperty ("begin", bg)]) @ |
140 (if bg = "" then [] else [ML_Pretty.ContextProperty ("begin", bg)]) @ |
147 (if en = "" then [] else [ML_Pretty.ContextProperty ("end", en)]); |
141 (if en = "" then [] else [ML_Pretty.ContextProperty ("end", en)]); |
148 val ind = short_nat indent; |
142 val ind = short_nat indent; |
149 in T (ML_Pretty.PrettyBlock (ind, consistent, context, map to_ML body)) end; |
143 in from_ML (ML_Pretty.PrettyBlock (ind, consistent, context, map to_ML body)) end; |
150 |
144 |
151 fun markup_block {markup, consistent, indent} body = |
145 fun markup_block {markup, consistent, indent} body = |
152 make_block {markup = YXML.output_markup markup, consistent = consistent, indent = indent} body; |
146 make_block {markup = YXML.output_markup markup, consistent = consistent, indent = indent} body; |
153 |
147 |
154 |
148 val str = from_ML o ML_Pretty.str; |
155 |
149 val dots = from_ML ML_Pretty.dots; |
156 (** derived operations to create formatting expressions **) |
150 |
157 |
151 fun brk_indent wd ind = from_ML (ML_Pretty.PrettyBreak (short_nat wd, short_nat ind)); |
158 val str = T o ML_Pretty.str; |
|
159 val dots = T ML_Pretty.dots; |
|
160 |
|
161 fun brk_indent wd ind = T (ML_Pretty.PrettyBreak (short_nat wd, short_nat ind)); |
|
162 fun brk wd = brk_indent wd 0; |
152 fun brk wd = brk_indent wd 0; |
163 val fbrk = T ML_Pretty.PrettyLineBreak; |
153 val fbrk = from_ML ML_Pretty.PrettyLineBreak; |
|
154 |
|
155 |
|
156 (* derived operations to create formatting expressions *) |
164 |
157 |
165 fun breaks prts = Library.separate (brk 1) prts; |
158 fun breaks prts = Library.separate (brk 1) prts; |
166 fun fbreaks prts = Library.separate fbrk prts; |
159 fun fbreaks prts = Library.separate fbrk prts; |
167 |
160 |
168 fun blk (indent, es) = |
161 fun blk (indent, es) = |
261 |
254 |
262 fun output_spaces (ops: output_ops) = #output ops o Symbol.spaces; |
255 fun output_spaces (ops: output_ops) = #output ops o Symbol.spaces; |
263 fun output_spaces_buffer ops = Buffer.add o #1 o output_spaces ops; |
256 fun output_spaces_buffer ops = Buffer.add o #1 o output_spaces ops; |
264 |
257 |
265 |
258 |
266 (* formatted output *) |
259 (* output tree *) |
|
260 |
|
261 datatype tree = |
|
262 Block of Markup.output * bool * int * tree list * int |
|
263 (*markup output, consistent, indentation, body, length*) |
|
264 | Break of bool * int * int (*mandatory flag, width if not taken, extra indentation if taken*) |
|
265 | Str of Output.output * int; (*string output, length*) |
|
266 |
|
267 fun tree_length (Block (_, _, _, _, len)) = len |
|
268 | tree_length (Break (_, wd, _)) = wd |
|
269 | tree_length (Str (_, len)) = len; |
267 |
270 |
268 local |
271 local |
269 |
272 |
270 type text = {tx: Buffer.T, ind: Buffer.T, pos: int, nl: int}; |
273 fun context_property context name = |
271 |
274 let |
272 val empty: text = |
275 fun get (ML_Pretty.ContextProperty (a, b)) = if name = a then SOME b else NONE |
273 {tx = Buffer.empty, |
276 | get _ = NONE; |
274 ind = Buffer.empty, |
277 in the_default "" (get_first get context) end; |
275 pos = 0, |
|
276 nl = 0}; |
|
277 |
|
278 fun newline s {tx, ind = _, pos = _, nl} : text = |
|
279 {tx = Buffer.add s tx, |
|
280 ind = Buffer.empty, |
|
281 pos = 0, |
|
282 nl = nl + 1}; |
|
283 |
|
284 fun control s {tx, ind, pos: int, nl} : text = |
|
285 {tx = Buffer.add s tx, |
|
286 ind = ind, |
|
287 pos = pos, |
|
288 nl = nl}; |
|
289 |
|
290 fun string (s, len) {tx, ind, pos: int, nl} : text = |
|
291 {tx = Buffer.add s tx, |
|
292 ind = Buffer.add s ind, |
|
293 pos = pos + len, |
|
294 nl = nl}; |
|
295 |
|
296 (*Add the lengths of the expressions until the next Break; if no Break then |
|
297 include "after", to account for text following this block.*) |
|
298 fun break_dist (Break _ :: _, _) = 0 |
|
299 | break_dist (e :: es, after) = tree_length e + break_dist (es, after) |
|
300 | break_dist ([], after) = after; |
|
301 |
|
302 val fbreak = Break (true, 1, 0); |
|
303 |
|
304 val force_break = fn Break (false, wd, ind) => Break (true, wd, ind) | e => e; |
|
305 val force_all = map force_break; |
|
306 |
|
307 (*Search for the next break (at this or higher levels) and force it to occur.*) |
|
308 fun force_next [] = [] |
|
309 | force_next ((e as Break _) :: es) = force_break e :: es |
|
310 | force_next (e :: es) = e :: force_next es; |
|
311 |
278 |
312 fun block_length indent = |
279 fun block_length indent = |
313 let |
280 let |
314 fun block_len len prts = |
281 fun block_len len prts = |
315 let |
282 let |
321 block_len len' (Break (false, indent + ind, 0) :: rest') |
288 block_len len' (Break (false, indent + ind, 0) :: rest') |
322 | [] => len') |
289 | [] => len') |
323 end; |
290 end; |
324 in block_len 0 end; |
291 in block_len 0 end; |
325 |
292 |
326 fun property context name = |
293 val fbreak = Break (true, 1, 0); |
327 let |
|
328 fun get (ML_Pretty.ContextProperty (a, b)) = if name = a then SOME b else NONE |
|
329 | get _ = NONE; |
|
330 in the_default "" (get_first get context) end; |
|
331 |
294 |
332 in |
295 in |
333 |
296 |
334 fun output_tree (ops: output_ops) make_length = |
297 fun output_tree (ops: output_ops) make_length = |
335 let |
298 let |
336 fun out (T (ML_Pretty.PrettyBlock (ind, consistent, context, body))) = |
299 fun out (ML_Pretty.PrettyBlock (ind, consistent, context, body)) = |
337 let |
300 let |
338 val bg = property context "begin"; |
301 val bg = context_property context "begin"; |
339 val en = property context "end"; |
302 val en = context_property context "end"; |
340 val m = #markup ops (bg, en); |
303 val m = #markup ops (bg, en); |
341 val indent = long_nat ind; |
304 val indent = long_nat ind; |
342 val body' = map (out o T) body; |
305 val body' = map out body; |
343 val len = if make_length then block_length indent body' else ~1; |
306 val len = if make_length then block_length indent body' else ~1; |
344 in Block (m, consistent, indent, body', len) end |
307 in Block (m, consistent, indent, body', len) end |
345 | out (T (ML_Pretty.PrettyBreak (wd, ind))) = Break (false, long_nat wd, long_nat ind) |
308 | out (ML_Pretty.PrettyBreak (wd, ind)) = Break (false, long_nat wd, long_nat ind) |
346 | out (T ML_Pretty.PrettyLineBreak) = fbreak |
309 | out ML_Pretty.PrettyLineBreak = fbreak |
347 | out (T (ML_Pretty.PrettyString s)) = Str (#output ops s ||> force_nat) |
310 | out (ML_Pretty.PrettyString s) = Str (#output ops s ||> force_nat) |
348 | out (T (ML_Pretty.PrettyStringWithWidth (s, n))) = Str (s, long_nat n); |
311 | out (ML_Pretty.PrettyStringWithWidth (s, n)) = Str (s, long_nat n); |
349 in out end; |
312 in out o to_ML end; |
|
313 |
|
314 end; |
|
315 |
|
316 |
|
317 (* formatted output *) |
|
318 |
|
319 local |
|
320 |
|
321 type text = {tx: Buffer.T, ind: Buffer.T, pos: int, nl: int}; |
|
322 |
|
323 val empty: text = |
|
324 {tx = Buffer.empty, |
|
325 ind = Buffer.empty, |
|
326 pos = 0, |
|
327 nl = 0}; |
|
328 |
|
329 fun newline s {tx, ind = _, pos = _, nl} : text = |
|
330 {tx = Buffer.add s tx, |
|
331 ind = Buffer.empty, |
|
332 pos = 0, |
|
333 nl = nl + 1}; |
|
334 |
|
335 fun control s {tx, ind, pos: int, nl} : text = |
|
336 {tx = Buffer.add s tx, |
|
337 ind = ind, |
|
338 pos = pos, |
|
339 nl = nl}; |
|
340 |
|
341 fun string (s, len) {tx, ind, pos: int, nl} : text = |
|
342 {tx = Buffer.add s tx, |
|
343 ind = Buffer.add s ind, |
|
344 pos = pos + len, |
|
345 nl = nl}; |
|
346 |
|
347 (*Add the lengths of the expressions until the next Break; if no Break then |
|
348 include "after", to account for text following this block.*) |
|
349 fun break_dist (Break _ :: _, _) = 0 |
|
350 | break_dist (e :: es, after) = tree_length e + break_dist (es, after) |
|
351 | break_dist ([], after) = after; |
|
352 |
|
353 val force_break = fn Break (false, wd, ind) => Break (true, wd, ind) | e => e; |
|
354 val force_all = map force_break; |
|
355 |
|
356 (*Search for the next break (at this or higher levels) and force it to occur.*) |
|
357 fun force_next [] = [] |
|
358 | force_next ((e as Break _) :: es) = force_break e :: es |
|
359 | force_next (e :: es) = e :: force_next es; |
|
360 |
|
361 in |
350 |
362 |
351 fun format_tree (ops: output_ops) input = |
363 fun format_tree (ops: output_ops) input = |
352 let |
364 let |
353 val margin = #margin ops; |
365 val margin = #margin ops; |
354 val breakgain = margin div 20; (*minimum added space required of a break*) |
366 val breakgain = margin div 20; (*minimum added space required of a break*) |
422 markup_buffer (Markup.break wd ind) (output_spaces_buffer ops wd) |
438 markup_buffer (Markup.break wd ind) (output_spaces_buffer ops wd) |
423 | out (Break (true, _, _)) = Buffer.add (output_newline ops) |
439 | out (Break (true, _, _)) = Buffer.add (output_newline ops) |
424 | out (Str (s, _)) = Buffer.add s; |
440 | out (Str (s, _)) = Buffer.add s; |
425 in Buffer.build o out o output_tree ops false end; |
441 in Buffer.build o out o output_tree ops false end; |
426 |
442 |
427 (*unformatted output*) |
443 val symbolic_output = Buffer.contents o symbolic; |
|
444 val symbolic_string_of = implode o symbolic_output; |
|
445 |
|
446 |
|
447 (* unformatted output: other markup only *) |
|
448 |
428 fun unformatted ops = |
449 fun unformatted ops = |
429 let |
450 let |
430 fun out (Block ((bg, en), _, _, prts, _)) = Buffer.add bg #> fold out prts #> Buffer.add en |
451 fun out (Block ((bg, en), _, _, prts, _)) = Buffer.add bg #> fold out prts #> Buffer.add en |
431 | out (Break (_, wd, _)) = output_spaces_buffer ops wd |
452 | out (Break (_, wd, _)) = output_spaces_buffer ops wd |
432 | out (Str (s, _)) = Buffer.add s; |
453 | out (Str (s, _)) = Buffer.add s; |
433 in Buffer.build o out o output_tree ops false end; |
454 in Buffer.build o out o output_tree ops false end; |
434 |
455 |
|
456 fun unformatted_string_of prt = |
|
457 let val ops = output_ops NONE |
|
458 in implode (#escape ops (Buffer.contents (unformatted ops prt))) end; |
|
459 |
435 |
460 |
436 (* output interfaces *) |
461 (* output interfaces *) |
437 |
462 |
438 val regularN = "pretty_regular"; |
463 val regularN = "pretty_regular"; |
439 val symbolicN = "pretty_symbolic"; |
464 val symbolicN = "pretty_symbolic"; |