Using imports attribute with import function

I have the following home manager structure. The root file of configuration is like this:

{
  pkgs,
  config,
  lib,
  ...
}: {
  programs = import ./programs {inherit pkgs config lib;};
  home = {
    stateVersion = "23.11";
  };
}

The default.nix file inside programs directory goes like this:

{
  pkgs,
  config,
  lib,
  ...
}: {
  # So basically, I want to split my config as much as possible. Especially with large configurations like neovim
  neovim = import ./neovim {inherit pkgs config lib;};
  alacritty = import ./alacritty {inherit pkgs config lib;};
  wezterm = import ./wezterm {inherit pkgs config lib;};
  tmux = import ./tmux {inherit pkgs config lib;};

  zsh = {
    enable = true;
  };
}

And finally, I have a default.nix file inside neovim directory that is like this

{
  pkgs,
  config,
  lib,
  ...
}: {
  # This is the place where I try to split my config assuming this will work as nixos module
  imports = [./plugins/lsp];

  enable = true;

  plugins = with pkgs.vimUtils;
  with pkgs.vimPlugins; [
    nvim-spectre
    # .
    # .
    # .
    # Really long list of plugins which I want to split
  ];

  extraPackages = with pkgs; [
    helm-ls # Helm language server
    # .
    # .
    # .
    # Really long list of packages which I want to split
  ];
}

And the default.nix file inside plugins/lsp folder which holds all lsp related configuration

{
  config,
  pkgs,
  ...
}: {
  plugins = with pkgs.vimPlugins; [
    {
      plugin = nvim-lspconfig;
      type = "lua";
      config = builtins.readFile ./plugins/nvim_lspconfig.lua;
    }
  ];
}

But this throws following error error: The option `home-manager.users.denis.programs.neovim.imports' does not exist. Which is true. At first, I assumed by just writing imports attribute it will just work as nixos module system but I was wrong. I did a bit of research about how nixos evaluates modules, find about config.system.build.toplevel and lib.evalModules but I wasn’t able to use them nor understand. Summarizing my question how to use import function when also recursively go over all imports attributes and finally merging everything into one attribute set?

Summarizing my question how to use import function when also recursively go over all imports attributes and finally merging everything into one attribute set?

basically you don’t, because that’s the module system’s job. instead of importing subtrees yourself you always write full modules, such that e.g. your neovim/default.nix assigns only to keys in the programs.neovim subtree, and list those in a “parent” imports list. recursively composing module is done via modules themselves importing more modules (that may restrict themselves to also assigning only to eg the programs.neovim subtree).

all modules in a configuration, including those recursively found via imports, are merged together during evaluation. due to this reason multiple modules can assign to the same subtree, so in your case you’d likely want to have a neovim/default.nix that’s

{ pkgs, config, lib, ... }: {
  imports = [ ./plugins/lsp ];
  programs.neovim = { ... };
}

and a neovim/plugins/lsp/default.nix that’s

{ pkgs, ... }: {
  programs.neovim.plugins = with pkgs.vimPlugins; [ { ... } ];
}

Yes, about that. This is how my configuration was written previously. I wanted to rewrite it differently, but in hindsight it probably wasn’t the best idea.