summaryrefslogtreecommitdiff
path: root/home-manager/neovim.nix
blob: 2b19257811068296bad7c27742513439c40f611b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
{ lib, config, pkgs, ... }: let
	cfg = config.programs._neovim;

	pluginDir = let
		extraPlugins = cfg.plugins.packages // {
			start = (cfg.plugins.packages.start or [])
				++ lib.optionals (cfg.plugins.lsp.enable && cfg.plugins.lsp.lspconfig.enable) [ cfg.plugins.lsp.lspconfig.pluginPackage ]
				++ lib.optionals cfg.plugins.treesitter.enable [ cfg.plugins.treesitter.pluginPackage ];
		};
	in 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 = pkgs.symlinkJoin {
		name = "nvim-extra-packages";
		paths = cfg.extraPackages
			++ lib.optionals cfg.plugins.lsp.enable cfg.plugins.lsp.languageServers.packages;
	};

	parserDir = let
		allTSParserPackages = builtins.filter lib.isDerivation
			(builtins.attrValues cfg.plugins.treesitter.parsers.installAllFromPackageSet);
	in pkgs.symlinkJoin {
		name = "nvim-treesitter-parsers";
		paths = if cfg.plugins.treesitter.parsers.installAll then allTSParserPackages else cfg.plugins.treesitter.parsers.packages;
	};

	finalPackage = pkgs.symlinkJoin {
		name = "neovim-not-wrapped";
		paths = [ cfg.package ];
		nativeBuildInputs = [ pkgs.makeWrapper ];
		postBuild = ''
			wrapProgram $out/bin/nvim \
				--prefix PATH : ${extraPackages} \
				--prefix XDG_DATA_DIRS : ${pluginDir}/share \
		'' + lib.optionalString cfg.plugins.treesitter.enable ''
				--add-flags '--cmd "set rtp^=${parserDir}"' \
				--add-flags '--cmd "set rtp^=${cfg.plugins.treesitter.pluginPackage}/runtime"' \
		'' + ''
			# blank line here to terminate multiline command string
		'' + 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";
				lspconfig = {
					enable = lib.mkEnableOption "install plugin `lspconfig.pluginPackage`";
					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.installAll = lib.mkEnableOption "install all available parsers. overrides `parsers.packages`";
				parsers.installAllFromPackageSet = lib.mkOption {
					  type = lib.types.attrsOf lib.types.anything;
					default = pkgs.vimPlugins.nvim-treesitter-parsers;
					defaultText = lib.literalExpression "pkgs.vimPlugins.nvim-treesitter-parsers";
					description = "parent package from which to install all treesitter parsers";
				};
				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 ];
	};
}