mirror of
https://github.com/nix-community/home-manager.git
synced 2025-11-08 19:46: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:
parent
c9d758b500
commit
89a9fa0f3f
4 changed files with 80 additions and 90 deletions
|
|
@ -211,9 +211,15 @@
|
||||||
toSCFG =
|
toSCFG =
|
||||||
{ }:
|
{ }:
|
||||||
let
|
let
|
||||||
inherit (lib) concatStringsSep mapAttrsToList any;
|
inherit (lib) concatStringsSep any;
|
||||||
inherit (builtins) typeOf replaceStrings elem;
|
inherit (builtins) typeOf replaceStrings elem;
|
||||||
|
|
||||||
|
filterNullDirectives = lib.filter (
|
||||||
|
directive:
|
||||||
|
!(directive ? "params" || directive ? "children")
|
||||||
|
|| !(directive.params or [ null ] == [ null ] && directive.children or [ ] == [ ])
|
||||||
|
);
|
||||||
|
|
||||||
# ListOf String -> String
|
# ListOf String -> String
|
||||||
indentStrings =
|
indentStrings =
|
||||||
let
|
let
|
||||||
|
|
@ -221,8 +227,8 @@
|
||||||
# the strings themselves *will* contain newlines, so you need
|
# the strings themselves *will* contain newlines, so you need
|
||||||
# to normalize the list by joining and resplitting them.
|
# to normalize the list by joining and resplitting them.
|
||||||
unlines = lib.splitString "\n";
|
unlines = lib.splitString "\n";
|
||||||
lines = lib.concatStringsSep "\n";
|
lines = concatStringsSep "\n";
|
||||||
indentAll = lines: concatStringsSep "\n" (map (x: " " + x) lines);
|
indentAll = lines: concatStringsSep "\n" (map (x: "\t" + x) lines);
|
||||||
in
|
in
|
||||||
stringsWithNewlines: indentAll (unlines (lines stringsWithNewlines));
|
stringsWithNewlines: indentAll (unlines (lines stringsWithNewlines));
|
||||||
|
|
||||||
|
|
@ -256,7 +262,7 @@
|
||||||
"\\"
|
"\\"
|
||||||
"\r"
|
"\r"
|
||||||
"\n"
|
"\n"
|
||||||
" "
|
"\t"
|
||||||
];
|
];
|
||||||
|
|
||||||
# OneOf [Int Float String Bool] -> String
|
# OneOf [Int Float String Bool] -> String
|
||||||
|
|
@ -284,7 +290,7 @@
|
||||||
# Bool -> ListOf (OneOf [Int Float String Bool]) -> String
|
# Bool -> ListOf (OneOf [Int Float String Bool]) -> String
|
||||||
toOptParamsString =
|
toOptParamsString =
|
||||||
cond: list:
|
cond: list:
|
||||||
lib.optionalString (cond) (
|
lib.optionalString cond (
|
||||||
lib.pipe list [
|
lib.pipe list [
|
||||||
(map literalValueToString)
|
(map literalValueToString)
|
||||||
(concatStringsSep " ")
|
(concatStringsSep " ")
|
||||||
|
|
@ -292,65 +298,25 @@
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
# Attrset Conversion
|
# Directive Conversion
|
||||||
# String -> AttrsOf Anything -> String
|
# ListOf NameParamChildrenTriplet -> ListOf String
|
||||||
convertAttrsToSCFG =
|
convertDirectivesToSCFG =
|
||||||
name: attrs:
|
directives:
|
||||||
let
|
map (
|
||||||
optParamsString = toOptParamsString (attrs ? "_params") attrs._params;
|
directive:
|
||||||
in
|
(literalValueToString directive.name)
|
||||||
''
|
+ toOptParamsString (directive ? "params" && directive.params != null) directive.params
|
||||||
${name}${optParamsString} {
|
+ lib.optionalString (directive ? "children" && directive.children != null) (
|
||||||
${indentStrings (convertToAttrsSCFG' attrs)}
|
" "
|
||||||
}'';
|
+ ''
|
||||||
|
{
|
||||||
# Attrset Conversion
|
${indentStrings (convertDirectivesToSCFG directive.children)}
|
||||||
# AttrsOf Anything -> ListOf String
|
}''
|
||||||
convertToAttrsSCFG' =
|
)
|
||||||
attrs:
|
) (filterNullDirectives directives);
|
||||||
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
|
in
|
||||||
attrs:
|
directives:
|
||||||
lib.optionalString (attrs != { }) ''
|
lib.optionalString (directives != [ ]) ''
|
||||||
${concatStringsSep "\n" (convertToAttrsSCFG' attrs)}
|
${lib.concatStringsSep "\n" (convertDirectivesToSCFG directives)}
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{ lib, ... }:
|
{ 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 = ''
|
nmt.script = ''
|
||||||
assertFileContent \
|
assertFileContent \
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@ dir {
|
||||||
blk1 p1 "\"p2\"" {
|
blk1 p1 "\"p2\"" {
|
||||||
sub1 arg11 arg12
|
sub1 arg11 arg12
|
||||||
sub2 arg21 arg22
|
sub2 arg21 arg22
|
||||||
|
sub2 arg1 arg2
|
||||||
sub3 arg31 arg32 {
|
sub3 arg31 arg32 {
|
||||||
sub-sub1
|
"sub sub1"
|
||||||
sub-sub2 arg321 arg322
|
sub-sub2 arg321 arg322
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,58 @@
|
||||||
{ lib, ... }:
|
{ lib, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
home.file."toscfg-example-result.txt".text = lib.hm.generators.toSCFG { } {
|
home.file."toscfg-example-result.txt".text = lib.hm.generators.toSCFG { } (
|
||||||
dir = {
|
lib.singleton {
|
||||||
blk1 = {
|
name = "dir";
|
||||||
_params = [
|
children = lib.singleton {
|
||||||
|
name = "blk1";
|
||||||
|
params = [
|
||||||
"p1"
|
"p1"
|
||||||
''"p2"''
|
''"p2"''
|
||||||
];
|
];
|
||||||
sub1 = [
|
children = [
|
||||||
"arg11"
|
{
|
||||||
"arg12"
|
name = "sub1";
|
||||||
|
params = [
|
||||||
|
"arg11"
|
||||||
|
"arg12"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "sub2";
|
||||||
|
params = [
|
||||||
|
"arg21"
|
||||||
|
"arg22"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "sub2";
|
||||||
|
params = [
|
||||||
|
"arg1"
|
||||||
|
"arg2"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "sub3";
|
||||||
|
params = [
|
||||||
|
"arg31"
|
||||||
|
"arg32"
|
||||||
|
];
|
||||||
|
children = [
|
||||||
|
{ name = "sub sub1"; }
|
||||||
|
{
|
||||||
|
name = "sub-sub2";
|
||||||
|
params = [
|
||||||
|
"arg321"
|
||||||
|
"arg322"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
];
|
];
|
||||||
sub2 = [
|
|
||||||
"arg21"
|
|
||||||
"arg22"
|
|
||||||
];
|
|
||||||
sub3 = {
|
|
||||||
_params = [
|
|
||||||
"arg31"
|
|
||||||
"arg32"
|
|
||||||
];
|
|
||||||
sub-sub1 = [ ];
|
|
||||||
sub-sub2 = [
|
|
||||||
"arg321"
|
|
||||||
"arg322"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
};
|
);
|
||||||
|
|
||||||
nmt.script = ''
|
nmt.script = ''
|
||||||
assertFileContent \
|
assertFileContent \
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue