module OI = Colitur_kernel.Overlay_ini type t = { lang : string option; overlays : string list; template : string option; format : string option; unknown_keys : string list; unknown_sections : string list; } let empty = { lang = None; overlays = []; template = None; format = None; unknown_keys = []; unknown_sections = [] } let lang t = t.lang let overlays t = t.overlays let template t = t.template let format t = t.format let unknown_keys t = t.unknown_keys let unknown_sections t = t.unknown_sections let of_string text = match OI.parse_sections text with | Error e -> Error e | Ok sections -> (* Any section that is not [defaults] is unrecognised -- including a plain typo such as [deafults] -- and must be REPORTED, never silently dropped: that is precisely the failure this feature exists to surface. *) let unknown_sections = List.filter_map (fun (s : OI.section) -> if s.OI.name = "defaults" then None else Some s.OI.name) sections in let acc = match List.find_opt (fun (s : OI.section) -> s.OI.name = "defaults") sections with | None -> empty | Some s -> (* Cons then reverse once at the end, not `@ [v]` per line: the latter is O(n^2) over the field count, a real hang on a machine-generated file with many overlay lines. *) let acc = List.fold_left (fun acc (k, v) -> match k with | "lang" -> { acc with lang = Some v } | "template" -> { acc with template = Some v } | "format" -> { acc with format = Some v } (* accumulates: a user has more than one overlay *) | "overlay" -> { acc with overlays = v :: acc.overlays } | other -> { acc with unknown_keys = other :: acc.unknown_keys }) empty s.OI.fields in { acc with overlays = List.rev acc.overlays; unknown_keys = List.rev acc.unknown_keys } in Ok { acc with unknown_sections } let resolve ~flag ~config ~default = match flag with | Some v -> (v, "flag") | None -> ( match config with Some v -> (v, "config") | None -> (default, "default"))