Skip to content

Commit 82d7971

Browse files
authored
Merge pull request #9237 from gasche/format-update-geometry
Format.pp_update_geometry: formatter -> (geometry -> geometry) -> unit
2 parents 018d45a + bc574f5 commit 82d7971

3 files changed

Lines changed: 49 additions & 12 deletions

File tree

Changes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ Working version
5757
- #8894: Added List.fold_left_map function combining map and fold.
5858
(Bernhard Schommer, review by Alain Frisch and github user @cfcs)
5959

60+
- #9237: `Format.pp_update_geometry ppf (fun geo -> {geo with ...})`
61+
for formatter geometry changes that are robust to new geometry fields.
62+
(Gabriel Scherer, review by Josh Berdine and ???)
63+
6064
### Other libraries:
6165

6266
- #9106: Register printer for Unix_error in win32unix, as in unix.

stdlib/format.ml

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -815,29 +815,48 @@ let pp_set_margin state n =
815815
(** Geometry functions and types *)
816816
type geometry = { max_indent:int; margin: int}
817817

818+
let validate_geometry {margin; max_indent} =
819+
if max_indent < 2 then
820+
Error "max_indent < 2"
821+
else if margin <= max_indent then
822+
Error "margin <= max_indent"
823+
else Ok ()
824+
818825
let check_geometry geometry =
819-
geometry.max_indent > 1
820-
&& geometry.margin > geometry.max_indent
826+
match validate_geometry geometry with
827+
| Ok () -> true
828+
| Error _ -> false
821829

822830
let pp_get_margin state () = state.pp_margin
823831

832+
let pp_set_full_geometry state {margin; max_indent} =
833+
pp_set_margin state margin;
834+
pp_set_max_indent state max_indent;
835+
()
836+
824837
let pp_set_geometry state ~max_indent ~margin =
825-
if max_indent < 2 then
826-
raise (Invalid_argument "Format.pp_set_geometry: max_indent < 2")
827-
else if margin <= max_indent then
828-
raise (Invalid_argument "Format.pp_set_geometry: margin <= max_indent")
829-
else
830-
pp_set_margin state margin; pp_set_max_indent state max_indent
838+
let geometry = { max_indent; margin } in
839+
match validate_geometry geometry with
840+
| Error msg ->
841+
raise (Invalid_argument ("Format.pp_set_geometry: " ^ msg))
842+
| Ok () ->
843+
pp_set_full_geometry state geometry
831844

832845
let pp_safe_set_geometry state ~max_indent ~margin =
833-
if check_geometry {max_indent;margin} then
834-
pp_set_geometry state ~max_indent ~margin
835-
else
836-
()
846+
let geometry = { max_indent; margin } in
847+
match validate_geometry geometry with
848+
| Error _msg ->
849+
()
850+
| Ok () ->
851+
pp_set_full_geometry state geometry
837852

838853
let pp_get_geometry state () =
839854
{ margin = pp_get_margin state (); max_indent = pp_get_max_indent state () }
840855

856+
let pp_update_geometry state update =
857+
let geometry = pp_get_geometry state () in
858+
pp_set_full_geometry state (update geometry)
859+
841860
(* Setting a formatter basic output functions. *)
842861
let pp_set_formatter_out_functions state {
843862
out_string = f;
@@ -1123,6 +1142,7 @@ and get_max_indent = pp_get_max_indent std_formatter
11231142
and set_geometry = pp_set_geometry std_formatter
11241143
and safe_set_geometry = pp_safe_set_geometry std_formatter
11251144
and get_geometry = pp_get_geometry std_formatter
1145+
and update_geometry = pp_update_geometry std_formatter
11261146

11271147
and set_max_boxes = pp_set_max_boxes std_formatter
11281148
and get_max_boxes = pp_get_max_boxes std_formatter

stdlib/format.mli

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,19 @@ val safe_set_geometry : max_indent:int -> margin:int -> unit
488488
@since 4.08.0
489489
*)
490490

491+
(**
492+
[pp_update_geometry ppf (fun geo -> { geo with ... })] lets you
493+
update a formatter's geometry in a way that is robust to extension
494+
of the [geometry] record with new fields.
495+
496+
Raises an invalid argument exception if the returned geometry
497+
does not satisfy {!check_geometry}.
498+
499+
@since 4.11.0
500+
*)
501+
val pp_update_geometry : formatter -> (geometry -> geometry) -> unit
502+
val update_geometry : (geometry -> geometry) -> unit
503+
491504
val pp_get_geometry: formatter -> unit -> geometry
492505
val get_geometry: unit -> geometry
493506
(** Return the current geometry of the formatter

0 commit comments

Comments
 (0)