mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-07 03:35:30 -05:00
moved box constructors into PrintBoxs toplevel;
more convenience constructors; more accurate printing of nested boxs bars
This commit is contained in:
parent
ebb8310f84
commit
6ef51a5717
2 changed files with 128 additions and 66 deletions
103
misc/printBox.ml
103
misc/printBox.ml
|
|
@ -137,7 +137,8 @@ let rec _find s c i =
|
|||
else _find s c (i+1)
|
||||
|
||||
let rec _lines s i k = match _find s '\n' i with
|
||||
| None -> ()
|
||||
| None ->
|
||||
if i<String.length s then k (String.sub s i (String.length s-i))
|
||||
| Some j ->
|
||||
let s' = String.sub s i (j-i) in
|
||||
k s';
|
||||
|
|
@ -227,37 +228,53 @@ module Box = struct
|
|||
|
||||
let _make shape =
|
||||
{ shape; size=(lazy (_size shape)); }
|
||||
|
||||
let line s =
|
||||
assert (_find s '\n' 0 = None);
|
||||
_make (Line s)
|
||||
|
||||
let text s =
|
||||
let acc = ref [] in
|
||||
_lines s 0 (fun x -> acc := x :: !acc);
|
||||
_make (Text (List.rev !acc))
|
||||
|
||||
let lines l =
|
||||
assert (List.for_all (fun s -> _find s '\n' 0 = None) l);
|
||||
_make (Text l)
|
||||
|
||||
let frame b = _make (Frame b)
|
||||
|
||||
let grid ?(framed=true) m =
|
||||
_make (Grid ((if framed then GridFramed else GridBase), m))
|
||||
|
||||
let init_grid ?framed ~line ~col f =
|
||||
let m = Array.init line (fun j-> Array.init col (fun i -> f ~line:j ~col:i)) in
|
||||
grid ?framed m
|
||||
|
||||
let vlist ?framed l =
|
||||
let a = Array.of_list l in
|
||||
grid ?framed (Array.map (fun line -> [| line |]) a)
|
||||
|
||||
let hlist ?framed l =
|
||||
grid ?framed [| Array.of_list l |]
|
||||
end
|
||||
|
||||
let line s =
|
||||
assert (_find s '\n' 0 = None);
|
||||
Box._make (Box.Line s)
|
||||
|
||||
let text s =
|
||||
let acc = ref [] in
|
||||
_lines s 0 (fun x -> acc := x :: !acc);
|
||||
Box._make (Box.Text (List.rev !acc))
|
||||
|
||||
let lines l =
|
||||
assert (List.for_all (fun s -> _find s '\n' 0 = None) l);
|
||||
Box._make (Box.Text l)
|
||||
|
||||
let int_ x = line (string_of_int x)
|
||||
let float_ x = line (string_of_float x)
|
||||
let bool_ x = line (string_of_bool x)
|
||||
|
||||
let frame b =
|
||||
Box._make (Box.Frame b)
|
||||
|
||||
let grid ?(framed=true) m =
|
||||
Box._make (Box.Grid ((if framed then Box.GridFramed else Box.GridBase), m))
|
||||
|
||||
let init_grid ?framed ~line ~col f =
|
||||
let m = Array.init line (fun j-> Array.init col (fun i -> f ~line:j ~col:i)) in
|
||||
grid ?framed m
|
||||
|
||||
let vlist ?framed l =
|
||||
let a = Array.of_list l in
|
||||
grid ?framed (Array.map (fun line -> [| line |]) a)
|
||||
|
||||
let hlist ?framed l =
|
||||
grid ?framed [| Array.of_list l |]
|
||||
|
||||
let hlist_map ?framed f l = hlist ?framed (List.map f l)
|
||||
let vlist_map ?framed f l = vlist ?framed (List.map f l)
|
||||
let grid_map ?framed f m = grid ?framed (Array.map (Array.map f) m)
|
||||
|
||||
let grid_text ?framed m = grid_map ?framed text m
|
||||
|
||||
let transpose m =
|
||||
let dim = Box._dim_matrix m in
|
||||
Array.init dim.x
|
||||
(fun i -> Array.init dim.y (fun j -> m.(j).(i)))
|
||||
|
||||
let _write_vline ~out pos n =
|
||||
for j=0 to n-1 do
|
||||
Output.put_char out (_move_y pos j) '|'
|
||||
|
|
@ -269,8 +286,9 @@ let _write_hline ~out pos n =
|
|||
done
|
||||
|
||||
(* render given box on the output, starting with upper left corner
|
||||
at the given position. *)
|
||||
let rec _render ~out b pos =
|
||||
at the given position. [expected_size] is the size of the
|
||||
available surrounding space *)
|
||||
let rec _render ?expected_size ~out b pos =
|
||||
match Box.shape b with
|
||||
| Box.Line s -> Output.put_string out pos s
|
||||
| Box.Text l ->
|
||||
|
|
@ -296,22 +314,35 @@ let rec _render ~out b pos =
|
|||
(* write boxes *)
|
||||
for j = 0 to dim.y - 1 do
|
||||
for i = 0 to dim.x - 1 do
|
||||
let expected_size = {
|
||||
x=columns.(i+1)-columns.(i);
|
||||
y=lines.(j+1)-lines.(j);
|
||||
} in
|
||||
let pos' = _move pos (columns.(i)) (lines.(j)) in
|
||||
_render ~out m.(j).(i) pos'
|
||||
_render ~expected_size ~out m.(j).(i) pos'
|
||||
done;
|
||||
done;
|
||||
|
||||
let len_hlines, len_vlines = match expected_size with
|
||||
| None -> columns.(dim.x), lines.(dim.y)
|
||||
| Some {x;y} -> x,y
|
||||
in
|
||||
|
||||
(* write frame if needed *)
|
||||
begin match grid_shape with
|
||||
| Box.GridBase -> ()
|
||||
| Box.GridFramed ->
|
||||
let size = Box.size b in
|
||||
for j=1 to dim.y - 1 do
|
||||
_write_hline ~out {pos with y=lines.(j)} size.x
|
||||
_write_hline ~out (_move_y pos (lines.(j)-1)) len_hlines
|
||||
done;
|
||||
for i=1 to dim.x - 1 do
|
||||
_write_vline ~out {pos with x=columns.(i)} size.y
|
||||
_write_vline ~out (_move_x pos (columns.(i)-1)) len_vlines
|
||||
done;
|
||||
for j=1 to dim.y - 1 do
|
||||
for i=1 to dim.x - 1 do
|
||||
Output.put_char out (_move pos (columns.(i)-1) (lines.(j)-1)) '+'
|
||||
done
|
||||
done
|
||||
end
|
||||
|
||||
let render out b =
|
||||
|
|
|
|||
|
|
@ -24,7 +24,19 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*)
|
||||
|
||||
(** {1 Pretty-Printing of Boxes} *)
|
||||
(** {1 Pretty-Printing of nested Boxes}
|
||||
|
||||
Allows to print nested boxes, lists, arrays, tables in a nice way
|
||||
on any monospaced support.
|
||||
|
||||
{[
|
||||
let b = PrintBox.(
|
||||
|
||||
|
||||
|
||||
]}
|
||||
|
||||
*)
|
||||
|
||||
type position = { x:int ; y: int }
|
||||
(** Positions are relative to the upper-left corner, that is,
|
||||
|
|
@ -62,37 +74,56 @@ module Box : sig
|
|||
|
||||
val size : t -> position
|
||||
(** Size needed to print the box *)
|
||||
|
||||
val line : string -> t
|
||||
(** Make a single-line box.
|
||||
@raise Invalid_argument if the string contains ['\n'] *)
|
||||
|
||||
val text : string -> t
|
||||
(** Any text, possibly with several lines *)
|
||||
|
||||
val lines : string list -> t
|
||||
(** Shortcut for {!text}, with a list of lines *)
|
||||
|
||||
val frame : t -> t
|
||||
(** Put a single frame around the box *)
|
||||
|
||||
val grid : ?framed:bool -> t array array -> t
|
||||
(** Grid of boxes (no frame between boxes). The matrix is indexed
|
||||
with lines first, then columns.
|
||||
@param framed if [true], each item of the grid will be framed.
|
||||
default value is [true] *)
|
||||
|
||||
val init_grid : ?framed:bool ->
|
||||
line:int -> col:int -> (line:int -> col:int -> t) -> t
|
||||
(** Same as {!grid} but takes the matrix as a function *)
|
||||
|
||||
val vlist : ?framed:bool -> t list -> t
|
||||
(** Vertical list of boxes *)
|
||||
|
||||
val hlist : ?framed:bool -> t list -> t
|
||||
(** Horizontal list of boxes *)
|
||||
end
|
||||
|
||||
val line : string -> Box.t
|
||||
(** Make a single-line box.
|
||||
@raise Invalid_argument if the string contains ['\n'] *)
|
||||
|
||||
val text : string -> Box.t
|
||||
(** Any text, possibly with several lines *)
|
||||
|
||||
val lines : string list -> Box.t
|
||||
(** Shortcut for {!text}, with a list of lines *)
|
||||
|
||||
val int_ : int -> Box.t
|
||||
|
||||
val bool_ : bool -> Box.t
|
||||
|
||||
val float_ : float -> Box.t
|
||||
|
||||
val frame : Box.t -> Box.t
|
||||
(** Put a single frame around the box *)
|
||||
|
||||
val grid : ?framed:bool -> Box.t array array -> Box.t
|
||||
(** Grid of boxes (no frame between boxes). The matrix is indexed
|
||||
with lines first, then columns. The array must be a proper matrix,
|
||||
that is, all lines must have the same number of columns!
|
||||
@param framed if [true], each item of the grid will be framed.
|
||||
default value is [true] *)
|
||||
|
||||
val grid_text : ?framed:bool -> string array array -> Box.t
|
||||
(** Same as {!grid}, but wraps every cell into a {!text} box *)
|
||||
|
||||
val transpose : 'a array array -> 'a array array
|
||||
(** Transpose a matrix *)
|
||||
|
||||
val init_grid : ?framed:bool ->
|
||||
line:int -> col:int -> (line:int -> col:int -> Box.t) -> Box.t
|
||||
(** Same as {!grid} but takes the matrix as a function *)
|
||||
|
||||
val vlist : ?framed:bool -> Box.t list -> Box.t
|
||||
(** Vertical list of boxes *)
|
||||
|
||||
val hlist : ?framed:bool -> Box.t list -> Box.t
|
||||
(** Horizontal list of boxes *)
|
||||
|
||||
val grid_map : ?framed:bool -> ('a -> Box.t) -> 'a array array -> Box.t
|
||||
|
||||
val vlist_map : ?framed:bool -> ('a -> Box.t) -> 'a list -> Box.t
|
||||
|
||||
val hlist_map : ?framed:bool -> ('a -> Box.t) -> 'a list -> Box.t
|
||||
|
||||
val render : Output.t -> Box.t -> unit
|
||||
|
||||
val to_string : Box.t -> string
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue