• 2 Posts
  • 17 Comments
Joined 1 year ago
cake
Cake day: August 10th, 2023

help-circle








  • I’ve analyzed the script a bit (…ok for more than 2 hours + 2 of refactoring), because the first time I absolutely didn’t understand it, now I’ve got it, but still, I won’t ever understand, why make the syntax so confusing?
    My system definition shouldn’t be a codegolfing competition (•ˋ _ ˊ•)

    TL;DR: I liked your script as a challenge to learn even more and I’m glad I did! Now I know a quite a bit more about the functions that Nix provides and how to use them, not a lot, but better than my previous almost 0, so thank you!

    Anyways, here's the unmangled thing explained for anyone else who's interested (wrote for plain evaluation, it's interesting what each part outputs):
    {
      /*
      builtins.unsafeGetAttrPos "_" { _ = null; }
    
      yields:
      {
        column = 46;
        file = "/path/to/this/slightly-unholy-file-finder.nix";
        line = 14;
      };
    
      you want to get the value of the name (which is the "key" in this key-value list) "file"
      */
      filePath = (builtins.unsafeGetAttrPos "_" { _ = null; }).file; # absolute path to current file
      directoryEntries = builtins.readDir ./.;
    
      entryNames = map
        (node: "./${node}")
        (
          # get name of files
          builtins.attrNames
            (
              /**
              use the function from before to remove this file right here
              from the set (NOT a list) of nodes found by readDir
              (may be files, dirs, etc.)
              
              Why?
              Because we start reading from the path ./
              which is where this file is located, of course
              */
              builtins.removeAttrs
                (builtins.readDir ./.)
                [
                  /*
                  get the current file name with some built-in, 
                  either un- or poorly documented function black magic fuckery
                  (I really wasn't able to find any proper documentation on this function)
                  */
                  (baseNameOf (builtins.unsafeGetAttrPos "_" { _ = null; }).file)
                ]
            )
        );
    }
    
    

    run it with:

    nix eval -f ./slightly-unholy-file-finder.nix
    

    There were multiple problems with this solution as I tried it:

    1. The missing baseName on line 39 which was needed to actually filter out the file path of the script that is being ran, because the paths I got out of readDir were relative (just for me? Did I change something in my environment? I’m not usre, the docs aren’t very clear)
    2. It doesn’t filter out files that are not .nix files
    3. It doesn’t filter out directories (may be intentional though, I personally don’t think that’s a great idea as far as I got)

    I’ll post later my own further improved solution starting from my own (tbh, by now more like our) script.




  • Thanks for the input! I figured there would be a reason why nobody seems to be doing it, but I still struggle to understand, at least for my current use case.
    What I’m trying to achieve for now is a solid configuration for my own user on any machine, I’m not trying to (and can’t) manage my own system currently as I’m using Fedora Kinoite as the host with only the Nix package manager installed. For now I haven’t had the chance to make machine specific configurations but I’m wondering, if on top of how it works now, we could write something like imports = [ ./programs/* ] and have all Nix files in that directory be imported, wouldn’t that be a good feature to have? Maybe you do have multiple machines, but maybe you also have several directories from where you will want to import everything regardless of the machine, sure you could make just one file for those if you’re not going to make distinctions, but I don’t want to put everything in one file because it would just get huge, whereas several files that do one thing are just easier to reason about to me.

    common collection of modules which must be imported everywhere

    That sounds interesting, do you have any examples I can refer to to know how to do that?

    Because NixOS/HM modules are monoidal, they often factor nicely.

    What does that mean exactly? I’m not really knowledgeable about functional programming, though that plus the rest of paragraph makes me think of how definitions are “composable” (maybe not the right word) in the sense that you can append and override options that are defined in other imported files without nullifying what was defined in them, is that it?



  • 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?