{
  inputs,
  lib,
  pkgs,
  pkgsHyprland,
  system,
}: {
  dotfiles = {
    home.activation = {
      /*
      Creates a consistent system requirement logging activation script.

      # Type

      ```
      systemRequirement :: String -> String -> (String | null) -> AttrSet
      ```

      # Arguments

      documentation
      : The documentation reference that can be ignored with `null`.

      literalExpression
      : The literal Nix expression that should be included in the system
        configuration.

      src
      : The module requiring the system configuration.

      # Examples

      ```nix
      documentation = "https://nixos.org/nixos/options.xhtml#opt-services.easyeffects.enable"
      literalExpression = "programs.dconf.enable = true;"
      src = "dotfiles.inputs.home-manager.services.easyeffects"

      systemRequirement src literalExpression documentation
      => {
        "dotfiles.inputs.home-manager.services.easyeffects" = {
          after = [ ... ];
          before = [ ... ];
          data = "printf 'trace: INFO: dotfiles.inputs.home-manager.services.easyeffects: %s\\n' \"include 'programs.dconf.enable = true;' in the system configuration: https://nixos.org/nixos/options.xhtml#opt-services.easyeffects.enable\"\n";
        };
      }

      systemRequirement src literalExpression null
      => {
        "dotfiles.inputs.home-manager.services.easyeffects" = {
          after = [ ... ];
          before = [ ... ];
          data = "printf 'trace: INFO: dotfiles.inputs.home-manager.services.easyeffects: %s\\n' \"include 'programs.dconf.enable = true;' in the system configuration\"\n";
        };
      }
      ```
      */
      systemRequirement = src: literalExpression: documentation:
        lib.dotfiles.home.activation.printf
        src
        "include '${literalExpression}' in the system configuration${
          lib.optionalString (documentation != null) ": ${documentation}"
        }";

      /*
      Creates a consistent logging activation script.

      # Type

      ```
      printf :: String -> String -> AttrSet
      ```

      # Arguments

      src
      : The module initiating the activation script.

      message
      : The message to print.

      # Examples

      ```nix
      config.nixpkgs.config.allowUnfree = true

      lib.dotfiles.lib.hm.dag.entryBefore.writeBoundary.printf
      "dotfiles.inputs.home-manager.nixpkgs.config.allowUnfree"
      "'nixpkgs.config.allowUnfree = ${
        lib.boolToString config.nixpkgs.config.allowUnfree
      };'";
      => {
        "dotfiles.inputs.home-manager.nixpkgs.config.allowUnfree" = {
          after = [ ... ];
          before = [ ... ];
          data = "printf 'trace: INFO: dotfiles.inputs.home-manager.nixpkgs.config.allowUnfree: %s\\n' \"'nixpkgs.config.allowUnfree = true;'\"\n";
        };
      }
      */
      printf = src: message: {
        ${src} = lib.hm.dag.entryBefore ["writeBoundary"] ''
          printf 'trace: INFO: %s: %s\n' "${src}" "${message}"
        '';
      };
    };

    homeManagerConfiguration = {
      /*
      Creates a named and extensible default Home Manager configuration.

      # Type

      ```
      homeManagerConfiguration :: String -> AttrSet -> AttrSet
      ```

      # Arguments

      extraConfig
      : The Home Manager configuration to merge with the default.

      meta
      : The `meta` attribute appended to the Home Manager configuration.

      name
      : The `<NAME>` of the Home Manager configuration, defined by the
        `<SYSTEM>-<ACCESSIBILITY>-<NAME>` naming convention.

      # Throws

      Throws an error if the Home Manager configuration already defines a `meta`
      attribute, preventing accidental overrides if Home Manager adds this
      attribute in future versions.

      # Examples

      ```nix
      homeManagerConfiguration
      "home-manager"
      {
        description =
          "Home Manager configuration enabling the home-manager program";
      }
      {
        imports = [modules/home-manager/programs/home-manager];
        config.dotfiles.inputs.home-manager.programs.home-manager.enable = true;
      }
      => { home-manager = { ... }; }
      ```
      */
      homeManagerConfiguration = name: meta: extraConfig: {
        ${name} =
          lib.attrsets.unionOfDisjoint
          (
            inputs.home-manager.lib.homeManagerConfiguration
            {
              inherit pkgs;

              extraSpecialArgs = {
                inherit inputs pkgsHyprland system;
                lib = lib.extend (_: _: inputs.home-manager.lib);
              };

              modules = [
                (
                  # The default config attribute set is merged with the
                  # extraConfig argument by merging the default config attribute
                  # set with extraConfig.config, using lib.mkMerge, and by
                  # merging the non-config extraConfig attributes with the
                  # merged config attribute, using the '//' operator. Excluding
                  # the extraConfig.config attribute from the '//' operation
                  # ensures that the default config.home attribute is not
                  # entirely overwritten by a potential extraConfig.config.home
                  # attribute, leveraging the same benefits lib.mkMerge has over
                  # '//'.
                  #
                  # Due to the following error, the more straightforward
                  # implementation of merging the default config attribute set
                  # directly with extraConfig, using lib.mkMerge, is not used:
                  #
                  #     error: The option `home.stateVersion' is used but not
                  #     defined.
                  #
                  # This error is most likely caused by the evaluation order
                  # implied by lib.mkMerge.
                  {config, ...}:
                    {
                      config = lib.mkMerge [
                        {
                          home = {
                            homeDirectory = "/home/${config.home.username}";
                            stateVersion = "23.05";
                            username = "naho";
                          };
                        }

                        (extraConfig.config or {})
                      ];
                    }
                    // builtins.removeAttrs extraConfig ["config"]
                )
              ];
            }
          )
          {inherit meta;};
      };

      /*
      Prepends a `prefix` to each attribute set key returned by a list of
      `files` to be imported.

      # Type

      ```
      prependPrefix :: String -> [Path] -> AttrSet
      ```

      # Arguments

      files
      : The list of files returning attribute sets to which to prepend the
        prefix to.

      prefix
      : The prefix to prepend to each attribute set key.

      # Examples

      ```nix
      import ./a
      => { a = { ... }; }

      import ./b
      => { b = { ... }; }

      prependPrefix "public" [./a ./b]
      => { public-a = { ... }; public-b = { ... }; }
      */
      prependPrefix = prefix: files:
        lib.mapAttrs'
        (
          name:
            lib.nameValuePair
            (prefix + lib.dotfiles.homeManagerConfiguration.separator + name)
        )
        (
          builtins.foldl'
          (acc: file: lib.attrsets.unionOfDisjoint acc (import file lib))
          {}
          files
        );

      /*
      The separator between the elements in the Home Manager configuration name.

      # Type

      ```
      separator :: String
      ```

      # Examples

      ```nix
      "<BEFORE>${separator}<AFTER>"
      => "<BEFORE>-<AFTER>"
      ```
      */
      separator = "-";
    };

    /*
    Recursively merges a list of attribute sets, similar to `lib.mkMerge`.

    Unlike `lib.mkMerge`, this returns a merged attribute set.

    # Type

    ```
    mergeAttrsMkMerge :: [AttrSet] -> AttrSet
    ```

    # Throws

    Throws an error if elements to be merged have different types.

    # Examples

    ```nix
    mergeAttrsMkMerge [
      {
        attrset = {
          attrset = {
            int = 0;
            list = [ 1 2 3 ];
          };
        };

        int = 4;
        list = [ 5 6 7 ];
      }
      {
        attrset = {
          attrset = {
            bool = false;
            int = 1;
          };
        };

        int = 1;
        list = [ 7 8 9 ];
      }
    ]
    => {
      attrset = {
        attrset = {
          bool = false;
          int = 1;
          list = [ 1 2 3 ];
        };
      };

      int = 1;
      list = [ 5 6 7 8 9 ];
    }

    mergeAttrsMkMerge [
      { int = 0; }
      { int = null; }
    ]
    => error: cannot merge different types: int and null
    ```
    */
    mergeAttrsMkMerge = lib.fix (
      self:
        builtins.zipAttrsWith (
          _: values: let
            expectedType = lib.last valueTypes;

            findFirst =
              lib.findFirst
              (type: type != expectedType)
              null
              valueTypes;

            last = lib.last values;
            valueTypes = map builtins.typeOf values;
          in
            lib.throwIf
            (findFirst != null)
            "cannot merge different types: ${findFirst} and ${expectedType}"
            (
              if builtins.isAttrs last
              then self values
              else if builtins.isList last
              then lib.unique (builtins.concatLists values)
              else last
            )
        )
    );

    /*
    Merges disjoint attribute sets.

    # Type

    ```
    mergeAttrsUnionOfDisjoint :: [AttrSet] -> AttrSet
    ```

    # Throws

    Throws an error for conflicting attribute keys.

    # Examples

    ```nix
    mergeAttrsUnionOfDisjoint [
      { a = 1; }
      { b = 2; }
      { c = 3; }
    ]
    => { a = 1; b = 2; c = 3; }

    mergeAttrsUnionOfDisjoint [
      { a = 1; d = 4; e = 5; }
      { b = 2; d = 4; f = 6; }
      { c = 3; e = 5; f = 6; }
    ]
    => error: unionOfDisjoint: collision on d; complete list: d
       error: unionOfDisjoint: collision on e; complete list: e f
       error: unionOfDisjoint: collision on f; complete list: e f
    */
    mergeAttrsUnionOfDisjoint = builtins.foldl' lib.attrsets.unionOfDisjoint {};

    /*
    `lib.mkEnableOption` wrapper with a custom `description`.

    # Type

    ```
    mkEnableOption :: String -> String -> AttrSet
    ```

    # Arguments

    module
    : The module attribute set containing the option to be enabled.

    option
    : The `module`-specific option.

    # Examples

    ```nix
    mkEnableOption "dotfiles.inputs.home-manager.programs.home-manager" "enable"
    => {
      _type = "option";
      default = false;
      description = "Whether to enable the internal `dotfiles.inputs.home-manager.programs.home-manager.enable` option.";
      example = true;
      type = { ... };
    }
    */
    mkEnableOption =
      lib.mkEnableOption (throw "initial description should never be evaluated")
      // {description = "";};

    /*
    `lib.mkOption` wrapper with a custom description for options interfacing
    Home Manager options.

    # Type

    ```
    mkInterfaceOption :: AttrSet -> AttrSet
    ```

    # Arguments

    attrs
    : The `lib.mkOption` argument.

    # Examples

    ```nix
    mkInterfaceOption { description = "programs.home-manager.enable"; }
    ==> {
      _type = "option";
      description = "Interfaces the\n[`programs.home-manager.enable`](https://nix-community.github.io/home-manager/options.xhtml)\noption.\n";
    }

    */
    mkInterfaceOption = attrs:
      lib.mkOption (
        attrs
        // {
          description = ''
            Interfaces the
            [`${attrs.description}`](
            https://nix-community.github.io/home-manager/options.xhtml)
            option.
          '';
        }
      );

    /*
    Creates the HTML body for `notify-send` notifications based on a list of
    `name`-`value` pairs.

    # Type

    ```
    body :: [{ name :: String; value :: String; }] -> String
    ```

    # Arguments

    name
    : The title of the `value`.

    value
    : The content of the `name`.

    # Examples

    ```nix
    body [
      (lib.nameValuePair "Title 1" "Content 1")
      (lib.nameValuePair "Title 2" "Content 2")
    ]
    => "<u>Title 1:</u> Content 1\n<u>Title 2:</u> Content 2\n"
    ```
    */
    notifySend.body = lib.concatMapStrings (
      {
        name,
        value,
      }: ''<u>${name}:</u> ${value}\n''
    );

    /*
    Raises the `base` to the power of `power`.

    Considering the small input size and the lack of a built-in power function
    [2], this naive power implementation should satisfy reasonable performance
    requirements.

    Due to the lack of a modulo and bitwise AND operator, it is questionable
    whether the recursive exponentiation by squaring [1] implementation would
    even be faster.

    [1]: https://en.wikipedia.org/wiki/Exponentiation_by_squaring
    [2]: https://github.com/NixOS/nix/issues/10387

    # Type

    ```
    pow :: Number -> Number -> Number
    ```

    # Arguments

    base
    : The base number to be raised.

    power
    : The exponent to raise `base` to.

    # Examples

    ```nix
    pow 2 5
    => 32
    ```
    */
    pow = lib.fix (
      self: base: power:
        if power != 0
        then base * (self base (power - 1))
        else 1
    );
  };
}
