My agentic slop goes here. Not intended for anyone else!
at jsont 4.3 kB view raw
1(** OCaml implementation of the Kitty text sizing protocol *) 2 3(* Types *) 4 5type vertical = [ `Bottom | `Center | `Top ] 6type horizontal = [ `Left | `Center | `Right ] 7 8type t = { 9 scale : int option; 10 width : int option; 11 numerator : int option; 12 denominator : int option; 13 vertical : vertical option; 14 horizontal : horizontal option; 15} 16 17(* Validation helpers *) 18 19let validate_scale n = 20 if n < 1 || n > 7 then 21 invalid_arg (Printf.sprintf "scale must be in range 1-7, got %d" n) 22 23let validate_width n = 24 if n < 0 || n > 7 then 25 invalid_arg (Printf.sprintf "width must be in range 0-7, got %d" n) 26 27let validate_numerator n = 28 if n < 0 || n > 15 then 29 invalid_arg (Printf.sprintf "numerator must be in range 0-15, got %d" n) 30 31let validate_denominator n = 32 if n < 0 || n > 15 then 33 invalid_arg (Printf.sprintf "denominator must be in range 0-15, got %d" n) 34 35(* Constructor *) 36 37let v ?scale ?width ?fraction ?vertical ?horizontal () = 38 Option.iter validate_scale scale; 39 Option.iter validate_width width; 40 let numerator, denominator = match fraction with 41 | None -> None, None 42 | Some (num, den) -> 43 validate_numerator num; 44 validate_denominator den; 45 Some num, Some den 46 in 47 { 48 scale; 49 width; 50 numerator; 51 denominator; 52 vertical; 53 horizontal; 54 } 55 56let empty = v () 57 58(* Conversion helpers *) 59 60let vertical_to_int = function 61 | `Bottom -> 0 62 | `Center -> 1 63 | `Top -> 2 64 65let horizontal_to_int = function 66 | `Left -> 0 67 | `Center -> 1 68 | `Right -> 2 69 70(* Escape sequence generation *) 71 72let metadata_to_string t = 73 let parts = [] in 74 let parts = match t.scale with 75 | Some s -> (Printf.sprintf "s=%d" s) :: parts 76 | None -> parts 77 in 78 let parts = match t.width with 79 | Some w -> (Printf.sprintf "w=%d" w) :: parts 80 | None -> parts 81 in 82 let parts = match t.numerator with 83 | Some n -> (Printf.sprintf "n=%d" n) :: parts 84 | None -> parts 85 in 86 let parts = match t.denominator with 87 | Some d -> (Printf.sprintf "d=%d" d) :: parts 88 | None -> parts 89 in 90 let parts = match t.vertical with 91 | Some v -> (Printf.sprintf "v=%d" (vertical_to_int v)) :: parts 92 | None -> parts 93 in 94 let parts = match t.horizontal with 95 | Some h -> (Printf.sprintf "h=%d" (horizontal_to_int h)) :: parts 96 | None -> parts 97 in 98 String.concat ":" (List.rev parts) 99 100let render t text = 101 (* Validate text length (max 4096 bytes of UTF-8) *) 102 let text_len = String.length text in 103 if text_len > 4096 then 104 invalid_arg (Printf.sprintf "text exceeds 4096 bytes (got %d)" text_len); 105 106 let metadata_str = metadata_to_string t in 107 108 (* OSC 66 ; metadata ; text BEL *) 109 (* Using \x1b for ESC and \x07 for BEL *) 110 if metadata_str = "" then 111 Printf.sprintf "\x1b]66;;%s\x07" text 112 else 113 Printf.sprintf "\x1b]66;%s;%s\x07" metadata_str text 114 115let render_to_channel oc t text = 116 output_string oc (render t text); 117 flush oc 118 119(* Fmt-style combinators *) 120 121let pp t ppf text = 122 Format.pp_print_string ppf (render t text) 123 124let styled t pp_inner ppf value = 125 (* We need to capture the inner formatter's output as a string first *) 126 let inner_str = Format.asprintf "%a" pp_inner value in 127 Format.pp_print_string ppf (render t inner_str) 128 129(* Convenience Fmt formatters *) 130 131let pp_double = pp (v ~scale:2 ()) 132let pp_triple = pp (v ~scale:3 ()) 133let pp_quadruple = pp (v ~scale:4 ()) 134let pp_half = pp (v ~fraction:(1, 2) ()) 135 136let pp_superscript = pp (v ~fraction:(1, 2) ~vertical:`Top ()) 137let pp_subscript = pp (v ~fraction:(1, 2) ~vertical:`Bottom ()) 138 139let pp_scaled n = pp (v ~scale:n ()) 140 141let styled_double pp_inner = styled (v ~scale:2 ()) pp_inner 142let styled_triple pp_inner = styled (v ~scale:3 ()) pp_inner 143 144let styled_superscript pp_inner = styled (v ~fraction:(1, 2) ~vertical:`Top ()) pp_inner 145let styled_subscript pp_inner = styled (v ~fraction:(1, 2) ~vertical:`Bottom ()) pp_inner 146 147(* Convenience functions *) 148 149let double text = render (v ~scale:2 ()) text 150let triple text = render (v ~scale:3 ()) text 151let quadruple text = render (v ~scale:4 ()) text 152let half text = render (v ~fraction:(1, 2) ()) text 153let superscript text = render (v ~fraction:(1, 2) ~vertical:`Top ()) text 154let subscript text = render (v ~fraction:(1, 2) ~vertical:`Bottom ()) text 155let scaled n text = render (v ~scale:n ()) text