1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-11-08 11:36:05 +01:00

generators: rewrite toSCFG

The former toSCFG implementation had several shortcomings which
did not consider a few possibilities SCFG provides. Details were lined
out in #7465.
The new interface needs more verbosity, but reflects better the
properties of the SCFG format. I also chose to use the names used in the
[Specification].

[Specification]: https://git.sr.ht/~emersion/scfg#specification-draft
This commit is contained in:
Anton Mosich 2025-09-01 23:40:41 +02:00 committed by Matthieu Coudron
parent c9d758b500
commit 89a9fa0f3f
4 changed files with 80 additions and 90 deletions

View file

@ -211,9 +211,15 @@
toSCFG =
{ }:
let
inherit (lib) concatStringsSep mapAttrsToList any;
inherit (lib) concatStringsSep any;
inherit (builtins) typeOf replaceStrings elem;
filterNullDirectives = lib.filter (
directive:
!(directive ? "params" || directive ? "children")
|| !(directive.params or [ null ] == [ null ] && directive.children or [ ] == [ ])
);
# ListOf String -> String
indentStrings =
let
@ -221,8 +227,8 @@
# the strings themselves *will* contain newlines, so you need
# to normalize the list by joining and resplitting them.
unlines = lib.splitString "\n";
lines = lib.concatStringsSep "\n";
indentAll = lines: concatStringsSep "\n" (map (x: " " + x) lines);
lines = concatStringsSep "\n";
indentAll = lines: concatStringsSep "\n" (map (x: "\t" + x) lines);
in
stringsWithNewlines: indentAll (unlines (lines stringsWithNewlines));
@ -256,7 +262,7 @@
"\\"
"\r"
"\n"
" "
"\t"
];
# OneOf [Int Float String Bool] -> String
@ -284,7 +290,7 @@
# Bool -> ListOf (OneOf [Int Float String Bool]) -> String
toOptParamsString =
cond: list:
lib.optionalString (cond) (
lib.optionalString cond (
lib.pipe list [
(map literalValueToString)
(concatStringsSep " ")
@ -292,65 +298,25 @@
]
);
# Attrset Conversion
# String -> AttrsOf Anything -> String
convertAttrsToSCFG =
name: attrs:
let
optParamsString = toOptParamsString (attrs ? "_params") attrs._params;
in
''
${name}${optParamsString} {
${indentStrings (convertToAttrsSCFG' attrs)}
}'';
# Attrset Conversion
# AttrsOf Anything -> ListOf String
convertToAttrsSCFG' =
attrs:
mapAttrsToList convertAttributeToSCFG (
lib.filterAttrs (name: val: !isNull val && name != "_params") attrs
);
# List Conversion
# String -> ListOf (OneOf [Int Float String Bool]) -> String
convertListOfFlatAttrsToSCFG =
name: list:
let
optParamsString = toOptParamsString (list != [ ]) list;
in
"${name}${optParamsString}";
# Combined Conversion
# String -> Anything -> String
convertAttributeToSCFG =
name: value:
lib.throwIf (name == "") "Directive must not be empty" (
let
vType = typeOf value;
in
if
elem vType [
"int"
"float"
"bool"
"string"
]
then
"${name} ${literalValueToString value}"
else if vType == "set" then
convertAttrsToSCFG name value
else if vType == "list" then
convertListOfFlatAttrsToSCFG name value
else
throw ''
Cannot convert type `(${typeOf value})` to SCFG:
${name} = ${toString value}
''
);
# Directive Conversion
# ListOf NameParamChildrenTriplet -> ListOf String
convertDirectivesToSCFG =
directives:
map (
directive:
(literalValueToString directive.name)
+ toOptParamsString (directive ? "params" && directive.params != null) directive.params
+ lib.optionalString (directive ? "children" && directive.children != null) (
" "
+ ''
{
${indentStrings (convertDirectivesToSCFG directive.children)}
}''
)
) (filterNullDirectives directives);
in
attrs:
lib.optionalString (attrs != { }) ''
${concatStringsSep "\n" (convertToAttrsSCFG' attrs)}
directives:
lib.optionalString (directives != [ ]) ''
${lib.concatStringsSep "\n" (convertDirectivesToSCFG directives)}
'';
}