| author | wenzelm | 
| Mon, 19 Nov 2012 20:23:47 +0100 | |
| changeset 50126 | 3dec88149176 | 
| parent 49656 | 7ff712de5747 | 
| child 50162 | e06eabc421e7 | 
| permissions | -rw-r--r-- | 
| 6118 | 1  | 
(* Title: Pure/General/pretty.ML  | 
| 8806 | 2  | 
Author: Lawrence C Paulson, Cambridge University Computer Laboratory  | 
| 
10952
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
3  | 
Author: Markus Wenzel, TU Munich  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
4  | 
|
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
5  | 
Generic pretty printing module.  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
6  | 
|
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
7  | 
Loosely based on  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
8  | 
D. C. Oppen, "Pretty Printing",  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
9  | 
ACM Transactions on Programming Languages and Systems (1980), 465-483.  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
10  | 
|
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
11  | 
The object to be printed is given as a tree with indentation and line  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
12  | 
breaking information. A "break" inserts a newline if the text until  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
13  | 
the next break is too long to fit on the current line. After the newline,  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
14  | 
text is indented to the level of the enclosing block. Normally, if a block  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
15  | 
is broken then all enclosing blocks will also be broken. Only "inconsistent  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
16  | 
breaks" are provided.  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
17  | 
|
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
18  | 
The stored length of a block is used in breakdist (to treat each inner block as  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
19  | 
a unit for breaking).  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
20  | 
*)  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
21  | 
|
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
22  | 
signature PRETTY =  | 
| 
14832
 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 
wenzelm 
parents: 
12421 
diff
changeset
 | 
23  | 
sig  | 
| 
48704
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
24  | 
val spaces: int -> string  | 
| 
40131
 
7cbebd636e79
explicitly qualify type Output.output, which is a slightly odd internal feature;
 
wenzelm 
parents: 
38474 
diff
changeset
 | 
25  | 
val default_indent: string -> int -> Output.output  | 
| 
 
7cbebd636e79
explicitly qualify type Output.output, which is a slightly odd internal feature;
 
wenzelm 
parents: 
38474 
diff
changeset
 | 
26  | 
val add_mode: string -> (string -> int -> Output.output) -> unit  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
27  | 
type T  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
28  | 
val str: string -> T  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
29  | 
val brk: int -> T  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
30  | 
val fbrk: T  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
31  | 
val breaks: T list -> T list  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
32  | 
val fbreaks: T list -> T list  | 
| 23645 | 33  | 
val blk: int * T list -> T  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
34  | 
val block: T list -> T  | 
| 23645 | 35  | 
val strs: string list -> T  | 
| 
49656
 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
36  | 
val raw_markup: Output.output * Output.output -> int * T list -> T  | 
| 23617 | 37  | 
val markup: Markup.T -> T list -> T  | 
| 26703 | 38  | 
val mark: Markup.T -> T -> T  | 
| 42266 | 39  | 
val mark_str: Markup.T * string -> T  | 
40  | 
val marks_str: Markup.T list * string -> T  | 
|
| 
49554
 
7b7bd2d7661d
more explicit keyword1/keyword2 markup -- avoid potential conflict with input token markup produced by Token_Marker;
 
wenzelm 
parents: 
48704 
diff
changeset
 | 
41  | 
val command: string -> T  | 
| 23617 | 42  | 
val keyword: string -> T  | 
| 23638 | 43  | 
val markup_chunks: Markup.T -> T list -> T  | 
| 18802 | 44  | 
val chunks: T list -> T  | 
| 19266 | 45  | 
val chunks2: T list -> T  | 
| 23617 | 46  | 
val block_enclose: T * T -> T list -> T  | 
| 18802 | 47  | 
val quote: T -> T  | 
48  | 
val backquote: T -> T  | 
|
49  | 
val separate: string -> T list -> T list  | 
|
50  | 
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
 | 
51  | 
val enclose: string -> string -> T list -> T  | 
| 18802 | 52  | 
val enum: string -> string -> string -> T list -> T  | 
| 30620 | 53  | 
val position: Position.T -> T  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
54  | 
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
 | 
