From 54ac35562a54e3cf797e9b40025f31b1d1b7752d Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Wed, 13 Nov 2019 21:26:40 -0600 Subject: [PATCH] refactor: generalize center/align with a single construct --- src/PrintBox.ml | 20 ++++++++++++-------- src/PrintBox.mli | 40 ++++++++++++++++++++++++++++++--------- src/PrintBox_text.ml | 37 +++++++++++++++++------------------- src/html/PrintBox_html.ml | 5 +++-- test/test1.ml | 8 ++++---- 5 files changed, 67 insertions(+), 43 deletions(-) diff --git a/src/PrintBox.ml b/src/PrintBox.ml index 5fc9e58..2f5f8ad 100644 --- a/src/PrintBox.ml +++ b/src/PrintBox.ml @@ -39,8 +39,11 @@ type view = } | Frame of t | Pad of position * t (* vertical and horizontal padding *) - | Align_right of t (* dynamic left-padding *) - | Center of t (* center vertically and horizontally *) + | Align of { + h: [`Left | `Center | `Right]; + v: [`Top | `Center | `Bottom]; + inner: t; + } | Grid of [`Bars | `None] * t array array | Tree of int * t * t array @@ -95,8 +98,13 @@ let pad b = pad' ~col:1 ~lines:1 b let hpad col b = pad' ~col ~lines:0 b let vpad lines b = pad' ~col:0 ~lines b -let align_right b = Align_right b -let center b = Center b +let align ~h ~v b : t = Align {h; v; inner=b} +let align_bottom b = align ~h:`Left ~v:`Bottom b +let align_right b = align ~h:`Right ~v:`Top b +let align_bottom_right b = align ~h:`Right ~v:`Bottom b +let center_h b = align ~h:`Center ~v:`Top b +let center_v b = align ~h:`Left ~v:`Center b +let center_hv b = align ~h:`Center ~v:`Center b let map_matrix f m = Array.map (Array.map f) m @@ -173,8 +181,6 @@ module Simple = struct type t = [ `Empty | `Pad of t - | `Align_right of t - | `Center of t | `Text of string | `Vlist of t list | `Hlist of t list @@ -185,8 +191,6 @@ module Simple = struct let rec to_box = function | `Empty -> empty | `Pad b -> pad (to_box b) - | `Align_right b -> align_right (to_box b) - | `Center b -> center (to_box b) | `Text t -> text t | `Vlist l -> vlist (List.map to_box l) | `Hlist l -> hlist (List.map to_box l) diff --git a/src/PrintBox.mli b/src/PrintBox.mli index ccc004b..5c5cd8d 100644 --- a/src/PrintBox.mli +++ b/src/PrintBox.mli @@ -105,8 +105,7 @@ type t (** The type [view] can be used to observe the inside of the box, now that [t] is opaque. - @since NEXT_RELEASE added [Align_right] - @since NEXT_RELEASE added [Center] + @since NEXT_RELEASE added [Align] *) type view = private | Empty @@ -116,8 +115,11 @@ type view = private } | Frame of t | Pad of position * t (* vertical and horizontal padding *) - | Align_right of t (* dynamic left-padding *) - | Center of t (* center vertically and horizontally *) + | Align of { + h: [`Left | `Center | `Right]; + v: [`Top | `Center | `Bottom]; + inner: t; + } (** Alignment within the surrounding box *) | Grid of [`Bars | `None] * t array array | Tree of int * t * t array (* int: indent *) @@ -179,12 +181,34 @@ val vpad : int -> t -> t val hpad : int -> t -> t (** Pad horizontally by [n] spaces *) +val align : h:[`Left | `Right | `Center] -> v:[`Top | `Bottom | `Center] -> t -> t +(** Control alignment of the given box wrt its surrounding box, if any. + @param h horizontal alignment + @param v vertical alignment + @since NEXT_RELEASE *) + val align_right : t -> t -(** Left-pad to the size of the surrounding box +(** Left-pad to the size of the surrounding box, as in [align ~h:`Right ~v:`Top] + @since NEXT_RELEASE *) + +val align_bottom : t -> t +(** Align to the bottom, as in [align ~h:`Left ~v:`Bottom] + @since NEXT_RELEASE *) + +val align_bottom_right : t -> t +(** Align to the right and to the bottom, as in [align ~h:`Right ~v:`Bottom] + @since NEXT_RELEASE *) + +val center_h : t -> t +(** Horizontal center, as in . + @since NEXT_RELEASE *) + +val center_v : t -> t +(** Vertical center. @since NEXT_RELEASE *) -val center : t -> t -(** Try to center within the surrounding box +val center_hv : t -> t +(** Try to center within the surrounding box, as in [align ~h:`Center ~v:`Center] @since NEXT_RELEASE *) val grid : @@ -290,8 +314,6 @@ module Simple : sig type t = [ `Empty | `Pad of t - | `Align_right of t - | `Center of t | `Text of string | `Vlist of t list | `Hlist of t list diff --git a/src/PrintBox_text.ml b/src/PrintBox_text.ml index 4ae7d06..c778a85 100644 --- a/src/PrintBox_text.ml +++ b/src/PrintBox_text.ml @@ -239,8 +239,11 @@ end = struct } | Frame of 'a | Pad of position * 'a (* vertical and horizontal padding *) - | Align_right of 'a (* dynamic left-padding *) - | Center of 'a + | Align of { + h: [`Left | `Center | `Right]; + v: [`Top | `Center | `Bottom]; + inner: 'a (* dynamic centering/alignment *) + } | Grid of [`Bars | `None] * 'a array array | Tree of int * 'a * 'a array @@ -321,8 +324,7 @@ end = struct | Frame t -> Pos.move (size t) 2 2 | Pad (dim, b') -> Pos.(size b' + (2 * dim)) - | Align_right b' -> size b' - | Center b' -> size b' + | Align {inner=b';_} -> size b' | Grid (style,m) -> let bars = match style with | `Bars -> true @@ -368,8 +370,7 @@ end = struct Text {l=List.rev !acc; style} | B.Frame t -> Frame (of_box t) | B.Pad (dim, t) -> Pad (dim, of_box t) - | B.Align_right t -> Align_right (of_box t) - | B.Center t -> Center (of_box t) + | B.Align {h;v;inner} -> Align {h;v;inner=of_box inner} | B.Grid (bars, m) -> Grid (bars, B.map_matrix of_box m) | B.Tree (i, b, l) -> Tree (i, of_box b, Array.map of_box l) in @@ -428,23 +429,19 @@ end = struct | Some p -> Some Pos.(p - (2*dim)) in render_rec ~offset:Pos.(offset+dim) ~ansi ?expected_size ~out b' Pos.(pos + dim) - | Align_right b' -> + | Align {h;v;inner=b'} -> begin match expected_size with | Some expected_size -> (* add padding on the left *) - let left_pad = max 0 (expected_size.x - (size b').x) in - let pos' = Pos.move pos left_pad 0 in - (* just render [b'] with new offset *) - render_rec ~offset ~ansi ~out b' pos'; - | None -> - render_rec ~ansi ~offset ~out b' pos - end - | Center b' -> - begin match expected_size with - | Some expected_size -> - (* add padding on every size *) - let hpad = max 0 ((expected_size.x - (size b').x) / 2) in - let vpad = max 0 ((expected_size.y - (size b').y) / 2) in + let hpad = match h with + | `Left -> 0 + | `Center -> max 0 ((expected_size.x - (size b').x) / 2) + | `Right -> max 0 (expected_size.x - (size b').x) + and vpad = match v with + | `Top -> 0 + | `Center -> max 0 ((expected_size.y - (size b').y) / 2) + | `Bottom -> max 0 (expected_size.y - (size b').y) + in let pos' = Pos.move pos hpad vpad in (* just render [b'] with new offset *) render_rec ~offset ~ansi ~out b' pos'; diff --git a/src/html/PrintBox_html.ml b/src/html/PrintBox_html.ml index 5f46985..b4b1177 100644 --- a/src/html/PrintBox_html.ml +++ b/src/html/PrintBox_html.ml @@ -58,10 +58,11 @@ let rec to_html_rec (b: B.t) : [< Html_types.flow5 > `Div `Ul `Table `P] html = H.p ~a l | B.Pad (_, b) | B.Frame b -> to_html_rec b - | B.Align_right b -> + | B.Align {h=`Right;inner=b;v=_} -> H.div ~a:[H.a_class ["align-right"]] [ to_html_rec b ] - | B.Center b -> + | B.Align {h=`Center;inner=b;v=_} -> H.div ~a:[H.a_class ["center"]] [ to_html_rec b ] + | B.Align {inner=b;_} -> to_html_rec b | B.Grid (bars, a) -> let class_ = match bars with | `Bars -> "framed" diff --git a/test/test1.ml b/test/test1.ml index 2074d5e..ebf8b0e 100644 --- a/test/test1.ml +++ b/test/test1.ml @@ -28,7 +28,7 @@ let () = let grid = B.frame @@ B.grid_l [ [B.text "the center of the triangle is"; B.empty]; - [B.center @@ B.text "lil' ol' me"; + [B.center_hv @@ B.text "lil' ol' me"; B.pad' ~col:0 ~lines:6 @@ B.text "t\na\nl\nl"]; [B.align_right (B.text "i'm aligned right"); B.empty]; [ B.text "loooooooooooooooooooooooooooooooooong"; B.empty; ]; @@ -60,9 +60,9 @@ module Box_in = struct let open B in frame @@ grid_l [ [ text "a"; text "looooooooooooooooooooooooo\noonng"]; - [ text "bx"; center @@ frame @@ record ["x", int 1; "y", int 2]]; + [ text "bx"; center_hv @@ frame @@ record ["x", int 1; "y", int 2]]; [ pad' ~col:2 ~lines:2 @@ text "?"; - center @@ record ["x", int 10; "y", int 20]]; + center_hv @@ record ["x", int 10; "y", int 20]]; ] let () = print_endline @@ PrintBox_text.to_string b @@ -75,7 +75,7 @@ module Unicode = struct B.(frame @@ vlist [text "nice unicode! 💪"; frame @@ hlist [ vlist[text "oï ωεird nums:\nπ/2\nτ/4"; - center @@ tree (text "0")[text "1"; tree (text "ω") [text "ω²"]]]; + center_hv @@ tree (text "0")[text "1"; tree (text "ω") [text "ω²"]]]; frame @@ frame @@ frame @@ vlist [text "sum=Σ_i a·xᵢ²\n—————\n1+1"; align_right @@ text "Ōₒ\nÀ"]]]);;