Kitty Graphics Protocol in OCaml
terminal graphics ocaml
1(* Kitty Graphics Protocol Unicode Placeholders - Implementation *) 2 3let placeholder_char = Uchar.of_int 0x10EEEE 4 5let diacritics = 6 [| 7 0x0305; 0x030D; 0x030E; 0x0310; 0x0312; 0x033D; 0x033E; 0x033F; 8 0x0346; 0x034A; 0x034B; 0x034C; 0x0350; 0x0351; 0x0352; 0x0357; 9 0x035B; 0x0363; 0x0364; 0x0365; 0x0366; 0x0367; 0x0368; 0x0369; 10 0x036A; 0x036B; 0x036C; 0x036D; 0x036E; 0x036F; 0x0483; 0x0484; 11 0x0485; 0x0486; 0x0487; 0x0592; 0x0593; 0x0594; 0x0595; 0x0597; 12 0x0598; 0x0599; 0x059C; 0x059D; 0x059E; 0x059F; 0x05A0; 0x05A1; 13 0x05A8; 0x05A9; 0x05AB; 0x05AC; 0x05AF; 0x05C4; 0x0610; 0x0611; 14 0x0612; 0x0613; 0x0614; 0x0615; 0x0616; 0x0617; 0x0657; 0x0658; 15 0x0659; 0x065A; 0x065B; 0x065D; 0x065E; 0x06D6; 0x06D7; 0x06D8; 16 0x06D9; 0x06DA; 0x06DB; 0x06DC; 0x06DF; 0x06E0; 0x06E1; 0x06E2; 17 0x06E4; 0x06E7; 0x06E8; 0x06EB; 0x06EC; 0x0730; 0x0732; 0x0733; 18 0x0735; 0x0736; 0x073A; 0x073D; 0x073F; 0x0740; 0x0741; 0x0743; 19 0x0745; 0x0747; 0x0749; 0x074A; 0x07EB; 0x07EC; 0x07ED; 0x07EE; 20 0x07EF; 0x07F0; 0x07F1; 0x07F3; 0x0816; 0x0817; 0x0818; 0x0819; 21 0x081B; 0x081C; 0x081D; 0x081E; 0x081F; 0x0820; 0x0821; 0x0822; 22 0x0823; 0x0825; 0x0826; 0x0827; 0x0829; 0x082A; 0x082B; 0x082C; 23 0x082D; 0x0951; 0x0953; 0x0954; 0x0F82; 0x0F83; 0x0F86; 0x0F87; 24 0x135D; 0x135E; 0x135F; 0x17DD; 0x193A; 0x1A17; 0x1A75; 0x1A76; 25 0x1A77; 0x1A78; 0x1A79; 0x1A7A; 0x1A7B; 0x1A7C; 0x1B6B; 0x1B6D; 26 0x1B6E; 0x1B6F; 0x1B70; 0x1B71; 0x1B72; 0x1B73; 0x1CD0; 0x1CD1; 27 0x1CD2; 0x1CDA; 0x1CDB; 0x1CE0; 0x1DC0; 0x1DC1; 0x1DC3; 0x1DC4; 28 0x1DC5; 0x1DC6; 0x1DC7; 0x1DC8; 0x1DC9; 0x1DCB; 0x1DCC; 0x1DD1; 29 0x1DD2; 0x1DD3; 0x1DD4; 0x1DD5; 0x1DD6; 0x1DD7; 0x1DD8; 0x1DD9; 30 0x1DDA; 0x1DDB; 0x1DDC; 0x1DDD; 0x1DDE; 0x1DDF; 0x1DE0; 0x1DE1; 31 0x1DE2; 0x1DE3; 0x1DE4; 0x1DE5; 0x1DE6; 0x1DFE; 0x20D0; 0x20D1; 32 0x20D4; 0x20D5; 0x20D6; 0x20D7; 0x20DB; 0x20DC; 0x20E1; 0x20E7; 33 0x20E9; 0x20F0; 0xA66F; 0xA67C; 0xA67D; 0xA6F0; 0xA6F1; 0xA8E0; 34 0xA8E1; 0xA8E2; 0xA8E3; 0xA8E4; 0xA8E5; 0xA8E6; 0xA8E7; 0xA8E8; 35 0xA8E9; 0xA8EA; 0xA8EB; 0xA8EC; 0xA8ED; 0xA8EE; 0xA8EF; 0xA8F0; 36 0xA8F1; 0xAAB0; 0xAAB2; 0xAAB3; 0xAAB7; 0xAAB8; 0xAABE; 0xAABF; 37 0xAAC1; 0xFE20; 0xFE21; 0xFE22; 0xFE23; 0xFE24; 0xFE25; 0xFE26; 38 0x10A0F; 0x10A38; 0x1D185; 0x1D186; 0x1D187; 0x1D188; 0x1D189; 39 0x1D1AA; 0x1D1AB; 0x1D1AC; 0x1D1AD; 0x1D242; 0x1D243; 0x1D244; 40 |] 41 42let diacritic n = Uchar.of_int diacritics.(n mod Array.length diacritics) 43let row_diacritic = diacritic 44let column_diacritic = diacritic 45let id_high_byte_diacritic = diacritic 46 47let add_uchar buf u = 48 let code = Uchar.to_int u in 49 let put = Buffer.add_char buf in 50 if code < 0x80 then put (Char.chr code) 51 else if code < 0x800 then ( 52 put (Char.chr (0xC0 lor (code lsr 6))); 53 put (Char.chr (0x80 lor (code land 0x3F)))) 54 else if code < 0x10000 then ( 55 put (Char.chr (0xE0 lor (code lsr 12))); 56 put (Char.chr (0x80 lor ((code lsr 6) land 0x3F))); 57 put (Char.chr (0x80 lor (code land 0x3F)))) 58 else ( 59 put (Char.chr (0xF0 lor (code lsr 18))); 60 put (Char.chr (0x80 lor ((code lsr 12) land 0x3F))); 61 put (Char.chr (0x80 lor ((code lsr 6) land 0x3F))); 62 put (Char.chr (0x80 lor (code land 0x3F)))) 63 64let write buf ~image_id ?placement_id ~rows ~cols () = 65 (* Set foreground color *) 66 Printf.bprintf buf "\027[38;2;%d;%d;%dm" 67 ((image_id lsr 16) land 0xFF) 68 ((image_id lsr 8) land 0xFF) 69 (image_id land 0xFF); 70 (* Optional placement ID in underline color *) 71 placement_id 72 |> Option.iter (fun pid -> 73 Printf.bprintf buf "\027[58;2;%d;%d;%dm" 74 ((pid lsr 16) land 0xFF) 75 ((pid lsr 8) land 0xFF) 76 (pid land 0xFF)); 77 (* High byte diacritic *) 78 let high_byte = (image_id lsr 24) land 0xFF in 79 let high_diac = 80 if high_byte > 0 then Some (id_high_byte_diacritic high_byte) else None 81 in 82 (* Write grid *) 83 for row = 0 to rows - 1 do 84 for col = 0 to cols - 1 do 85 add_uchar buf placeholder_char; 86 add_uchar buf (row_diacritic row); 87 add_uchar buf (column_diacritic col); 88 high_diac |> Option.iter (add_uchar buf) 89 done; 90 if row < rows - 1 then Buffer.add_string buf "\n\r" 91 done; 92 (* Reset colors *) 93 Buffer.add_string buf "\027[39m"; 94 if Option.is_some placement_id then Buffer.add_string buf "\027[59m"