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;
# 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
''
${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}
''
);
in
attrs:
lib.optionalString (attrs != { }) ''
${concatStringsSep "\n" (convertToAttrsSCFG' attrs)}
directives:
lib.optionalString (directives != [ ]) ''
${lib.concatStringsSep "\n" (convertDirectivesToSCFG directives)}
'';
}

View file

@ -1,7 +1,7 @@
{ lib, ... }:
{
home.file."toscfg-empty-result.txt".text = lib.hm.generators.toSCFG { } { };
home.file."toscfg-empty-result.txt".text = lib.hm.generators.toSCFG { } [ ];
nmt.script = ''
assertFileContent \

View file

@ -2,8 +2,9 @@ dir {
blk1 p1 "\"p2\"" {
sub1 arg11 arg12
sub2 arg21 arg22
sub2 arg1 arg2
sub3 arg31 arg32 {
sub-sub1
"sub sub1"
sub-sub2 arg321 arg322
}
}

View file

@ -1,35 +1,58 @@
{ lib, ... }:
{
home.file."toscfg-example-result.txt".text = lib.hm.generators.toSCFG { } {
dir = {
blk1 = {
_params = [
home.file."toscfg-example-result.txt".text = lib.hm.generators.toSCFG { } (
lib.singleton {
name = "dir";
children = lib.singleton {
name = "blk1";
params = [
"p1"
''"p2"''
];
sub1 = [
children = [
{
name = "sub1";
params = [
"arg11"
"arg12"
];
sub2 = [
}
{
name = "sub2";
params = [
"arg21"
"arg22"
];
sub3 = {
_params = [
}
{
name = "sub2";
params = [
"arg1"
"arg2"
];
}
{
name = "sub3";
params = [
"arg31"
"arg32"
];
sub-sub1 = [ ];
sub-sub2 = [
children = [
{ name = "sub sub1"; }
{
name = "sub-sub2";
params = [
"arg321"
"arg322"
];
}
];
}
];
};
};
};
};
}
);
nmt.script = ''
assertFileContent \