55  | 
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
 | 
56  | 
val big_list: string -> T list -> T  | 
| 9730 | 57  | 
val indent: int -> T -> T  | 
| 23645 | 58  | 
val unbreakable: T -> T  | 
| 36745 | 59  | 
val margin_default: int Unsynchronized.ref  | 
| 23645 | 60  | 
val symbolicN: string  | 
| 36745 | 61  | 
val output_buffer: int option -> T -> Buffer.T  | 
| 
40131
 
7cbebd636e79
explicitly qualify type Output.output, which is a slightly odd internal feature;
 
wenzelm 
parents: 
38474 
diff
changeset
 | 
62  | 
val output: int option -> T -> Output.output  | 
| 36745 | 63  | 
val string_of_margin: int -> T -> string  | 
| 23645 | 64  | 
val string_of: T -> string  | 
| 
49656
 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
65  | 
val writeln: T -> unit  | 
| 
 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
66  | 
val symbolic_output: T -> Output.output  | 
| 
49565
 
ea4308b7ef0f
ML support for generic graph display, with browser and graphview backends (via print modes);
 
wenzelm 
parents: 
49554 
diff
changeset
 | 
67  | 
val symbolic_string_of: T -> string  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
68  | 
val str_of: T -> string  | 
| 36748 | 69  | 
val to_ML: T -> ML_Pretty.pretty  | 
70  | 
val from_ML: ML_Pretty.pretty -> T  | 
|
| 
14832
 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 
wenzelm 
parents: 
12421 
diff
changeset
 | 
71  | 
end;  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
72  | 
|
| 23617 | 73  | 
structure Pretty: PRETTY =  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
74  | 
struct  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
75  | 
|
| 
48704
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
76  | 
(** spaces **)  | 
| 
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
77  | 
|
| 
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
78  | 
local  | 
| 
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
79  | 
val small_spaces = Vector.tabulate (65, fn i => Library.replicate_string i Symbol.space);  | 
| 
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
80  | 
in  | 
| 
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
81  | 
fun spaces k =  | 
| 
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
82  | 
if k < 64 then Vector.sub (small_spaces, k)  | 
| 
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
83  | 
else Library.replicate_string (k div 64) (Vector.sub (small_spaces, 64)) ^  | 
| 
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
84  | 
Vector.sub (small_spaces, k mod 64);  | 
| 
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
85  | 
end;  | 
| 
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
86  | 
|
| 
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
87  | 
|
| 
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
88  | 
|
| 23617 | 89  | 
(** print mode operations **)  | 
90  | 
||
| 
48704
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
91  | 
fun default_indent (_: string) = spaces;  | 
| 23617 | 92  | 
|
93  | 
local  | 
|
| 23698 | 94  | 
  val default = {indent = default_indent};
 | 
| 43684 | 95  | 
  val modes = Synchronized.var "Pretty.modes" (Symtab.make [("", default)]);
 | 
| 23617 | 96  | 
in  | 
| 43684 | 97  | 
fun add_mode name indent =  | 
| 
46894
 
e2ad717ec889
allow redefining pretty/markup modes (not output due to bootstrap issues) -- to support reloading of theory src/HOL/src/Tools/Code_Generator;
 
wenzelm 
parents: 
45666 
diff
changeset
 | 
98  | 
Synchronized.change modes (fn tab =>  | 
| 
 
e2ad717ec889
allow redefining pretty/markup modes (not output due to bootstrap issues) -- to support reloading of theory src/HOL/src/Tools/Code_Generator;
 
wenzelm 
parents: 
45666 
diff
changeset
 | 
99  | 
(if not (Symtab.defined tab name) then ()  | 
| 
 
e2ad717ec889
allow redefining pretty/markup modes (not output due to bootstrap issues) -- to support reloading of theory src/HOL/src/Tools/Code_Generator;
 
wenzelm 
parents: 
45666 
diff
changeset
 | 
100  | 
       else warning ("Redefining pretty mode " ^ quote name);
 | 
| 
 
e2ad717ec889
allow redefining pretty/markup modes (not output due to bootstrap issues) -- to support reloading of theory src/HOL/src/Tools/Code_Generator;
 
wenzelm 
parents: 
45666 
diff
changeset
 | 
101  | 
       Symtab.update (name, {indent = indent}) tab));
 | 
