Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default values, but properly this time #60

Merged
merged 3 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions builder/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ let
'';

thisPackage = packageDefinitions.${name} { inherit pkgs; };
categories = thisPackage.categories;
pkgCategories = thisPackage.categories;
settings = {
wrapRc = true;
viAlias = false;
Expand Down Expand Up @@ -109,8 +109,10 @@ let
optionalLuaAdditions = {};
optionalLuaPreInit = {};
bashBeforeWrapper = {};
extraCats = {}; # set of lists of lists of strings of other categories to enable
} // (categoryDefinitions {
inherit settings categories pkgs name;
categories = pkgCategories;
inherit settings pkgs name;
}));
inherit (final_cat_defs_set)
startupPlugins optionalPlugins lspsAndRuntimeDeps
Expand All @@ -122,6 +124,8 @@ let

ncTools = import ./ncTools.nix { inherit (pkgs) lib; };

categories = ncTools.applyExtraCats pkgCategories final_cat_defs_set.extraCats;

in
let
# copy entire flake to store directory
Expand Down
34 changes: 34 additions & 0 deletions builder/ncTools.nix
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,38 @@
);
in f [] [rhs lhs];

applyExtraCats = pkgcats: xtracats: let
applyExtraCatsInternal = prev: xtracats: pkgcats: let
filteredCatPaths = filterAndFlatten pkgcats xtracats;
# remove if already included
checkPath = atpath: if atpath == [] then true
else if lib.attrByPath atpath null pkgcats == true
then false
else checkPath (lib.reverseList (tail (lib.reverseList atpath)));
filtered = lib.unique (filter (v: checkPath v) filteredCatPaths);
toMerge = map (v: lib.setAttrByPath v true) filtered;
finalMergeable = foldl' recursiveUpdatePickShallower {} toMerge;
firstRes = recursiveUpdatePickShallower finalMergeable pkgcats;
# recurse until it doesnt change, so that values applying
# to the newly enabled categories can have an effect.
in if firstRes == prev then firstRes
else applyExtraCatsInternal firstRes xtracats firstRes;
in if xtracats == {} then pkgcats
else applyExtraCatsInternal pkgcats xtracats pkgcats;

recursiveUpdatePickShallower = lhs: rhs: let
pred = path: lh: rh: ! isAttrs lh || ! isAttrs rh;
picker = left: right: if ! isAttrs left then left else right;
f = attrPath:
zipAttrsWith (n: values:
let here = attrPath ++ [n]; in
if length values == 1 then
head values
else if pred here (elemAt values 1) (head values) then
picker (elemAt values 1) (head values)
else
f here values
);
in f [] [rhs lhs];

}
85 changes: 51 additions & 34 deletions nixCatsHelp/nixCats_format.txt
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,14 @@ github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/setup-hooks/make-wrapper
to run before the wrapper starts within the wrapper's bash environment.
CAUTION: only use this if you know what you are doing and why you need
to do it. Whenever possible, use extraWrapperArgs instead.
<extraCats>
a flexible set of categories, each containing a list of attribute paths,
specified as lists of strings. Thus each category would contain a list of
lists of strings.
Allows inclusion of extra categories contingent on each lists inclusion in the package,
and is useful for creating default values for subcategories.
For more info, see below at
:h |nixCats.flake.outputs.categoryDefinitions.default_values|
}

In essence, the contents of each set listed here are filtered
Expand Down Expand Up @@ -393,7 +401,9 @@ single derivation.
<
*nixCats.flake.outputs.categoryDefinitions.default_values*

First Kind: implicit, when value is in another section of categoryDefinitions
There are 2 ways of creating default values in nixCats.

#1 Implicit: when value is in another section of categoryDefinitions

If in your categoryDefinitions you had the following:
>nix
Expand Down Expand Up @@ -463,44 +473,51 @@ Sometimes it is not and a list of packages would be better suited.

This leads us to our second way to make a default value:

Second Way: explicit, default values within the same section of categoryDefinitions

`utils.catsWithDefault` takes the categories set passed to your
categoryDefinitions, the attribute path to the current set it is within,
a list of default values, and a set of subcategories
>nix
optionalPlugins = {
debug = utils.catsWithDefault categories [ "debug" ]
(with pkgs.vimPlugins; [
nvim-dap
nvim-dap-ui
nvim-dap-virtual-text
]) (with pkgs.vimPlugins; {
go = [ nvim-dap-go ];
});
};
<
If you were to put the following in your
categories set of a packageDefinitions function:
>nix
debug.go = true;
<
then it would also include the
values in the list passed as the 3rd argument.
#2 Explicit: using extraCats section of categoryDefinitions.

