Allows to print nested boxes, lists, arrays, tables in several formats, including:
- text (assuming monospace font)
- HTML (using tyxml )
- LaTeX (not implemented yet)
See https://c-cube.github.io/printbox/
See the test/ and examples/ directories for illustrations of potential usage.
BSD-2-clauses
Ideally, use opam with OCaml >= 4.08:
$ opam install printbox printbox-text
Manually:
$ make install
# #require "printbox";;
# #require "printbox-text";;
# module B = PrintBox;;
module B = PrintBox
# let box = B.(hlist [ text "hello"; text "world"; ]);;
val box : B.t = <abstr>
# PrintBox_text.output stdout box;;
helloβworld
- : unit = ()
# let box =
B.(hlist
[ text "I love\nto\npress\nenter";
grid_text [| [|"a"; "bbb"|];
[|"c"; "hello world"|] |]
])
|> B.frame;;
val box : B.t = <abstr>
# PrintBox_text.output stdout box;;
ββββββββ¬ββ¬ββββββββββββ
βI loveβaβbbb β
βto βββΌββββββββββββ€
βpress βcβhello worldβ
βenter β β β
ββββββββ΄ββ΄ββββββββββββ
- : unit = ()
# let square n =
(* function to make a square *)
Array.init n
(fun i -> Array.init n (fun j -> B.sprintf "(%d,%d)" i j))
|> B.grid ;;
val square : int -> B.t = <fun>
# let sq = square 5;;
val sq : B.t = <abstr>
# PrintBox_text.output stdout sq;;
(0,0)β(0,1)β(0,2)β(0,3)β(0,4)
ββββββΌββββββΌββββββΌββββββΌβββββ
(1,0)β(1,1)β(1,2)β(1,3)β(1,4)
ββββββΌββββββΌββββββΌββββββΌβββββ
(2,0)β(2,1)β(2,2)β(2,3)β(2,4)
ββββββΌββββββΌββββββΌββββββΌβββββ
(3,0)β(3,1)β(3,2)β(3,3)β(3,4)
ββββββΌββββββΌββββββΌββββββΌβββββ
(4,0)β(4,1)β(4,2)β(4,3)β(4,4)
- : unit = ()
Why not put a frame around this? That's easy.
# let sq2 = square 3 |> B.frame ;;
val sq2 : B.t = <abstr>
# PrintBox_text.output stdout sq2;;
βββββββ¬ββββββ¬ββββββ
β(0,0)β(0,1)β(0,2)β
βββββββΌββββββΌββββββ€
β(1,0)β(1,1)β(1,2)β
βββββββΌββββββΌββββββ€
β(2,0)β(2,1)β(2,2)β
βββββββ΄ββββββ΄ββββββ
- : unit = ()
We can also create trees and display them using indentation:
# let tree =
B.tree (B.text "root")
[ B.tree (B.text "a") [B.text "a1\na1"; B.text "a2\na2\na2"];
B.tree (B.text "b") [B.text "b1\nb1"; B.text "b2"; B.text "b3"];
];;
val tree : B.t = <abstr>
# PrintBox_text.output stdout tree;;
root
ββa
β ββa1
β β a1
β ββa2
β a2
β a2
ββb
ββb1
β b1
ββb2
ββb3
- : unit = ()
PrintBox_text
contains a Format
-compatible pretty-printer that
can be used as a default printer for boxes.
# #install_printer PrintBox_text.pp;;
# PrintBox.(frame @@ frame @@ init_grid ~line:3 ~col:2 (fun ~line:i ~col:j -> sprintf "%d.%d" i j));;
- : B.t =
βββββββββββ
ββββββ¬βββββ
ββ0.0β0.1ββ
ββββββΌββββ€β
ββ1.0β1.1ββ
ββββββΌββββ€β
ββ2.0β2.1ββ
ββββββ΄βββββ
βββββββββββ
# #remove_printer PrintBox_text.pp;;
Note that this pretty-printer plays nicely with Format
boxes:
# let b = PrintBox.(frame @@ hlist [text "a\nb"; text "c"]);;
val b : B.t = <abstr>
# Format.printf "some text %a around@." PrintBox_text.pp b;;
some text βββ¬ββ
βaβcβ
βbβ β
βββ΄ββ around
- : unit = ()
Also works with basic styling on text now:
# let b2 = PrintBox.(
let style = Style.(fg_color Red) in
frame @@ hlist [text_with_style style "a\nb"; text "c"]);;
val b2 : B.t = <abstr>
# Format.printf "some text %a around@." (PrintBox_text.pp_with ~style:true) b2;;
some text βββ¬ββ
βaβcβ
βbβ β
βββ΄ββ around
- : unit = ()
# let b3 = PrintBox.(
let style = Style.(fg_color Red) in
frame @@ grid_l [
[text_with_style style "a\nb";
line_with_style Style.(set_bold true @@ bg_color Green) "OH!"];
[text "c"; text "ballot"];
])
val b3 : PrintBox.t = <abstr>
utop [1]: print_endline @@ PrintBox_text.to_string b3;;
Unicode (utf8) text is handled.
# let b =
PrintBox.(frame @@
hlist [
vlist[text "oΓ― ΟΞ΅ird nums:\nΟ/2\nΟ/4";
tree (text "0")[text "1"; tree (text "Ο") [text "ΟΒ²"]]];
frame @@ vlist [text "sum=Ξ£_i aΒ·xα΅’Β²\nβββββ\n1+1"; text "Εβ\nΓ"]]);;
val b : B.t = <abstr>
# print_endline @@ PrintBox_text.to_string b;;
ββββββββββββββββ¬ββββββββββββββββ
βoΓ― ΟΞ΅ird nums:βββββββββββββββββ
βΟ/2 ββsum=Ξ£_i aΒ·xα΅’Β²ββ
βΟ/4 βββββββ ββ
ββββββββββββββββ€β1+1 ββ
β0 ββββββββββββββββ€β
βββ1 ββΕβ ββ
βββΟ ββΓ ββ
β ββΟΒ² βββββββββββββββββ
ββββββββββββββββ΄ββββββββββββββββ
- : unit = ()
Assuming you have loaded printbox-html
somehow:
let out = open_out "/tmp/foo.html";;
output_string out (PrintBox_html.to_string_doc (square 5));;
which prints some HTML in the file foo.html.
Note that trees are printed in HTML using nested lists, and
that PrintBox_html.to_string_doc
will insert some javascript to
make sub-lists fold/unfold on click (this is useful to display very large
trees compactly and exploring them incrementally). But there is also
an alternative solution where trees are printed in HTML using the
<details>
element. To activate it, use the tree_summary
config:
# #require "printbox-html";;
# print_endline PrintBox_html.(to_string
~config:Config.(tree_summary true default)
B.(tree (text "0")[text "1"; tree (text "Ο") [text "ΟΒ²"]]));;
<div><details><summary><span>0</span></summary><ul><li><div>1</div></li><li><details><summary><span>Ο</span></summary><ul><li><div>ΟΒ²</div></li></ul></details></li></ul></details></div>
- : unit = ()