open Types open Array (* TODO: implement this so cli can use a dsl to specify colourising patterns *) type culr = { colours : colour array; sz : int; mutable current : int; mutable first : bool; mutable text_output : bool; } module Culriser = struct type filter = (colour -> bool) list type sort = int array let run_filters (f : filter) el = List.fold_left (fun res filt -> if not (filt el) then false else res) true f let create ?(filters = []) (c : colour array) = let ( @ ) = append in let colours = if List.length filters > 0 then fold_left (fun acc el -> if run_filters filters el then acc @ [| el |] else acc) [||] c else c in { colours; sz = length colours; current = 0; first = true; text_output = false; } let current t = t.colours.(t.current) let next t = t.current <- (t.current + 1) mod t.sz; current t let reset t = t.current <- 0; t.first <- true; t.text_output <- false let serialise_with_colour t serialiser chunk = Emitter.serialise serialiser chunk; match chunk with | Separator _ -> if not t.first then if t.text_output then ( Emitter.serialise serialiser (Ansi [ Fg (next t) ]); t.text_output <- false) else Emitter.serialise serialiser (Ansi [ Fg (current t) ]) | Delimiter _ -> reset t; Emitter.serialise serialiser (Ansi [ Fg (current t) ]) | Text _ -> if t.first then t.first <- false; if not t.text_output then t.text_output <- true | _ -> () end let ansi_filter t s = s |> function | Ansi a -> ( let open List in let ol = length a and result = a |> filter (function Fg _ | Bg _ -> false | _ -> true) |> fold_left (fun acc el -> if el = Reset then acc @ [ el; Fg (Culriser.current t) ] else acc @ [ el ]) [] in let rl = length result in match (rl, ol) with (* empty ansi code is equivalent to a reset *) | 0, 0 -> Ansi [ Reset; Fg (Culriser.current t) ] (* if we filtered everything out of it produce no tokens *) | 0, _ -> Empty | _, _ -> Ansi result) | n -> n