open Types open Array let ansi_filter s = s |> function | Ansi a -> Types.Ansi (List.filter (function Fg _ | Bg _ -> false | _ -> true) a) | n -> n let permute (order : int array) (colours : colour array) = let olen = length order and clen = length colours in match (olen, clen) with (* nothing provided, take default 16 pal colours *) | 0, 0 -> Seq.ints 0 |> Seq.take 16 |> Seq.map (fun i -> Simple i) |> of_seq (* colours provided with no order, take them as is *) | 0, _ -> colours (* order provided with no colours, map to palette colours *) | _, 0 -> order |> map (fun o -> Simple o) (* order and colours provided, apply order to colours and sub palette where order index exceeds colour array length *) | _, _ -> order |> mapi (fun i o -> if order.(i) < clen then colours.(order.(i)) else Simple o) (* TODO: implement this so cli can use a dsl to specify colourising patterns *) type culr = { colours : colour array; sz : int; mutable current : int } 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 s f (c : colour array) = let ( @ ) = append in let colours = c |> permute s |> fun c -> if List.length f > 0 then fold_left (fun acc el -> if run_filters f el then acc @ [| el |] else acc) [||] c else c in { colours; sz = length colours; current = 0 } let next t = let ret = t.current and nv = t.current + 1 in if nv >= t.sz then t.current <- 0 else t.current <- nv; t.colours.(ret) let reset t = t.current <- 0 let serialise_with_colour t serialiser chunk = (match chunk with | Separator _ -> Emitter.serialise serialiser (Ansi [ Fg (next t) ]) | Delimiter _ -> reset t; Emitter.serialise serialiser (Ansi [ Fg (next t) ]) | _ -> ()); Emitter.serialise serialiser chunk end