Kitty Graphics Protocol in OCaml
terminal graphics ocaml

restructure

+285 -342
+9 -18
lib/kgp.ml
··· 1 (* Kitty Terminal Graphics Protocol - Main Module *) 2 3 - (* Re-export polymorphic variant types *) 4 - type format = Kgp_types.format 5 - type transmission = Kgp_types.transmission 6 - type compression = Kgp_types.compression 7 - type quiet = Kgp_types.quiet 8 - type cursor = Kgp_types.cursor 9 - type composition = Kgp_types.composition 10 - type delete = Kgp_types.delete 11 - type animation_state = Kgp_types.animation_state 12 - 13 - (* Type conversion modules *) 14 - module Format = Kgp_types.Format 15 - module Transmission = Kgp_types.Transmission 16 - module Compression = Kgp_types.Compression 17 - module Quiet = Kgp_types.Quiet 18 - module Cursor = Kgp_types.Cursor 19 - module Composition = Kgp_types.Composition 20 - module Delete = Kgp_types.Delete 21 22 (* Configuration modules *) 23 module Placement = Kgp_placement
··· 1 (* Kitty Terminal Graphics Protocol - Main Module *) 2 3 + (* Type modules *) 4 + module Format = Kgp_format 5 + module Transmission = Kgp_transmission 6 + module Compression = Kgp_compression 7 + module Quiet = Kgp_quiet 8 + module Cursor = Kgp_cursor 9 + module Composition = Kgp_composition 10 + module Delete = Kgp_delete 11 + module Animation_state = Kgp_animation_state 12 13 (* Configuration modules *) 14 module Placement = Kgp_placement
+8 -41
lib/kgp.mli
··· 25 See {{:https://sw.kovidgoyal.net/kitty/graphics-protocol/} Kitty Graphics Protocol} 26 for the full specification. *) 27 28 - (** {1 Polymorphic Variant Types} *) 29 - 30 - type format = Kgp_types.format 31 - (** Image data formats. [`Rgba32] is 32-bit RGBA (4 bytes per pixel), 32 - [`Rgb24] is 24-bit RGB (3 bytes per pixel), [`Png] is PNG encoded data. *) 33 - 34 - type transmission = Kgp_types.transmission 35 - (** Transmission methods. [`Direct] sends data inline, [`File] reads from a path, 36 - [`Tempfile] reads from a temp file that the terminal deletes after reading. *) 37 - 38 - type compression = Kgp_types.compression 39 - (** Compression options. [`None] for raw data, [`Zlib] for RFC 1950 compression. *) 40 - 41 - type quiet = Kgp_types.quiet 42 - (** Response suppression. [`Noisy] sends all responses (default), 43 - [`Errors_only] suppresses OK responses, [`Silent] suppresses all. *) 44 - 45 - type cursor = Kgp_types.cursor 46 - (** Cursor movement after displaying. [`Move] advances cursor (default), 47 - [`Static] keeps cursor in place. *) 48 - 49 - type composition = Kgp_types.composition 50 - (** Composition modes. [`Alpha_blend] for full blending (default), 51 - [`Overwrite] for simple pixel replacement. *) 52 - 53 - type delete = Kgp_types.delete 54 - (** Delete target specification. Each variant has two forms: one that only 55 - removes placements (e.g., [`All_visible]) and one that also frees the 56 - image data (e.g., [`All_visible_and_free]). *) 57 - 58 - type animation_state = Kgp_types.animation_state 59 - (** Animation playback state. [`Stop] halts animation, [`Loading] runs but 60 - waits for new frames at end, [`Run] runs normally and loops. *) 61 - 62 (** {1 Type Modules} *) 63 64 - module Format = Kgp_types.Format 65 - module Transmission = Kgp_types.Transmission 66 - module Compression = Kgp_types.Compression 67 - module Quiet = Kgp_types.Quiet 68 - module Cursor = Kgp_types.Cursor 69 - module Composition = Kgp_types.Composition 70 - module Delete = Kgp_types.Delete 71 72 (** {1 Configuration Modules} *) 73
··· 25 See {{:https://sw.kovidgoyal.net/kitty/graphics-protocol/} Kitty Graphics Protocol} 26 for the full specification. *) 27 28 (** {1 Type Modules} *) 29 30 + module Format = Kgp_format 31 + module Transmission = Kgp_transmission 32 + module Compression = Kgp_compression 33 + module Quiet = Kgp_quiet 34 + module Cursor = Kgp_cursor 35 + module Composition = Kgp_composition 36 + module Delete = Kgp_delete 37 + module Animation_state = Kgp_animation_state 38 39 (** {1 Configuration Modules} *) 40
+1 -5
lib/kgp_animation.ml
··· 1 - (* Kitty Graphics Protocol Animation - Implementation *) 2 - 3 - type state = Kgp_types.animation_state 4 - 5 type t = 6 - [ `Set_state of state * int option 7 | `Set_gap of int * int 8 | `Set_current of int ] 9
··· 1 type t = 2 + [ `Set_state of Kgp_animation_state.t * int option 3 | `Set_gap of int * int 4 | `Set_current of int ] 5
+2 -5
lib/kgp_animation.mli
··· 2 3 Animation control operations. *) 4 5 - type state = Kgp_types.animation_state 6 - (** Animation playback state. *) 7 - 8 type t = 9 - [ `Set_state of state * int option 10 | `Set_gap of int * int 11 | `Set_current of int ] 12 (** Animation control operations. *) 13 14 - val set_state : ?loops:int -> state -> t 15 (** Set animation state. 16 @param loops Number of loops: 0 = ignored, 1 = infinite, n = n-1 loops *) 17
··· 2 3 Animation control operations. *) 4 5 type t = 6 + [ `Set_state of Kgp_animation_state.t * int option 7 | `Set_gap of int * int 8 | `Set_current of int ] 9 (** Animation control operations. *) 10 11 + val set_state : ?loops:int -> Kgp_animation_state.t -> t 12 (** Set animation state. 13 @param loops Number of loops: 0 = ignored, 1 = infinite, n = n-1 loops *) 14
+6
lib/kgp_animation_state.ml
···
··· 1 + type t = [ `Stop | `Loading | `Run ] 2 + 3 + let to_int : t -> int = function 4 + | `Stop -> 1 5 + | `Loading -> 2 6 + | `Run -> 3
+13
lib/kgp_animation_state.mli
···
··· 1 + (** Animation Playback State 2 + 3 + Controls the playback state of animated images. *) 4 + 5 + type t = [ `Stop | `Loading | `Run ] 6 + (** Animation playback states. 7 + 8 + - [`Stop] - Halt animation playback 9 + - [`Loading] - Run animation but wait for new frames at end 10 + - [`Run] - Run animation normally and loop *) 11 + 12 + val to_int : t -> int 13 + (** Convert to protocol integer (1, 2, or 3). *)
+15 -41
lib/kgp_command.ml
··· 1 - (* Kitty Graphics Protocol Command - Implementation *) 2 - 3 type action = 4 [ `Transmit 5 | `Transmit_and_display ··· 12 13 type t = { 14 action : action; 15 - format : Kgp_types.format option; 16 - transmission : Kgp_types.transmission option; 17 - compression : Kgp_types.compression option; 18 width : int option; 19 height : int option; 20 size : int option; 21 offset : int option; 22 - quiet : Kgp_types.quiet option; 23 image_id : int option; 24 image_number : int option; 25 placement : Kgp_placement.t option; 26 - delete : Kgp_types.delete option; 27 frame : Kgp_frame.t option; 28 animation : Kgp_animation.t option; 29 compose : Kgp_compose.t option; ··· 148 | `Animate -> 'a' 149 | `Compose -> 'c' 150 151 - let delete_char : Kgp_types.delete -> char = function 152 - | `All_visible -> 'a' 153 - | `All_visible_and_free -> 'A' 154 - | `By_id _ -> 'i' 155 - | `By_id_and_free _ -> 'I' 156 - | `By_number _ -> 'n' 157 - | `By_number_and_free _ -> 'N' 158 - | `At_cursor -> 'c' 159 - | `At_cursor_and_free -> 'C' 160 - | `At_cell _ -> 'p' 161 - | `At_cell_and_free _ -> 'P' 162 - | `At_cell_z _ -> 'q' 163 - | `At_cell_z_and_free _ -> 'Q' 164 - | `By_column _ -> 'x' 165 - | `By_column_and_free _ -> 'X' 166 - | `By_row _ -> 'y' 167 - | `By_row_and_free _ -> 'Y' 168 - | `By_z_index _ -> 'z' 169 - | `By_z_index_and_free _ -> 'Z' 170 - | `By_id_range _ -> 'r' 171 - | `By_id_range_and_free _ -> 'R' 172 - | `Frames -> 'f' 173 - | `Frames_and_free -> 'F' 174 - 175 let write_placement w (p : Kgp_placement.t) = 176 kv_int_opt w 'x' (Kgp_placement.source_x p); 177 kv_int_opt w 'y' (Kgp_placement.source_y p); ··· 185 kv_int_opt w 'p' (Kgp_placement.placement_id p); 186 Kgp_placement.cursor p 187 |> Option.iter (fun c -> 188 - kv_int_if w 'C' ~default:0 (Some (Kgp_types.Cursor.to_int c))); 189 if Kgp_placement.unicode_placeholder p then kv_int w 'U' 1 190 191 - let write_delete w (d : Kgp_types.delete) = 192 - kv_char w 'd' (delete_char d); 193 match d with 194 | `By_id (id, pid) | `By_id_and_free (id, pid) -> 195 kv_int w 'i' id; ··· 222 kv_int_opt w 'z' (Kgp_frame.gap_ms f); 223 Kgp_frame.composition f 224 |> Option.iter (fun c -> 225 - kv_int_if w 'X' ~default:0 (Some (Kgp_types.Composition.to_int c))); 226 kv_int32_opt w 'Y' (Kgp_frame.background_color f) 227 228 let write_animation w : Kgp_animation.t -> unit = function 229 | `Set_state (state, loops) -> 230 - let s = match state with `Stop -> 1 | `Loading -> 2 | `Run -> 3 in 231 kv_int w 's' s; 232 kv_int_opt w 'v' loops 233 | `Set_gap (frame, gap_ms) -> ··· 246 kv_int_opt w 'Y' (Kgp_compose.source_y c); 247 Kgp_compose.composition c 248 |> Option.iter (fun comp -> 249 - kv_int_if w 'C' ~default:0 (Some (Kgp_types.Composition.to_int comp))) 250 251 let write_control_data buf cmd = 252 let w = kv_writer buf in ··· 255 (* Quiet - only if non-default *) 256 cmd.quiet 257 |> Option.iter (fun q -> 258 - kv_int_if w 'q' ~default:0 (Some (Kgp_types.Quiet.to_int q))); 259 (* Format *) 260 cmd.format 261 - |> Option.iter (fun f -> kv_int w 'f' (Kgp_types.Format.to_int f)); 262 (* Transmission - only for transmit/frame actions, always include t=d for compatibility *) 263 (match cmd.action with 264 | `Transmit | `Transmit_and_display | `Frame -> ( 265 match cmd.transmission with 266 - | Some t -> kv_char w 't' (Kgp_types.Transmission.to_char t) 267 | None -> kv_char w 't' 'd') 268 | _ -> ()); 269 (* Compression *) 270 cmd.compression 271 |> Option.iter (fun c -> 272 - Kgp_types.Compression.to_char c |> Option.iter (kv_char w 'o')); 273 (* Dimensions *) 274 kv_int_opt w 's' cmd.width; 275 kv_int_opt w 'v' cmd.height;
··· 1 type action = 2 [ `Transmit 3 | `Transmit_and_display ··· 10 11 type t = { 12 action : action; 13 + format : Kgp_format.t option; 14 + transmission : Kgp_transmission.t option; 15 + compression : Kgp_compression.t option; 16 width : int option; 17 height : int option; 18 size : int option; 19 offset : int option; 20 + quiet : Kgp_quiet.t option; 21 image_id : int option; 22 image_number : int option; 23 placement : Kgp_placement.t option; 24 + delete : Kgp_delete.t option; 25 frame : Kgp_frame.t option; 26 animation : Kgp_animation.t option; 27 compose : Kgp_compose.t option; ··· 146 | `Animate -> 'a' 147 | `Compose -> 'c' 148 149 let write_placement w (p : Kgp_placement.t) = 150 kv_int_opt w 'x' (Kgp_placement.source_x p); 151 kv_int_opt w 'y' (Kgp_placement.source_y p); ··· 159 kv_int_opt w 'p' (Kgp_placement.placement_id p); 160 Kgp_placement.cursor p 161 |> Option.iter (fun c -> 162 + kv_int_if w 'C' ~default:0 (Some (Kgp_cursor.to_int c))); 163 if Kgp_placement.unicode_placeholder p then kv_int w 'U' 1 164 165 + let write_delete w (d : Kgp_delete.t) = 166 + kv_char w 'd' (Kgp_delete.to_char d); 167 match d with 168 | `By_id (id, pid) | `By_id_and_free (id, pid) -> 169 kv_int w 'i' id; ··· 196 kv_int_opt w 'z' (Kgp_frame.gap_ms f); 197 Kgp_frame.composition f 198 |> Option.iter (fun c -> 199 + kv_int_if w 'X' ~default:0 (Some (Kgp_composition.to_int c))); 200 kv_int32_opt w 'Y' (Kgp_frame.background_color f) 201 202 let write_animation w : Kgp_animation.t -> unit = function 203 | `Set_state (state, loops) -> 204 + let s = Kgp_animation_state.to_int state in 205 kv_int w 's' s; 206 kv_int_opt w 'v' loops 207 | `Set_gap (frame, gap_ms) -> ··· 220 kv_int_opt w 'Y' (Kgp_compose.source_y c); 221 Kgp_compose.composition c 222 |> Option.iter (fun comp -> 223 + kv_int_if w 'C' ~default:0 (Some (Kgp_composition.to_int comp))) 224 225 let write_control_data buf cmd = 226 let w = kv_writer buf in ··· 229 (* Quiet - only if non-default *) 230 cmd.quiet 231 |> Option.iter (fun q -> 232 + kv_int_if w 'q' ~default:0 (Some (Kgp_quiet.to_int q))); 233 (* Format *) 234 cmd.format 235 + |> Option.iter (fun f -> kv_int w 'f' (Kgp_format.to_int f)); 236 (* Transmission - only for transmit/frame actions, always include t=d for compatibility *) 237 (match cmd.action with 238 | `Transmit | `Transmit_and_display | `Frame -> ( 239 match cmd.transmission with 240 + | Some t -> kv_char w 't' (Kgp_transmission.to_char t) 241 | None -> kv_char w 't' 'd') 242 | _ -> ()); 243 (* Compression *) 244 cmd.compression 245 |> Option.iter (fun c -> 246 + Kgp_compression.to_char c |> Option.iter (kv_char w 'o')); 247 (* Dimensions *) 248 kv_int_opt w 's' cmd.width; 249 kv_int_opt w 'v' cmd.height;
+19 -19
lib/kgp_command.mli
··· 11 val transmit : 12 ?image_id:int -> 13 ?image_number:int -> 14 - ?format:Kgp_types.format -> 15 - ?transmission:Kgp_types.transmission -> 16 - ?compression:Kgp_types.compression -> 17 ?width:int -> 18 ?height:int -> 19 ?size:int -> 20 ?offset:int -> 21 - ?quiet:Kgp_types.quiet -> 22 unit -> 23 t 24 (** Transmit image data without displaying. *) ··· 26 val transmit_and_display : 27 ?image_id:int -> 28 ?image_number:int -> 29 - ?format:Kgp_types.format -> 30 - ?transmission:Kgp_types.transmission -> 31 - ?compression:Kgp_types.compression -> 32 ?width:int -> 33 ?height:int -> 34 ?size:int -> 35 ?offset:int -> 36 - ?quiet:Kgp_types.quiet -> 37 ?placement:Kgp_placement.t -> 38 unit -> 39 t 40 (** Transmit image data and display it immediately. *) 41 42 val query : 43 - ?format:Kgp_types.format -> 44 - ?transmission:Kgp_types.transmission -> 45 ?width:int -> 46 ?height:int -> 47 - ?quiet:Kgp_types.quiet -> 48 unit -> 49 t 50 (** Query terminal support without storing the image. *) ··· 55 ?image_id:int -> 56 ?image_number:int -> 57 ?placement:Kgp_placement.t -> 58 - ?quiet:Kgp_types.quiet -> 59 unit -> 60 t 61 (** Display a previously transmitted image. *) 62 63 (** {1 Deletion} *) 64 65 - val delete : ?quiet:Kgp_types.quiet -> Kgp_types.delete -> t 66 (** Delete images or placements. *) 67 68 (** {1 Animation} *) ··· 70 val frame : 71 ?image_id:int -> 72 ?image_number:int -> 73 - ?format:Kgp_types.format -> 74 - ?transmission:Kgp_types.transmission -> 75 - ?compression:Kgp_types.compression -> 76 ?width:int -> 77 ?height:int -> 78 - ?quiet:Kgp_types.quiet -> 79 frame:Kgp_frame.t -> 80 unit -> 81 t ··· 84 val animate : 85 ?image_id:int -> 86 ?image_number:int -> 87 - ?quiet:Kgp_types.quiet -> 88 Kgp_animation.t -> 89 t 90 (** Control animation playback. *) ··· 92 val compose : 93 ?image_id:int -> 94 ?image_number:int -> 95 - ?quiet:Kgp_types.quiet -> 96 Kgp_compose.t -> 97 t 98 (** Compose animation frames. *)
··· 11 val transmit : 12 ?image_id:int -> 13 ?image_number:int -> 14 + ?format:Kgp_format.t -> 15 + ?transmission:Kgp_transmission.t -> 16 + ?compression:Kgp_compression.t -> 17 ?width:int -> 18 ?height:int -> 19 ?size:int -> 20 ?offset:int -> 21 + ?quiet:Kgp_quiet.t -> 22 unit -> 23 t 24 (** Transmit image data without displaying. *) ··· 26 val transmit_and_display : 27 ?image_id:int -> 28 ?image_number:int -> 29 + ?format:Kgp_format.t -> 30 + ?transmission:Kgp_transmission.t -> 31 + ?compression:Kgp_compression.t -> 32 ?width:int -> 33 ?height:int -> 34 ?size:int -> 35 ?offset:int -> 36 + ?quiet:Kgp_quiet.t -> 37 ?placement:Kgp_placement.t -> 38 unit -> 39 t 40 (** Transmit image data and display it immediately. *) 41 42 val query : 43 + ?format:Kgp_format.t -> 44 + ?transmission:Kgp_transmission.t -> 45 ?width:int -> 46 ?height:int -> 47 + ?quiet:Kgp_quiet.t -> 48 unit -> 49 t 50 (** Query terminal support without storing the image. *) ··· 55 ?image_id:int -> 56 ?image_number:int -> 57 ?placement:Kgp_placement.t -> 58 + ?quiet:Kgp_quiet.t -> 59 unit -> 60 t 61 (** Display a previously transmitted image. *) 62 63 (** {1 Deletion} *) 64 65 + val delete : ?quiet:Kgp_quiet.t -> Kgp_delete.t -> t 66 (** Delete images or placements. *) 67 68 (** {1 Animation} *) ··· 70 val frame : 71 ?image_id:int -> 72 ?image_number:int -> 73 + ?format:Kgp_format.t -> 74 + ?transmission:Kgp_transmission.t -> 75 + ?compression:Kgp_compression.t -> 76 ?width:int -> 77 ?height:int -> 78 + ?quiet:Kgp_quiet.t -> 79 frame:Kgp_frame.t -> 80 unit -> 81 t ··· 84 val animate : 85 ?image_id:int -> 86 ?image_number:int -> 87 + ?quiet:Kgp_quiet.t -> 88 Kgp_animation.t -> 89 t 90 (** Control animation playback. *) ··· 92 val compose : 93 ?image_id:int -> 94 ?image_number:int -> 95 + ?quiet:Kgp_quiet.t -> 96 Kgp_compose.t -> 97 t 98 (** Compose animation frames. *)
+1 -3
lib/kgp_compose.ml
··· 1 - (* Kitty Graphics Protocol Compose - Implementation *) 2 - 3 type t = { 4 source_frame : int; 5 dest_frame : int; ··· 9 source_y : int option; 10 dest_x : int option; 11 dest_y : int option; 12 - composition : Kgp_types.composition option; 13 } 14 15 let make ~source_frame ~dest_frame ?width ?height ?source_x ?source_y ?dest_x
··· 1 type t = { 2 source_frame : int; 3 dest_frame : int; ··· 7 source_y : int option; 8 dest_x : int option; 9 dest_y : int option; 10 + composition : Kgp_composition.t option; 11 } 12 13 let make ~source_frame ~dest_frame ?width ?height ?source_x ?source_y ?dest_x
+2 -2
lib/kgp_compose.mli
··· 14 ?source_y:int -> 15 ?dest_x:int -> 16 ?dest_y:int -> 17 - ?composition:Kgp_types.composition -> 18 unit -> 19 t 20 (** Compose a rectangle from one frame onto another. *) ··· 29 val source_y : t -> int option 30 val dest_x : t -> int option 31 val dest_y : t -> int option 32 - val composition : t -> Kgp_types.composition option
··· 14 ?source_y:int -> 15 ?dest_x:int -> 16 ?dest_y:int -> 17 + ?composition:Kgp_composition.t -> 18 unit -> 19 t 20 (** Compose a rectangle from one frame onto another. *) ··· 29 val source_y : t -> int option 30 val dest_x : t -> int option 31 val dest_y : t -> int option 32 + val composition : t -> Kgp_composition.t option
+5
lib/kgp_composition.ml
···
··· 1 + type t = [ `Alpha_blend | `Overwrite ] 2 + 3 + let to_int : t -> int = function 4 + | `Alpha_blend -> 0 5 + | `Overwrite -> 1
+12
lib/kgp_composition.mli
···
··· 1 + (** Pixel Composition Mode 2 + 3 + Controls how pixels are blended when compositing images or animation frames. *) 4 + 5 + type t = [ `Alpha_blend | `Overwrite ] 6 + (** Composition modes. 7 + 8 + - [`Alpha_blend] - Full alpha blending (default) 9 + - [`Overwrite] - Simple pixel replacement *) 10 + 11 + val to_int : t -> int 12 + (** Convert to protocol integer (0 or 1). *)
+5
lib/kgp_compression.ml
···
··· 1 + type t = [ `None | `Zlib ] 2 + 3 + let to_char : t -> char option = function 4 + | `None -> None 5 + | `Zlib -> Some 'z'
+13
lib/kgp_compression.mli
···
··· 1 + (** Data Compression 2 + 3 + Specifies compression applied to image data before transmission. *) 4 + 5 + type t = [ `None | `Zlib ] 6 + (** Compression options. 7 + 8 + - [`None] - Raw uncompressed data 9 + - [`Zlib] - RFC 1950 zlib compression *) 10 + 11 + val to_char : t -> char option 12 + (** Convert to protocol character. Returns [None] for no compression, 13 + [Some 'z'] for zlib. *)
+5
lib/kgp_cursor.ml
···
··· 1 + type t = [ `Move | `Static ] 2 + 3 + let to_int : t -> int = function 4 + | `Move -> 0 5 + | `Static -> 1
+12
lib/kgp_cursor.mli
···
··· 1 + (** Cursor Movement Behavior 2 + 3 + Controls cursor position after displaying an image. *) 4 + 5 + type t = [ `Move | `Static ] 6 + (** Cursor movement behavior. 7 + 8 + - [`Move] - Advance cursor past the displayed image (default) 9 + - [`Static] - Keep cursor in place *) 10 + 11 + val to_int : t -> int 12 + (** Convert to protocol integer (0 or 1). *)
+47
lib/kgp_delete.ml
···
··· 1 + type t = 2 + [ `All_visible 3 + | `All_visible_and_free 4 + | `By_id of int * int option 5 + | `By_id_and_free of int * int option 6 + | `By_number of int * int option 7 + | `By_number_and_free of int * int option 8 + | `At_cursor 9 + | `At_cursor_and_free 10 + | `At_cell of int * int 11 + | `At_cell_and_free of int * int 12 + | `At_cell_z of int * int * int 13 + | `At_cell_z_and_free of int * int * int 14 + | `By_column of int 15 + | `By_column_and_free of int 16 + | `By_row of int 17 + | `By_row_and_free of int 18 + | `By_z_index of int 19 + | `By_z_index_and_free of int 20 + | `By_id_range of int * int 21 + | `By_id_range_and_free of int * int 22 + | `Frames 23 + | `Frames_and_free ] 24 + 25 + let to_char : t -> char = function 26 + | `All_visible -> 'a' 27 + | `All_visible_and_free -> 'A' 28 + | `By_id _ -> 'i' 29 + | `By_id_and_free _ -> 'I' 30 + | `By_number _ -> 'n' 31 + | `By_number_and_free _ -> 'N' 32 + | `At_cursor -> 'c' 33 + | `At_cursor_and_free -> 'C' 34 + | `At_cell _ -> 'p' 35 + | `At_cell_and_free _ -> 'P' 36 + | `At_cell_z _ -> 'q' 37 + | `At_cell_z_and_free _ -> 'Q' 38 + | `By_column _ -> 'x' 39 + | `By_column_and_free _ -> 'X' 40 + | `By_row _ -> 'y' 41 + | `By_row_and_free _ -> 'Y' 42 + | `By_z_index _ -> 'z' 43 + | `By_z_index_and_free _ -> 'Z' 44 + | `By_id_range _ -> 'r' 45 + | `By_id_range_and_free _ -> 'R' 46 + | `Frames -> 'f' 47 + | `Frames_and_free -> 'F'
+47
lib/kgp_delete.mli
···
··· 1 + (** Image Deletion Target 2 + 3 + Specifies which images or placements to delete. Each deletion type has 4 + two variants: one that only removes placements and one that also frees 5 + the underlying image data. *) 6 + 7 + type t = 8 + [ `All_visible 9 + | `All_visible_and_free 10 + | `By_id of int * int option 11 + | `By_id_and_free of int * int option 12 + | `By_number of int * int option 13 + | `By_number_and_free of int * int option 14 + | `At_cursor 15 + | `At_cursor_and_free 16 + | `At_cell of int * int 17 + | `At_cell_and_free of int * int 18 + | `At_cell_z of int * int * int 19 + | `At_cell_z_and_free of int * int * int 20 + | `By_column of int 21 + | `By_column_and_free of int 22 + | `By_row of int 23 + | `By_row_and_free of int 24 + | `By_z_index of int 25 + | `By_z_index_and_free of int 26 + | `By_id_range of int * int 27 + | `By_id_range_and_free of int * int 28 + | `Frames 29 + | `Frames_and_free ] 30 + (** Deletion target specification. 31 + 32 + - [`All_visible] - All visible placements 33 + - [`By_id (id, placement_id)] - By image ID and optional placement ID 34 + - [`By_number (n, placement_id)] - By image number and optional placement ID 35 + - [`At_cursor] - Placement at cursor position 36 + - [`At_cell (x, y)] - Placement at cell coordinates 37 + - [`At_cell_z (x, y, z)] - Placement at cell with specific z-index 38 + - [`By_column c] - All placements in column c 39 + - [`By_row r] - All placements in row r 40 + - [`By_z_index z] - All placements with z-index z 41 + - [`By_id_range (min, max)] - All images with IDs in range 42 + - [`Frames] - Animation frames only 43 + 44 + The [_and_free] variants also release the image data from memory. *) 45 + 46 + val to_char : t -> char 47 + (** Convert to protocol character for the delete command. *)
+6
lib/kgp_format.ml
···
··· 1 + type t = [ `Rgba32 | `Rgb24 | `Png ] 2 + 3 + let to_int : t -> int = function 4 + | `Rgba32 -> 32 5 + | `Rgb24 -> 24 6 + | `Png -> 100
+13
lib/kgp_format.mli
···
··· 1 + (** Image Data Format 2 + 3 + Specifies the pixel format of image data being transmitted. *) 4 + 5 + type t = [ `Rgba32 | `Rgb24 | `Png ] 6 + (** Image data formats. 7 + 8 + - [`Rgba32] - 32-bit RGBA (4 bytes per pixel) 9 + - [`Rgb24] - 24-bit RGB (3 bytes per pixel) 10 + - [`Png] - PNG encoded data *) 11 + 12 + val to_int : t -> int 13 + (** Convert to protocol integer value (32, 24, or 100). *)
+1 -3
lib/kgp_frame.ml
··· 1 - (* Kitty Graphics Protocol Frame - Implementation *) 2 - 3 type t = { 4 x : int option; 5 y : int option; 6 base_frame : int option; 7 edit_frame : int option; 8 gap_ms : int option; 9 - composition : Kgp_types.composition option; 10 background_color : int32 option; 11 } 12
··· 1 type t = { 2 x : int option; 3 y : int option; 4 base_frame : int option; 5 edit_frame : int option; 6 gap_ms : int option; 7 + composition : Kgp_composition.t option; 8 background_color : int32 option; 9 } 10
+2 -2
lib/kgp_frame.mli
··· 11 ?base_frame:int -> 12 ?edit_frame:int -> 13 ?gap_ms:int -> 14 - ?composition:Kgp_types.composition -> 15 ?background_color:int32 -> 16 unit -> 17 t ··· 35 val base_frame : t -> int option 36 val edit_frame : t -> int option 37 val gap_ms : t -> int option 38 - val composition : t -> Kgp_types.composition option 39 val background_color : t -> int32 option
··· 11 ?base_frame:int -> 12 ?edit_frame:int -> 13 ?gap_ms:int -> 14 + ?composition:Kgp_composition.t -> 15 ?background_color:int32 -> 16 unit -> 17 t ··· 35 val base_frame : t -> int option 36 val edit_frame : t -> int option 37 val gap_ms : t -> int option 38 + val composition : t -> Kgp_composition.t option 39 val background_color : t -> int32 option
+1 -3
lib/kgp_placement.ml
··· 1 - (* Kitty Graphics Protocol Placement - Implementation *) 2 - 3 type t = { 4 source_x : int option; 5 source_y : int option; ··· 11 rows : int option; 12 z_index : int option; 13 placement_id : int option; 14 - cursor : Kgp_types.cursor option; 15 unicode_placeholder : bool; 16 } 17
··· 1 type t = { 2 source_x : int option; 3 source_y : int option; ··· 9 rows : int option; 10 z_index : int option; 11 placement_id : int option; 12 + cursor : Kgp_cursor.t option; 13 unicode_placeholder : bool; 14 } 15
+2 -2
lib/kgp_placement.mli
··· 16 ?rows:int -> 17 ?z_index:int -> 18 ?placement_id:int -> 19 - ?cursor:Kgp_types.cursor -> 20 ?unicode_placeholder:bool -> 21 unit -> 22 t ··· 50 val rows : t -> int option 51 val z_index : t -> int option 52 val placement_id : t -> int option 53 - val cursor : t -> Kgp_types.cursor option 54 val unicode_placeholder : t -> bool
··· 16 ?rows:int -> 17 ?z_index:int -> 18 ?placement_id:int -> 19 + ?cursor:Kgp_cursor.t -> 20 ?unicode_placeholder:bool -> 21 unit -> 22 t ··· 50 val rows : t -> int option 51 val z_index : t -> int option 52 val placement_id : t -> int option 53 + val cursor : t -> Kgp_cursor.t option 54 val unicode_placeholder : t -> bool
+6
lib/kgp_quiet.ml
···
··· 1 + type t = [ `Noisy | `Errors_only | `Silent ] 2 + 3 + let to_int : t -> int = function 4 + | `Noisy -> 0 5 + | `Errors_only -> 1 6 + | `Silent -> 2
+13
lib/kgp_quiet.mli
···
··· 1 + (** Response Suppression Level 2 + 3 + Controls which terminal responses are sent back to the application. *) 4 + 5 + type t = [ `Noisy | `Errors_only | `Silent ] 6 + (** Response suppression levels. 7 + 8 + - [`Noisy] - Send all responses (default) 9 + - [`Errors_only] - Suppress OK responses, only send errors 10 + - [`Silent] - Suppress all responses *) 11 + 12 + val to_int : t -> int 13 + (** Convert to protocol integer (0, 1, or 2). *)
+6
lib/kgp_transmission.ml
···
··· 1 + type t = [ `Direct | `File | `Tempfile ] 2 + 3 + let to_char : t -> char = function 4 + | `Direct -> 'd' 5 + | `File -> 'f' 6 + | `Tempfile -> 't'
+13
lib/kgp_transmission.mli
···
··· 1 + (** Data Transmission Method 2 + 3 + Specifies how image data is transmitted to the terminal. *) 4 + 5 + type t = [ `Direct | `File | `Tempfile ] 6 + (** Transmission methods. 7 + 8 + - [`Direct] - Data is sent inline in the escape sequence 9 + - [`File] - Terminal reads from a file path 10 + - [`Tempfile] - Terminal reads and deletes a temporary file *) 11 + 12 + val to_char : t -> char 13 + (** Convert to protocol character ('d', 'f', or 't'). *)
-89
lib/kgp_types.ml
··· 1 - (* Kitty Graphics Protocol Types - Implementation *) 2 - 3 - type format = [ `Rgba32 | `Rgb24 | `Png ] 4 - type transmission = [ `Direct | `File | `Tempfile ] 5 - type compression = [ `None | `Zlib ] 6 - type quiet = [ `Noisy | `Errors_only | `Silent ] 7 - type cursor = [ `Move | `Static ] 8 - type composition = [ `Alpha_blend | `Overwrite ] 9 - 10 - type delete = 11 - [ `All_visible 12 - | `All_visible_and_free 13 - | `By_id of int * int option 14 - | `By_id_and_free of int * int option 15 - | `By_number of int * int option 16 - | `By_number_and_free of int * int option 17 - | `At_cursor 18 - | `At_cursor_and_free 19 - | `At_cell of int * int 20 - | `At_cell_and_free of int * int 21 - | `At_cell_z of int * int * int 22 - | `At_cell_z_and_free of int * int * int 23 - | `By_column of int 24 - | `By_column_and_free of int 25 - | `By_row of int 26 - | `By_row_and_free of int 27 - | `By_z_index of int 28 - | `By_z_index_and_free of int 29 - | `By_id_range of int * int 30 - | `By_id_range_and_free of int * int 31 - | `Frames 32 - | `Frames_and_free ] 33 - 34 - type animation_state = [ `Stop | `Loading | `Run ] 35 - 36 - module Format = struct 37 - type t = format 38 - 39 - let to_int : t -> int = function 40 - | `Rgba32 -> 32 41 - | `Rgb24 -> 24 42 - | `Png -> 100 43 - end 44 - 45 - module Transmission = struct 46 - type t = transmission 47 - 48 - let to_char : t -> char = function 49 - | `Direct -> 'd' 50 - | `File -> 'f' 51 - | `Tempfile -> 't' 52 - end 53 - 54 - module Compression = struct 55 - type t = compression 56 - 57 - let to_char : t -> char option = function 58 - | `None -> None 59 - | `Zlib -> Some 'z' 60 - end 61 - 62 - module Quiet = struct 63 - type t = quiet 64 - 65 - let to_int : t -> int = function 66 - | `Noisy -> 0 67 - | `Errors_only -> 1 68 - | `Silent -> 2 69 - end 70 - 71 - module Cursor = struct 72 - type t = cursor 73 - 74 - let to_int : t -> int = function 75 - | `Move -> 0 76 - | `Static -> 1 77 - end 78 - 79 - module Composition = struct 80 - type t = composition 81 - 82 - let to_int : t -> int = function 83 - | `Alpha_blend -> 0 84 - | `Overwrite -> 1 85 - end 86 - 87 - module Delete = struct 88 - type t = delete 89 - end
···
-109
lib/kgp_types.mli
··· 1 - (** Kitty Graphics Protocol Types 2 - 3 - This module defines the base polymorphic variant types used throughout 4 - the Kitty graphics protocol implementation. *) 5 - 6 - (** {1 Polymorphic Variant Types} *) 7 - 8 - type format = [ `Rgba32 | `Rgb24 | `Png ] 9 - (** Image data formats. [`Rgba32] is 32-bit RGBA (4 bytes per pixel), 10 - [`Rgb24] is 24-bit RGB (3 bytes per pixel), [`Png] is PNG encoded data. *) 11 - 12 - type transmission = [ `Direct | `File | `Tempfile ] 13 - (** Transmission methods. [`Direct] sends data inline, [`File] reads from a path, 14 - [`Tempfile] reads from a temp file that the terminal deletes after reading. *) 15 - 16 - type compression = [ `None | `Zlib ] 17 - (** Compression options. [`None] for raw data, [`Zlib] for RFC 1950 compression. *) 18 - 19 - type quiet = [ `Noisy | `Errors_only | `Silent ] 20 - (** Response suppression. [`Noisy] sends all responses (default), 21 - [`Errors_only] suppresses OK responses, [`Silent] suppresses all. *) 22 - 23 - type cursor = [ `Move | `Static ] 24 - (** Cursor movement after displaying. [`Move] advances cursor (default), 25 - [`Static] keeps cursor in place. *) 26 - 27 - type composition = [ `Alpha_blend | `Overwrite ] 28 - (** Composition modes. [`Alpha_blend] for full blending (default), 29 - [`Overwrite] for simple pixel replacement. *) 30 - 31 - type delete = 32 - [ `All_visible 33 - | `All_visible_and_free 34 - | `By_id of int * int option 35 - | `By_id_and_free of int * int option 36 - | `By_number of int * int option 37 - | `By_number_and_free of int * int option 38 - | `At_cursor 39 - | `At_cursor_and_free 40 - | `At_cell of int * int 41 - | `At_cell_and_free of int * int 42 - | `At_cell_z of int * int * int 43 - | `At_cell_z_and_free of int * int * int 44 - | `By_column of int 45 - | `By_column_and_free of int 46 - | `By_row of int 47 - | `By_row_and_free of int 48 - | `By_z_index of int 49 - | `By_z_index_and_free of int 50 - | `By_id_range of int * int 51 - | `By_id_range_and_free of int * int 52 - | `Frames 53 - | `Frames_and_free ] 54 - (** Delete target specification. Each variant has two forms: one that only 55 - removes placements (e.g., [`All_visible]) and one that also frees the 56 - image data (e.g., [`All_visible_and_free]). Tuple variants contain 57 - (image_id, optional_placement_id) or (x, y) coordinates. *) 58 - 59 - type animation_state = [ `Stop | `Loading | `Run ] 60 - (** Animation playback state. [`Stop] halts animation, [`Loading] runs but 61 - waits for new frames at end, [`Run] runs normally and loops. *) 62 - 63 - (** {1 Type Modules} *) 64 - 65 - module Format : sig 66 - type t = format 67 - 68 - val to_int : t -> int 69 - (** Convert to protocol integer value (32, 24, or 100). *) 70 - end 71 - 72 - module Transmission : sig 73 - type t = transmission 74 - 75 - val to_char : t -> char 76 - (** Convert to protocol character ('d', 'f', or 't'). *) 77 - end 78 - 79 - module Compression : sig 80 - type t = compression 81 - 82 - val to_char : t -> char option 83 - (** Convert to protocol character ([None] or [Some 'z']). *) 84 - end 85 - 86 - module Quiet : sig 87 - type t = quiet 88 - 89 - val to_int : t -> int 90 - (** Convert to protocol integer (0, 1, or 2). *) 91 - end 92 - 93 - module Cursor : sig 94 - type t = cursor 95 - 96 - val to_int : t -> int 97 - (** Convert to protocol integer (0 or 1). *) 98 - end 99 - 100 - module Composition : sig 101 - type t = composition 102 - 103 - val to_int : t -> int 104 - (** Convert to protocol integer (0 or 1). *) 105 - end 106 - 107 - module Delete : sig 108 - type t = delete 109 - end
···