{ lib, config, pkgs, ... }: let cfg = config.programs._neovim; extraPlugins = cfg.plugins.packages // { start = (cfg.plugins.packages.start or []) ++ lib.optionals cfg.plugins.lsp.enable [ cfg.plugins.lsp.pluginPackage ] ++ lib.optionals cfg.plugins.treesitter.enable [ cfg.plugins.treesitter.pluginPackage ] ++ lib.optionals cfg.plugins.treesitter.enable cfg.plugins.treesitter.parsers.packages; }; pluginDir = pkgs.linkFarm "nvim-site" (lib.concatLists (lib.mapAttrsToList (stage: plugins: map (plugin: { name = "share/nvim/site/pack/plugins/${stage}/${plugin.name}"; path = plugin; }) plugins ) extraPlugins)); extraPackages = cfg.extraPackages ++ lib.optionals cfg.plugins.lsp.enable cfg.plugins.lsp.languageServers.packages; finalPackage = pkgs.symlinkJoin { name = "neovim-not-wrapped"; paths = [ cfg.package ]; nativeBuildInputs = [ pkgs.makeWrapper ]; postBuild = '' wrapProgram $out/bin/nvim \ --prefix PATH : ${pkgs.lib.makeBinPath extraPackages} \ --prefix XDG_DATA_DIRS : ${pluginDir}/share '' + lib.optionalString cfg.viAlias '' ln -s $out/bin/nvim $out/bin/vi '' + lib.optionalString cfg.vimAlias '' ln -s $out/bin/nvim $out/bin/vim ''; }; in { options.programs._neovim = { enable = lib.mkEnableOption "install and configure neovim"; package = lib.mkPackageOption pkgs "neovim" {}; viAlias = lib.mkEnableOption "alias vi => nvim"; vimAlias = lib.mkEnableOption "alias vim => nvim"; plugins = { lsp = { enable = lib.mkEnableOption "install defined language servers into nvim path"; pluginPackage = lib.mkPackageOption pkgs.vimPlugins "nvim-lspconfig" {}; languageServers.packages = lib.mkOption { type = lib.types.listOf lib.types.package; default = [ ]; description = "language server packages to add to nvim path when lsp is enabled"; }; }; treesitter = { enable = lib.mkEnableOption "install treesitter and parsers as nvim plugins"; pluginPackage = lib.mkPackageOption pkgs.vimPlugins "nvim-treesitter" {}; parsers.packages = lib.mkOption { type = lib.types.listOf lib.types.package; default = [ ]; description = "treesitter parsers to install as plugins"; }; }; packages = lib.mkOption { type = lib.types.attrsOf (lib.types.listOf lib.types.package); default = [ ]; example = { start = with pkgs.vimPlugins; [ nvim-colorizer-lua ]; }; description = "extra plugins to be made available to nvim via packpath, organized by stage"; }; }; extraPackages = lib.mkOption { type = lib.types.listOf lib.types.package; default = [ ]; description = "extra packages to add to nvim path"; }; }; config = lib.mkIf cfg.enable { # NOTE: Don't use programs.neovim since that will build neovim from source home.packages = [ finalPackage ]; }; }