{"id":16613122,"url":"https://github.com/c-cube/printbox","last_synced_at":"2026-02-28T18:33:14.696Z","repository":{"id":37617181,"uuid":"56173691","full_name":"c-cube/printbox","owner":"c-cube","description":"print nested boxes, lists, arrays, tables in several formats","archived":false,"fork":false,"pushed_at":"2025-05-14T17:08:06.000Z","size":2682,"stargazers_count":80,"open_issues_count":5,"forks_count":10,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-10-19T22:49:25.211Z","etag":null,"topics":["ocaml","pretty-printing","tables","text-rendering","tree"],"latest_commit_sha":null,"homepage":"https://c-cube.github.io/printbox/","language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/c-cube.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-04-13T17:48:07.000Z","updated_at":"2025-08-15T13:06:42.000Z","dependencies_parsed_at":"2022-08-19T03:50:34.160Z","dependency_job_id":"68bdcbe6-22bd-4f11-9f9d-43708c301088","html_url":"https://github.com/c-cube/printbox","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/c-cube/printbox","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-cube%2Fprintbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-cube%2Fprintbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-cube%2Fprintbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-cube%2Fprintbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/c-cube","download_url":"https://codeload.github.com/c-cube/printbox/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-cube%2Fprintbox/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29946798,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-28T18:21:26.597Z","status":"ssl_error","status_checked_at":"2026-02-28T18:19:38.892Z","response_time":90,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ocaml","pretty-printing","tables","text-rendering","tree"],"created_at":"2024-10-12T01:46:02.533Z","updated_at":"2026-02-28T18:33:14.679Z","avatar_url":"https://github.com/c-cube.png","language":"OCaml","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PrintBox [![build](https://github.com/c-cube/printbox/actions/workflows/main.yml/badge.svg)](https://github.com/c-cube/printbox/actions/workflows/main.yml)\n\nAllows to print nested boxes, lists, arrays, tables in several formats,\nincluding:\n\n- text (assuming monospace font)\n- HTML (using [tyxml](https://github.com/ocsigen/tyxml/) )\n- LaTeX (*not implemented yet*)\n\n\n## Documentation\n\nSee https://c-cube.github.io/printbox/\n\nSee the [test/](test/) and [examples/](examples/) directories for illustrations of potential usage.\n\n## License\n\nBSD-2-clauses\n\n## Build\n\nIdeally, use [opam](http://opam.ocaml.org/) with OCaml \u003e= 4.08:\n\n```sh non-deterministic=command\n$ opam install printbox printbox-text\n```\n\nManually:\n\n```sh non-deterministic=command\n$ make install\n```\n\n## A few examples\n\n#### importing the module\n\n```ocaml\n# #require \"printbox\";;\n# #require \"printbox-text\";;\n\n# module B = PrintBox;;\nmodule B = PrintBox\n```\n\n#### simple box\n\n```ocaml\n# let box = B.(hlist [ text \"hello\"; text \"world\"; ]);;\nval box : B.t = \u003cabstr\u003e\n\n# PrintBox_text.output stdout box;;\nhello│world\n- : unit = ()\n```\n\n#### less simple boxes\n\n```ocaml\n# let box =\n  B.(hlist\n  [ text \"I love\\nto\\npress\\nenter\";\n    grid_text [| [|\"a\"; \"bbb\"|];\n    [|\"c\"; \"hello world\"|] |]\n  ])\n  |\u003e B.frame;;\nval box : B.t = \u003cabstr\u003e\n\n# PrintBox_text.output stdout box;;\n┌──────┬─┬───────────┐\n│I love│a│bbb        │\n│to    ├─┼───────────┤\n│press │c│hello world│\n│enter │ │           │\n└──────┴─┴───────────┘\n- : unit = ()\n```\n\n#### printing a table\n\n```ocaml\n# let square n =\n  (* function to make a square *)\n  Array.init n\n    (fun i -\u003e Array.init n (fun j -\u003e B.sprintf \"(%d,%d)\" i j))\n  |\u003e B.grid ;;\nval square : int -\u003e B.t = \u003cfun\u003e\n\n# let sq = square 5;;\nval sq : B.t = \u003cabstr\u003e\n# PrintBox_text.output stdout sq;;\n(0,0)│(0,1)│(0,2)│(0,3)│(0,4)\n─────┼─────┼─────┼─────┼─────\n(1,0)│(1,1)│(1,2)│(1,3)│(1,4)\n─────┼─────┼─────┼─────┼─────\n(2,0)│(2,1)│(2,2)│(2,3)│(2,4)\n─────┼─────┼─────┼─────┼─────\n(3,0)│(3,1)│(3,2)│(3,3)│(3,4)\n─────┼─────┼─────┼─────┼─────\n(4,0)│(4,1)│(4,2)│(4,3)│(4,4)\n- : unit = ()\n```\n\n#### frame\n\nWhy not put a frame around this? That's easy.\n\n```ocaml\n# let sq2 = square 3 |\u003e B.frame ;;\nval sq2 : B.t = \u003cabstr\u003e\n\n# PrintBox_text.output stdout sq2;;\n┌─────┬─────┬─────┐\n│(0,0)│(0,1)│(0,2)│\n├─────┼─────┼─────┤\n│(1,0)│(1,1)│(1,2)│\n├─────┼─────┼─────┤\n│(2,0)│(2,1)│(2,2)│\n└─────┴─────┴─────┘\n- : unit = ()\n```\n\n#### tree\n\nWe can also create trees and display them using indentation:\n\n```ocaml\n# let tree =\n  B.tree (B.text \"root\")\n    [ B.tree (B.text \"a\") [B.text \"a1\\na1\"; B.text \"a2\\na2\\na2\"];\n      B.tree (B.text \"b\") [B.text \"b1\\nb1\"; B.text \"b2\"; B.text \"b3\"];\n    ];;\nval tree : B.t = \u003cabstr\u003e\n\n# PrintBox_text.output stdout tree;;\nroot\n├─a\n│ ├─a1\n│ │ a1\n│ └─a2\n│   a2\n│   a2\n└─b\n  ├─b1\n  │ b1\n  ├─b2\n  └─b3\n- : unit = ()\n```\n\n#### Installing the pretty-printer in the toplevel\n\n`PrintBox_text` contains a `Format`-compatible pretty-printer that\ncan be used as a default printer for boxes.\n\n```ocaml\n# #install_printer PrintBox_text.pp;;\n# PrintBox.(frame @@ frame @@ init_grid ~line:3 ~col:2 (fun ~line:i ~col:j -\u003e sprintf \"%d.%d\" i j));;\n- : B.t =\n┌─────────┐\n│┌───┬───┐│\n││0.0│0.1││\n│├───┼───┤│\n││1.0│1.1││\n│├───┼───┤│\n││2.0│2.1││\n│└───┴───┘│\n└─────────┘\n# #remove_printer PrintBox_text.pp;;\n```\n\nNote that this pretty-printer plays nicely with `Format` boxes:\n\n```ocaml\n# let b = PrintBox.(frame @@ hlist [text \"a\\nb\"; text \"c\"]);;\nval b : B.t = \u003cabstr\u003e\n# Format.printf \"some text %a around@.\" PrintBox_text.pp b;;\nsome text ┌─┬─┐\n          │a│c│\n          │b│ │\n          └─┴─┘ around\n- : unit = ()\n```\n\nAlso works with basic styling on text now:\n\n```ocaml\n# let b2 = PrintBox.(\n    let style = Style.(fg_color Red) in\n  frame @@ hlist [text_with_style style \"a\\nb\"; text \"c\"]);;\nval b2 : B.t = \u003cabstr\u003e\n# Format.printf \"some text %a around@.\" (PrintBox_text.pp_with ~style:true) b2;;\nsome text ┌─┬─┐\n          │a│c│\n          │b│ │\n          └─┴─┘ around\n- : unit = ()\n```\n\n```ocaml non-deterministic=command\n# let b3 = PrintBox.(\n    let style = Style.(fg_color Red) in\n    frame @@ grid_l [\n      [text_with_style style \"a\\nb\";\n       line_with_style Style.(set_bold true @@ bg_color Green) \"OH!\"];\n      [text \"c\"; text \"ballot\"];\n    ])\nval b3 : PrintBox.t = \u003cabstr\u003e\nutop [1]: print_endline @@ PrintBox_text.to_string b3;;\n```\n\ngives ![the following image](./.screen1.png).\n\n#### Handling unicode\n\nUnicode (utf8) text is handled.\n\n```ocaml\n# let b =\n  PrintBox.(frame @@\n    hlist [\n      vlist[text \"oï ωεird nums:\\nπ/2\\nτ/4\";\n        tree (text \"0\")[text \"1\"; tree (text \"ω\") [text \"ω²\"]]];\n      frame @@ vlist [text \"sum=Σ_i a·xᵢ²\\n—————\\n1+1\"; text \"Ōₒ\\nÀ\"]]);;\nval b : B.t = \u003cabstr\u003e\n\n# print_endline @@ PrintBox_text.to_string b;;\n┌──────────────┬───────────────┐\n│oï ωεird nums:│┌─────────────┐│\n│π/2           ││sum=Σ_i a·xᵢ²││\n│τ/4           ││—————        ││\n├──────────────┤│1+1          ││\n│0             │├─────────────┤│\n│├─1           ││Ōₒ           ││\n│└─ω           ││À            ││\n│  └─ω²        │└─────────────┘│\n└──────────────┴───────────────┘\n- : unit = ()\n```\n\n#### HTML output (with `tyxml`)\n\nAssuming you have loaded `printbox-html` somehow:\n\n```ocaml non-deterministic=command\nlet out = open_out \"/tmp/foo.html\";;\noutput_string out (PrintBox_html.to_string_doc (square 5));;\n```\n\nwhich prints some HTML in the file [foo.html](docs/foo.html).\nNote that trees are printed in HTML using nested lists, and\nthat `PrintBox_html.to_string_doc` will insert some javascript to\nmake sub-lists fold/unfold on click (this is useful to display very large\ntrees compactly and exploring them incrementally). But there is also\nan alternative solution where trees are printed in HTML using the\n`\u003cdetails\u003e` element. To activate it, use the `tree_summary` config:\n\n```ocaml\n# #require \"printbox-html\";;\n# print_endline PrintBox_html.(to_string\n  ~config:Config.(tree_summary true default)\n    B.(tree (text \"0\")[text \"1\"; tree (text \"ω\") [text \"ω²\"]]));;\n\u003cdiv\u003e\u003cdetails\u003e\u003csummary\u003e\u003cspan\u003e0\u003c/span\u003e\u003c/summary\u003e\u003cul\u003e\u003cli\u003e\u003cdiv\u003e1\u003c/div\u003e\u003c/li\u003e\u003cli\u003e\u003cdetails\u003e\u003csummary\u003e\u003cspan\u003eω\u003c/span\u003e\u003c/summary\u003e\u003cul\u003e\u003cli\u003e\u003cdiv\u003eω²\u003c/div\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/details\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/details\u003e\u003c/div\u003e\n\n- : unit = ()\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fc-cube%2Fprintbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fc-cube%2Fprintbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fc-cube%2Fprintbox/lists"}