Skip to content

Commit

Permalink
lib/to-lua: fix removing empties nested in lists
Browse files Browse the repository at this point in the history
- Add options for removing empty/null list entries (default false)
- Fix recursion into attrs that are themselves list entries

Fixes nix-community#1804
  • Loading branch information
MattSturgeon committed Jul 3, 2024
1 parent 87f50db commit 9b25eaa
Showing 2 changed files with 125 additions and 11 deletions.
46 changes: 35 additions & 11 deletions lib/to-lua.nix
Original file line number Diff line number Diff line change
@@ -84,9 +84,21 @@ rec {
*/
removeEmptyAttrValues ? true,

/**
If this option is true, lists like [ { } [ ] "" ]
will render as { "" }
*/
removeEmptyListEntries ? false,

/**
If this option is true, lists like [ null "" ]
will render as { "" }
*/
removeNullListEntries ? false,

/**
If this option is true, attrsets like { a.__empty = null; }
will render as { ["a"] = { } }, ignoring removeEmptyAttrValues and removeNullAttrValues.
will render as { ["a"] = { } }, ignoring other filters such as removeEmptyAttrValues.
*/
allowExplicitEmpty ? true,

@@ -111,7 +123,12 @@ rec {
}:
let
# If any of these are options are set, we need to preprocess the value
needsPreprocessing = removeNullAttrValues || removeEmptyAttrValues || allowExplicitEmpty;
needsPreprocessing =
allowExplicitEmpty
|| removeEmptyAttrValues
|| removeNullAttrValues
|| removeEmptyListEntries
|| removeNullListEntries;

# Slight optimization: only preprocess if we actually need to
preprocessValue = value: if needsPreprocessing then removeEmptiesRecursive value else value;
@@ -125,23 +142,30 @@ rec {
else if allowRawValues && value ? __raw then
value
else if isList value then
map removeEmptiesRecursive value
let
needsFiltering = removeNullListEntries || removeEmptyListEntries;
fn =
v: (removeNullListEntries -> (v != null)) && (removeEmptyListEntries -> (v != [ ] && v != { }));
v' = map removeEmptiesRecursive value;
in
if needsFiltering then filter fn v' else v'
else if isAttrs value then
concatMapAttrs (
n: v:
let
v' = removeEmptiesRecursive v;
in
if removeNullAttrValues && v == null then
{ }
else if removeEmptyAttrValues && (v == [ ] || v == { }) then
{ }
else if allowExplicitEmpty && v ? __empty then
{ ${n} = { }; }
else if isAttrs v then
let
v' = removeEmptiesRecursive v;
in
if v' == { } then { } else { ${n} = v'; }
# Optimisation: check if v is empty before evaluating v'
else if removeEmptyAttrValues && (v == [ ] || v == { }) then
{ }
else if removeEmptyAttrValues && (v' == [ ] || v' == { }) then
{ }
else
{ ${n} = v; }
{ ${n} = v'; }
) value
else
value;
90 changes: 90 additions & 0 deletions tests/lib-tests.nix
Original file line number Diff line number Diff line change
@@ -137,6 +137,55 @@ let
expected = ''{ }'';
};

testToLuaObjectAttrListFilters = {
expr = helpers.toLuaObject {
a = null;
b = { };
c = [ ];
d = {
e = null;
f = { };
};
g = [
{
x = null;
y = null;
z = null;
}
{
x = { };
y = [ ];
z = null;
}
];
__unkeyed-1 = [
{
x = null;
y = null;
z = null;
}
{
x = { };
y = [ ];
z = null;
}
[
{
x = null;
y = null;
z = null;
}
{
x = { };
y = [ ];
z = null;
}
]
];
};
expected = ''{ { { }, { }, { { }, { } } }, g = { { }, { } } }'';
};

testToLuaObjectEmptyTable = {
expr = helpers.toLuaObject {
a = null;
@@ -153,6 +202,47 @@ let
expected = ''{ c = { }, d = { g = { } } }'';
};

testToLuaObjectEmptyListEntries = {
expr = helpers.lua.toLua' { removeEmptyListEntries = true; } [
{ }
[ ]
[ { } ]
null
1
2
[
null
3
4
{ }
[ ]
[ { } ]
]
5
];
expected = "{ nil, 1, 2, { nil, 3, 4 }, 5 }";
};

testToLuaObjectNullListEntries = {
expr = helpers.lua.toLua' { removeNullListEntries = true; } [
null
1
2
[
null
3
4
[
null
5
6
]
]
7
];
expected = "{ 1, 2, { 3, 4, { 5, 6 } }, 7 }";
};

testIsLuaKeyword = {
expr = builtins.mapAttrs (_: builtins.filter helpers.lua.isKeyword) luaNames;
expected = {

0 comments on commit 9b25eaa

Please sign in to comment.