diff --git a/modules/output.nix b/modules/output.nix index 3aee8a1c..44f0d18a 100644 --- a/modules/output.nix +++ b/modules/output.nix @@ -27,28 +27,6 @@ with lib; let }; in { options = { - viAlias = mkOption { - type = types.bool; - default = false; - description = '' - Symlink vi to nvim binary. - ''; - }; - - vimAlias = mkOption { - type = types.bool; - default = false; - description = '' - Symlink vim to nvim binary. - ''; - }; - - package = mkOption { - type = types.package; - default = pkgs.neovim-unwrapped; - description = "Neovim to use for nixvim"; - }; - extraPlugins = mkOption { type = with types; listOf (either package pluginWithConfigType); default = []; @@ -64,42 +42,41 @@ in { extraConfigLua = mkOption { type = types.lines; default = ""; - description = "Extra contents for init.lua"; + description = "Extra contents for the file"; }; extraConfigLuaPre = mkOption { type = types.lines; default = ""; - description = "Extra contents for init.lua before everything else"; + description = "Extra contents for the file before everything else"; }; extraConfigLuaPost = mkOption { type = types.lines; default = ""; - description = "Extra contents for init.lua after everything else"; + description = "Extra contents for the file after everything else"; }; extraConfigVim = mkOption { type = types.lines; default = ""; - description = "Extra contents for init.vim"; + description = "Extra contents for the file, in vimscript"; }; - wrapRc = mkOption { - type = types.bool; - description = "Should the config be included in the wrapper script"; - default = false; + type = mkOption { + type = types.enum ["vim" "lua"]; + default = "lua"; + description = "Whether the generated file is a vim or a lua file"; }; - finalPackage = mkOption { - type = types.package; - description = "Wrapped neovim"; - readOnly = true; - }; - - initContent = mkOption { + path = mkOption { type = types.str; - description = "The content of the init.lua file"; + description = "Path of the file relative to the config directory"; + }; + + content = mkOption { + type = types.str; + description = "The content of the config file"; readOnly = true; visible = false; }; @@ -112,71 +89,29 @@ in { }; config = let - defaultPlugin = { - plugin = null; - config = ""; - optional = false; - }; + contentLua = '' + ${config.extraConfigLuaPre} + vim.cmd([[ + ${config.extraConfigVim} + ]]) + ${config.extraConfigLua} + ${config.extraConfigLuaPost} + ''; - normalizedPlugins = map (x: - defaultPlugin - // ( - if x ? plugin - then x - else {plugin = x;} - )) - config.extraPlugins; - - neovimConfig = pkgs.neovimUtils.makeNeovimConfig ({ - inherit (config) viAlias vimAlias extraLuaPackages; - # inherit customRC; - plugins = normalizedPlugins; - } - # Necessary to make sure the runtime path is set properly in NixOS 22.05, - # or more generally before the commit: - # cda1f8ae468 - neovim: pass packpath via the wrapper - // optionalAttrs (functionArgs pkgs.neovimUtils.makeNeovimConfig ? configure) { - configure.packages = { - nixvim = { - start = map (x: x.plugin) normalizedPlugins; - opt = []; - }; - }; - }); - - customRC = - '' - vim.cmd([[ - ${neovimConfig.neovimRcContent} - ]]) - '' - + (optionalString (config.extraConfigLuaPre != "") '' + contentVim = '' + lua << EOF ${config.extraConfigLuaPre} - '') - + (optionalString (config.extraConfigVim != "") '' - vim.cmd([[ - ${config.extraConfigVim} - ]]) - '') - + (optionalString (config.extraConfigLua != "" || config.extraConfigLuaPost != "") '' + EOF + ${config.extraConfigVim} + lua << EOF ${config.extraConfigLua} ${config.extraConfigLuaPost} - ''); - - extraWrapperArgs = builtins.concatStringsSep " " ( - (optional (config.extraPackages != []) - ''--prefix PATH : "${makeBinPath config.extraPackages}"'') - ++ (optional (config.wrapRc) - ''--add-flags -u --add-flags "${pkgs.writeText "init.lua" customRC}"'') - ); - - wrappedNeovim = pkgs.wrapNeovimUnstable config.package (neovimConfig - // { - wrapperArgs = lib.escapeShellArgs neovimConfig.wrapperArgs + " " + extraWrapperArgs; - wrapRc = false; - }); + EOF + ''; in { - finalPackage = wrappedNeovim; - initContent = customRC; + content = + if config.type == "lua" + then contentLua + else contentVim; }; } diff --git a/wrappers/_shared.nix b/wrappers/_shared.nix index 5d5086bb..e6e0727f 100644 --- a/wrappers/_shared.nix +++ b/wrappers/_shared.nix @@ -1,10 +1,18 @@ -{ +modules: { lib, pkgs, + config, ... }: let inherit (lib) mkEnableOption mkOption mkOptionType mkForce mkMerge mkIf types; in { + topLevelModules = + [ + ./modules/output.nix + (import ./modules/files.nix (modules pkgs)) + ] + ++ (modules pkgs); + helpers = mkOption { type = mkOptionType { name = "helpers"; @@ -14,4 +22,16 @@ in { description = "Use this option to access the helpers"; default = import ../plugins/helpers.nix {inherit (pkgs) lib;}; }; + + configFiles = let + cfg = config.programs.nixvim; + in + lib.mapAttrs' + ( + _: file: + lib.nameValuePair + "nvim/${file.path}" + {text = file.content;} + ) + cfg.files; } diff --git a/wrappers/darwin.nix b/wrappers/darwin.nix index 258d3a38..36f01cf8 100644 --- a/wrappers/darwin.nix +++ b/wrappers/darwin.nix @@ -5,19 +5,19 @@ modules: { ... } @ args: let inherit (lib) mkEnableOption mkOption mkOptionType mkForce mkMerge mkIf types; - shared = import ./_shared.nix args; + shared = import ./_shared.nix modules args; cfg = config.programs.nixvim; in { options = { programs.nixvim = mkOption { default = {}; - type = types.submodule ((modules pkgs) - ++ [ + type = types.submodule ([ { options.enable = mkEnableOption "nixvim"; config.wrapRc = mkForce true; } - ]); + ] + ++ shared.topLevelModules); }; nixvim.helpers = shared.helpers; }; diff --git a/wrappers/hm.nix b/wrappers/hm.nix index 476bec94..6c1a0bab 100644 --- a/wrappers/hm.nix +++ b/wrappers/hm.nix @@ -5,18 +5,23 @@ modules: { ... } @ args: let inherit (lib) mkEnableOption mkOption mkOptionType mkMerge mkIf types; - shared = import ./_shared.nix args; + shared = import ./_shared.nix modules args; cfg = config.programs.nixvim; + files = + shared.configFiles + // { + "nvim/init.lua".text = cfg.initContent; + }; in { options = { programs.nixvim = mkOption { default = {}; - type = types.submodule ((modules pkgs) - ++ [ + type = types.submodule ([ { options.enable = mkEnableOption "nixvim"; } - ]); + ] + ++ shared.topLevelModules); }; nixvim.helpers = shared.helpers; }; @@ -26,7 +31,7 @@ in { (mkMerge [ {home.packages = [cfg.finalPackage];} (mkIf (!cfg.wrapRc) { - xdg.configFile."nvim/init.lua".text = cfg.initContent; + xdg.configFile = files; }) { warnings = cfg.warnings; diff --git a/wrappers/modules/files.nix b/wrappers/modules/files.nix new file mode 100644 index 00000000..02fb98d4 --- /dev/null +++ b/wrappers/modules/files.nix @@ -0,0 +1,64 @@ +modules: { + pkgs, + config, + lib, + ... +}: let + inherit (lib) types; + fileModuleType = types.submodule ({ + name, + config, + ... + }: { + imports = modules; + options.plugin = lib.mkOption { + type = types.package; + description = "A derivation with the content of the file in it"; + readOnly = true; + internal = true; + }; + config = { + path = name; + type = lib.mkDefault ( + if lib.hasSuffix ".vim" name + then "vim" + else "lua" + ); + plugin = pkgs.writeTextDir config.path config.content; + }; + }); +in { + options = { + files = lib.mkOption { + type = types.attrsOf fileModuleType; + description = "Files to include in the vim config"; + default = {}; + }; + + filesPlugin = lib.mkOption { + type = types.package; + description = "A derivation with all the files inside"; + internal = true; + readOnly = true; + }; + }; + + config = let + files = config.files; + concatFilesOption = attr: + lib.flatten (lib.mapAttrsToList (_: file: builtins.getAttr attr file) files); + in { + # Each file can declare plugins/packages/warnings/assertions + extraPlugins = concatFilesOption "extraPlugins"; + extraPackages = concatFilesOption "extraPackages"; + warnings = concatFilesOption "warnings"; + assertions = concatFilesOption "assertions"; + + # A directory with all the files in it + filesPlugin = pkgs.buildEnv { + name = "nixvim-config"; + paths = lib.mapAttrsToList (_: file: file.plugin) files; + ignoreCollisions = true; # Collisions can't happen by construction + }; + }; +} diff --git a/wrappers/modules/output.nix b/wrappers/modules/output.nix new file mode 100644 index 00000000..d2fb042a --- /dev/null +++ b/wrappers/modules/output.nix @@ -0,0 +1,134 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; let + pluginWithConfigType = types.submodule { + options = { + config = mkOption { + type = types.lines; + description = "vimscript for this plugin to be placed in init.vim"; + default = ""; + }; + + optional = + mkEnableOption "optional" + // { + description = "Don't load by default (load with :packadd)"; + }; + + plugin = mkOption { + type = types.package; + description = "vim plugin"; + }; + }; + }; +in { + options = { + viAlias = mkOption { + type = types.bool; + default = false; + description = '' + Symlink vi to nvim binary. + ''; + }; + + vimAlias = mkOption { + type = types.bool; + default = false; + description = '' + Symlink vim to nvim binary. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.neovim-unwrapped; + description = "Neovim to use for nixvim"; + }; + + wrapRc = mkOption { + type = types.bool; + description = "Should the config be included in the wrapper script"; + default = false; + }; + + finalPackage = mkOption { + type = types.package; + description = "Wrapped neovim"; + readOnly = true; + }; + + initContent = mkOption { + type = types.str; + description = "The content of the init.lua file"; + readOnly = true; + visible = false; + }; + }; + + config = let + defaultPlugin = { + plugin = null; + config = ""; + optional = false; + }; + + normalizedPlugins = map (x: + defaultPlugin + // ( + if x ? plugin + then x + else {plugin = x;} + )) + config.extraPlugins; + + neovimConfig = pkgs.neovimUtils.makeNeovimConfig ({ + inherit (config) viAlias vimAlias; + # inherit customRC; + plugins = normalizedPlugins; + } + # Necessary to make sure the runtime path is set properly in NixOS 22.05, + # or more generally before the commit: + # cda1f8ae468 - neovim: pass packpath via the wrapper + // optionalAttrs (functionArgs pkgs.neovimUtils.makeNeovimConfig ? configure) { + configure.packages = { + nixvim = { + start = map (x: x.plugin) normalizedPlugins; + opt = []; + }; + }; + }); + + customRC = + '' + vim.cmd([[ + ${neovimConfig.neovimRcContent} + ]]) + '' + + config.content; + + extraWrapperArgs = builtins.concatStringsSep " " ( + (optional (config.extraPackages != []) + ''--prefix PATH : "${makeBinPath config.extraPackages}"'') + ++ (optional (config.wrapRc) + ''--add-flags -u --add-flags "${pkgs.writeText "init.lua" customRC}"'') + ); + + wrappedNeovim = pkgs.wrapNeovimUnstable config.package (neovimConfig + // { + wrapperArgs = lib.escapeShellArgs neovimConfig.wrapperArgs + " " + extraWrapperArgs; + wrapRc = false; + }); + in { + type = lib.mkForce "lua"; + finalPackage = wrappedNeovim; + initContent = customRC; + extraPlugins = + if config.wrapRc + then [config.filesPlugin] + else []; + }; +} diff --git a/wrappers/nixos.nix b/wrappers/nixos.nix index 1341f8b4..1e73af5c 100644 --- a/wrappers/nixos.nix +++ b/wrappers/nixos.nix @@ -5,18 +5,23 @@ modules: { ... } @ args: let inherit (lib) mkEnableOption mkOption mkOptionType mkMerge mkIf types; - shared = import ./_shared.nix args; + shared = import ./_shared.nix modules args; cfg = config.programs.nixvim; + files = + shared.configFiles + // { + "nvim/sysinit.lua".text = cfg.initContent; + }; in { options = { programs.nixvim = mkOption { default = {}; - type = types.submodule ((modules pkgs) - ++ [ + type = types.submodule ([ { options.enable = mkEnableOption "nixvim"; } - ]); + ] + ++ shared.topLevelModules); }; nixvim.helpers = shared.helpers; }; @@ -26,7 +31,7 @@ in { (mkMerge [ {environment.systemPackages = [cfg.finalPackage];} (mkIf (!cfg.wrapRc) { - environment.etc."nvim/sysinit.lua".text = cfg.initContent; + environment.etc = files; environment.variables."VIM" = "/etc/nvim"; }) { diff --git a/wrappers/standalone.nix b/wrappers/standalone.nix index f526d834..1dcab6f0 100644 --- a/wrappers/standalone.nix +++ b/wrappers/standalone.nix @@ -6,8 +6,13 @@ default_pkgs: modules: { wrap = {wrapRc = true;}; + shared = import ./_shared.nix modules { + inherit pkgs lib; + config = {}; + }; + eval = lib.evalModules { - modules = (modules pkgs) ++ [module wrap]; + modules = [module wrap] ++ shared.topLevelModules; }; handleAssertions = config: let