package b0
Software construction and deployment kit
Install
dune-project
Dependency
Authors
Maintainers
Sources
b0-0.0.6.tbz
sha512=e9aa779e66c08fc763019f16d4706f465d16c05d6400b58fbd0313317ef33ddea51952e2b058db28e65f7ddb7012f328c8bf02d8f1da17bb543348541a2587f0
doc/src/b0.file/b0_meta.ml.html
Source file b0_meta.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
(*--------------------------------------------------------------------------- Copyright (c) 2020 The b0 programmers. All rights reserved. SPDX-License-Identifier: ISC ---------------------------------------------------------------------------*) open B0_std (* Keys *) module Key = struct type t = V : 'a typed -> t and 'a typed = { default : 'a option; doc : string; id : 'a Type.Id.t; name : string; pp_value : 'a Fmt.t; scope : B0_scope.t; untyped : t; } let[@inline] uid k = Type.Id.uid k.id let defs = ref String.Map.empty let add k = defs := String.Map.add k.name k.untyped !defs (* Typed keys *) let kind = "key" let make ?(doc = "undocumented") ?default name ~pp_value = let id = Type.Id.make () in let name, scope = B0_scope.current_make_unique_qualified_name ~defs:!defs ~kind name in let rec k = { default; doc; id; name; pp_value; scope; untyped } and untyped = V k in add k; k let make_tag ?doc name = make ?doc name ~default:false ~pp_value:Fmt.bool let name k = k.name let default k = k.default let get_default k = Option.get k.default let doc k = k.doc let pp_value k = k.pp_value (* Existential keys *) let equal (V k0) (V k1) = Int.equal (uid k0) (uid k1) let compare (V k0) (V k1) = Int.compare (uid k0) (uid k1) let compare_by_name (V k0) (V k1) = String.compare (name k0) (name k1) let pp_name_str = Fmt.st [`Fg `Yellow] let pp_name ppf k = pp_name_str ppf k.name let pp ppf (V k) = pp_name_str ppf k.name (* Lookup keys by name *) let find n = match String.Map.find n !defs with | exception Not_found -> None | k -> Some k let get n = match find n with | Some v -> v | None -> Fmt.invalid_arg "No meta key named %s" n let get_or_suggest n = match find n with | Some v -> Ok v | None -> let add_sugg k v acc = if String.edit_distance k n <= 2 then v :: acc else acc in Error (List.rev (String.Map.fold add_sugg !defs [])) let get_or_hint n = match get_or_suggest n with | Ok _ as v -> v | Error suggs -> let kind = Fmt.any "meta key" and hint = Fmt.did_you_mean in let pp = Fmt.unknown' ~kind pp_name_str ~hint in let name (V k) = name k in Fmt.error "@[%a@]" pp (n, List.map name suggs) let fold f acc = match B0_scope.current_is_root () with | true -> let add _ v acc = f v acc in String.Map.fold add !defs acc | false -> let prefix = B0_scope.current_scope_prefix () in let add k v acc = if String.starts_with ~prefix k then f v acc else acc in String.Map.fold add !defs acc let list () = List.sort compare_by_name (fold List.cons []) let get_list_or_hint ~all_if_empty names = if all_if_empty && names = [] then Ok (list ()) else let rec loop vs es = function | [] -> if es <> [] then Error (String.concat "\n" (List.rev es)) else Ok (List.rev vs) | n :: ns -> match get_or_hint n with | Ok v -> loop (v :: vs) es ns | Error e -> loop vs (e :: es) ns in loop [] [] names end type 'a key = 'a Key.typed let err_no_default k = Fmt.invalid_arg "Key %a has no default value" Key.pp_name k let err_no_such_key_name k = Fmt.invalid_arg "Key %a not found in map" Key.pp_name_str k let err_no_such_key k = Fmt.invalid_arg "Key %a not found in map" Key.pp_name k (* Metadadta *) type binding = B : 'a key * 'a -> binding module M = Map.Make (Int) type t = binding M.t let empty = M.empty (* Predicates *) let is_empty = M.is_empty let mem k m = M.mem (Key.uid k) m let has_tag : bool key -> t -> bool = fun k m -> match Key.default k with | None -> err_no_default k | Some default -> match M.find_opt (Key.uid k) m with | None -> default | Some (B (k', v)) -> match Type.Id.provably_equal k.Key.id k'.Key.id with | Some Type.Equal -> v | None -> assert false (* Adding and removing *) let add k v m = M.add (Key.uid k) (B (k, v)) m let tag k m = add k true m let add_some k o m = match o with None -> m | Some v -> add k v m let add_some_or_default k o m = match k.Key.default with | None -> err_no_default k | Some default -> add k (match o with None -> default | Some v -> v) m let add_if_undef k v m = let update = function None -> Some (B (k, v)) | Some _ as b -> b in M.update (Key.uid k) update m let override m ~by = let override _ _ by = Some by in M.union override m by let remove k m = M.remove (Key.uid k) m (* Lookup *) let find : type a. a key -> t -> a option = fun k m -> match M.find_opt (Key.uid k) m with | None -> None | Some (B (k', v)) -> match Type.Id.provably_equal k.Key.id k'.Key.id with | Some Type.Equal -> Some v | None -> assert false let find_or_default : type a. a key -> t -> a = fun k m -> match k.Key.default with | None -> err_no_default k | Some default -> match M.find_opt (Key.uid k) m with | None -> default | Some (B (k', v)) -> match Type.Id.provably_equal k.Key.id k'.Key.id with | Some Type.Equal -> v | None -> assert false let get k m = match find k m with | Some v -> v | None -> err_no_such_key k (* Bindings *) let find_binding k m = M.find_opt (Key.uid k) m let find_binding_by_name n m = match Key.find n with | None -> None | Some (Key.V k) -> M.find_opt (Key.uid k) m let get_binding k m = match find_binding k m with | None -> err_no_such_key k | Some v -> v let get_binding_by_name n m = match find_binding_by_name n m with | None -> err_no_such_key_name n | Some v -> v let pp_binding ppf (B (k, v)) = Fmt.field k.Key.name Fun.id k.Key.pp_value ppf v (* Traversing *) let fold f m acc = M.fold (fun _ b acc -> f b acc) m acc (* Formatting *) let pp ppf m = (* The circumvolution here is to print in key name order. *) let add_binding _ (B (k, v) as b) acc = String.Map.add (Key.name k) b acc in let bindings = M.fold add_binding m String.Map.empty in (Fmt.vbox @@ Fmt.iter_bindings String.Map.iter (Fmt.using snd pp_binding)) ppf bindings let pp_non_empty ppf m = if M.is_empty m then () else (Fmt.cut ppf (); pp ppf m) (* Standard keys *) let string_list = Fmt.(list ~sep:sp string) let string_list_key k ~doc = Key.make k ~doc ~pp_value:string_list let string_key ?default k ~doc = Key.make k ?default ~doc ~pp_value:Fmt.string (* End-user information. *) let () = B0_scope.open_lib ~module':__MODULE__ "meta" let = string_list_key "authors" ~doc:"Author list" let description = string_key "description" ~doc:"Description" let = string_list_key "descr-tags" ~doc:"Description tags" let homepage = string_key "homepage" ~doc:"Homepage URI" let issues = string_key "issues" ~doc:"Issue tracker URI" type spdxid = string let licenses = string_list_key "licenses" ~doc:"License list (SPDX ids)" let maintainers = string_list_key "maintainers" ~doc:"Maintainer list" let online_doc = string_key "online-doc" ~doc:"Online documentation URI" let repo = string_key "repo" ~doc:"VCS source repository URI" let synopsis = string_key "synopsis" ~default:"Undocumented" ~doc:"One line synopsis" (* Entity tags *) let bench = Key.make_tag "bench" ~doc:"Benchmarking entity" let build = Key.make_tag "build" ~doc:"A build system entity" let deprecated = Key.make_tag "deprecated" ~doc:"Deprecated entity" let dev = Key.make_tag "dev" ~doc:"Development entity" let doc = Key.make_tag "doc" ~doc:"Documentation entity" let exe = Key.make_tag "exe" ~doc:"Executable entity" let test = Key.make_tag "test" ~doc:"Testing entity" let lib = Key.make_tag "lib" ~doc:"Library entity" let long = Key.make_tag "long" ~doc:"Entity is associated to a lengthy process" let public = Key.make_tag "public" ~doc:"Public entity" let run = Key.make_tag "run" ~doc:"Entity should be part of a run in a given context." let sample = Key.make_tag "sample" ~doc:"Demonstration entity." let warning = string_key "warning" ~doc:"A warning output when the entity is used" let exe_file = let doc = "Absolute file path to a built executable." in let pp_value = Fmt.any "<built value>" in Key.make "exe-file" ~doc ~pp_value let tool_name = let doc = "Executable tool name without platform specific extension" in Key.make "tool-name" ~doc ~pp_value:Fmt.string let () = B0_scope.close ()
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>