Dynamically creating an attribute set from option inside config

So, I’m working on a module for thefuck and getting kinda desperate trying to do something that I hoped was simple. This is my current module:

{ config, lib, pkgs, ... }:
with lib;
let
  cfg = config.programs.thefuck;
in {
  options.programs.thefuck = {
    enable = mkEnableOption "Magnificient app which corrects your previous console command";

    fucks = mkOption {
      type = with types; listOf path;
      default = [];
      description = "List of files to put under .config/thefuck/rules";
      example = literalExample ''
         [
          ./nix_command_not_found.py
         ]
      '';
    };
  };

  config = mkIf cfg.enable {
    home.packages = [ pkgs.thefuck ];

    home.file = listToAttrs (map (fuck: {
      name = ".config/thefuck/rules/${baseNameOf fuck}.source";
      value = fuck;
    }) cfg.fucks );

  };
}

What I want is that after evaluating my config (with the same value for fucks as the example) it creates something like this

{
  home.packages = [ thefuck ];

  home.files = {
    ".config/thefuck/rules".source = <path to nix_command_not_found>;
  };
}

Of course I would want to add more files in this way, but even with this simple example I can’t find how to do it. I’ve tried different forms using // or mkMerge but they always give me infinite recursion errors due to (my guess) using cfg.fucks in them.

Any ideas?

I managed to get it to work! For the record, this was my solution:

{ config, lib, pkgs, ... }:
with lib;
let
  cfg = config.programs.thefuck;
in {
  options.programs.thefuck = {
    enable = mkEnableOption "Magnificient app which corrects your previous console command";

    fucks = mkOption {
      type = with types; listOf path;
      default = [];
      description = "List of files to put under .config/thefuck/rules";
      example = literalExample ''
         [
          ./nix_command_not_found.py
         ]
      '';
    };
  };

  config = mkIf cfg.enable {
    home.packages = [ pkgs.thefuck ];

    home.file = mkMerge (map (fuck: {
      ".config/thefuck/rules/${baseNameOf fuck}".source = fuck;
    }) cfg.fucks);
  };
}

This is much cuter than my previous try and actually works.

1 Like