pkgs: {
toKDL = let
lib = pkgs.lib;
util = import ../. pkgs;
inherit (lib)
concatStringsSep
mapAttrsToList
any
flip
flatten
filterAttrs
optional
const
;
inherit (builtins) typeOf replaceStrings elem;
inherit (util.str) concat;
inherit (util.fn) compose;
indentStrings = compose (concatStringsSep "\n") (map (concat "\t"));
sanitizeString = replaceStrings ["\n" ''"''] ["\\n" ''\"''];
literalValueToString = element: let type = typeOf element; in
if type == "null"
then "null"
else if type == "bool"
then
if element
then "true"
else "false"
else if type == "string"
then ''"${sanitizeString element}"''
else if elem type ["int" "float"]
then toString element
else abort "Not implemented type: ${type}";
convertAttrsToKDL = name: attrs: let
children =
((attrs._children or [])
|> map (mapAttrsToList convertAttributeToKDL)
|> flatten
)
++
(attrs
|> filterAttrs (name: const <|
!elem name [
"_args"
"_props"
"_children"
]
)
|> mapAttrsToList convertAttributeToKDL);
in
concatStringsSep " " (
[name]
++ map literalValueToString (attrs._args or [])
++ mapAttrsToList (name: value: "${name}=${literalValueToString value}") (attrs._props or {})
++ optional (children != []) ''
{
${indentStrings children}
}
''
);
convertListOfFlatAttrsToKDL = name: list: "${name} ${list |> map literalValueToString |> concatStringsSep " "}";
convertListOfNonFlatAttrsToKDL = name: list: ''
${name} {
${indentStrings (map (convertAttributeToKDL "-") list)}
}
'';
convertListToKDL = name: list:
if !any (flip elem list) ["list" "set"]
then convertListOfFlatAttrsToKDL name list
else convertListOfNonFlatAttrsToKDL name list;
convertAttributeToKDL = name: value: let
vType = typeOf value;
in
if elem vType [
"int"
"float"
"bool"
"null"
"string"
]
then "${name} ${literalValueToString value}"
else if vType == "set"
then convertAttrsToKDL name value
else if vType == "list"
then convertListToKDL name value
else abort ''
Cannot convert type `(${typeOf value})` to KDL:
${name} = ${toString value}
'';
in compose (concatStringsSep "\n") (mapAttrsToList convertAttributeToKDL);
}