+
+let save_out_readable chan csv =
+ (* Escape all the strings in the CSV file first. *)
+ let csv = List.map (List.map String.escaped) csv in
+
+ let csv = square csv in
+
+ (* Find the width of each column. *)
+ let widths =
+ match csv with
+ | [] -> []
+ | r :: _ ->
+ let n = List.length r in
+ let lengths = List.map (List.map String.length) csv in
+ let max2rows r1 r2 =
+ let rp = List.combine r1 r2 in
+ List.map (fun ((a : int), (b : int)) -> max a b) rp
+ in
+ let rec repeat x = function
+ | 0 -> []
+ | i -> x :: repeat x (i-1)
+ in
+ List.fold_left max2rows (repeat 0 n) lengths in
+
+ (* Print out each cell at the correct width. *)
+ let rec repeat f = function
+ | 0 -> ()
+ | i -> f (); repeat f (i-1)
+ in
+ List.iter (
+ fun row ->
+ let row = List.combine widths row in
+ List.iter (
+ fun (width, cell) ->
+ output_string chan cell;
+ let n = String.length cell in
+ repeat (fun () -> output_char chan ' ') (width - n + 1)
+ ) row;
+ output_char chan '\n'
+ ) csv
+
+let print_readable = save_out_readable stdout