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.
This commit is contained in:
Matt Sturgeon 2024-09-12 14:56:36 +01:00
parent f47e8f8f79
commit 4e5bd1d79b
No known key found for this signature in database
GPG key ID: 4F91844CED1A8299
12 changed files with 165 additions and 84 deletions

View file

@ -10,7 +10,12 @@
... ...
}: }:
let let
evaluatedNixvim = helpers.modules.evalNixvim { check = false; }; evaluatedNixvim = helpers.modules.evalNixvim {
extraSpecialArgs = {
defaultPkgs = pkgs;
};
check = false;
};
in in
{ {
checks = { checks = {

View file

@ -1,21 +1,39 @@
{ lib, pkgs }: { lib }:
rec { # 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. Write a lua file to the nix store, formatted using stylua.
# Type # Type
``` ```
writeLua :: String -> String -> Derivation writeLuaWith :: pkgs -> String -> String -> Derivation
``` ```
# Arguments # Arguments
- [pkgs] A nixpkgs instance
- [name] The name of the derivation - [name] The name of the derivation
- [text] The content of the lua file - [text] The content of the lua file
*/ */
writeLua = writeLuaWith =
name: text: pkgs: name: text:
pkgs.runCommand name { inherit text; } '' pkgs.runCommand name { inherit text; } ''
echo -n "$text" > "$out" echo -n "$text" > "$out"
@ -33,16 +51,17 @@ rec {
# Type # Type
``` ```
writeByteCompiledLua :: String -> String -> Derivation writeByteCompiledLuaWith :: pkgs -> String -> String -> Derivation
``` ```
# Arguments # Arguments
- [pkgs] A nixpkgs instance
- [name] The name of the derivation - [name] The name of the derivation
- [text] The content of the lua file - [text] The content of the lua file
*/ */
writeByteCompiledLua = writeByteCompiledLuaWith =
name: text: pkgs: name: text:
pkgs.runCommandLocal name { inherit text; } '' pkgs.runCommandLocal name { inherit text; } ''
echo -n "$text" > "$out" echo -n "$text" > "$out"
@ -56,54 +75,57 @@ rec {
# Type # Type
``` ```
byteCompileLuaFile :: String -> String -> Derivation byteCompileLuaFileWith :: pkgs -> String -> String -> Derivation
``` ```
# Arguments # Arguments
- [pkgs] A nixpkgs instance
- [name] The name of the derivation - [name] The name of the derivation
- [src] The path to the source lua file - [src] The path to the source lua file
*/ */
byteCompileLuaFile = byteCompileLuaFileWith =
name: src: pkgs: name: src:
pkgs.runCommandLocal name { inherit src; } '' pkgs.runCommandLocal name { inherit src; } ''
${lib.getExe' pkgs.luajit "luajit"} -bd -- "$src" "$out" ${lib.getExe' pkgs.luajit "luajit"} -bd -- "$src" "$out"
''; '';
# Setup hook to byte compile all lua files in the output directory. # Setup hook to byte compile all lua files in the output directory.
# Invalid lua files are ignored. # Invalid lua files are ignored.
byteCompileLuaHook = pkgs.makeSetupHook { name = "byte-compile-lua-hook"; } ( byteCompileLuaHookWith =
let pkgs:
luajit = lib.getExe' pkgs.luajit "luajit"; pkgs.makeSetupHook { name = "byte-compile-lua-hook"; } (
in let
pkgs.writeText "byte-compile-lua-hook.sh" # bash luajit = lib.getExe' pkgs.luajit "luajit";
'' in
byteCompileLuaPostFixup() { pkgs.writeText "byte-compile-lua-hook.sh" # bash
# Target is a single file ''
if [[ -f $out ]]; then byteCompileLuaPostFixup() {
if [[ $out = *.lua ]]; then # Target is a single file
tmp=$(mktemp) if [[ -f $out ]]; then
${luajit} -bd -- "$out" "$tmp" if [[ $out = *.lua ]]; then
mv "$tmp" "$out" tmp=$(mktemp)
fi ${luajit} -bd -- "$out" "$tmp"
return mv "$tmp" "$out"
fi fi
return
fi
# Target is a directory # Target is a directory
while IFS= read -r -d "" file; do while IFS= read -r -d "" file; do
tmp=$(mktemp -u "$file.XXXX") tmp=$(mktemp -u "$file.XXXX")
# Ignore invalid lua files # Ignore invalid lua files
if ${luajit} -bd -- "$file" "$tmp"; then if ${luajit} -bd -- "$file" "$tmp"; then
mv "$tmp" "$file" mv "$tmp" "$file"
else else
echo "WARNING: Ignoring byte compiling error for '$file' lua file" >&2 echo "WARNING: Ignoring byte compiling error for '$file' lua file" >&2
fi fi
done < <(find "$out" -type f,l -name "*.lua" -print0) done < <(find "$out" -type f,l -name "*.lua" -print0)
} }
postFixupHooks+=(byteCompileLuaPostFixup) postFixupHooks+=(byteCompileLuaPostFixup)
'' ''
); );
/* /*
Returns an overridden derivation with all lua files byte compiled. Returns an overridden derivation with all lua files byte compiled.
@ -111,19 +133,22 @@ rec {
# Type # Type
``` ```
byteCompileLuaDrv :: Derivation -> Derivation byteCompileLuaDrvWith :: pkgs -> Derivation -> Derivation
``` ```
# Arguments # Arguments
- [pkgs] A nixpkgs instance
- [drv] Input derivation - [drv] Input derivation
*/ */
byteCompileLuaDrv = byteCompileLuaDrvWith =
drv: pkgs: drv:
drv.overrideAttrs ( drv.overrideAttrs (
prev: prev:
{ {
nativeBuildInputs = prev.nativeBuildInputs or [ ] ++ [ byteCompileLuaHook ]; nativeBuildInputs = prev.nativeBuildInputs or [ ] ++ [
(lib.nixvim.builders.byteCompileLuaHookWith pkgs)
];
} }
// lib.optionalAttrs (prev ? buildCommand) { // lib.optionalAttrs (prev ? buildCommand) {
buildCommand = '' buildCommand = ''
@ -132,4 +157,4 @@ rec {
''; '';
} }
); );
} })

View file

@ -1,5 +1,5 @@
{ {
pkgs, pkgs ? null,
lib ? pkgs.lib, lib ? pkgs.lib,
_nixvimTests ? false, _nixvimTests ? false,
... ...
@ -14,10 +14,48 @@ lib.fix (
helpers = self; # TODO: stop using `helpers` in the subsections helpers = self; # TODO: stop using `helpers` in the subsections
lib = self.extendedLib; lib = self.extendedLib;
}; };
in
{ # Define this outside of the attrs to avoid infinite recursion,
autocmd = call ./autocmd-helpers.nix { }; # since the final value will have been merged from two places
builders = call ./builders.nix { }; 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 { }; deprecation = call ./deprecation.nix { };
extendedLib = call ./extend-lib.nix { inherit lib; }; extendedLib = call ./extend-lib.nix { inherit lib; };
keymaps = call ./keymap-helpers.nix { }; keymaps = call ./keymap-helpers.nix { };
@ -27,18 +65,11 @@ lib.fix (
options = call ./options.nix { }; options = call ./options.nix { };
utils = call ./utils.nix { inherit _nixvimTests; }; utils = call ./utils.nix { inherit _nixvimTests; };
vim-plugin = call ./vim-plugin.nix { }; vim-plugin = call ./vim-plugin.nix { };
inherit builders;
# Top-level helper aliases: # Top-level helper aliases:
# TODO: deprecate some aliases # TODO: deprecate some aliases
inherit (self.builders)
writeLua
writeByteCompiledLua
byteCompileLuaFile
byteCompileLuaHook
byteCompileLuaDrv
;
inherit (self.deprecation) inherit (self.deprecation)
getOptionRecursive getOptionRecursive
mkDeprecatedSubOptionModule mkDeprecatedSubOptionModule

View file

@ -1,19 +1,17 @@
{ {
pkgs,
lib, lib,
helpers, self,
}: }:
rec { rec {
# Minimal specialArgs required to evaluate nixvim modules
specialArgs = specialArgsWith { };
# Build specialArgs for evaluating nixvim modules # Build specialArgs for evaluating nixvim modules
specialArgsWith = 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` # TODO: deprecate `helpers`
inherit lib helpers; helpers = self;
defaultPkgs = pkgs;
} }
// extraSpecialArgs; // extraSpecialArgs;

View file

@ -6,6 +6,8 @@
... ...
}: }:
let let
builders = lib.nixvim.builders.withPkgs pkgs;
fileTypeModule = fileTypeModule =
{ {
name, name,
@ -73,10 +75,10 @@ let
then then
if lib.isDerivation config.source then if lib.isDerivation config.source then
# Source is a derivation # Source is a derivation
helpers.byteCompileLuaDrv config.source builders.byteCompileLuaDrv config.source
else else
# Source is a path or string # Source is a path or string
helpers.byteCompileLuaFile derivationName config.source builders.byteCompileLuaFile derivationName config.source
else else
config.source; config.source;
}; };

View file

@ -3,7 +3,6 @@
config, config,
lib, lib,
pkgs, pkgs,
helpers,
... ...
}: }:
{ {
@ -18,7 +17,8 @@
config = config =
let let
derivationName = "nvim-" + lib.replaceStrings [ "/" ] [ "-" ] name; 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 in
{ {
path = lib.mkDefault name; path = lib.mkDefault name;

View file

@ -8,6 +8,7 @@
let let
inherit (lib) types mkOption mkPackageOption; inherit (lib) types mkOption mkPackageOption;
inherit (lib) optional optionalString optionalAttrs; inherit (lib) optional optionalString optionalAttrs;
builders = lib.nixvim.builders.withPkgs pkgs;
in in
{ {
options = { options = {
@ -91,7 +92,7 @@ in
let let
byteCompile = byteCompile =
p: p:
(helpers.byteCompileLuaDrv p).overrideAttrs ( (builders.byteCompileLuaDrv p).overrideAttrs (
prev: lib.optionalAttrs (prev ? dependencies) { dependencies = map byteCompile prev.dependencies; } prev: lib.optionalAttrs (prev ? dependencies) { dependencies = map byteCompile prev.dependencies; }
); );
in in
@ -223,8 +224,8 @@ in
config.content config.content
]; ];
textInit = helpers.writeLua "init.lua" customRC; textInit = builders.writeLua "init.lua" customRC;
byteCompiledInit = helpers.writeByteCompiledLua "init.lua" customRC; byteCompiledInit = builders.writeByteCompiledLua "init.lua" customRC;
init = init =
if if
config.type == "lua" config.type == "lua"
@ -250,7 +251,7 @@ in
paths = [ config.package ]; paths = [ config.package ];
# Required attributes from original neovim package # Required attributes from original neovim package
inherit (config.package) lua meta; inherit (config.package) lua meta;
nativeBuildInputs = [ helpers.byteCompileLuaHook ]; nativeBuildInputs = [ builders.byteCompileLuaHook ];
postBuild = '' postBuild = ''
# Replace Nvim's binary symlink with a regular file, # Replace Nvim's binary symlink with a regular file,
# or Nvim will use original runtime directory # or Nvim will use original runtime directory

View file

@ -1,4 +1,4 @@
{ pkgs, helpers, ... }: { pkgs, ... }:
let let
isByteCompiledFun = '' isByteCompiledFun = ''
local function is_byte_compiled(filename) local function is_byte_compiled(filename)
@ -25,7 +25,15 @@ let
in in
{ {
default = default =
{ config, ... }: {
config,
lib,
pkgs,
...
}:
let
writeLua = lib.nixvim.builders.writeLuaWith pkgs;
in
{ {
performance.byteCompileLua.enable = true; performance.byteCompileLua.enable = true;
@ -33,7 +41,7 @@ in
# By text # By text
"plugin/file_text.lua".text = "vim.opt.tabstop = 2"; "plugin/file_text.lua".text = "vim.opt.tabstop = 2";
# By simple source derivation using buildCommand # 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 # By standard derivation, it needs to execute fixupPhase
"plugin/file_drv.lua".source = pkgs.stdenvNoCC.mkDerivation { "plugin/file_drv.lua".source = pkgs.stdenvNoCC.mkDerivation {
name = "file_drv.lua"; name = "file_drv.lua";
@ -48,13 +56,13 @@ in
"plugin/file_string.lua".source = builtins.toFile "file_path.lua" "vim.opt.tabstop = 2"; "plugin/file_string.lua".source = builtins.toFile "file_path.lua" "vim.opt.tabstop = 2";
# By derivation converted to string # By derivation converted to string
"plugin/file_drv_string.lua".source = toString ( "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 # Non-lua files
"plugin/test.vim".text = "set tabstop=2"; "plugin/test.vim".text = "set tabstop=2";
"plugin/test.json".text = builtins.toJSON { a = 1; }; "plugin/test.json".text = builtins.toJSON { a = 1; };
# Lua file with txt extension won't be byte compiled # 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 = { files = {

View file

@ -23,7 +23,10 @@ in
default = { }; default = { };
type = types.submoduleWith { type = types.submoduleWith {
shorthandOnlyDefinesConfig = true; shorthandOnlyDefinesConfig = true;
specialArgs = config.lib.nixvim.modules.specialArgsWith { darwinConfig = config; }; specialArgs = config.lib.nixvim.modules.specialArgsWith {
defaultPkgs = pkgs;
darwinConfig = config;
};
modules = [ modules = [
./modules/darwin.nix ./modules/darwin.nix
../modules/top-level ../modules/top-level

View file

@ -22,7 +22,10 @@ in
default = { }; default = { };
type = types.submoduleWith { type = types.submoduleWith {
shorthandOnlyDefinesConfig = true; shorthandOnlyDefinesConfig = true;
specialArgs = config.lib.nixvim.modules.specialArgsWith { hmConfig = config; }; specialArgs = config.lib.nixvim.modules.specialArgsWith {
defaultPkgs = pkgs;
hmConfig = config;
};
modules = [ modules = [
./modules/hm.nix ./modules/hm.nix
../modules/top-level ../modules/top-level

View file

@ -23,7 +23,10 @@ in
default = { }; default = { };
type = types.submoduleWith { type = types.submoduleWith {
shorthandOnlyDefinesConfig = true; shorthandOnlyDefinesConfig = true;
specialArgs = config.lib.nixvim.modules.specialArgsWith { nixosConfig = config; }; specialArgs = config.lib.nixvim.modules.specialArgsWith {
defaultPkgs = pkgs;
nixosConfig = config;
};
modules = [ modules = [
./modules/nixos.nix ./modules/nixos.nix
../modules/top-level ../modules/top-level

View file

@ -19,7 +19,9 @@ let
mod mod
./modules/standalone.nix ./modules/standalone.nix
]; ];
inherit extraSpecialArgs; extraSpecialArgs = {
defaultPkgs = pkgs;
} // extraSpecialArgs;
}; };
inherit (evaledModule.config) enableMan finalPackage printInitPackage; inherit (evaledModule.config) enableMan finalPackage printInitPackage;
in in