Skip to content

Commit

Permalink
lib: segregate and deprecate functions that need pkgs
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
MattSturgeon committed Sep 13, 2024
1 parent f47e8f8 commit 4e5bd1d
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 85 deletions.
7 changes: 6 additions & 1 deletion flake-modules/tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
...
}:
let
evaluatedNixvim = helpers.modules.evalNixvim { check = false; };
evaluatedNixvim = helpers.modules.evalNixvim {
extraSpecialArgs = {
defaultPkgs = pkgs;
};
check = false;
};
in
{
checks = {
Expand Down
121 changes: 73 additions & 48 deletions lib/builders.nix
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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"
Expand All @@ -56,74 +75,80 @@ 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
# 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)
''
);
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)
}
postFixupHooks+=(byteCompileLuaPostFixup)
''
);

/*
Returns an overridden derivation with all lua files byte compiled.
# 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 = ''
Expand All @@ -132,4 +157,4 @@ rec {
'';
}
);
}
})
53 changes: 42 additions & 11 deletions lib/default.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
pkgs,
pkgs ? null,
lib ? pkgs.lib,
_nixvimTests ? false,
...
Expand All @@ -14,10 +14,48 @@ lib.fix (
helpers = self; # TODO: stop using `helpers` in the subsections
lib = self.extendedLib;
};

# 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 { };
builders = call ./builders.nix { };
deprecation = call ./deprecation.nix { };
extendedLib = call ./extend-lib.nix { inherit lib; };
keymaps = call ./keymap-helpers.nix { };
Expand All @@ -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
Expand Down
14 changes: 6 additions & 8 deletions lib/modules.nix
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
6 changes: 4 additions & 2 deletions modules/files.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
...
}:
let
builders = lib.nixvim.builders.withPkgs pkgs;

fileTypeModule =
{
name,
Expand Down Expand Up @@ -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;
};
Expand Down
4 changes: 2 additions & 2 deletions modules/top-level/files/submodule.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
config,
lib,
pkgs,
helpers,
...
}:
{
Expand All @@ -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;
Expand Down
9 changes: 5 additions & 4 deletions modules/top-level/output.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
let
inherit (lib) types mkOption mkPackageOption;
inherit (lib) optional optionalString optionalAttrs;
builders = lib.nixvim.builders.withPkgs pkgs;
in
{
options = {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"
Expand All @@ -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
Expand Down
Loading

0 comments on commit 4e5bd1d

Please sign in to comment.