It also can accept an attrset as its default value:
extraCats section of categoryDefinitions contains categories of attribute
paths. If that category is defined, the categories specified by the attribute
paths will also be enabled. This means you could make it so that if you
included the go category, it could then enable debug.go and lsp.go for you.
But in addition to that, it can be combined with the implicit form of creating
default values above in an interesting way.
>nix
environmentVariables = {
test = utils.catsWithDefault categories [ "test" ] {
CATTESTVARDEFAULT = "It worked!";
} {
subtest1 = {
CATTESTVAR = "It worked!";
categoryDefinitions = { pkgs, settings, categories, name, ... }@packageDef: {
lspsAndRuntimeDeps = {
debug = with pkgs; {
go = [ delve ];
};
subtest2 = {
CATTESTVAR3 = "It didn't work!";
go = with pkgs; [
gopls
gotools
go-tools
gccgo
];
};
startupPlugins = {
debug = with pkgs.vimPlugins; {
default = [
nvim-dap
nvim-dap-ui
nvim-dap-virtual-text
];
go = [ nvim-dap-go ];
};
};
extraCats = {
# due to the implicit form of default values in different sections,
# this will enable debug.default
# if any subcategory of debug is enabled
# thus, enabling debug.go would also enable debug.default
debug = [
[ "debug" "default" ]
];
# and if go is enabled, it enables debug.go
# which then enables debug.default
go = [
[ "debug" "go" ] # yes it has to be a list of lists
];
};
};
<
---------------------------------------------------------------------------------------
Expand Down
44 changes: 32 additions & 12 deletions templates/example/flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,18 @@
# to get the name packadd expects, use the
# `:NixCats pawsible` command to see them all
optionalPlugins = {
debug = utils.catsWithDefault categories [ "debug" ]
(with pkgs.vimPlugins; [
nvim-dap
nvim-dap-ui
nvim-dap-virtual-text
]) (with pkgs.vimPlugins; {
debug = with pkgs.vimPlugins; {
# it is possible to add default values.
# there is nothing special about the word "default"
# but we have turned this subcategory into a default value
# via the extraCats section at the bottom of categoryDefinitions.
default = [
nvim-dap
nvim-dap-ui
nvim-dap-virtual-text
];
go = [ nvim-dap-go ];
});
};
lint = with pkgs.vimPlugins; [
nvim-lint
];
Expand Down Expand Up @@ -265,9 +269,10 @@
# this section is for environmentVariables that should be available
# at RUN TIME for plugins. Will be available to path within neovim terminal
environmentVariables = {
test = utils.catsWithDefault categories [ "test" ] {
CATTESTVARDEFAULT = "It worked!";
} {
test = {
default = {
CATTESTVARDEFAULT = "It worked!";
};
subtest1 = {
CATTESTVAR = "It worked!";
};
Expand Down Expand Up @@ -300,6 +305,20 @@
extraLuaPackages = {
general = [ (_:[]) ];
};

# this will enable test.default and debug.default
# if any subcategory of test or debug is enabled
extraCats = {
test = [
[ "test" "default" ]
];
debug = [
[ "debug" "default" ]
];
go = [
[ "debug" "go" ] # yes it has to be a list of lists
];
};
};


Expand Down Expand Up @@ -345,8 +364,10 @@
test = {
subtest1 = true;
};

# enabling this category will enable the go category,
# and ALSO debug.go and debug.default due to our extraCats in categoryDefinitions.
# go = true; # <- disabled but you could enable it with override
# debug.go = true; # <- disabled but you could enable it with override

# this does not have an associated category of plugins,
# but lua can still check for it
Expand Down Expand Up @@ -388,7 +409,6 @@
format = true;
test = true;
# go = true; # <- disabled but you could enable it with override
# debug.go = true; # <- disabled but you could enable it with override
lspDebugMode = false;
themer = true;
colorscheme = "catppuccin";
Expand Down
122 changes: 64 additions & 58 deletions utils/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -114,64 +114,6 @@ with builtins; rec {
# i.e. cache_location = mkLuaInline "vim.fn.stdpath('cache')",
mkLuaInline = expr: { __type = "nix-to-lua-inline"; inherit expr; };

# finds an included category in lib.attrByPath false categories
# adds defaults to it, returns the resulting set with the added values
# TODO: this is a somewhat brittle solution. Find a better one.
# but it works well enough for now,
# and will be fixable without changing the interface.
catsWithDefault = categories: attrpath: defaults: subcategories: let
include_path = let
flattener = cats: let
mapper = attrs: map (v: if isAttrs v then mapper v else v) (attrValues attrs);
flatten = accum: LoLoS: foldl' (acc: v: if any (i: isList i) v then flatten acc v else acc ++ [ v ]) accum LoLoS;
in flatten [] (mapper cats);

mapToSetOfPaths = cats: let
removeNullPaths = attrs: lib.filterAttrsRecursive (n: v: v != null) attrs;
mapToPaths = attrs: lib.mapAttrsRecursiveCond (as: ! lib.isDerivation as) (path: v: if v == true then path else null) attrs;
in removeNullPaths (mapToPaths cats);

result = let
final_cats = lib.attrByPath attrpath false categories;
allIncPaths = flattener (mapToSetOfPaths final_cats);
in if isAttrs final_cats && ! lib.isDerivation final_cats && allIncPaths != []
then head allIncPaths
else [];
in
result;

toMerge = let
firstGet = if isAttrs subcategories && ! lib.isDerivation subcategories
then lib.attrByPath include_path [] subcategories
else if isList subcategories then subcategories else [ subcategories ];

fIncPath = if isAttrs firstGet && ! lib.isDerivation firstGet
then include_path ++ [ "default" ] else include_path;

normed = let
listType = if isAttrs firstGet && ! lib.isDerivation firstGet
then lib.attrByPath fIncPath [] subcategories
else if isList firstGet then firstGet else [ firstGet ];
attrType = let
pre = if isAttrs firstGet && ! lib.isDerivation firstGet
then lib.attrByPath fIncPath {} subcategories
else firstGet;
basename = if fIncPath != [] then tail fIncPath else "default";
fin = if isAttrs pre && ! lib.isDerivation pre then pre else { ${basename} = pre; };
in
fin;
in
if isList defaults then listType else if isAttrs defaults then attrType else throw "defaults must be a list or a set";

final = lib.setAttrByPath fIncPath (if isList defaults then normed ++ defaults else { inherit normed; default = defaults; });
in
final;

in
if isAttrs subcategories && ! lib.isDerivation subcategories then
lib.recursiveUpdateUntilDRV subcategories toMerge
else toMerge;

# flake-utils' main function, because its all I used
# Builds a map from <attr>=value to <attr>.<system>=value for each system
eachSystem = systems: f:
Expand Down Expand Up @@ -315,6 +257,70 @@ with builtins; rec {
}
);

catsWithDefault = categories: attrpath: defaults: subcategories: let
include_path = let
flattener = cats: let
mapper = attrs: map (v: if isAttrs v then mapper v else v) (attrValues attrs);
flatten = accum: LoLoS: foldl' (acc: v: if any (i: isList i) v then flatten acc v else acc ++ [ v ]) accum LoLoS;
in flatten [] (mapper cats);

mapToSetOfPaths = cats: let
removeNullPaths = attrs: lib.filterAttrsRecursive (n: v: v != null) attrs;
mapToPaths = attrs: lib.mapAttrsRecursiveCond (as: ! lib.isDerivation as) (path: v: if v == true then path else null) attrs;
in removeNullPaths (mapToPaths cats);

result = let
final_cats = lib.attrByPath attrpath false categories;
allIncPaths = flattener (mapToSetOfPaths final_cats);
in if isAttrs final_cats && ! lib.isDerivation final_cats && allIncPaths != []
then head allIncPaths
else [];
in
result;

toMerge = let
firstGet = if isAttrs subcategories && ! lib.isDerivation subcategories
then lib.attrByPath include_path [] subcategories
else if isList subcategories then subcategories else [ subcategories ];

fIncPath = if isAttrs firstGet && ! lib.isDerivation firstGet
then include_path ++ [ "default" ] else include_path;

normed = let
listType = if isAttrs firstGet && ! lib.isDerivation firstGet
then lib.attrByPath fIncPath [] subcategories
else if isList firstGet then firstGet else [ firstGet ];
attrType = let
pre = if isAttrs firstGet && ! lib.isDerivation firstGet
then lib.attrByPath fIncPath {} subcategories
else firstGet;
basename = if fIncPath != [] then tail fIncPath else "default";
fin = if isAttrs pre && ! lib.isDerivation pre then pre else { ${basename} = pre; };
in
fin;
in
if isList defaults then listType else if isAttrs defaults then attrType else throw "defaults must be a list or a set";

final = lib.setAttrByPath fIncPath (if isList defaults then normed ++ defaults else { inherit normed; default = defaults; });
in
builtins.trace ''
nixCats.utils.catsWithDefault is being deprecated, due to be removed before 2025.

It is being removed due to not playing well
with merging categoryDefinitions together.

A new, more capable method has been added.

To create default values, use extraCats section of categoryDefinitions
as outlined in :h nixCats.flake.outputs.categoryDefinitions.default_values,
and demonstrated in the main example template
'' final;

in
if isAttrs subcategories && ! lib.isDerivation subcategories then
lib.recursiveUpdateUntilDRV subcategories toMerge
else toMerge;

};

# https://github.com/NixOS/nixpkgs/blob/nixos-23.05/lib/attrsets.nix
Expand Down