···11+(**************************************************************************)
22+(* *)
33+(* OCaml *)
44+(* *)
55+(* Florian Angeletti, projet Cambium, Inria Paris *)
66+(* *)
77+(* Copyright 2021 Institut National de Recherche en Informatique et *)
88+(* en Automatique. *)
99+(* *)
1010+(* All rights reserved. This file is distributed under the terms of *)
1111+(* the GNU Lesser General Public License version 2.1, with the *)
1212+(* special exception on linking described in the file LICENSE. *)
1313+(* *)
1414+(**************************************************************************)
1515+1616+1717+type box_type =
1818+ | H
1919+ | V
2020+ | HV
2121+ | HoV
2222+ | B
2323+2424+type stag = Format.stag
2525+2626+type element =
2727+ | Text of string
2828+ | With_size of int
2929+ | Open_box of { kind: box_type ; indent:int }
3030+ | Close_box
3131+ | Open_tag of Format.stag
3232+ | Close_tag
3333+ | Open_tbox
3434+ | Tab_break of { width : int; offset : int }
3535+ | Set_tab
3636+ | Close_tbox
3737+ | Simple_break of { spaces : int; indent: int }
3838+ | Break of { fits : string * int * string as 'a; breaks : 'a }
3939+ | Flush of { newline:bool }
4040+ | Newline
4141+ | If_newline
4242+4343+ | Deprecated of (Format.formatter -> unit)
4444+4545+type doc = { rev:element list } [@@unboxed]
4646+4747+type t = doc
4848+4949+let empty : doc = { rev = [] }
5050+5151+let to_list doc = List.rev doc.rev
5252+let add doc x = { rev = x :: doc.rev }
5353+let fold f acc doc = List.fold_left f acc (to_list doc)
5454+let append left right = { rev = right.rev @ left.rev }
5555+5656+let format_open_box_gen ppf kind indent =
5757+ match kind with
5858+ | H-> Format.pp_open_hbox ppf ()
5959+ | V -> Format.pp_open_vbox ppf indent
6060+ | HV -> Format.pp_open_hvbox ppf indent
6161+ | HoV -> Format.pp_open_hovbox ppf indent
6262+ | B -> Format.pp_open_box ppf indent
6363+6464+let interpret_elt ppf = function
6565+ | Text x -> Format.pp_print_string ppf x
6666+ | Open_box { kind; indent } -> format_open_box_gen ppf kind indent
6767+ | Close_box -> Format.pp_close_box ppf ()
6868+ | Open_tag tag -> Format.pp_open_stag ppf tag
6969+ | Close_tag -> Format.pp_close_stag ppf ()
7070+ | Open_tbox -> Format.pp_open_tbox ppf ()
7171+ | Tab_break {width;offset} -> Format.pp_print_tbreak ppf width offset
7272+ | Set_tab -> Format.pp_set_tab ppf ()
7373+ | Close_tbox -> Format.pp_close_tbox ppf ()
7474+ | Simple_break {spaces;indent} -> Format.pp_print_break ppf spaces indent
7575+ | Break {fits;breaks} -> Format.pp_print_custom_break ppf ~fits ~breaks
7676+ | Flush {newline=true} -> Format.pp_print_newline ppf ()
7777+ | Flush {newline=false} -> Format.pp_print_flush ppf ()
7878+ | Newline -> Format.pp_force_newline ppf ()
7979+ | If_newline -> Format.pp_print_if_newline ppf ()
8080+ | With_size _ -> ()
8181+ | Deprecated pr -> pr ppf
8282+8383+let rec interpret ppf = function
8484+ | [] -> ()
8585+ | With_size size :: Text text :: l ->
8686+ Format.pp_print_as ppf size text;
8787+ interpret ppf l
8888+ | x :: l ->
8989+ interpret_elt ppf x;
9090+ interpret ppf l
9191+9292+let format ppf doc = interpret ppf (to_list doc)
9393+9494+module Core = struct
9595+9696+ let open_box kind indent doc = add doc (Open_box {kind;indent})
9797+ let close_box doc = add doc Close_box
9898+9999+ let string s doc = add doc (Text s)
100100+ let bytes b doc = add doc (Text (Bytes.to_string b))
101101+ let with_size size doc = add doc (With_size size)
102102+103103+ let int n doc = add doc (Text (string_of_int n))
104104+ let float f doc = add doc (Text (string_of_float f))
105105+ let char c doc = add doc (Text (String.make 1 c))
106106+ let bool c doc = add doc (Text (Bool.to_string c))
107107+108108+ let break ~spaces ~indent doc = add doc (Simple_break {spaces; indent})
109109+ let space doc = break ~spaces:1 ~indent:0 doc
110110+ let cut = break ~spaces:0 ~indent:0
111111+112112+ let custom_break ~fits ~breaks doc = add doc (Break {fits;breaks})
113113+114114+ let force_newline doc = add doc Newline
115115+ let if_newline doc = add doc If_newline
116116+117117+ let flush doc = add doc (Flush {newline=false})
118118+ let force_stop doc = add doc (Flush {newline=true})
119119+120120+ let open_tbox doc = add doc Open_tbox
121121+ let set_tab doc = add doc Set_tab
122122+ let tab_break ~width ~offset doc = add doc (Tab_break {width;offset})
123123+ let tab doc = tab_break ~width:0 ~offset:0 doc
124124+ let close_tbox doc = add doc Close_tbox
125125+126126+ let open_tag stag doc = add doc (Open_tag stag)
127127+ let close_tag doc = add doc Close_tag
128128+129129+ let iter ?(sep=Fun.id) ~iter:iterator elt l doc =
130130+ let first = ref false in
131131+ let rdoc = ref doc in
132132+ let print x =
133133+ if !first then (first := false; rdoc := elt x !rdoc)
134134+ else rdoc := !rdoc |> sep |> elt x
135135+ in
136136+ iterator print l;
137137+ !rdoc
138138+139139+ let rec list ?(sep=Fun.id) elt l doc = match l with
140140+ | [] -> doc
141141+ | [a] -> elt a doc
142142+ | a :: ((_ :: _) as q) ->
143143+ doc |> elt a |> sep |> list ~sep elt q
144144+145145+ let array ?sep elt a doc = iter ?sep ~iter:Array.iter elt a doc
146146+ let seq ?sep elt s doc = iter ?sep ~iter:Seq.iter elt s doc
147147+148148+ let option ?(none=Fun.id) elt o doc = match o with
149149+ | None -> none doc
150150+ | Some x -> elt x doc
151151+152152+ let either ~left ~right x doc = match x with
153153+ | Either.Left x -> left x doc
154154+ | Either.Right x -> right x doc
155155+156156+ let result ~ok ~error x doc = match x with
157157+ | Ok x -> ok x doc
158158+ | Error x -> error x doc
159159+160160+ (* To format free-flowing text *)
161161+ let rec subtext len left right s doc =
162162+ let flush doc =
163163+ doc |> string (String.sub s left (right - left))
164164+ in
165165+ let after_flush doc = subtext len (right+1) (right+1) s doc in
166166+ if right = len then
167167+ if left <> len then flush doc else doc
168168+ else
169169+ match s.[right] with
170170+ | '\n' ->
171171+ doc |> flush |> force_newline |> after_flush
172172+ | ' ' ->
173173+ doc |> flush |> space |> after_flush
174174+ (* there is no specific support for '\t'
175175+ as it is unclear what a right semantics would be *)
176176+ | _ -> subtext len left (right + 1) s doc
177177+178178+ let text s doc =
179179+ subtext (String.length s) 0 0 s doc
180180+181181+ type ('a,'b) fmt = ('a, doc, doc, 'b) format4
182182+ type printer0 = doc -> doc
183183+ type 'a printer = 'a -> printer0
184184+185185+ let output_formatting_lit fmting_lit doc =
186186+ let open CamlinternalFormatBasics in
187187+ match fmting_lit with
188188+ | Close_box -> close_box doc
189189+ | Close_tag -> close_tag doc
190190+ | Break (_, width, offset) -> break ~spaces:width ~indent:offset doc
191191+ | FFlush -> flush doc
192192+ | Force_newline -> force_newline doc
193193+ | Flush_newline -> force_stop doc
194194+ | Magic_size (_, n) -> with_size n doc
195195+ | Escaped_at -> char '@' doc
196196+ | Escaped_percent -> char '%' doc
197197+ | Scan_indic c -> doc |> char '@' |> char c
198198+199199+ let to_string doc =
200200+ let b = Buffer.create 20 in
201201+ let convert = function
202202+ | Text s -> Buffer.add_string b s
203203+ | _ -> ()
204204+ in
205205+ fold (fun () x -> convert x) () doc;
206206+ Buffer.contents b
207207+208208+ let box_type =
209209+ let open CamlinternalFormatBasics in
210210+ function
211211+ | Pp_fits -> H
212212+ | Pp_hbox -> H
213213+ | Pp_vbox -> V
214214+ | Pp_hovbox -> HoV
215215+ | Pp_hvbox -> HV
216216+ | Pp_box -> B
217217+218218+ let rec compose_acc acc doc =
219219+ let open CamlinternalFormat in
220220+ match acc with
221221+ | CamlinternalFormat.Acc_formatting_lit (p, f) ->
222222+ doc |> compose_acc p |> output_formatting_lit f
223223+ | Acc_formatting_gen (p, Acc_open_tag acc') ->
224224+ let tag = to_string (compose_acc acc' empty) in
225225+ let doc = compose_acc p doc in
226226+ doc |> open_tag (Format.String_tag tag)
227227+ | Acc_formatting_gen (p, Acc_open_box acc') ->
228228+ let doc = compose_acc p doc in
229229+ let box = to_string (compose_acc acc' empty) in
230230+ let (indent, bty) = CamlinternalFormat.open_box_of_string box in
231231+ doc |> open_box (box_type bty) indent
232232+ | Acc_string_literal (p, s)
233233+ | Acc_data_string (p, s) ->
234234+ doc |> compose_acc p |> string s
235235+ | Acc_char_literal (p, c)
236236+ | Acc_data_char (p, c) -> doc |> compose_acc p |> char c
237237+ | Acc_delay (p, f) -> doc |> compose_acc p |> f
238238+ | Acc_flush p -> doc |> compose_acc p |> flush
239239+ | Acc_invalid_arg (_p, msg) -> invalid_arg msg;
240240+ | End_of_acc -> doc
241241+242242+ let kprintf k (CamlinternalFormatBasics.Format (fmt, _)) =
243243+ CamlinternalFormat.make_printf
244244+ (fun acc doc -> doc |> compose_acc acc |> k )
245245+ End_of_acc fmt
246246+247247+ let printf doc = kprintf Fun.id doc
248248+ let kmsg k (CamlinternalFormatBasics.Format (fmt, _)) =
249249+ CamlinternalFormat.make_printf
250250+ (fun acc -> k (compose_acc acc empty))
251251+ End_of_acc fmt
252252+253253+ let msg fmt = kmsg Fun.id fmt
254254+255255+end
256256+257257+(** Compatibility interface *)
258258+259259+type formatter = doc ref
260260+type 'a printer = formatter -> 'a -> unit
261261+262262+let formatter d = d
263263+264264+(** {1 Primitive functions }*)
265265+266266+let pp_print_string ppf s = ppf := Core.string s !ppf
267267+268268+let pp_print_as ppf size s =
269269+ ppf := !ppf |> Core.with_size size |> Core.string s
270270+271271+let pp_print_substring ~pos ~len ppf s =
272272+ ppf := Core.string (String.sub s pos len) !ppf
273273+274274+let pp_print_substring_as ~pos ~len ppf size s =
275275+ ppf :=
276276+ !ppf
277277+ |> Core.with_size size
278278+ |> Core.string (String.sub s pos len)
279279+280280+let pp_print_bytes ppf s = ppf := Core.string (Bytes.to_string s) !ppf
281281+let pp_print_text ppf s = ppf := Core.text s !ppf
282282+let pp_print_char ppf c = ppf := Core.char c !ppf
283283+let pp_print_int ppf c = ppf := Core.int c !ppf
284284+let pp_print_float ppf f = ppf := Core.float f !ppf
285285+let pp_print_bool ppf b = ppf := Core.bool b !ppf
286286+let pp_print_nothing _ _ = ()
287287+288288+let pp_close_box ppf () = ppf := Core.close_box !ppf
289289+let pp_close_stag ppf () = ppf := Core.close_tag !ppf
290290+291291+let pp_print_break ppf spaces indent = ppf := Core.break ~spaces ~indent !ppf
292292+293293+let pp_print_custom_break ppf ~fits ~breaks =
294294+ ppf := Core.custom_break ~fits ~breaks !ppf
295295+296296+let pp_print_space ppf () = pp_print_break ppf 1 0
297297+let pp_print_cut ppf () = pp_print_break ppf 0 0
298298+299299+let pp_print_flush ppf () = ppf := Core.flush !ppf
300300+let pp_force_newline ppf () = ppf := Core.force_newline !ppf
301301+let pp_print_newline ppf () = ppf := Core.force_stop !ppf
302302+let pp_print_if_newline ppf () =ppf := Core.if_newline !ppf
303303+304304+let pp_open_stag ppf stag = ppf := !ppf |> Core.open_tag stag
305305+306306+let pp_open_box_gen ppf indent bxty =
307307+ let box_type = Core.box_type bxty in
308308+ ppf := !ppf |> Core.open_box box_type indent
309309+310310+let pp_open_box ppf indent = pp_open_box_gen ppf indent Pp_box
311311+312312+313313+let pp_open_tbox ppf () = ppf := !ppf |> Core.open_tbox
314314+315315+let pp_close_tbox ppf () = ppf := !ppf |> Core.close_tbox
316316+317317+let pp_set_tab ppf () = ppf := !ppf |> Core.set_tab
318318+319319+let pp_print_tab ppf () = ppf := !ppf |> Core.tab
320320+321321+let pp_print_tbreak ppf width offset =
322322+ ppf := !ppf |> Core.tab_break ~width ~offset
323323+324324+let pp_doc ppf doc = ppf := append !ppf doc
325325+326326+module Driver = struct
327327+ (* Interpret a formatting entity on a formatter. *)
328328+ let output_formatting_lit ppf
329329+ (fmting_lit:CamlinternalFormatBasics.formatting_lit)
330330+ = match fmting_lit with
331331+ | Close_box -> pp_close_box ppf ()
332332+ | Close_tag -> pp_close_stag ppf ()
333333+ | Break (_, width, offset) -> pp_print_break ppf width offset
334334+ | FFlush -> pp_print_flush ppf ()
335335+ | Force_newline -> pp_force_newline ppf ()
336336+ | Flush_newline -> pp_print_newline ppf ()
337337+ | Magic_size (_, _) -> ()
338338+ | Escaped_at -> pp_print_char ppf '@'
339339+ | Escaped_percent -> pp_print_char ppf '%'
340340+ | Scan_indic c -> pp_print_char ppf '@'; pp_print_char ppf c
341341+342342+343343+344344+ let compute_tag output tag_acc =
345345+ let buf = Buffer.create 16 in
346346+ let buf_fmt = Format.formatter_of_buffer buf in
347347+ let ppf = ref empty in
348348+ output ppf tag_acc;
349349+ pp_print_flush ppf ();
350350+ format buf_fmt !ppf;
351351+ let len = Buffer.length buf in
352352+ if len < 2 then Buffer.contents buf
353353+ else Buffer.sub buf 1 (len - 2)
354354+355355+ (* Recursively output an "accumulator" containing a reversed list of
356356+ printing entities (string, char, flus, ...) in an output_stream. *)
357357+ (* Differ from Printf.output_acc by the interpretation of formatting. *)
358358+ (* Used as a continuation of CamlinternalFormat.make_printf. *)
359359+ let rec output_acc ppf (acc: _ CamlinternalFormat.acc) =
360360+ match acc with
361361+ | Acc_string_literal (Acc_formatting_lit (p, Magic_size (_, size)), s)
362362+ | Acc_data_string (Acc_formatting_lit (p, Magic_size (_, size)), s) ->
363363+ output_acc ppf p;
364364+ pp_print_as ppf size s;
365365+ | Acc_char_literal (Acc_formatting_lit (p, Magic_size (_, size)), c)
366366+ | Acc_data_char (Acc_formatting_lit (p, Magic_size (_, size)), c) ->
367367+ output_acc ppf p;
368368+ pp_print_as ppf size (String.make 1 c);
369369+ | Acc_formatting_lit (p, f) ->
370370+ output_acc ppf p;
371371+ output_formatting_lit ppf f;
372372+ | Acc_formatting_gen (p, Acc_open_tag acc') ->
373373+ output_acc ppf p;
374374+ pp_open_stag ppf (Format.String_tag (compute_tag output_acc acc'))
375375+ | Acc_formatting_gen (p, Acc_open_box acc') ->
376376+ output_acc ppf p;
377377+ let (indent, bty) =
378378+ let box_info = compute_tag output_acc acc' in
379379+ CamlinternalFormat.open_box_of_string box_info
380380+ in
381381+ pp_open_box_gen ppf indent bty
382382+ | Acc_string_literal (p, s)
383383+ | Acc_data_string (p, s) -> output_acc ppf p; pp_print_string ppf s;
384384+ | Acc_char_literal (p, c)
385385+ | Acc_data_char (p, c) -> output_acc ppf p; pp_print_char ppf c;
386386+ | Acc_delay (p, f) -> output_acc ppf p; f ppf;
387387+ | Acc_flush p -> output_acc ppf p; pp_print_flush ppf ();
388388+ | Acc_invalid_arg (p, msg) -> output_acc ppf p; invalid_arg msg;
389389+ | End_of_acc -> ()
390390+end
391391+392392+let kfprintf k ppf (CamlinternalFormatBasics.Format (fmt, _)) =
393393+ CamlinternalFormat.make_printf
394394+ (fun acc -> Driver.output_acc ppf acc; k ppf)
395395+ End_of_acc fmt
396396+let fprintf doc fmt = kfprintf ignore doc fmt
397397+398398+399399+let kdprintf k (CamlinternalFormatBasics.Format (fmt, _)) =
400400+ CamlinternalFormat.make_printf
401401+ (fun acc -> k (fun ppf -> Driver.output_acc ppf acc))
402402+ End_of_acc fmt
403403+404404+let dprintf fmt = kdprintf (fun i -> i) fmt
405405+406406+let doc_printf fmt =
407407+ let ppf = ref empty in
408408+ kfprintf (fun _ -> let doc = !ppf in ppf := empty; doc) ppf fmt
409409+410410+let kdoc_printf k fmt =
411411+ let ppf = ref empty in
412412+ kfprintf (fun ppf ->
413413+ let doc = !ppf in
414414+ ppf := empty;
415415+ k doc
416416+ )
417417+ ppf fmt
418418+419419+let core f x doc =
420420+ let r = ref doc in
421421+ f r x;
422422+ !r
423423+424424+let format_printer f ppf x =
425425+ let doc = core f x empty in
426426+ format ppf doc
427427+let compat = format_printer
428428+429429+let kasprintf k fmt =
430430+ kdoc_printf (fun doc -> k (Format.asprintf "%a" format doc)) fmt
431431+let asprintf fmt = kasprintf Fun.id fmt
432432+433433+let pp_print_iter ?(pp_sep=pp_print_cut) iter elt ppf c =
434434+ let sep = core pp_sep () in
435435+ ppf:= Core.iter ~sep ~iter (core elt) c !ppf
436436+437437+let pp_print_list ?(pp_sep=pp_print_cut) elt ppf l =
438438+ ppf := Core.list ~sep:(core pp_sep ()) (core elt) l !ppf
439439+440440+let pp_print_array ?pp_sep elt ppf a =
441441+ pp_print_iter ?pp_sep Array.iter elt ppf a
442442+let pp_print_seq ?pp_sep elt ppf s = pp_print_iter ?pp_sep Seq.iter elt ppf s
443443+444444+let pp_print_option ?(none=fun _ () -> ()) elt ppf o =
445445+ ppf := Core.option ~none:(core none ()) (core elt) o !ppf
446446+447447+let pp_print_result ~ok ~error ppf r =
448448+ ppf := Core.result ~ok:(core ok) ~error:(core error) r !ppf
449449+450450+let pp_print_either ~left ~right ppf e =
451451+ ppf := Core.either ~left:(core left) ~right:(core right) e !ppf
452452+453453+let comma ppf () = fprintf ppf ",@ "
454454+455455+let pp_two_columns ?(sep = "|") ?max_lines ppf (lines: (string * string) list) =
456456+ let left_column_size =
457457+ List.fold_left (fun acc (s, _) -> Int.max acc (String.length s)) 0 lines in
458458+ let lines_nb = List.length lines in
459459+ let ellipsed_first, ellipsed_last =
460460+ match max_lines with
461461+ | Some max_lines when lines_nb > max_lines ->
462462+ let printed_lines = max_lines - 1 in (* the ellipsis uses one line *)
463463+ let lines_before = printed_lines / 2 + printed_lines mod 2 in
464464+ let lines_after = printed_lines / 2 in
465465+ (lines_before, lines_nb - lines_after - 1)
466466+ | _ -> (-1, -1)
467467+ in
468468+ fprintf ppf "@[<v>";
469469+ List.iteri (fun k (line_l, line_r) ->
470470+ if k = ellipsed_first then fprintf ppf "...@,";
471471+ if ellipsed_first <= k && k <= ellipsed_last then ()
472472+ else fprintf ppf "%*s %s %s@," left_column_size line_l sep line_r
473473+ ) lines;
474474+ fprintf ppf "@]"
475475+476476+let deprecated_printer pr ppf = ppf := add !ppf (Deprecated pr)
+290
utils/format_doc.mli
···11+(**************************************************************************)
22+(* *)
33+(* OCaml *)
44+(* *)
55+(* Florian Angeletti, projet Cambium, Inria Paris *)
66+(* *)
77+(* Copyright 2024 Institut National de Recherche en Informatique et *)
88+(* en Automatique. *)
99+(* *)
1010+(* All rights reserved. This file is distributed under the terms of *)
1111+(* the GNU Lesser General Public License version 2.1, with the *)
1212+(* special exception on linking described in the file LICENSE. *)
1313+(* *)
1414+(**************************************************************************)
1515+1616+(** Composable document for the {!Format} formatting engine. *)
1717+1818+(** This module introduces a pure and immutable document type which represents a
1919+ sequence of formatting instructions to be printed by a formatting engine at
2020+ later point. At the same time, it also provides format string interpreter
2121+ which produces this document type from format string and their associated
2222+ printers.
2323+2424+ The module is designed to be source compatible with code defining format
2525+ printers: replacing `Format` by `Format_doc` in your code will convert
2626+ `Format` printers to `Format_doc` printers.
2727+*)
2828+2929+(** Format box types *)
3030+type box_type =
3131+ | H
3232+ | V
3333+ | HV
3434+ | HoV
3535+ | B
3636+3737+type stag = Format.stag
3838+3939+(** Base formatting instruction recognized by {!Format} *)
4040+type element =
4141+ | Text of string
4242+ | With_size of int
4343+ | Open_box of { kind: box_type ; indent:int }
4444+ | Close_box
4545+ | Open_tag of Format.stag
4646+ | Close_tag
4747+ | Open_tbox
4848+ | Tab_break of { width : int; offset : int }
4949+ | Set_tab
5050+ | Close_tbox
5151+ | Simple_break of { spaces : int; indent : int }
5252+ | Break of { fits : string * int * string as 'a; breaks : 'a }
5353+ | Flush of { newline:bool }
5454+ | Newline
5555+ | If_newline
5656+5757+ | Deprecated of (Format.formatter -> unit)
5858+ (** Escape hatch: a {!Format} printer used to provide backward-compatibility
5959+ for user-defined printer (from the [#install_printer] toplevel directive
6060+ for instance). *)
6161+6262+ (** Immutable document type*)
6363+type t
6464+type doc = t
6565+6666+(** Empty document *)
6767+val empty: t
6868+6969+(** [format ppf doc] sends the format instruction of [doc] to the Format's
7070+ formatter [doc]. *)
7171+val format: Format.formatter -> doc -> unit
7272+7373+(** Fold over a document as a sequence of instructions *)
7474+val fold: ('acc -> element -> 'acc) -> 'acc -> doc -> 'acc
7575+7676+(** Immutable API for composing {!doc} *)
7777+module Core: sig
7878+ type ('a,'b) fmt = ('a, doc, doc,'b) format4
7979+8080+ type printer0 = doc -> doc
8181+ type 'a printer = 'a -> printer0
8282+8383+8484+ (** {!msg} and {!kmsg} produce a document from a format string and its
8585+ argument *)
8686+ val msg: ('a,doc) fmt -> 'a
8787+ val kmsg: (doc -> 'b) -> ('a,'b) fmt -> 'a
8888+8989+ (** {!printf} and {!kprintf} produce a printer from a format string and its
9090+ argument*)
9191+ val printf: ('a, printer0) fmt -> 'a
9292+ val kprintf: (doc -> 'b) -> ('a, doc -> 'b) fmt -> 'a
9393+9494+ (** The functions below mirror {!Format} printers, without the [pp_print_]
9595+ prefix naming convention *)
9696+ val open_box: box_type -> int -> printer0
9797+ val close_box: printer0
9898+9999+ val text: string printer
100100+ val string: string printer
101101+ val bytes: bytes printer
102102+ val with_size: int printer
103103+104104+ val int: int printer
105105+ val float: float printer
106106+ val char: char printer
107107+ val bool: bool printer
108108+109109+ val space: printer0
110110+ val cut: printer0
111111+ val break: spaces:int -> indent:int -> printer0
112112+113113+ val custom_break:
114114+ fits:(string * int * string as 'a) -> breaks:'a -> printer0
115115+ val force_newline: printer0
116116+ val if_newline: printer0
117117+118118+ val flush: printer0
119119+ val force_stop: printer0
120120+121121+ val open_tbox: printer0
122122+ val set_tab: printer0
123123+ val tab: printer0
124124+ val tab_break: width:int -> offset:int -> printer0
125125+ val close_tbox: printer0
126126+127127+ val open_tag: stag printer
128128+ val close_tag: printer0
129129+130130+ val list: ?sep:printer0 -> 'a printer -> 'a list printer
131131+ val iter:
132132+ ?sep:printer0 -> iter:(('a -> unit) -> 'b -> unit) -> 'a printer
133133+ ->'b printer
134134+ val array: ?sep:printer0 -> 'a printer -> 'a array printer
135135+ val seq: ?sep:printer0 -> 'a printer -> 'a Seq.t printer
136136+137137+ val option: ?none:printer0 -> 'a printer -> 'a option printer
138138+ val result: ok:'a printer -> error:'e printer -> ('a,'e) result printer
139139+ val either: left:'a printer -> right:'b printer -> ('a,'b) Either.t printer
140140+141141+end
142142+143143+(** {1 Compatibility API} *)
144144+145145+(** The functions and types below provides source compatibility with format
146146+printers and conversion function from {!Format_doc} printers to {!Format}
147147+printers. The reverse direction is implemented using an escape hatch in the
148148+formatting instruction and should only be used to preserve backward
149149+compatibility. *)
150150+151151+type formatter
152152+type 'a printer = formatter -> 'a -> unit
153153+154154+val formatter: doc ref -> formatter
155155+(** [formatter rdoc] creates a {!formatter} that updates the [rdoc] reference *)
156156+157157+(** Translate a {!Format_doc} printer to a {!Format} one. *)
158158+val compat: 'a printer -> Format.formatter -> 'a -> unit
159159+160160+(** If necessary, embbed a {!Format} printer inside a formatting instruction
161161+ stream. This breaks every guarantees provided by {!Format_doc}. *)
162162+val deprecated_printer: (Format.formatter -> unit) -> formatter -> unit
163163+164164+165165+(** {2 Format string interpreters }*)
166166+167167+val fprintf : formatter -> ('a, formatter,unit) format -> 'a
168168+val kfprintf:
169169+ (formatter -> 'a) -> formatter ->
170170+ ('b, formatter, unit, 'a) format4 -> 'b
171171+172172+val asprintf : ('a, formatter, unit, string) format4 -> 'a
173173+val kasprintf : (string -> 'a) -> ('b, formatter, unit, 'a) format4 -> 'b
174174+175175+176176+val dprintf : ('a, formatter, unit, formatter -> unit) format4 -> 'a
177177+val kdprintf:
178178+ ((formatter -> unit) -> 'a) ->
179179+ ('b, formatter, unit, 'a) format4 -> 'b
180180+181181+(** {!doc_printf} and {!kdoc_printf} creates a document directly *)
182182+val doc_printf: ('a, formatter, unit, doc) format4 -> 'a
183183+val kdoc_printf: (doc -> 'r) -> ('a, formatter, unit, 'r) format4 -> 'a
184184+185185+(** {2 Compatibility with {!Core} }*)
186186+187187+val core: 'a printer -> 'a Core.printer
188188+val pp_doc: doc printer
189189+190190+(** {2 Source compatibility with Format}*)
191191+192192+(** {3 String printers } *)
193193+194194+val pp_print_string: string printer
195195+val pp_print_substring: pos:int -> len:int -> string printer
196196+val pp_print_text: string printer
197197+val pp_print_bytes: bytes printer
198198+199199+val pp_print_as: formatter -> int -> string -> unit
200200+val pp_print_substring_as:
201201+ pos:int -> len:int -> formatter -> int -> string -> unit
202202+203203+(** {3 Primitive type printers }*)
204204+205205+val pp_print_char: char printer
206206+val pp_print_int: int printer
207207+val pp_print_float: float printer
208208+val pp_print_bool: bool printer
209209+val pp_print_nothing: unit printer
210210+211211+(** {3 Printer combinators }*)
212212+213213+val pp_print_iter:
214214+ ?pp_sep:unit printer -> (('a -> unit) -> 'b -> unit) ->
215215+ 'a printer -> 'b printer
216216+217217+val pp_print_list: ?pp_sep:unit printer -> 'a printer -> 'a list printer
218218+val pp_print_array: ?pp_sep:unit printer -> 'a printer -> 'a array printer
219219+val pp_print_seq: ?pp_sep:unit printer -> 'a printer -> 'a Seq.t printer
220220+221221+val pp_print_option: ?none:unit printer -> 'a printer -> 'a option printer
222222+val pp_print_result: ok:'a printer -> error:'e printer -> ('a,'e) result printer
223223+val pp_print_either:
224224+ left:'a printer -> right:'b printer -> ('a,'b) Either.t printer
225225+226226+227227+(** {3 Boxes and tags }*)
228228+229229+val pp_open_stag: Format.stag printer
230230+val pp_close_stag: unit printer
231231+232232+val pp_open_box: int printer
233233+val pp_close_box: unit printer
234234+235235+(** {3 Break hints} *)
236236+237237+val pp_print_space: unit printer
238238+val pp_print_cut: unit printer
239239+val pp_print_break: formatter -> int -> int -> unit
240240+val pp_print_custom_break:
241241+ formatter -> fits:(string * int * string as 'c) -> breaks:'c -> unit
242242+243243+(** {3 Tabulations }*)
244244+245245+val pp_open_tbox: unit printer
246246+val pp_close_tbox: unit printer
247247+val pp_set_tab: unit printer
248248+val pp_print_tab: unit printer
249249+val pp_print_tbreak: formatter -> int -> int -> unit
250250+251251+(** {3 Newlines and flushing }*)
252252+253253+val pp_print_if_newline: unit printer
254254+val pp_force_newline: unit printer
255255+val pp_print_flush: unit printer
256256+val pp_print_newline: unit printer
257257+258258+(** {1 Compiler specific functions }*)
259259+260260+(** {2 Separators }*)
261261+262262+val comma: unit printer
263263+264264+(** {2 Compiler output} *)
265265+266266+val pp_two_columns :
267267+ ?sep:string -> ?max_lines:int ->
268268+ formatter -> (string * string) list -> unit
269269+(** [pp_two_columns ?sep ?max_lines ppf l] prints the lines in [l] as two
270270+ columns separated by [sep] ("|" by default). [max_lines] can be used to
271271+ indicate a maximum number of lines to print -- an ellipsis gets inserted at
272272+ the middle if the input has too many lines.
273273+274274+ Example:
275275+276276+ {v pp_two_columns ~max_lines:3 Format.std_formatter [
277277+ "abc", "hello";
278278+ "def", "zzz";
279279+ "a" , "bllbl";
280280+ "bb" , "dddddd";
281281+ ] v}
282282+283283+ prints
284284+285285+ {v
286286+ abc | hello
287287+ ...
288288+ bb | dddddd
289289+ v}
290290+*)