57 lines
1.6 KiB
OCaml
57 lines
1.6 KiB
OCaml
open Types
|
|
|
|
type serialiser = { mutable buf : bytes; mutable pos : int }
|
|
|
|
(* convert ansi variants to appropriate output codes *)
|
|
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 ->
|
|
if i <= 8 then prefix ^ si i else (if bg then "10" else "9") ^ si (i - 8)
|
|
| 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"
|
|
|
|
(* print all serialised data and reset buffer *)
|
|
let flush t =
|
|
if t.pos > 0 then (
|
|
print_bytes (Bytes.sub t.buf 0 t.pos);
|
|
t.pos <- 0)
|
|
|
|
let serialise t chunk =
|
|
if chunk != Empty then (
|
|
let input =
|
|
match chunk with
|
|
| Text s -> s
|
|
| Separator s -> s
|
|
| Delimiter s -> s
|
|
| Ansi a -> write_ansi a
|
|
| Empty -> assert false
|
|
and sz = Bytes.length t.buf in
|
|
let input_sz = String.length input in
|
|
if t.pos + input_sz > sz then flush t;
|
|
if input_sz > sz then print_string input
|
|
else (
|
|
Bytes.blit_string input 0 t.buf t.pos input_sz;
|
|
t.pos <- t.pos + input_sz))
|
|
else ()
|
|
|
|
let create = { buf = Bytes.create 4096; pos = 0 }
|