From 4e5bd1d79bb88b98e4d23241096989373150112c Mon Sep 17 00:00:00 2001 From: Matt Sturgeon Date: Thu, 12 Sep 2024 14:56:36 +0100 Subject: [PATCH] lib: segregate and deprecate functions that need `pkgs` Splits everything that depends on a `pkgs` instance into an optional attrs, allowing `helpers.nix` to be bootstrapped without `pkgs`. This required some refactoring: - `modules.specialArgs` is only available when `pkgs` is used - `modules.specialArgsWith` now requires `defaultPkgs` be provided - `builders.*` now have `*With` variants that take `pkgs` as an argument and a `withPkgs` function that returns the old interface - Had to define the fixed part of `builders` outside the attrs for now, to avoid infinite recursion. - The old `builders` are now deprecated, and print a warning when evaluated - `withOptoinalFns` was introduced to merge the optional attrs into the final lib. --- flake-modules/tests.nix | 7 +- lib/builders.nix | 117 +++++++++++------- lib/default.nix | 55 ++++++-- lib/modules.nix | 14 +-- modules/files.nix | 6 +- modules/top-level/files/submodule.nix | 4 +- modules/top-level/output.nix | 9 +- .../modules/performance/byte-compile-lua.nix | 18 ++- wrappers/darwin.nix | 5 +- wrappers/hm.nix | 5 +- wrappers/nixos.nix | 5 +- wrappers/standalone.nix | 4 +- 12 files changed, 165 insertions(+), 84 deletions(-) diff --git a/flake-modules/tests.nix b/flake-modules/tests.nix index 12b3f990..452102c1 100644 --- a/flake-modules/tests.nix +++ b/flake-modules/tests.nix @@ -10,7 +10,12 @@ ... }: let - evaluatedNixvim = helpers.modules.evalNixvim { check = false; }; + evaluatedNixvim = helpers.modules.evalNixvim { + extraSpecialArgs = { + defaultPkgs = pkgs; + }; + check = false; + }; in { checks = { diff --git a/lib/builders.nix b/lib/builders.nix index ec7443af..5eaceefb 100644 --- a/lib/builders.nix +++ b/lib/builders.nix @@ -1,21 +1,39 @@ -{ lib, pkgs }: -rec { +{ lib }: +# NOTE: use local recursion instead of accessing `lib.nixvim.builders`. +# The latter isn't a fixed shape since it may get the deprecated functions meregd in, +# which would lead to infinite recursion. +lib.fix (builders: { + # Curry a nixpkgs instance into the *With functions below, dropping the `With` suffix + withPkgs = + pkgs: + lib.concatMapAttrs ( + name: fn: + let + match' = builtins.match "(.*)With" name; + name' = builtins.head match'; + in + lib.optionalAttrs (match' != null) { + ${name'} = fn pkgs; + } + ) builders; + /* Write a lua file to the nix store, formatted using stylua. # Type ``` - writeLua :: String -> String -> Derivation + writeLuaWith :: pkgs -> String -> String -> Derivation ``` # Arguments + - [pkgs] A nixpkgs instance - [name] The name of the derivation - [text] The content of the lua file */ - writeLua = - name: text: + writeLuaWith = + pkgs: name: text: pkgs.runCommand name { inherit text; } '' echo -n "$text" > "$out" @@ -33,16 +51,17 @@ rec { # Type ``` - writeByteCompiledLua :: String -> String -> Derivation + writeByteCompiledLuaWith :: pkgs -> String -> String -> Derivation ``` # Arguments + - [pkgs] A nixpkgs instance - [name] The name of the derivation - [text] The content of the lua file */ - writeByteCompiledLua = - name: text: + writeByteCompiledLuaWith = + pkgs: name: text: pkgs.runCommandLocal name { inherit text; } '' echo -n "$text" > "$out" @@ -56,54 +75,57 @@ rec { # Type ``` - byteCompileLuaFile :: String -> String -> Derivation + byteCompileLuaFileWith :: pkgs -> String -> String -> Derivation ``` # Arguments + - [pkgs] A nixpkgs instance - [name] The name of the derivation - [src] The path to the source lua file */ - byteCompileLuaFile = - name: src: + byteCompileLuaFileWith = + pkgs: name: src: pkgs.runCommandLocal name { inherit src; } '' ${lib.getExe' pkgs.luajit "luajit"} -bd -- "$src" "$out" ''; # Setup hook to byte compile all lua files in the output directory. # Invalid lua files are ignored. - byteCompileLuaHook = pkgs.makeSetupHook { name = "byte-compile-lua-hook"; } ( - let - luajit = lib.getExe' pkgs.luajit "luajit"; - in - pkgs.writeText "byte-compile-lua-hook.sh" # bash - '' - byteCompileLuaPostFixup() { - # Target is a single file - if [[ -f $out ]]; then - if [[ $out = *.lua ]]; then - tmp=$(mktemp) - ${luajit} -bd -- "$out" "$tmp" - mv "$tmp" "$out" - fi - return - fi + byteCompileLuaHookWith = + pkgs: + pkgs.makeSetupHook { name = "byte-compile-lua-hook"; } ( + let + luajit = lib.getExe' pkgs.luajit "luajit"; + in + pkgs.writeText "byte-compile-lua-hook.sh" # bash + '' + byteCompileLuaPostFixup() { + # Target is a single file + if [[ -f $out ]]; then + if [[ $out = *.lua ]]; then + tmp=$(mktemp) + ${luajit} -bd -- "$out" "$tmp" + mv "$tmp" "$out" + fi + return + fi - # Target is a directory - while IFS= read -r -d "" file; do - tmp=$(mktemp -u "$file.XXXX") - # Ignore invalid lua files - if ${luajit} -bd -- "$file" "$tmp"; then - mv "$tmp" "$file" - else - echo "WARNING: Ignoring byte compiling error for '$file' lua file" >&2 - fi - done < <(find "$out" -type f,l -name "*.lua" -print0) - } + # Target is a directory + while IFS= read -r -d "" file; do + tmp=$(mktemp -u "$file.XXXX") + # Ignore invalid lua files + if ${luajit} -bd -- "$file" "$tmp"; then + mv "$tmp" "$file" + else + echo "WARNING: Ignoring byte compiling error for '$file' lua file" >&2 + fi + done < <(find "$out" -type f,l -name "*.lua" -print0) + } - postFixupHooks+=(byteCompileLuaPostFixup) - '' - ); + postFixupHooks+=(byteCompileLuaPostFixup) + '' + ); /* Returns an overridden derivation with all lua files byte compiled. @@ -111,19 +133,22 @@ rec { # Type ``` - byteCompileLuaDrv :: Derivation -> Derivation + byteCompileLuaDrvWith :: pkgs -> Derivation -> Derivation ``` # Arguments + - [pkgs] A nixpkgs instance - [drv] Input derivation */ - byteCompileLuaDrv = - drv: + byteCompileLuaDrvWith = + pkgs: drv: drv.overrideAttrs ( prev: { - nativeBuildInputs = prev.nativeBuildInputs or [ ] ++ [ byteCompileLuaHook ]; + nativeBuildInputs = prev.nativeBuildInputs or [ ] ++ [ + (lib.nixvim.builders.byteCompileLuaHookWith pkgs) + ]; } // lib.optionalAttrs (prev ? buildCommand) { buildCommand = '' @@ -132,4 +157,4 @@ rec { ''; } ); -} +}) diff --git a/lib/default.nix b/lib/default.nix index d7bd6dba..20edcf62 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,5 +1,5 @@ { - pkgs, + pkgs ? null, lib ? pkgs.lib, _nixvimTests ? false, ... @@ -14,10 +14,48 @@ lib.fix ( helpers = self; # TODO: stop using `helpers` in the subsections lib = self.extendedLib; }; - in - { - autocmd = call ./autocmd-helpers.nix { }; + + # Define this outside of the attrs to avoid infinite recursion, + # since the final value will have been merged from two places builders = call ./builders.nix { }; + + # Merge in deprecated functions that require a nixpkgs instance + # Does shallow recursion, only one level deeper than normal + # Does nothing when `pkgs` is null + withOptionalFns = + if pkgs == null then + lib.id + else + lib.recursiveUpdateUntil + ( + path: lhs: rhs: + builtins.length path > 1 + ) + { + # Minimal specialArgs required to evaluate nixvim modules + # FIXME: our minimal specialArgs should not need `pkgs` + modules.specialArgs = self.modules.specialArgsWith { + defaultPkgs = pkgs; + }; + + # We used to provide top-level access to the "builder" functions, with `pkgs` already baked in + # TODO: deprecated 2024-09-13; remove after 24.11 + builders = lib.mapAttrs ( + name: + lib.warn "`${name}` is deprecated. You should either use `${name}With` or access `${name}` via `builders.withPkgs`." + ) (builders.withPkgs pkgs); + + inherit (self.builders) + writeLua + writeByteCompiledLua + byteCompileLuaFile + byteCompileLuaHook + byteCompileLuaDrv + ; + }; + in + withOptionalFns { + autocmd = call ./autocmd-helpers.nix { }; deprecation = call ./deprecation.nix { }; extendedLib = call ./extend-lib.nix { inherit lib; }; keymaps = call ./keymap-helpers.nix { }; @@ -27,18 +65,11 @@ lib.fix ( options = call ./options.nix { }; utils = call ./utils.nix { inherit _nixvimTests; }; vim-plugin = call ./vim-plugin.nix { }; + inherit builders; # Top-level helper aliases: # TODO: deprecate some aliases - inherit (self.builders) - writeLua - writeByteCompiledLua - byteCompileLuaFile - byteCompileLuaHook - byteCompileLuaDrv - ; - inherit (self.deprecation) getOptionRecursive mkDeprecatedSubOptionModule diff --git a/lib/modules.nix b/lib/modules.nix index f58dee7b..c38e48a8 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -1,19 +1,17 @@ { - pkgs, lib, - helpers, + self, }: rec { - # Minimal specialArgs required to evaluate nixvim modules - specialArgs = specialArgsWith { }; - # Build specialArgs for evaluating nixvim modules specialArgsWith = - extraSpecialArgs: + # TODO: switch defaultPkgs -> pkgsPath (i.e. pkgs.path or inputs.nixvim) + # FIXME: Ideally, we should not require callers to pass in _anything_ specific + { defaultPkgs, ... }@extraSpecialArgs: { + inherit lib defaultPkgs; # TODO: deprecate `helpers` - inherit lib helpers; - defaultPkgs = pkgs; + helpers = self; } // extraSpecialArgs; diff --git a/modules/files.nix b/modules/files.nix index 6b5b3def..6389e211 100644 --- a/modules/files.nix +++ b/modules/files.nix @@ -6,6 +6,8 @@ ... }: let + builders = lib.nixvim.builders.withPkgs pkgs; + fileTypeModule = { name, @@ -73,10 +75,10 @@ let then if lib.isDerivation config.source then # Source is a derivation - helpers.byteCompileLuaDrv config.source + builders.byteCompileLuaDrv config.source else # Source is a path or string - helpers.byteCompileLuaFile derivationName config.source + builders.byteCompileLuaFile derivationName config.source else config.source; }; diff --git a/modules/top-level/files/submodule.nix b/modules/top-level/files/submodule.nix index c31a95c3..8f454337 100644 --- a/modules/top-level/files/submodule.nix +++ b/modules/top-level/files/submodule.nix @@ -3,7 +3,6 @@ config, lib, pkgs, - helpers, ... }: { @@ -18,7 +17,8 @@ config = let derivationName = "nvim-" + lib.replaceStrings [ "/" ] [ "-" ] name; - writeContent = if config.type == "lua" then helpers.writeLua else pkgs.writeText; + writeContent = + if config.type == "lua" then lib.nixvim.builders.writeLuaWith pkgs else pkgs.writeText; in { path = lib.mkDefault name; diff --git a/modules/top-level/output.nix b/modules/top-level/output.nix index 5ed993ee..66c47a28 100644 --- a/modules/top-level/output.nix +++ b/modules/top-level/output.nix @@ -8,6 +8,7 @@ let inherit (lib) types mkOption mkPackageOption; inherit (lib) optional optionalString optionalAttrs; + builders = lib.nixvim.builders.withPkgs pkgs; in { options = { @@ -91,7 +92,7 @@ in let byteCompile = p: - (helpers.byteCompileLuaDrv p).overrideAttrs ( + (builders.byteCompileLuaDrv p).overrideAttrs ( prev: lib.optionalAttrs (prev ? dependencies) { dependencies = map byteCompile prev.dependencies; } ); in @@ -223,8 +224,8 @@ in config.content ]; - textInit = helpers.writeLua "init.lua" customRC; - byteCompiledInit = helpers.writeByteCompiledLua "init.lua" customRC; + textInit = builders.writeLua "init.lua" customRC; + byteCompiledInit = builders.writeByteCompiledLua "init.lua" customRC; init = if config.type == "lua" @@ -250,7 +251,7 @@ in paths = [ config.package ]; # Required attributes from original neovim package inherit (config.package) lua meta; - nativeBuildInputs = [ helpers.byteCompileLuaHook ]; + nativeBuildInputs = [ builders.byteCompileLuaHook ]; postBuild = '' # Replace Nvim's binary symlink with a regular file, # or Nvim will use original runtime directory diff --git a/tests/test-sources/modules/performance/byte-compile-lua.nix b/tests/test-sources/modules/performance/byte-compile-lua.nix index e0dd61e3..1d42d654 100644 --- a/tests/test-sources/modules/performance/byte-compile-lua.nix +++ b/tests/test-sources/modules/performance/byte-compile-lua.nix @@ -1,4 +1,4 @@ -{ pkgs, helpers, ... }: +{ pkgs, ... }: let isByteCompiledFun = '' local function is_byte_compiled(filename) @@ -25,7 +25,15 @@ let in { default = - { config, ... }: + { + config, + lib, + pkgs, + ... + }: + let + writeLua = lib.nixvim.builders.writeLuaWith pkgs; + in { performance.byteCompileLua.enable = true; @@ -33,7 +41,7 @@ in # By text "plugin/file_text.lua".text = "vim.opt.tabstop = 2"; # By simple source derivation using buildCommand - "plugin/file_source.lua".source = helpers.writeLua "file_source.lua" "vim.opt.tabstop = 2"; + "plugin/file_source.lua".source = writeLua "file_source.lua" "vim.opt.tabstop = 2"; # By standard derivation, it needs to execute fixupPhase "plugin/file_drv.lua".source = pkgs.stdenvNoCC.mkDerivation { name = "file_drv.lua"; @@ -48,13 +56,13 @@ in "plugin/file_string.lua".source = builtins.toFile "file_path.lua" "vim.opt.tabstop = 2"; # By derivation converted to string "plugin/file_drv_string.lua".source = toString ( - helpers.writeLua "file_drv_string.lua" "vim.opt.tabstop = 2" + writeLua "file_drv_string.lua" "vim.opt.tabstop = 2" ); # Non-lua files "plugin/test.vim".text = "set tabstop=2"; "plugin/test.json".text = builtins.toJSON { a = 1; }; # Lua file with txt extension won't be byte compiled - "test.txt".source = helpers.writeLua "test.txt" "vim.opt.tabstop = 2"; + "test.txt".source = writeLua "test.txt" "vim.opt.tabstop = 2"; }; files = { diff --git a/wrappers/darwin.nix b/wrappers/darwin.nix index e9498a8e..6c36aed0 100644 --- a/wrappers/darwin.nix +++ b/wrappers/darwin.nix @@ -23,7 +23,10 @@ in default = { }; type = types.submoduleWith { shorthandOnlyDefinesConfig = true; - specialArgs = config.lib.nixvim.modules.specialArgsWith { darwinConfig = config; }; + specialArgs = config.lib.nixvim.modules.specialArgsWith { + defaultPkgs = pkgs; + darwinConfig = config; + }; modules = [ ./modules/darwin.nix ../modules/top-level diff --git a/wrappers/hm.nix b/wrappers/hm.nix index 32d2cbc5..ab518bb1 100644 --- a/wrappers/hm.nix +++ b/wrappers/hm.nix @@ -22,7 +22,10 @@ in default = { }; type = types.submoduleWith { shorthandOnlyDefinesConfig = true; - specialArgs = config.lib.nixvim.modules.specialArgsWith { hmConfig = config; }; + specialArgs = config.lib.nixvim.modules.specialArgsWith { + defaultPkgs = pkgs; + hmConfig = config; + }; modules = [ ./modules/hm.nix ../modules/top-level diff --git a/wrappers/nixos.nix b/wrappers/nixos.nix index 83a51aa1..516c8113 100644 --- a/wrappers/nixos.nix +++ b/wrappers/nixos.nix @@ -23,7 +23,10 @@ in default = { }; type = types.submoduleWith { shorthandOnlyDefinesConfig = true; - specialArgs = config.lib.nixvim.modules.specialArgsWith { nixosConfig = config; }; + specialArgs = config.lib.nixvim.modules.specialArgsWith { + defaultPkgs = pkgs; + nixosConfig = config; + }; modules = [ ./modules/nixos.nix ../modules/top-level diff --git a/wrappers/standalone.nix b/wrappers/standalone.nix index a3c79947..6cffc97a 100644 --- a/wrappers/standalone.nix +++ b/wrappers/standalone.nix @@ -19,7 +19,9 @@ let mod ./modules/standalone.nix ]; - inherit extraSpecialArgs; + extraSpecialArgs = { + defaultPkgs = pkgs; + } // extraSpecialArgs; }; inherit (evaledModule.config) enableMan finalPackage printInitPackage; in