My solution:

let

  nixFilesInDirectory = directory:
    (
      map (file: "${directory}/${file}")
      (
        builtins.filter
          (
            nodeName:
              (builtins.isList (builtins.match ".+\.nix$" nodeName)) &&
              # checking that it is NOT a directory by seeing
              # if the node name forcefully used as a directory is an invalid path
              (!builtins.pathExists "${directory}/${nodeName}/.")
          )
          (builtins.attrNames (builtins.readDir directory))
      )
    );

  nixFilesInDirectories = directoryList:
    (
      builtins.concatMap
        (directory: nixFilesInDirectory directory)
        (directoryList)
    );
  # ...
in {
  imports = nixFilesInDirectories ([
      "${./programs}"
      "${./programs/terminal-niceties}"
  ]);
  # ...
}

snippet from the full source code: quazar-omega/home-manager-config (L5-L26)

credits:


I’m trying out Nix Home Manager and learning its features little by little.
I’ve been trying to split my app configurations into their own files now and saw that many do the following:

  1. Make a directory containing all the app specific configurations:
programs/
└── helix.nix
  1. Make a catch-all file default.nix that selectively imports the files inside:
programs/
├── default.nix
└── helix.nix

Content:

{
  imports = [
    ./helix.nix
  ];
}
  1. Import the directory (picking up the default.nix) within the home-manager configuration:
{
  # some stuff...
  imports = [
    ./programs
  ];
 # some other stuff...
}

I’d like to avoid having to write each and every file I’ll create into the imports of default.nix, that kinda defeats the point of separating it if I’ll have to specify everything anyway, so is there a way to do so? I haven’t found different ways to do this in various Nix discussions.


Example I’m looking at: https://github.com/fufexan/dotfiles/blob/main/home/terminal/default.nix

My own repository: https://codeberg.org/quazar-omega/home-manager-config

  • gomp@lemmy.ml
    link
    fedilink
    English
    arrow-up
    2
    ·
    6 months ago

    There’s the readDir builtin, but I expect nix might complain if you use that

    • QuazarOmegaOPA
      link
      fedilink
      English
      arrow-up
      3
      ·
      edit-2
      6 months ago

      Oh this is actually great! Searching it up a bit I came across this old Reddit thread that has a solution, so I applied it to my own config which first got me this:

      {
        # ...
        imports = builtins.map
          (file: "${./programs}/${file}")
          (builtins.attrNames (builtins.readDir ./programs));
        # ...
      }
      

      Then I wanted to refine it to only import .nix files (very much trial and error generated code, I don’t even know what I’m doing, but it somehow works lmao):

      {
        # ...
        imports = builtins.map
          (file: "${./programs}/${file}")
            (builtins.filter (file: (builtins.isList (builtins.match ".+\.nix$" file)))
            (builtins.attrNames (builtins.readDir ./programs)));
        # ...
      }
      

      Thanks for the tip, gotta say I’m very happy! Though I’m wondering how could there not be a simpler solution, it seems like such a common/basic thing to want, maybe what I’m doing is actually undesirable for some reason I’m too noob to understand?