terminal user interface to jujutsu. Focused on speed and clarity
1open Jj_tui
2open Notty
3open Notty.I
4
5let test_node : Render_jj_graph.node =
6 {
7 parents = [];
8 creation_time = Int64.zero;
9 working_copy = true;
10 immutable = false;
11 wip = false;
12 change_id = "ztooztwk";
13 commit_id = "235795c5";
14 description = "(no description set)";
15 bookmarks = [];
16 author_email = "eli.jambu@gmail.com";
17 author_timestamp = "2026-01-15 14:05:59";
18 empty = true;
19 hidden = false;
20 divergent = false;
21 is_preview = false;
22 }
23
24let render_commit (node : Render_jj_graph.node) : image =
25 let open Notty.A in
26 let styled_text attr text = string attr text in
27 let change_id_short =
28 String.sub node.change_id 0 (min 8 (String.length node.change_id))
29 in
30 let commit_id_short =
31 String.sub node.commit_id 0 (min 8 (String.length node.commit_id))
32 in
33 let description_line =
34 match String.split_on_char '\n' node.description with
35 | first :: _ when String.trim first <> "" -> String.trim first
36 | _ -> "(no description set)"
37 in
38
39 let line1 =
40 hcat
41 [
42 styled_text (fg lightcyan ++ st bold) change_id_short;
43 styled_text (fg white ++ st dim) (" " ^ node.author_email);
44 styled_text (fg white ++ st dim) (" " ^ node.author_timestamp);
45 styled_text (fg cyan ++ st dim) (" " ^ commit_id_short);
46 ]
47 in
48
49 let description_with_prefix =
50 if node.empty then "(empty) " ^ description_line else description_line
51 in
52 let line2 = styled_text (fg white ++ st dim) description_with_prefix in
53 vcat [ line1; line2 ]
54
55let () =
56 let content = render_commit test_node in
57 let graph = string A.empty "@ " in
58
59 Printf.printf "Content height: %d\n" (height content);
60 Printf.printf "Content width: %d\n" (width content);
61 Printf.printf "\nExpected output:\n";
62 Printf.printf "@ ztooztwk eli.jambu@gmail.com 2026-01-15 14:05:59 235795c5\n";
63 Printf.printf "│ (empty) (no description set)\n";
64 Printf.printf "\nActual rendering test:\n";
65
66 let node_glyphs = [ "○"; "@"; "◌"; "◆" ] in
67 let graph_continuation =
68 let chars = "@ " in
69 let replaced = ref chars in
70 List.iter
71 (fun glyph ->
72 replaced := Str.global_replace (Str.regexp_string glyph) "│" !replaced)
73 node_glyphs;
74 string A.empty !replaced
75 in
76
77 let lines =
78 List.init (height content) (fun i ->
79 let line_img = vcrop i 1 content in
80 if i = 0 then hcat [ graph; line_img ]
81 else hcat [ graph_continuation; line_img ])
82 in
83 let result = vcat lines in
84
85 Printf.printf "Result height: %d\n" (height result);
86 Printf.printf "Result width: %d\n" (width result);
87
88 ()