| 23617 | 102  | 
fun get_mode () =  | 
| 43684 | 103  | 
the_default default  | 
104  | 
(Library.get_first (Symtab.lookup (Synchronized.value modes)) (print_mode_value ()));  | 
|
| 23617 | 105  | 
end;  | 
106  | 
||
107  | 
fun mode_indent x y = #indent (get_mode ()) x y;  | 
|
| 23645 | 108  | 
|
| 
48704
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
109  | 
val output_spaces = Output.output o spaces;  | 
| 23645 | 110  | 
val add_indent = Buffer.add o output_spaces;  | 
| 23617 | 111  | 
|
112  | 
||
| 
10952
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
113  | 
|
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
114  | 
(** printing items: compound phrases, strings, and breaks **)  | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
115  | 
|
| 37529 | 116  | 
abstype T =  | 
| 
40131
 
7cbebd636e79
explicitly qualify type Output.output, which is a slightly odd internal feature;
 
wenzelm 
parents: 
38474 
diff
changeset
 | 
117  | 
Block of (Output.output * Output.output) * T list * int * int  | 
| 
 
7cbebd636e79
explicitly qualify type Output.output, which is a slightly odd internal feature;
 
wenzelm 
parents: 
38474 
diff
changeset
 | 
118  | 
(*markup output, body, indentation, length*)  | 
| 
 
7cbebd636e79
explicitly qualify type Output.output, which is a slightly odd internal feature;
 
wenzelm 
parents: 
38474 
diff
changeset
 | 
119  | 
| String of Output.output * int (*text, length*)  | 
| 
 
7cbebd636e79
explicitly qualify type Output.output, which is a slightly odd internal feature;
 
wenzelm 
parents: 
38474 
diff
changeset
 | 
120  | 
| Break of bool * int (*mandatory flag, width if not taken*)  | 
| 37529 | 121  | 
with  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
122  | 
|
| 23645 | 123  | 
fun length (Block (_, _, _, len)) = len  | 
124  | 
| length (String (_, len)) = len  | 
|
125  | 
| length (Break (_, wd)) = wd;  | 
|
126  | 
||
| 9730 | 127  | 
|
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
128  | 
|
| 23645 | 129  | 
(** derived operations to create formatting expressions **)  | 
130  | 
||
131  | 
val str = String o Output.output_width;  | 
|
132  | 
||
133  | 
fun brk wd = Break (false, wd);  | 
|
| 
36690
 
97d2780ad6f0
uniform treatment of length = 1 for forced breaks, also makes ML/Pretty.length coincide with Scala/XML.content_length;
 
wenzelm 
parents: 
36689 
diff
changeset
 | 
134  | 
val fbrk = Break (true, 1);  | 
| 23645 | 135  | 
|
136  | 
fun breaks prts = Library.separate (brk 1) prts;  | 
|
137  | 
fun fbreaks prts = Library.separate fbrk prts;  | 
|
138  | 
||
| 
49656
 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
139  | 
fun raw_markup m (indent, es) =  | 
| 23645 | 140  | 
let  | 
141  | 
fun sum [] k = k  | 
|
142  | 
| sum (e :: es) k = sum es (length e + k);  | 
|
143  | 
in Block (m, es, indent, sum es 0) end;  | 
|
144  | 
||
| 
49656
 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
145  | 
fun markup_block m arg = raw_markup (Markup.output m) arg;  | 
| 
30667
 
53fbf7c679b0
Block markup: maintain output version within tree values (in accordance with String) -- changes operational behaviour wrt. print_mode;
 
wenzelm 
parents: 
30624 
diff
changeset
 | 
146  | 
|
| 
38474
 
e498dc2eb576
uniform Markup.empty/Markup.Empty in ML and Scala;
 
wenzelm 
parents: 
37529 
diff
changeset
 | 
