Terminal styling and layout widgets for OCaml (tables, trees, panels, colors)
at main 79 lines 2.7 kB view raw
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2025 Thomas Gazagnaire. All rights reserved. 3 SPDX-License-Identifier: MIT 4 ---------------------------------------------------------------------------*) 5 6open Crowbar 7open Tty 8 9(* Width is always non-negative *) 10let test_width_non_negative s = 11 let w = Width.string_width s in 12 check (w >= 0) 13 14(* Span width matches underlying width *) 15let test_span_width_consistency s = 16 let span = Span.text s in 17 let span_w = Span.width span in 18 let direct_w = Width.string_width s in 19 check (span_w = direct_w) 20 21(* Span concatenation width is sum of widths *) 22let test_span_concat_width s1 s2 = 23 let span1 = Span.text s1 in 24 let span2 = Span.text s2 in 25 let combined = Span.(span1 ++ span2) in 26 let w1 = Span.width span1 in 27 let w2 = Span.width span2 in 28 let w_combined = Span.width combined in 29 check (w_combined = w1 + w2) 30 31(* Table rendering doesn't crash *) 32let test_table_render_no_crash headers row = 33 if List.length headers > 0 && List.length row > 0 then 34 let cols = List.map Table.column headers in 35 let rows = [ List.map Span.text row ] in 36 let table = Table.of_rows cols rows in 37 let _ = Table.to_string table in 38 check true 39 else check true 40 41(* Tree rendering doesn't crash *) 42let test_tree_render_no_crash label = 43 let tree = Tree.of_tree (Tree.Node (Span.text label, [])) in 44 let _ = Tree.to_string tree in 45 check true 46 47(* Panel rendering doesn't crash *) 48let test_panel_render_no_crash content = 49 let panel = Panel.v (Span.text content) in 50 let _ = Panel.to_string panel in 51 check true 52 53(* Color hex parsing and equality *) 54let test_color_rgb_roundtrip r g b = 55 let c = Color.rgb r g b in 56 let c2 = Color.rgb r g b in 57 check (Color.equal c c2) 58 59(* Truncate never increases width *) 60let test_truncate_width s width = 61 let width = abs width mod 1000 in 62 let truncated = Width.truncate width s in 63 let truncated_w = Width.string_width truncated in 64 check (truncated_w <= width) 65 66let suite = 67 ( "tty", 68 [ 69 test_case "width non-negative" [ bytes ] test_width_non_negative; 70 test_case "span width consistency" [ bytes ] test_span_width_consistency; 71 test_case "span concat width" [ bytes; bytes ] test_span_concat_width; 72 test_case "table render" 73 [ list bytes; list bytes ] 74 test_table_render_no_crash; 75 test_case "tree render" [ bytes ] test_tree_render_no_crash; 76 test_case "panel render" [ bytes ] test_panel_render_no_crash; 77 test_case "color rgb roundtrip" [ int; int; int ] test_color_rgb_roundtrip; 78 test_case "truncate width" [ bytes; int ] test_truncate_width; 79 ] )