open Types open Seq let match_env_order = let open Types in function | "rainbow-pair" -> RainbowPair | "rainbow-split" -> RainbowSplit | "tonepair" -> TonePair | "straight" -> Straight | "default" -> Default | "random" -> Random | s -> ( let parse = Parse.parse_env_order s in parse |> function [||] -> Straight | e -> Explicit e) let ( >>= ) = Option.bind let getenv_opt s = Sys.getenv_opt s >>= fun s -> if String.length s > 0 then Some s else None let explode s = s |> String.to_seq |> Array.of_seq let get_parser = let open Parsers in let sep = getenv_opt "CULR_SEP" and del = getenv_opt "CULR_DELIM" in match (sep, del) with | Some s, Some d -> create_parser ~separator:(explode s) ~delimiter:(explode d) () | None, Some d -> create_parser ~delimiter:(explode d) () | Some s, None -> create_parser ~separator:(explode s) () | None, None -> create_parser () let to_sixteen f = ints 0 |> take 16 |> f |> Array.of_seq let permute (order : order) (colours : colour array) = let open Array in let make_intrinsic = map (fun i -> Intrinsic i) in match order with | Explicit e -> let clen = length colours in e |> map (fun index -> if index < clen then colours.(index) else Intrinsic index) | RainbowPair -> [| 1; 9; 3; 11; 2; 10; 6; 14; 4; 12; 5; 13; 7; 15 |] |> make_intrinsic | RainbowSplit -> [| 1; 3; 2; 6; 4; 5; 9; 11; 10; 14; 12; 13; 7; 15 |] |> make_intrinsic | TonePair -> let open Seq in let lows = ints 1 |> take 8 in let highs = lows |> map (fun i -> i + 8) in interleave lows highs |> Array.of_seq |> make_intrinsic | Straight -> let open Seq in ints 0 |> take 16 |> Array.of_seq |> make_intrinsic | Default -> let open Seq in ints 0 |> take 16 |> filter (fun i -> not (i = 0 || i = 8)) |> Array.of_seq |> make_intrinsic | Random -> Random.self_init (); shuffle ~rand:Random.int colours; colours let get_colours = let colours = getenv_opt "CULRS" and order = getenv_opt "CULR_ORDER" and init_default_colours = to_sixteen (map (fun x -> Types.Intrinsic x)) and init_order_for_colours c = let open Seq in ints 0 |> take (Array.length c) |> Array.of_seq in match (colours, order) with | None, None -> permute Default init_default_colours | None, Some o -> permute (match_env_order o) init_default_colours | Some c, None -> let colours = Parse.parse_env_colours c in permute (Explicit (init_order_for_colours colours)) colours | Some c, Some o -> ( let colours = Parse.parse_env_colours c and order = match_env_order o in match order with | Explicit _ | Random -> permute order colours | _ -> colours)