147  | 
val blk = markup_block Markup.empty;  | 
| 23645 | 148  | 
fun block prts = blk (2, prts);  | 
149  | 
val strs = block o breaks o map str;  | 
|
150  | 
||
151  | 
fun markup m prts = markup_block m (0, prts);  | 
|
| 42266 | 152  | 
fun mark m prt = if m = Markup.empty then prt else markup m [prt];  | 
153  | 
fun mark_str (m, s) = mark m (str s);  | 
|
154  | 
fun marks_str (ms, s) = fold_rev mark ms (str s);  | 
|
155  | 
||
| 
49554
 
7b7bd2d7661d
more explicit keyword1/keyword2 markup -- avoid potential conflict with input token markup produced by Token_Marker;
 
wenzelm 
parents: 
48704 
diff
changeset
 | 
156  | 
fun command name = mark_str (Isabelle_Markup.keyword1, name);  | 
| 
 
7b7bd2d7661d
more explicit keyword1/keyword2 markup -- avoid potential conflict with input token markup produced by Token_Marker;
 
wenzelm 
parents: 
48704 
diff
changeset
 | 
157  | 
fun keyword name = mark_str (Isabelle_Markup.keyword2, name);  | 
| 23645 | 158  | 
|
159  | 
fun markup_chunks m prts = markup m (fbreaks prts);  | 
|
| 
38474
 
e498dc2eb576
uniform Markup.empty/Markup.Empty in ML and Scala;
 
wenzelm 
parents: 
37529 
diff
changeset
 | 
160  | 
val chunks = markup_chunks Markup.empty;  | 
| 23645 | 161  | 
fun chunks2 prts = blk (0, flat (Library.separate [fbrk, fbrk] (map single prts)));  | 
162  | 
||
| 36733 | 163  | 
fun block_enclose (prt1, prt2) prts = chunks [block (fbreaks (prt1 :: prts)), prt2];  | 
| 23645 | 164  | 
|
165  | 
fun quote prt = blk (1, [str "\"", prt, str "\""]);  | 
|
166  | 
fun backquote prt = blk (1, [str "`", prt, str "`"]);  | 
|
167  | 
||
168  | 
fun separate sep prts =  | 
|
169  | 
flat (Library.separate [str sep, brk 1] (map single prts));  | 
|
170  | 
||
171  | 
val commas = separate ",";  | 
|
172  | 
||
173  | 
fun enclose lpar rpar prts =  | 
|
174  | 
block (str lpar :: (prts @ [str rpar]));  | 
|
175  | 
||
176  | 
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: 
9730 
diff
changeset
 | 
177  | 
|
| 30620 | 178  | 
val position =  | 
179  | 
  enum "," "{" "}" o map (fn (x, y) => str (x ^ "=" ^ y)) o Position.properties_of;
 | 
|
180  | 
||
| 23645 | 181  | 
val list = enum ",";  | 
182  | 
fun str_list lpar rpar strs = list lpar rpar (map str strs);  | 
|
183  | 
||
184  | 
fun big_list name prts = block (fbreaks (str name :: prts));  | 
|
185  | 
||
186  | 
fun indent 0 prt = prt  | 
|
| 
48704
 
85a3de10567d
tuned signature -- make Pretty less dependent on Symbol;
 
wenzelm 
parents: 
46894 
diff
changeset
 | 
187  | 
| indent n prt = blk (0, [str (spaces n), prt]);  | 
| 23645 | 188  | 
|
189  | 
fun unbreakable (Break (_, wd)) = String (output_spaces wd, wd)  | 
|
190  | 
| unbreakable (Block (m, es, indent, wd)) = Block (m, map unbreakable es, indent, wd)  | 
|
191  | 
| unbreakable (e as String _) = e;  | 
|
192  | 
||
193  | 
||
194  | 
||
195  | 
(** formatting **)  | 
|
196  | 
||
197  | 
(* formatted output *)  | 
|
198  | 
||
199  | 
local  | 
|
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
200  | 
|
| 17756 | 201  | 
type text = {tx: Buffer.T, ind: Buffer.T, pos: int, nl: int};
 | 
