open Types type serialiser = { mutable buf : string; sz : int; mutable pos : int } let write_ansi a = let rec intersperse sep ls = match ls with | [] | [ _ ] -> ls | hd :: tl -> hd :: sep :: intersperse sep tl and string_of_colour ?(bg = false) c = let prefix = if bg then "4" else "3" and si = string_of_int in c |> function | Intrinsic i -> prefix ^ si i | Simple i -> prefix ^ "8;5;" ^ si i | RGB (r, g, b) -> prefix ^ "8;2;" ^ si r ^ ";" ^ si g ^ ";" ^ si b in let ansi = a |> List.map (fun a -> match a with | Fg c -> string_of_colour c | Bg c -> string_of_colour ~bg:true c | Reset -> "0" | Other i -> string_of_int i) |> intersperse ";" |> List.fold_left (fun acc el -> acc ^ el) "" in "\x1b[" ^ ansi ^ "m" let flush t = if t.pos > 0 then ( print_string (String.sub t.buf 0 t.pos); t.pos <- 0) let serialise t chunk = let input = match chunk with | Text s -> s | Separator s -> s | Delimiter s -> s | Ansi a -> write_ansi a in let input_sz = String.length input in if t.pos + input_sz > t.sz then flush t; if input_sz > t.sz then print_string input else t.buf <- (if t.pos > 0 then String.sub t.buf 0 t.pos else "") ^ input; t.pos <- t.pos + input_sz let create = { buf = String.empty; sz = 4096; pos = 0 } let print_debug t = print_endline ("pos is " ^ string_of_int t.pos ^ "\nsz is " ^ string_of_int t.sz ^ "\ncontents are: " ^ t.buf)