@@ -215,6 +215,12 @@ module Light_table = struct
215215 let header, data = extract [] grid in
216216 Some (header, alignments, data)
217217 with Table_not_safe -> None )
218+
219+ let alignment_chars = function
220+ | Some `Left -> (" :" , " -" )
221+ | Some `Center -> (" :" , " :" )
222+ | Some `Right -> (" -" , " :" )
223+ | None -> (" -" , " -" )
218224end
219225
220226let non_wrap_space sp =
@@ -356,32 +362,69 @@ and fmt_table_heavy c (((grid, alignments), _) : table) =
356362 fmt_block_markup " table" (list grid force_break fmt_row)
357363
358364and fmt_table_light c (header , alignments , data ) =
359- let fmt_align = function
360- | Some `Left -> str " :--"
361- | Some `Center -> str " :-:"
362- | Some `Right -> str " --:"
363- | None -> str " ---"
365+ (* Format every cells into strings to then compute the width of columns. *)
366+ let format_rows_to_strings =
367+ let format_cell_to_string elems =
368+ Format_. asprintf " %a " Fmt. eval
369+ @@ fmt_inline_elements c ~wrap: false elems
370+ in
371+ List. map ~f: (List. map ~f: format_cell_to_string)
372+ in
373+ let header = format_rows_to_strings header
374+ and data = format_rows_to_strings data in
375+ let column_width =
376+ let column_count =
377+ let f acc row = max acc (List. length row) in
378+ let compute init rows = List. fold_left rows ~init ~f in
379+ let aligns_count =
380+ Option. value_map alignments ~default: 0 ~f: List. length
381+ in
382+ compute (compute aligns_count header) data
383+ in
384+ let column_min_width = if Option. is_some alignments then 3 else 1 in
385+ let widths = Array. init column_count ~f: (fun _ -> column_min_width) in
386+ let compute_column_widths row =
387+ List. iteri row ~f: (fun i cell ->
388+ widths.(i) < - max widths.(i) (Fmt. str_length cell) )
389+ in
390+ List. iter ~f: compute_column_widths header ;
391+ List. iter ~f: compute_column_widths data ;
392+ Array. get widths
364393 in
365- let has_header = not (List. is_empty header)
366- and has_data = not (List. is_empty data) in
367- let fmt_alignment_row =
368- opt alignments (fun aligns ->
369- str " |"
370- $ list aligns (str " |" ) fmt_align
371- $ str " |"
372- $ fmt_if has_data force_break )
394+ let align_row, align_of_column =
395+ let align_column i align =
396+ let l, r = Light_table. alignment_chars align in
397+ l ^ String. make (column_width i - 2 ) '-' ^ r
398+ in
399+ match alignments with
400+ | Some aligns ->
401+ let aligns_ar = Array. of_list aligns in
402+ let aligns_get i =
403+ if i > = Array. length aligns_ar then `Left
404+ else Option. value ~default: `Left aligns_ar.(i)
405+ in
406+ ([List. mapi ~f: align_column aligns], aligns_get)
407+ | None -> ([] , fun _ -> `Left )
408+ in
409+ let padding n = str (String. make n ' ' ) in
410+ let fmt_cell i s =
411+ let pad = column_width i - Fmt. str_length s in
412+ let l, r =
413+ if pad < = 0 then (noop, noop)
414+ else
415+ match align_of_column i with
416+ | `Left -> (noop, padding pad)
417+ | `Center -> (padding (pad / 2 ), padding ((pad + 1 ) / 2 ))
418+ | `Right -> (padding pad, noop)
419+ in
420+ l $ str s $ r
373421 in
374- (* Don't allow inline elements to wrap, meaning the line won't break if the
375- row breaks the margin. *)
376- let fmt_cell elems = fmt_inline_elements c ~wrap: false elems in
377- let fmt_row row = str " | " $ list row (str " | " ) fmt_cell $ str " |" in
378- let fmt_rows rows = list rows force_break fmt_row in
379- let fmt_grid =
380- fmt_rows header
381- $ fmt_if has_header force_break
382- $ fmt_alignment_row $ fmt_rows data
422+ let fmt_row row =
423+ let row = List. mapi row ~f: fmt_cell in
424+ str " |" $ list row (str " |" ) Fn. id $ str " |"
383425 in
384- fmt_block_markup ~force_break: true " t" (vbox 0 fmt_grid)
426+ fmt_block_markup ~force_break: true " t"
427+ (vbox 0 (list (header @ align_row @ data) force_break fmt_row))
385428
386429and fmt_table c table =
387430 match Light_table. of_table table with
0 commit comments