202  | 
||
203  | 
val empty: text =  | 
|
| 
10952
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
204  | 
 {tx = Buffer.empty,
 | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
205  | 
ind = Buffer.empty,  | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
206  | 
pos = 0,  | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
207  | 
nl = 0};  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
208  | 
|
| 32784 | 209  | 
fun newline {tx, ind = _, pos = _, nl} : text =
 | 
| 
14832
 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 
wenzelm 
parents: 
12421 
diff
changeset
 | 
210  | 
 {tx = Buffer.add (Output.output "\n") tx,
 | 
| 
10952
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
211  | 
ind = Buffer.empty,  | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
212  | 
pos = 0,  | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
213  | 
nl = nl + 1};  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
214  | 
|
| 
23628
 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 
wenzelm 
parents: 
23617 
diff
changeset
 | 
215  | 
fun control s {tx, ind, pos: int, nl} : text =
 | 
| 
 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 
wenzelm 
parents: 
23617 
diff
changeset
 | 
216  | 
 {tx = Buffer.add s tx,
 | 
| 
 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 
wenzelm 
parents: 
23617 
diff
changeset
 | 
217  | 
ind = ind,  | 
| 
 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 
wenzelm 
parents: 
23617 
diff
changeset
 | 
218  | 
pos = pos,  | 
| 
 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 
wenzelm 
parents: 
23617 
diff
changeset
 | 
219  | 
nl = nl};  | 
| 
 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 
wenzelm 
parents: 
23617 
diff
changeset
 | 
220  | 
|
| 17756 | 221  | 
fun string (s, len) {tx, ind, pos: int, nl} : text =
 | 
| 
10952
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
222  | 
 {tx = Buffer.add s tx,
 | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
223  | 
ind = Buffer.add s ind,  | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
224  | 
pos = pos + len,  | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
225  | 
nl = nl};  | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
226  | 
|
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
227  | 
fun blanks wd = string (output_spaces wd, wd);  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
228  | 
|
| 17756 | 229  | 
fun indentation (buf, len) {tx, ind, pos, nl} : text =
 | 
| 
10952
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
230  | 
let val s = Buffer.content buf in  | 
| 23617 | 231  | 
   {tx = Buffer.add (mode_indent s len) tx,
 | 
| 
10952
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
232  | 
ind = Buffer.add s ind,  | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
233  | 
pos = pos + len,  | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
234  | 
nl = nl}  | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
235  | 
end;  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
236  | 
|
| 
10952
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
237  | 
(*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: 
9730 
diff
changeset
 | 
238  | 
include "after", to account for text following this block.*)  | 
| 36687 | 239  | 
fun breakdist (Break _ :: _, _) = 0  | 
240  | 
| breakdist (Block (_, _, _, len) :: es, after) = len + breakdist (es, after)  | 
|
| 32784 | 241  | 
| breakdist (String (_, len) :: es, after) = len + breakdist (es, after)  | 
| 
10952
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
242  | 
| breakdist ([], after) = after;  | 
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
243  | 
|
| 
 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 
wenzelm 
parents: 
9730 
diff
changeset
 | 
244  | 
(*Search for the next break (at this or higher levels) and force it to occur.*)  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
245  | 
fun forcenext [] = []  | 
| 
36690
 
97d2780ad6f0
uniform treatment of length = 1 for forced breaks, also makes ML/Pretty.length coincide with Scala/XML.content_length;
 
wenzelm 
parents: 
36689 
diff
changeset
 | 
246  | 
| forcenext (Break _ :: es) = fbrk :: es  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
247  | 
| forcenext (e :: es) = e :: forcenext es;  | 
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
248  | 
|
| 23645 | 249  | 
in  | 
| 19266 | 250  | 
|
| 36745 | 251  | 
fun formatted margin input =  | 
252  | 
let  | 
|
253  | 
val breakgain = margin div 20; (*minimum added space required of a break*)  | 
|
254  | 
val emergencypos = margin div 2; (*position too far to right*)  | 
|
255  | 
||
256  | 
(*es is list of expressions to print;  | 
|
257  | 
blockin is the indentation of the current block;  | 
|
258  | 
after is the width of the following context until next break.*)  | 
|
259  | 
fun format ([], _, _) text = text  | 
|
260  | 
      | format (e :: es, block as (_, blockin), after) (text as {ind, pos, nl, ...}) =
 | 
