src/Pure/General/pretty.ML
changeset 36754 403585a89772
parent 36733 5e1f305ae867
child 36756 7361d5dde9ce
equal deleted inserted replaced
36753:6e1f3d609a68 36754:403585a89772
    50   val list: string -> string -> T list -> T
    50   val list: string -> string -> T list -> T
    51   val str_list: string -> string -> string list -> T
    51   val str_list: string -> string -> string list -> T
    52   val big_list: string -> T list -> T
    52   val big_list: string -> T list -> T
    53   val indent: int -> T -> T
    53   val indent: int -> T -> T
    54   val unbreakable: T -> T
    54   val unbreakable: T -> T
    55   val setmargin: int -> unit
    55   val margin_default: int Unsynchronized.ref
    56   val setmp_margin_CRITICAL: int -> ('a -> 'b) -> 'a -> 'b
       
    57   val setdepth: int -> unit
    56   val setdepth: int -> unit
    58   val to_ML: T -> ML_Pretty.pretty
    57   val to_ML: T -> ML_Pretty.pretty
    59   val from_ML: ML_Pretty.pretty -> T
    58   val from_ML: ML_Pretty.pretty -> T
    60   val symbolicN: string
    59   val symbolicN: string
    61   val output_buffer: T -> Buffer.T
    60   val output_buffer: int option -> T -> Buffer.T
    62   val output: T -> output
    61   val output: int option -> T -> output
       
    62   val string_of_margin: int -> T -> string
    63   val string_of: T -> string
    63   val string_of: T -> string
    64   val str_of: T -> string
    64   val str_of: T -> string
    65   val writeln: T -> unit
    65   val writeln: T -> unit
    66   type pp
    66   type pp
    67   val pp: (term -> T) * (typ -> T) * (sort -> T) * (class list -> T) * (arity -> T) -> pp
    67   val pp: (term -> T) * (typ -> T) * (sort -> T) * (class list -> T) * (arity -> T) -> pp
   179 
   179 
   180 (** formatting **)
   180 (** formatting **)
   181 
   181 
   182 (* margin *)
   182 (* margin *)
   183 
   183 
   184 fun make_margin_info m =
   184 val margin_default = Unsynchronized.ref 76;  (*right margin, or page width*)
   185  {margin = m,                   (*right margin, or page width*)
       
   186   breakgain = m div 20,         (*minimum added space required of a break*)
       
   187   emergencypos = m div 2};      (*position too far to right*)
       
   188 
       
   189 val margin_info = Unsynchronized.ref (make_margin_info 76);
       
   190 fun setmargin m = margin_info := make_margin_info m;
       
   191 fun setmp_margin_CRITICAL m f = setmp_CRITICAL margin_info (make_margin_info m) f;
       
   192 
   185 
   193 
   186 
   194 (* depth limitation *)
   187 (* depth limitation *)
   195 
   188 
   196 val depth = Unsynchronized.ref 0;   (*maximum depth; 0 means no limit*)
   189 val depth = Unsynchronized.ref 0;   (*maximum depth; 0 means no limit*)
   257 (*Search for the next break (at this or higher levels) and force it to occur.*)
   250 (*Search for the next break (at this or higher levels) and force it to occur.*)
   258 fun forcenext [] = []
   251 fun forcenext [] = []
   259   | forcenext (Break _ :: es) = fbrk :: es
   252   | forcenext (Break _ :: es) = fbrk :: es
   260   | forcenext (e :: es) = e :: forcenext es;
   253   | forcenext (e :: es) = e :: forcenext es;
   261 
   254 
   262 (*es is list of expressions to print;
       
   263   blockin is the indentation of the current block;
       
   264   after is the width of the following context until next break.*)
       
   265 fun format ([], _, _) text = text
       
   266   | format (e :: es, block as (_, blockin), after) (text as {ind, pos, nl, ...}) =
       
   267       (case e of
       
   268         Block ((bg, en), bes, indent, _) =>
       
   269           let
       
   270             val {emergencypos, ...} = ! margin_info;
       
   271             val pos' = pos + indent;
       
   272             val pos'' = pos' mod emergencypos;
       
   273             val block' =
       
   274               if pos' < emergencypos then (ind |> add_indent indent, pos')
       
   275               else (add_indent pos'' Buffer.empty, pos'');
       
   276             val btext: text = text
       
   277               |> control bg
       
   278               |> format (bes, block', breakdist (es, after))
       
   279               |> control en;
       
   280             (*if this block was broken then force the next break*)
       
   281             val es' = if nl < #nl btext then forcenext es else es;
       
   282           in format (es', block, after) btext end
       
   283       | Break (force, wd) =>
       
   284           let val {margin, breakgain, ...} = ! margin_info in
       
   285             (*no break if text to next break fits on this line
       
   286               or if breaking would add only breakgain to space*)
       
   287             format (es, block, after)
       
   288               (if not force andalso
       
   289                   pos + wd <= Int.max (margin - breakdist (es, after), blockin + breakgain)
       
   290                 then text |> blanks wd  (*just insert wd blanks*)
       
   291                 else text |> newline |> indentation block)
       
   292           end
       
   293       | String str => format (es, block, after) (string str text));
       
   294 
       
   295 in
   255 in
   296 
   256 
   297 fun formatted e = #tx (format ([prune e], (Buffer.empty, 0), 0) empty);
   257 fun formatted margin input =
       
   258   let
       
   259     val breakgain = margin div 20;     (*minimum added space required of a break*)
       
   260     val emergencypos = margin div 2;   (*position too far to right*)
       
   261 
       
   262     (*es is list of expressions to print;
       
   263       blockin is the indentation of the current block;
       
   264       after is the width of the following context until next break.*)
       
   265     fun format ([], _, _) text = text
       
   266       | format (e :: es, block as (_, blockin), after) (text as {ind, pos, nl, ...}) =
       
   267           (case e of
       
   268             Block ((bg, en), bes, indent, _) =>
       
   269               let
       
   270                 val pos' = pos + indent;
       
   271                 val pos'' = pos' mod emergencypos;
       
   272                 val block' =
       
   273                   if pos' < emergencypos then (ind |> add_indent indent, pos')
       
   274                   else (add_indent pos'' Buffer.empty, pos'');
       
   275                 val btext: text = text
       
   276                   |> control bg
       
   277                   |> format (bes, block', breakdist (es, after))
       
   278                   |> control en;
       
   279                 (*if this block was broken then force the next break*)
       
   280                 val es' = if nl < #nl btext then forcenext es else es;
       
   281               in format (es', block, after) btext end
       
   282           | Break (force, wd) =>
       
   283               (*no break if text to next break fits on this line
       
   284                 or if breaking would add only breakgain to space*)
       
   285               format (es, block, after)
       
   286                 (if not force andalso
       
   287                     pos + wd <= Int.max (margin - breakdist (es, after), blockin + breakgain)
       
   288                   then text |> blanks wd  (*just insert wd blanks*)
       
   289                   else text |> newline |> indentation block)
       
   290           | String str => format (es, block, after) (string str text));
       
   291   in
       
   292     #tx (format ([prune input], (Buffer.empty, 0), 0) empty)
       
   293   end;
   298 
   294 
   299 end;
   295 end;
   300 
   296 
   301 
   297 
   302 (* special output *)
   298 (* special output *)
   334 
   330 
   335 (* output interfaces *)
   331 (* output interfaces *)
   336 
   332 
   337 val symbolicN = "pretty_symbolic";
   333 val symbolicN = "pretty_symbolic";
   338 
   334 
   339 fun output_buffer prt =
   335 fun output_buffer margin prt =
   340   if print_mode_active symbolicN then symbolic prt
   336   if print_mode_active symbolicN then symbolic prt
   341   else formatted prt;
   337   else formatted (the_default (! margin_default) margin) prt;
   342 
   338 
   343 val output = Buffer.content o output_buffer;
   339 val output = Buffer.content oo output_buffer;
   344 val string_of = Output.escape o output;
   340 fun string_of_margin margin = Output.escape o output (SOME margin);
       
   341 val string_of = Output.escape o output NONE;
   345 val str_of = Output.escape o Buffer.content o unformatted;
   342 val str_of = Output.escape o Buffer.content o unformatted;
   346 val writeln = Output.writeln o string_of;
   343 val writeln = Output.writeln o string_of;
   347 
   344 
   348 
   345 
   349 
   346