From 086873bed9ff25b6aa3ea05b707645f2d9d1d174 Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Sun, 7 Jul 2024 16:09:31 +0100 Subject: [PATCH] modules: refactor `extraFiles` Moved `extraFiles` from `modules/output.nix` into its own file `modules/files.nix`. Users should now assign text to a `text` attribute, however they could also assign a file path to a `source` attribute instead. The old method of directly assigning a string still works, and is coerced to the new type along with a deprecation warning. --- modules/default.nix | 1 + modules/files.nix | 82 +++++++++++++++++++++ modules/output.nix | 6 -- modules/top-level/files/default.nix | 43 +++++++++-- modules/top-level/files/submodule.nix | 15 ++-- plugins/languages/treesitter/treesitter.nix | 2 +- tests/test-sources/modules/extra-files.nix | 8 +- wrappers/_shared.nix | 28 +++++-- 8 files changed, 157 insertions(+), 28 deletions(-) create mode 100644 modules/files.nix diff --git a/modules/default.nix b/modules/default.nix index 878bb02b..7b2c2c18 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -12,6 +12,7 @@ ./diagnostics.nix ./doc.nix ./editorconfig.nix + ./files.nix ./filetype.nix ./highlights.nix ./keymaps.nix diff --git a/modules/files.nix b/modules/files.nix new file mode 100644 index 00000000..68606af0 --- /dev/null +++ b/modules/files.nix @@ -0,0 +1,82 @@ +{ + lib, + helpers, + pkgs, + ... +}: +let + fileType = lib.types.submodule ( + { + name, + config, + options, + ... + }: + { + options = { + enable = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Whether this file should be generated. + This option allows specific files to be disabled. + ''; + }; + + target = lib.mkOption { + type = lib.types.str; + defaultText = lib.literalMD "the attribute name"; + description = '' + Name of symlink, relative to nvim config. + ''; + }; + + text = lib.mkOption { + type = with lib.types; nullOr lines; + default = null; + description = "Text of the file."; + }; + + source = lib.mkOption { + type = lib.types.path; + description = "Path of the source file."; + }; + }; + + config = + let + derivationName = "nvim-" + lib.replaceStrings [ "/" ] [ "-" ] name; + in + { + target = lib.mkDefault name; + source = lib.mkIf (config.text != null) ( + # mkDerivedConfig uses the option's priority, and calls our function with the option's value. + # This means our `source` definition has the same priority as `text`. + lib.mkDerivedConfig options.text (pkgs.writeText derivationName) + ); + }; + } + ); + + # TODO: Added 2024-07-07, remove after 24.11 + # Before we had a fileType, we used types.str. + coercedFileType = helpers.transitionType lib.types.str (text: { inherit text; }) fileType; +in +{ + options = { + extraFiles = lib.mkOption { + type = lib.types.attrsOf coercedFileType; + description = "Extra files to add to the runtime path"; + default = { }; + example = lib.literalExpression '' + { + "ftplugin/nix.lua".text = ''' + vim.opt.tabstop = 2 + vim.opt.shiftwidth = 2 + vim.opt.expandtab = true + '''; + } + ''; + }; + }; +} diff --git a/modules/output.nix b/modules/output.nix index 22163f60..0cfdd5b7 100644 --- a/modules/output.nix +++ b/modules/output.nix @@ -95,12 +95,6 @@ in description = "Extra lua packages to include with neovim"; default = _: [ ]; }; - - extraFiles = mkOption { - type = types.attrsOf types.str; - description = "Extra files to add to the runtime path"; - default = { }; - }; }; config = diff --git a/modules/top-level/files/default.nix b/modules/top-level/files/default.nix index cdd2910c..c8a3d248 100644 --- a/modules/top-level/files/default.nix +++ b/modules/top-level/files/default.nix @@ -1,6 +1,7 @@ { pkgs, config, + options, lib, helpers, ... @@ -49,8 +50,8 @@ in config = let - inherit (config) files; - concatFilesOption = attr: lib.flatten (lib.mapAttrsToList (_: builtins.getAttr attr) files); + extraFiles = lib.filter (file: file.enable) (lib.attrValues config.extraFiles); + concatFilesOption = attr: lib.flatten (lib.mapAttrsToList (_: builtins.getAttr attr) config.files); in { # Each file can declare plugins/packages/warnings/assertions @@ -59,12 +60,38 @@ in warnings = concatFilesOption "warnings"; assertions = concatFilesOption "assertions"; + # Add files to extraFiles + extraFiles = lib.mkDerivedConfig options.files ( + lib.mapAttrs' ( + _: file: { + name = file.path; + value.source = file.plugin; + } + ) + ); + # A directory with all the files in it - filesPlugin = pkgs.buildEnv { - name = "nixvim-config"; - paths = - (lib.mapAttrsToList (_: file: file.plugin) files) - ++ (lib.mapAttrsToList pkgs.writeTextDir config.extraFiles); - }; + # Implementation based on NixOS's /etc module + filesPlugin = pkgs.runCommandLocal "nvim-config" { } '' + set -euo pipefail + + makeEntry() { + src="$1" + target="$2" + mkdir -p "$out/$(dirname "$target")" + cp "$src" "$out/$target" + } + + mkdir -p "$out" + ${lib.concatMapStringsSep "\n" ( + { target, source, ... }: + lib.escapeShellArgs [ + "makeEntry" + # Force local source paths to be added to the store + "${source}" + target + ] + ) extraFiles} + ''; }; } diff --git a/modules/top-level/files/submodule.nix b/modules/top-level/files/submodule.nix index 0de14b29..13095bb6 100644 --- a/modules/top-level/files/submodule.nix +++ b/modules/top-level/files/submodule.nix @@ -14,9 +14,14 @@ internal = true; }; }; - config = { - path = name; - type = lib.mkDefault (if lib.hasSuffix ".vim" name then "vim" else "lua"); - plugin = pkgs.writeTextDir config.path config.content; - }; + config = + let + derivationName = "nvim-" + lib.replaceStrings [ "/" ] [ "-" ] name; + in + { + path = lib.mkDefault name; + type = lib.mkDefault (if lib.hasSuffix ".vim" name then "vim" else "lua"); + # No need to use mkDerivedConfig; this option is readOnly. + plugin = pkgs.writeText derivationName config.content; + }; } diff --git a/plugins/languages/treesitter/treesitter.nix b/plugins/languages/treesitter/treesitter.nix index 81b9f14d..9999c2cf 100644 --- a/plugins/languages/treesitter/treesitter.nix +++ b/plugins/languages/treesitter/treesitter.nix @@ -178,7 +178,7 @@ in ''); extraFiles = mkIf cfg.nixvimInjections { - "queries/nix/injections.scm" = '' + "queries/nix/injections.scm".text = '' ;; extends (binding diff --git a/tests/test-sources/modules/extra-files.nix b/tests/test-sources/modules/extra-files.nix index 33807e49..ba6a645a 100644 --- a/tests/test-sources/modules/extra-files.nix +++ b/tests/test-sources/modules/extra-files.nix @@ -1,7 +1,13 @@ { query = { extraFiles = { - "queries/lua/injections.scm" = '' + "testing/test-case.nix".source = ./extra-files.nix; + "testing/123.txt".text = '' + One + Two + Three + ''; + "queries/lua/injections.scm".text = '' ;; extends ''; }; diff --git a/wrappers/_shared.nix b/wrappers/_shared.nix index 026fc655..0a68f04f 100644 --- a/wrappers/_shared.nix +++ b/wrappers/_shared.nix @@ -1,23 +1,37 @@ helpers: { lib, config, ... }: let - inherit (lib) mkOption mkOptionType; + inherit (lib) + isAttrs + listToAttrs + map + mkOption + mkOptionType + ; cfg = config.programs.nixvim; + extraFiles = lib.filter (file: file.enable) (lib.attrValues cfg.extraFiles); in { helpers = mkOption { type = mkOptionType { name = "helpers"; description = "Helpers that can be used when writing nixvim configs"; - check = builtins.isAttrs; + check = isAttrs; }; description = "Use this option to access the helpers"; default = helpers; }; - configFiles = - (lib.mapAttrs' (_: file: lib.nameValuePair "nvim/${file.path}" { text = file.content; }) cfg.files) - // (lib.mapAttrs' ( - path: content: lib.nameValuePair "nvim/${path}" { text = content; } - ) cfg.extraFiles); + # extraFiles, but nested under "nvim/" for use in etc/xdg config + configFiles = listToAttrs ( + map ( + { target, source, ... }: + { + name = "nvim/" + target; + value = { + inherit source; + }; + } + ) extraFiles + ); }