|
261  | 
(case e of  | 
|
262  | 
Block ((bg, en), bes, indent, _) =>  | 
|
263  | 
let  | 
|
264  | 
val pos' = pos + indent;  | 
|
265  | 
val pos'' = pos' mod emergencypos;  | 
|
266  | 
val block' =  | 
|
267  | 
if pos' < emergencypos then (ind |> add_indent indent, pos')  | 
|
268  | 
else (add_indent pos'' Buffer.empty, pos'');  | 
|
269  | 
val btext: text = text  | 
|
270  | 
|> control bg  | 
|
271  | 
|> format (bes, block', breakdist (es, after))  | 
|
272  | 
|> control en;  | 
|
273  | 
(*if this block was broken then force the next break*)  | 
|
274  | 
val es' = if nl < #nl btext then forcenext es else es;  | 
|
275  | 
in format (es', block, after) btext end  | 
|
276  | 
| Break (force, wd) =>  | 
|
277  | 
(*no break if text to next break fits on this line  | 
|
278  | 
or if breaking would add only breakgain to space*)  | 
|
279  | 
format (es, block, after)  | 
|
280  | 
(if not force andalso  | 
|
281  | 
pos + wd <= Int.max (margin - breakdist (es, after), blockin + breakgain)  | 
|
282  | 
then text |> blanks wd (*just insert wd blanks*)  | 
|
283  | 
else text |> newline |> indentation block)  | 
|
284  | 
| String str => format (es, block, after) (string str text));  | 
|
285  | 
in  | 
|
| 
36747
 
7361d5dde9ce
discontinued Pretty.setdepth, which appears to be largely unused, but can disrupt important markup if enabled accidentally;
 
wenzelm 
parents: 
36745 
diff
changeset
 | 
286  | 
#tx (format ([input], (Buffer.empty, 0), 0) empty)  | 
| 36745 | 287  | 
end;  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
288  | 
|
| 23645 | 289  | 
end;  | 
| 
14832
 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 
wenzelm 
parents: 
12421 
diff
changeset
 | 
290  | 
|
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
291  | 
|
| 23645 | 292  | 
(* special output *)  | 
| 18802 | 293  | 
|
| 23645 | 294  | 
(*symbolic markup -- no formatting*)  | 
295  | 
fun symbolic prt =  | 
|
296  | 
let  | 
|
| 
30667
 
53fbf7c679b0
Block markup: maintain output version within tree values (in accordance with String) -- changes operational behaviour wrt. print_mode;
 
wenzelm 
parents: 
30624 
diff
changeset
 | 
297  | 
fun out (Block ((bg, en), [], _, _)) = Buffer.add bg #> Buffer.add en  | 
| 
 
53fbf7c679b0
Block markup: maintain output version within tree values (in accordance with String) -- changes operational behaviour wrt. print_mode;
 
wenzelm 
parents: 
30624 
diff
changeset
 | 
298  | 
| out (Block ((bg, en), prts, indent, _)) =  | 
| 45666 | 299  | 
Buffer.add bg #>  | 
300  | 
Buffer.markup (Isabelle_Markup.block indent) (fold out prts) #>  | 
|
301  | 
Buffer.add en  | 
|
| 23645 | 302  | 
| out (String (s, _)) = Buffer.add s  | 
| 45666 | 303  | 
| out (Break (false, wd)) =  | 
304  | 
Buffer.markup (Isabelle_Markup.break wd) (Buffer.add (output_spaces wd))  | 
|
| 
36689
 
379f5b1e7f91
replaced slightly odd fbreak markup by plain "\n", which also coincides with regular linebreaks produced outside the ML pretty engine;
 
wenzelm 
parents: 
36687 
diff
changeset
 | 
305  | 
| out (Break (true, _)) = Buffer.add (Output.output "\n");  | 
| 23645 | 306  | 
in out prt Buffer.empty end;  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
307  | 
|
| 23645 | 308  | 
(*unformatted output*)  | 
309  | 
fun unformatted prt =  | 
|
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
310  | 
let  | 
| 
30667
 
53fbf7c679b0
Block markup: maintain output version within tree values (in accordance with String) -- changes operational behaviour wrt. print_mode;
 
wenzelm 
parents: 
30624 
diff
changeset
 | 
311  | 
fun fmt (Block ((bg, en), prts, _, _)) = Buffer.add bg #> fold fmt prts #> Buffer.add en  | 
| 23617 | 312  | 
| fmt (String (s, _)) = Buffer.add s  | 
| 
36690
 
97d2780ad6f0
uniform treatment of length = 1 for forced breaks, also makes ML/Pretty.length coincide with Scala/XML.content_length;
 
wenzelm 
parents: 
36689 
diff
changeset
 | 
313  | 
| fmt (Break (_, wd)) = Buffer.add (output_spaces wd);  | 
| 
36747
 
7361d5dde9ce
discontinued Pretty.setdepth, which appears to be largely unused, but can disrupt important markup if enabled accidentally;
 
wenzelm 
parents: 
36745 
diff
changeset
 | 
314  | 
in fmt prt Buffer.empty end;  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
315  | 
|
| 
30624
 
e755b8b76365
simplified datatype ML_Pretty.pretty: model Isabelle not Poly/ML;
 
wenzelm 
parents: 
30620 
diff
changeset
 | 
316  | 
|
| 36748 | 317  | 
(* output interfaces *)  | 
| 30620 | 318  | 
|
| 36748 | 319  | 
val margin_default = Unsynchronized.ref 76; (*right margin, or page width*)  | 
| 23645 | 320  | 
|
321  | 
val symbolicN = "pretty_symbolic";  | 
|
322  | 
||
| 36745 | 323  | 
fun output_buffer margin prt =  | 
| 23645 | 324  | 
if print_mode_active symbolicN then symbolic prt  | 
| 36745 | 325  | 
else formatted (the_default (! margin_default) margin) prt;  | 
| 23645 | 326  | 
|
| 36745 | 327  | 
val output = Buffer.content oo output_buffer;  | 
328  | 
fun string_of_margin margin = Output.escape o output (SOME margin);  | 
|
329  | 
val string_of = Output.escape o output NONE;  | 
|
| 
49656
 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
330  | 
val writeln = Output.writeln o string_of;  | 
| 
 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
331  | 
|
| 
 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
332  | 
val symbolic_output = Buffer.content o symbolic;  | 
| 
 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
333  | 
val symbolic_string_of = Output.escape o symbolic_output;  | 
| 
 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
334  | 
|
| 23645 | 335  | 
val str_of = Output.escape o Buffer.content o unformatted;  | 
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
336  | 
|
| 
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
337  | 
|
| 
14832
 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 
wenzelm 
parents: 
12421 
diff
changeset
 | 
338  | 
|
| 36748 | 339  | 
(** ML toplevel pretty printing **)  | 
340  | 
||
341  | 
fun to_ML (Block (m, prts, ind, _)) = ML_Pretty.Block (m, map to_ML prts, ind)  | 
|
342  | 
| to_ML (String s) = ML_Pretty.String s  | 
|
343  | 
| to_ML (Break b) = ML_Pretty.Break b;  | 
|
344  | 
||
| 
49656
 
7ff712de5747
treat wrapped markup elements as raw markup delimiters;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
345  | 
fun from_ML (ML_Pretty.Block (m, prts, ind)) = raw_markup m (ind, map from_ML prts)  | 
| 36748 | 346  | 
| from_ML (ML_Pretty.String s) = String s  | 
347  | 
| from_ML (ML_Pretty.Break b) = Break b;  | 
|
348  | 
||
| 37529 | 349  | 
end;  | 
350  | 
||
| 
6116
 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 
wenzelm 
parents:  
diff
changeset
 | 
351  | 
end;  |