Format, how to disable pretty printing?

Is there a way to make sure that for a few lines the pretty printing machinery of Format will not try to interfere with output instructions – basically set it in Printf mode.

Just off the cuff, I might try to write a formatter that wrapped a provided formatter, and mappid all the interesting pp ops to no-ops: that is, boxes, cuts, breaks, etc. And just pass thru the rest. That would leave the pp context established before your code was called, I guess. Probably a way to disable that too

It depends a lot on what you mean by disabling pretty-printing and what are the source of the output instruction.

If the source is a format string, it is possible to write an alternative interpreter that ignore all formatting instructions.

If the source are printing functions (that are modifying a formatter state), it is too late to disable the emission of formatting instructions. A degraded option would be to print first to a buffer formatter with “infinite” margin and where the newline and indent instructions are disabled

let neutral_buffer () =
  let b = Buffer.create 100 in
  let ppf = Format.formatter_of_buffer b in
  let fns = Format.pp_get_formatter_out_functions ppf () in
  let disabled = Format.{
      fns with
      out_indent = ignore;
      out_newline = ignore;
    }
  in
  Format.pp_set_formatter_out_functions ppf disabled;
  Format.pp_set_geometry ppf
    ~max_indent:(Format.pp_infinity - 2) ~margin:(Format.pp_infinity - 1);
  b, ppf

let disable_formatting ppf pr =
  let b, bppf = neutral_buffer () in
  pr bppf;
  Format.pp_print_flush bppf ();
  let s = Buffer.contents b in
  Format.pp_print_string ppf s


let test =
  let vbox = Format.dprintf "@[<v>D@ E@ F@]" in
  let bbox = Format.dprintf "@[I@ J@ K@]" in
  Format.printf "@[<v>A@ B@ C%aG@ H@ %a L@ M@ J@]@."
    disable_formatting vbox
    disable_formatting bbox

which prints

A
B
CDEFG
H
I J K L
M
J

where the first group CDEFG illustrates the fact that we lose information about the space component of break hints inside vbox.

I think that an accurate description would be:

let pp_no_pp ppf v = Format.fprintf ppf "%s" (to_string v) 

without this disturbing too much an established pretty printing context. Of course it may break a few boxes, the point here is for the result of to_string to be acurately represented in the output. Being understood that to_string may have newlines therein and that I’d rather avoid first printing to a string.

The use case is an AST which has layout information under the form of strings of whitespace (including newlines). I would like to provide a pp that ignores the layout information and does pretty printing using Format, but also a pp_layout that does not use the pretty printing engine but uses the layout information of the AST.

If the aim is to insert a printer output as text without modifying the current formatting context, having a secondary formatter as suggested by @Chet_Murthy might work while avoiding building the full output in a separate buffer:

let secondary_formatter ppf =
  let out_spaces n = Format.pp_print_string ppf (String.make n ' ') in
  let fns = Format.{
      out_indent = out_spaces;
      out_spaces;
      out_newline = (fun () -> Format.pp_print_string ppf "\n");
      out_string = (fun s start len -> Format.pp_print_string ppf (String.sub s start len));
      out_flush = ignore;
    }
  in
  Format.formatter_of_out_functions fns


let pp_no_pp ppf pr =
  let intermediary = secondary_formatter ppf in
  pr intermediary;
  Format.pp_print_flush intermediary ()