mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2026-01-29 04:14:51 -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)
|
else _find s c (i+1)
|
||||||
|
|
||||||
let rec _lines s i k = match _find s '\n' i with
|
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 ->
|
| Some j ->
|
||||||
let s' = String.sub s i (j-i) in
|
let s' = String.sub s i (j-i) in
|
||||||
k s';
|
k s';
|
||||||
|
|
@ -227,37 +228,53 @@ module Box = struct
|
||||||
|
|
||||||
let _make shape =
|
let _make shape =
|
||||||
{ shape; size=(lazy (_size 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
|
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 =
|
let _write_vline ~out pos n =
|
||||||
for j=0 to n-1 do
|
for j=0 to n-1 do
|
||||||
Output.put_char out (_move_y pos j) '|'
|
Output.put_char out (_move_y pos j) '|'
|
||||||
|
|
@ -269,8 +286,9 @@ let _write_hline ~out pos n =
|
||||||
done
|
done
|
||||||
|
|
||||||
(* render given box on the output, starting with upper left corner
|
(* render given box on the output, starting with upper left corner
|
||||||
at the given position. *)
|
at the given position. [expected_size] is the size of the
|
||||||
let rec _render ~out b pos =
|
available surrounding space *)
|
||||||
|
let rec _render ?expected_size ~out b pos =
|
||||||
match Box.shape b with
|
match Box.shape b with
|
||||||
| Box.Line s -> Output.put_string out pos s
|
| Box.Line s -> Output.put_string out pos s
|
||||||
| Box.Text l ->
|
| Box.Text l ->
|
||||||
|
|
@ -296,22 +314,35 @@ let rec _render ~out b pos =
|
||||||
(* write boxes *)
|
(* write boxes *)
|
||||||
for j = 0 to dim.y - 1 do
|
for j = 0 to dim.y - 1 do
|
||||||
for i = 0 to dim.x - 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
|
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;
|
||||||
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 *)
|
(* write frame if needed *)
|
||||||
begin match grid_shape with
|
begin match grid_shape with
|
||||||
| Box.GridBase -> ()
|
| Box.GridBase -> ()
|
||||||
| Box.GridFramed ->
|
| Box.GridFramed ->
|
||||||
let size = Box.size b in
|
|
||||||
for j=1 to dim.y - 1 do
|
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;
|
done;
|
||||||
for i=1 to dim.x - 1 do
|
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;
|
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
|
end
|
||||||
|
|
||||||
let render out b =
|
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.
|
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 }
|
type position = { x:int ; y: int }
|
||||||
(** Positions are relative to the upper-left corner, that is,
|
(** Positions are relative to the upper-left corner, that is,
|
||||||
|
|
@ -62,37 +74,56 @@ module Box : sig
|
||||||
|
|
||||||
val size : t -> position
|
val size : t -> position
|
||||||
(** Size needed to print the box *)
|
(** 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
|
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 render : Output.t -> Box.t -> unit
|
||||||
|
|
||||||
val to_string : Box.t -> string
|
val to_string : Box.t -> string
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue