48 val writeln: T -> unit |
49 val writeln: T -> unit |
49 val str_of: T -> string |
50 val str_of: T -> string |
50 val pprint: T -> pprint_args -> unit |
51 val pprint: T -> pprint_args -> unit |
51 val setdepth: int -> unit |
52 val setdepth: int -> unit |
52 val setmargin: int -> unit |
53 val setmargin: int -> unit |
|
54 val setmp_margin: int -> ('a -> 'b) -> 'a -> 'b |
53 end; |
55 end; |
54 |
56 |
55 structure Pretty : PRETTY = |
57 structure Pretty : PRETTY = |
56 struct |
58 struct |
57 |
59 |
98 |
100 |
99 (*** Formatting ***) |
101 (*** Formatting ***) |
100 |
102 |
101 (* margin *) |
103 (* margin *) |
102 |
104 |
103 (*example values*) |
105 fun make_margin_info m = |
104 val margin = ref 80 (*right margin, or page width*) |
106 {margin = m, (*right margin, or page width*) |
105 and breakgain = ref 4 (*minimum added space required of a break*) |
107 breakgain = m div 20, (*minimum added space required of a break*) |
106 and emergencypos = ref 40; (*position too far to right*) |
108 emergencypos = m div 2}; (*position too far to right*) |
107 |
109 |
108 fun setmargin m = |
110 val margin_info = ref (make_margin_info 76); |
109 (margin := m; |
111 fun setmargin m = margin_info := make_margin_info m; |
110 breakgain := !margin div 20; |
112 fun setmp_margin m f = setmp margin_info (make_margin_info m) f; |
111 emergencypos := !margin div 2); |
|
112 |
|
113 val () = setmargin 76; |
|
114 |
|
115 |
113 |
116 (*Search for the next break (at this or higher levels) and force it to occur*) |
114 (*Search for the next break (at this or higher levels) and force it to occur*) |
117 fun forcenext [] = [] |
115 fun forcenext [] = [] |
118 | forcenext (Break(_,wd) :: es) = Break(true,0) :: es |
116 | forcenext (Break(_,wd) :: es) = Break(true,0) :: es |
119 | forcenext (e :: es) = e :: forcenext es; |
117 | forcenext (e :: es) = e :: forcenext es; |
123 after is the width of the following context until next break. *) |
121 after is the width of the following context until next break. *) |
124 fun format ([], _, _) text = text |
122 fun format ([], _, _) text = text |
125 | format (e::es, blockin, after) (text as {pos,nl,...}) = |
123 | format (e::es, blockin, after) (text as {pos,nl,...}) = |
126 (case e of |
124 (case e of |
127 Block(bes,indent,wd) => |
125 Block(bes,indent,wd) => |
128 let val blockin' = (pos + indent) mod !emergencypos |
126 let val blockin' = (pos + indent) mod #emergencypos (! margin_info) |
129 val btext = format(bes, blockin', breakdist(es,after)) text |
127 val btext = format(bes, blockin', breakdist(es,after)) text |
130 (*If this block was broken then force the next break.*) |
128 (*If this block was broken then force the next break.*) |
131 val es2 = if nl < #nl(btext) then forcenext es else es |
129 val es2 = if nl < #nl(btext) then forcenext es else es |
132 in format (es2,blockin,after) btext end |
130 in format (es2,blockin,after) btext end |
133 | String (s, len) => format (es,blockin,after) (string s len text) |
131 | String (s, len) => format (es,blockin,after) (string s len text) |
134 | Break(force,wd) => (*no break if text to next break fits on this line |
132 | Break(force,wd) => (*no break if text to next break fits on this line |
135 or if breaking would add only breakgain to space *) |
133 or if breaking would add only breakgain to space *) |
136 format (es,blockin,after) |
134 format (es,blockin,after) |
137 (if not force andalso |
135 (if not force andalso |
138 pos+wd <= Int.max(!margin - breakdist(es,after), |
136 pos+wd <= Int.max(#margin (! margin_info) - breakdist(es,after), |
139 blockin + !breakgain) |
137 blockin + #breakgain (! margin_info)) |
140 then blanks wd text (*just insert wd blanks*) |
138 then blanks wd text (*just insert wd blanks*) |
141 else blanks blockin (newline text))); |
139 else blanks blockin (newline text))); |
142 |
140 |
143 |
141 |
144 (*** Exported functions to create formatting expressions ***) |
142 (*** Exported functions to create formatting expressions ***) |
147 | length (String (_, len)) = len |
145 | length (String (_, len)) = len |
148 | length (Break(_, wd)) = wd; |
146 | length (Break(_, wd)) = wd; |
149 |
147 |
150 fun str s = String (s, size s); |
148 fun str s = String (s, size s); |
151 fun strlen s len = String (s, len); |
149 fun strlen s len = String (s, len); |
|
150 fun strlen_real s len = strlen s (Real.round len); |
152 val sym = String o apsnd Real.round o Symbol.output_width; |
151 val sym = String o apsnd Real.round o Symbol.output_width; |
153 |
152 |
154 fun spc n = str (repstring " " n); |
153 fun spc n = str (repstring " " n); |
155 |
154 |
156 fun brk wd = Break (false, wd); |
155 fun brk wd = Break (false, wd); |
226 let |
225 let |
227 fun s_of (Block (prts, _, _)) = implode (map s_of prts) |
226 fun s_of (Block (prts, _, _)) = implode (map s_of prts) |
228 | s_of (String (s, _)) = s |
227 | s_of (String (s, _)) = s |
229 | s_of (Break (false, wd)) = repstring " " wd |
228 | s_of (Break (false, wd)) = repstring " " wd |
230 | s_of (Break (true, _)) = " "; |
229 | s_of (Break (true, _)) = " "; |
231 in |
230 in s_of (prune (! depth) prt) end; |
232 s_of (prune (! depth) prt) |
|
233 end; |
|
234 |
231 |
235 (*Part of the interface to the Poly/ML and New Jersey ML pretty printers*) |
232 (*Part of the interface to the Poly/ML and New Jersey ML pretty printers*) |
236 fun pprint prt (put_str, begin_blk, put_brk, put_fbrk, end_blk) = |
233 fun pprint prt (put_str, begin_blk, put_brk, put_fbrk, end_blk) = |
237 let |
234 let |
238 fun pp (Block (prts, ind, _)) = (begin_blk ind; pp_lst prts; end_blk ()) |
235 fun pp (Block (prts, ind, _)) = (begin_blk ind; pp_lst prts; end_blk ()) |