hello. first of all, i am pretty new in nix(os), so my understanding is a bit shaky sometimes. and sorry for the longread in advance.
i found your project while searching for ways to automate the process of importing modules. and your project looks amazing! it's like everything i wanted in my head.
before i found it, i even wanted to start implementing something like this by myself to comply with DRY principle, because modular configuration with options becomes boilerplate'y. and now i see no reason to. thank you.
so, i started to migrate my configuration. right now i have a structure for apps only: no "feature" sets like "cli", "gui", "development", etc..
aside from that, i have a single pattern: every module's enable option is dependent on parent's enable option. if shimeoki is enabled, then all shimeoki.XXX modules are enabled, if shimeoki.nixvim is enabled, then shimeoki.nixvim.plugins or shimeoki.nixvim.languages are enabled and so on.
i planned for my configuration to be used internally and externally. for my own usage, i can write
shimeoki = {
enable = true;
waybar.enable = false;
};
to enable everything, except for waybar. and other users can write
shimeoki = {
waybar.enable = true;
};
to enable waybar only.
i think it's pretty convenient. so, is this pattern possible in denix?
i tried to write
options = { myconfig, ... }: delib.singleEnableOption myconfig.enable;
but it errors, because "an option declaration has type lambda". i think that's because singleEnableOption is a function itself, so it becomes a closure.
of course, a declaration like this works:
options =
{ myconfig, ... }:
{
zoxide = with delib; {
enable = boolOption myconfig.enable;
};
};
but it's pretty verbose and not very convenient. something like this
options.zoxide =
{ myconfig, ... }:
with delib;
{
enable = boolOption myconfig.enable;
};
doesn't work, because the value assigned to options needs to be a lambda, and not to any of the values "below" options.
and besides from the verbosity, you need to write myconfig with full path to the current module. in case of a refactoring, this becomes a nightmare.
i think something like "relative paths", but for the modules would be amazing. my idea is to add a parent variable to the closure of options, which equals to "parent attribute set" of the current module name.
for example, the example above with more nested module would look like this:
options =
{ parent, ... }:
{
nixvim.plugins.lualine = with delib; {
enable = boolOption parent.enable; # parent equals to nixvim.plugins
};
};
and to go even further, this could be translated into the wrapper function like singleEnableOption:
options = delib.singleCascadeEnableOption { };
or singleEnableCascadeOption. naming is debatable. it shouldn't have an argument, but as i know all functions in nix should have one argument, and i don't know if this could be a non-function to "hide" the argument.
the issue is, that i don't know is this even implementable (and if so, i would like to help), and is this against your philosophy or not. maybe, this can be done as an extension.
that was the first problem. it was just about providing a convenient interface to functionality that's already available, but i don't know about the second problem in this regard.
as mentioned above, i want to allow other users to import my modules into their configuration to use them. so, i do something like this in my flake:
nixosModules.shimeoki = ./shimeoki/nixos.nix;
nixosModules.default = self.nixosModules.shimeoki;
homeModules.shimeoki = ./shimeoki/hm.nix;
homeModules.default = self.homeModules.shimeoki;
where ./shimeoki/nixos.nix imports all <app>/nixos modules. these modules contain only nixos options. ./shimeoki/hm.nix works the same way, but declares home-manager options. the code can be viewed in the repository.
and, as i think it should work, the user adds my flake to their flake in the inputs, and then writes something like this:
{ inputs, ... }:
{
imports = [
inputs.nixconfig.nixosModules.shimeoki
];
shimeoki.enable = true; # enable all nixos options from my modules
}
so, is this possible in denix? as i got it, it uses the "monomodule" approach, where delib.module contains the configuration for all platforms at once, and activates it based on the platform. if the platform is not nixos, then nixos is skipped, and the same applies to darwin and home. so, modules are not available to me, because they are "generated" dynamically based on the platform. is that right?
with this approach, is this possible to achieve similar functionality to mine? that the user can import modules for the selected platform from my flake and use them, i mean.
i haven't looked into the code yet, but if denix.lib.configurations uses "module generation based on platform" logic inside and then passes it to nixpkgs.lib.nixosSystem in modules, then the api can look something like this:
with denix.lib; {
nixosModules.shimeoki = modules "nixos";
homeModules.shimeoki = modules "home";
};
the issue with this approach that the nixos module in this case would export the home-manager modules as well (because if the platform is nixos, home platform is not disabled, but config is just declared in a different way), but i personally don't think it's a problem. it's probably weird to just import the nixos module without the home configuration, and many flakes do this as well (import home-manager module is nixos module is imported and home-manager is present).
hello. first of all, i am pretty new in nix(os), so my understanding is a bit shaky sometimes. and sorry for the longread in advance.
i found your project while searching for ways to automate the process of importing modules. and your project looks amazing! it's like everything i wanted in my head.
before i found it, i even wanted to start implementing something like this by myself to comply with DRY principle, because modular configuration with options becomes boilerplate'y. and now i see no reason to. thank you.
so, i started to migrate my configuration. right now i have a structure for apps only: no "feature" sets like "cli", "gui", "development", etc..
aside from that, i have a single pattern: every module's enable option is dependent on parent's enable option. if
shimeokiis enabled, then allshimeoki.XXXmodules are enabled, ifshimeoki.nixvimis enabled, thenshimeoki.nixvim.pluginsorshimeoki.nixvim.languagesare enabled and so on.i planned for my configuration to be used internally and externally. for my own usage, i can write
to enable everything, except for waybar. and other users can write
to enable waybar only.
i think it's pretty convenient. so, is this pattern possible in denix?
i tried to write
but it errors, because "an option declaration has type
lambda". i think that's because singleEnableOption is a function itself, so it becomes a closure.of course, a declaration like this works:
but it's pretty verbose and not very convenient. something like this
doesn't work, because the value assigned to
optionsneeds to be a lambda, and not to any of the values "below" options.and besides from the verbosity, you need to write
myconfigwith full path to the current module. in case of a refactoring, this becomes a nightmare.i think something like "relative paths", but for the modules would be amazing. my idea is to add a
parentvariable to the closure ofoptions, which equals to "parent attribute set" of the current module name.for example, the example above with more nested module would look like this:
and to go even further, this could be translated into the wrapper function like
singleEnableOption:or
singleEnableCascadeOption. naming is debatable. it shouldn't have an argument, but as i know all functions in nix should have one argument, and i don't know if this could be a non-function to "hide" the argument.the issue is, that i don't know is this even implementable (and if so, i would like to help), and is this against your philosophy or not. maybe, this can be done as an extension.
that was the first problem. it was just about providing a convenient interface to functionality that's already available, but i don't know about the second problem in this regard.
as mentioned above, i want to allow other users to import my modules into their configuration to use them. so, i do something like this in my flake:
where
./shimeoki/nixos.niximports all<app>/nixosmodules. these modules contain only nixos options../shimeoki/hm.nixworks the same way, but declares home-manager options. the code can be viewed in the repository.and, as i think it should work, the user adds my flake to their flake in the inputs, and then writes something like this:
so, is this possible in denix? as i got it, it uses the "monomodule" approach, where
delib.modulecontains the configuration for all platforms at once, and activates it based on the platform. if the platform is notnixos, thennixosis skipped, and the same applies todarwinandhome. so, modules are not available to me, because they are "generated" dynamically based on the platform. is that right?with this approach, is this possible to achieve similar functionality to mine? that the user can import modules for the selected platform from my flake and use them, i mean.
i haven't looked into the code yet, but if
denix.lib.configurationsuses "module generation based on platform" logic inside and then passes it tonixpkgs.lib.nixosSysteminmodules, then the api can look something like this:the issue with this approach that the nixos module in this case would export the home-manager modules as well (because if the platform is nixos, home platform is not disabled, but config is just declared in a different way), but i personally don't think it's a problem. it's probably weird to just import the nixos module without the home configuration, and many flakes do this as well (import home-manager module is nixos module is imported and home-manager is present).