Skip to content

Commit 65b71cb

Browse files
committed
modules/performance: add ability to byte compile lua configuration files
This commit adds support for byte compiling lua configuration files. It's enabled by default (if byte compiling is enabled at all) and can be disabled with `performance.byteCompileLua.configs` toggle. To implement this feature `extraFiles.<name>.finalSource` internal read-only option is introduced. `source` option cannot be used because it's user configurable. In order to access the values of the `performance.byteCompileLua` options, parent config is added to specialArgs of extraFiles submodule. Then the usages of `source` option changed to `finalSource` in all relevant places (filesPlugin and wrappers). Added more helpers for various cases of byte compiling: * `byteCompileLuaFile` byte compiles lua file * `byteCompileLuaHook` is a setup hook that byte compiles all lua files * `byteCompileLuaDrv` overrides derivation by adding byteCompileLuaHook to it Added tests to validate that extraFiles specified by various methods are handled correctly. Added a separate home-manager test, that is intended to validate that extraFiles propagated to wrapper modules are correctly byte compiled.
1 parent 05419f9 commit 65b71cb

File tree

10 files changed

+290
-14
lines changed

10 files changed

+290
-14
lines changed

flake-modules/wrappers.nix

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@
1515
inherit (inputs) home-manager;
1616
nixvim = self;
1717
}).activationPackage;
18+
home-manager-extra-files-byte-compiling =
19+
import ../tests/modules/hm-extra-files-byte-compiling.nix
20+
{
21+
inherit pkgs;
22+
inherit (inputs) home-manager;
23+
nixvim = self;
24+
};
1825
}
1926
// pkgs.lib.optionalAttrs (!pkgs.stdenv.isDarwin) {
2027
nixos-module =

lib/builders.nix

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{ lib, pkgs }:
2-
{
2+
rec {
33
/*
44
Write a lua file to the nix store, formatted using stylua.
55
@@ -48,4 +48,86 @@
4848
4949
${lib.getExe' pkgs.luajit "luajit"} -bd -- "$out" "$out"
5050
'';
51+
52+
/*
53+
Get a source lua file and write a byte compiled copy of it
54+
to the nix store.
55+
56+
# Type
57+
58+
```
59+
byteCompileLuaFile :: String -> String -> Derivation
60+
```
61+
62+
# Arguments
63+
64+
- [name] The name of the derivation
65+
- [src] The path to the source lua file
66+
*/
67+
byteCompileLuaFile =
68+
name: src:
69+
pkgs.runCommandLocal name { inherit src; } ''
70+
${lib.getExe' pkgs.luajit "luajit"} -bd -- "$src" "$out"
71+
'';
72+
73+
# Setup hook to byte compile all lua files in the output directory.
74+
# Invalid lua files are ignored.
75+
byteCompileLuaHook = pkgs.makeSetupHook { name = "byte-compile-lua-hook"; } (
76+
let
77+
luajit = lib.getExe' pkgs.luajit "luajit";
78+
in
79+
pkgs.writeText "byte-compile-lua-hook.sh" # bash
80+
''
81+
byteCompileLuaPostFixup() {
82+
# Target is a single file
83+
if [[ -f $out ]]; then
84+
if [[ $out = *.lua ]]; then
85+
tmp=$(mktemp)
86+
${luajit} -bd -- "$out" "$tmp"
87+
mv "$tmp" "$out"
88+
fi
89+
return
90+
fi
91+
92+
# Target is a directory
93+
while IFS= read -r -d "" file; do
94+
tmp=$(mktemp -u "$file.XXXX")
95+
# Ignore invalid lua files
96+
if ${luajit} -bd -- "$file" "$tmp"; then
97+
mv "$tmp" "$file"
98+
fi
99+
done < <(find "$out" -type f,l -name "*.lua" -print0)
100+
}
101+
102+
postFixupHooks+=(byteCompileLuaPostFixup)
103+
''
104+
);
105+
106+
/*
107+
Returns an overridden derivation with all lua files byte compiled.
108+
109+
# Type
110+
111+
```
112+
byteCompileLuaDrv :: Derivation -> Derivation
113+
```
114+
115+
# Arguments
116+
117+
- [drv] Input derivation
118+
*/
119+
byteCompileLuaDrv =
120+
drv:
121+
drv.overrideAttrs (
122+
prev:
123+
{
124+
nativeBuildInputs = prev.nativeBuildInputs or [ ] ++ [ byteCompileLuaHook ];
125+
}
126+
// lib.optionalAttrs (prev ? buildCommand) {
127+
buildCommand = ''
128+
${prev.buildCommand}
129+
runHook postFixup
130+
'';
131+
}
132+
);
51133
}

modules/files.nix

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
lib,
33
helpers,
44
pkgs,
5+
config,
56
...
67
}:
78
let
8-
fileType = lib.types.submodule (
9+
fileTypeModule =
910
{
1011
name,
1112
config,
1213
options,
14+
topConfig,
1315
...
1416
}:
1517
{
@@ -41,6 +43,14 @@ let
4143
type = lib.types.path;
4244
description = "Path of the source file.";
4345
};
46+
47+
finalSource = lib.mkOption {
48+
type = lib.types.path;
49+
description = "Path to the final source file.";
50+
readOnly = true;
51+
visible = false;
52+
internal = true;
53+
};
4454
};
4555

4656
config =
@@ -54,9 +64,29 @@ let
5464
# This means our `source` definition has the same priority as `text`.
5565
lib.mkDerivedConfig options.text (pkgs.writeText derivationName)
5666
);
67+
finalSource =
68+
# Byte compile lua files if performance.byteCompileLua option is enabled
69+
if
70+
lib.hasSuffix ".lua" config.target
71+
&& topConfig.performance.byteCompileLua.enable
72+
&& topConfig.performance.byteCompileLua.configs
73+
then
74+
if lib.isDerivation config.source then
75+
# Source is a derivation
76+
helpers.byteCompileLuaDrv config.source
77+
else
78+
# Source is a path or string
79+
helpers.byteCompileLuaFile derivationName config.source
80+
else
81+
config.source;
5782
};
58-
}
59-
);
83+
};
84+
85+
fileType = lib.types.submoduleWith {
86+
shorthandOnlyDefinesConfig = true;
87+
modules = [ fileTypeModule ];
88+
specialArgs.topConfig = config;
89+
};
6090

6191
# TODO: Added 2024-07-07, remove after 24.11
6292
# Before we had a fileType, we used types.str.

modules/performance.nix

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ in
1212
default = true;
1313
example = false;
1414
};
15+
configs = lib.mkOption {
16+
description = "Whether to byte compile lua configuration files.";
17+
type = types.bool;
18+
default = true;
19+
example = false;
20+
};
1521
};
1622

1723
combinePlugins = {

modules/top-level/files/default.nix

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@ in
8484
8585
mkdir -p "$out"
8686
${lib.concatMapStringsSep "\n" (
87-
{ target, source, ... }:
87+
{ target, finalSource, ... }:
8888
lib.escapeShellArgs [
8989
"makeEntry"
9090
# Force local source paths to be added to the store
91-
"${source}"
91+
"${finalSource}"
9292
target
9393
]
9494
) extraFiles}

tests/fetch-tests.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ let
1414
file = "${root}/${relativePath}/${name}";
1515
in
1616
if type == "regular" then
17-
[
17+
lib.optional (lib.hasSuffix ".nix" name) [
1818
{
1919
namespace = namespace ++ [ (lib.strings.removeSuffix ".nix" name) ];
2020
cases = import file;
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
{
2+
nixvim,
3+
pkgs,
4+
home-manager,
5+
}:
6+
let
7+
config = {
8+
home = {
9+
username = "nixvim";
10+
homeDirectory = "/invalid/dir";
11+
stateVersion = "24.05";
12+
};
13+
14+
programs.nixvim = {
15+
enable = true;
16+
17+
performance.byteCompileLua.enable = true;
18+
19+
extraFiles = {
20+
"extra-files/test1.lua".text = "vim.opt.tabstop = 2";
21+
"extra-files/test2.lua".source = builtins.toFile "file_source.lua" "vim.opt.tabstop = 2";
22+
"extra-files/test3.lua".source = pkgs.writeText "test3.lua" "vim.opt.tabstop = 2";
23+
"extra-files/test.vim".text = "set tabstop=2";
24+
"extra-files/test.json".text = builtins.toJSON { a = 1; };
25+
};
26+
27+
files = {
28+
"files/test.lua".opts.tabstop = 2;
29+
"files/test.vim".opts.tabstop = 2;
30+
};
31+
};
32+
};
33+
34+
homeFilesByteCompilingEnabled =
35+
(home-manager.lib.homeManagerConfiguration {
36+
inherit pkgs;
37+
38+
modules = [
39+
nixvim.homeManagerModules.nixvim
40+
config
41+
{ programs.nixvim.performance.byteCompileLua.configs = true; }
42+
];
43+
}).config.home-files;
44+
45+
homeFilesByteCompilingDisabled =
46+
(home-manager.lib.homeManagerConfiguration {
47+
inherit pkgs;
48+
49+
modules = [
50+
nixvim.homeManagerModules.nixvim
51+
config
52+
{ programs.nixvim.performance.byteCompileLua.configs = false; }
53+
];
54+
}).config.home-files;
55+
in
56+
pkgs.runCommand "home-manager-extra-files-byte-compiling" { } ''
57+
is_binary() {
58+
! grep -qI . "$1"
59+
}
60+
test_byte_compiled() {
61+
if ! is_binary "$home_files/.config/nvim/$1"; then
62+
echo "File $1 is expected to be byte compiled, but it's not"
63+
exit 1
64+
fi
65+
}
66+
test_not_byte_compiled() {
67+
if is_binary "$home_files/.config/nvim/$1"; then
68+
echo "File $1 is not expected to be byte compiled, but it is"
69+
exit 1
70+
fi
71+
}
72+
73+
# Test directory with extraFiles byte compiling enabled
74+
home_files="${homeFilesByteCompilingEnabled}"
75+
76+
echo "Testing home-files with extraFiles byte compiling enabled"
77+
78+
# extraFiles
79+
test_byte_compiled extra-files/test1.lua
80+
test_byte_compiled extra-files/test2.lua
81+
test_byte_compiled extra-files/test3.lua
82+
test_not_byte_compiled extra-files/test.vim
83+
test_not_byte_compiled extra-files/test.json
84+
# files
85+
test_byte_compiled files/test.lua
86+
test_not_byte_compiled files/test.vim
87+
88+
# Test directory with extraFiles byte compiling disabled
89+
home_files="${homeFilesByteCompilingDisabled}"
90+
91+
echo "Testing home-files with extraFiles byte compiling disabled"
92+
93+
# extraFiles
94+
test_not_byte_compiled extra-files/test1.lua
95+
test_not_byte_compiled extra-files/test2.lua
96+
test_not_byte_compiled extra-files/test3.lua
97+
test_not_byte_compiled extra-files/test.vim
98+
test_not_byte_compiled extra-files/test.json
99+
# files
100+
test_not_byte_compiled files/test.lua
101+
test_not_byte_compiled files/test.vim
102+
103+
touch $out
104+
''

tests/test-sources/modules/performance/byte-compile-lua.nix

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,31 @@ in
3030
performance.byteCompileLua.enable = true;
3131

3232
extraFiles = {
33+
# By text
3334
"plugin/file_text.lua".text = "vim.opt.tabstop = 2";
35+
# By simple source derivation using buildCommand
3436
"plugin/file_source.lua".source = helpers.writeLua "file_source.lua" "vim.opt.tabstop = 2";
37+
# By standard derivation, it needs to execute fixupPhase
38+
"plugin/file_drv.lua".source = pkgs.stdenvNoCC.mkDerivation {
39+
name = "file_drv.lua";
40+
src = pkgs.emptyDirectory;
41+
buildPhase = ''
42+
echo "vim.opt.tabstop = 2" > $out
43+
'';
44+
};
45+
# By path
46+
"plugin/file_path.lua".source = ./files/file.lua;
47+
# By string
48+
"plugin/file_string.lua".source = builtins.toFile "file_path.lua" "vim.opt.tabstop = 2";
49+
# By derivation converted to string
50+
"plugin/file_drv_string.lua".source = toString (
51+
helpers.writeLua "file_drv_string.lua" "vim.opt.tabstop = 2"
52+
);
53+
# Non-lua files
3554
"plugin/test.vim".text = "set tabstop=2";
3655
"plugin/test.json".text = builtins.toJSON { a = 1; };
56+
# Lua file with txt extension won't be byte compiled
57+
"test.txt".source = helpers.writeLua "test.txt" "vim.opt.tabstop = 2";
3758
};
3859

3960
files = {
@@ -64,14 +85,19 @@ in
6485
local init_content = vim.fn.system("${config.printInitPackage}/bin/nixvim-print-init")
6586
assert(init_content:find("VALIDATING_STRING"), "nixvim-print-init's output is byte compiled")
6687
67-
-- extraFiles
68-
test_rtp_file("plugin/file_text.lua", false)
69-
test_rtp_file("plugin/file_source.lua", false)
88+
-- lua extraFiles are byte compiled
89+
test_rtp_file("plugin/file_text.lua", true)
90+
test_rtp_file("plugin/file_source.lua", true)
91+
test_rtp_file("plugin/file_drv.lua", true)
92+
test_rtp_file("plugin/file_path.lua", true)
93+
test_rtp_file("plugin/file_string.lua", true)
94+
test_rtp_file("plugin/file_drv_string.lua", true)
7095
test_rtp_file("plugin/test.vim", false)
7196
test_rtp_file("plugin/test.json", false)
97+
test_rtp_file("test.txt", false)
7298
73-
-- files
74-
test_rtp_file("plugin/file.lua", false)
99+
-- lua files are byte compiled
100+
test_rtp_file("plugin/file.lua", true)
75101
test_rtp_file("plugin/file.vim", false)
76102
77103
-- Plugins and neovim runtime aren't byte compiled by default
@@ -136,4 +162,24 @@ in
136162
assert(not is_byte_compiled(init), "MYVIMRC is not expected to be byte compiled, but it is")
137163
'';
138164
};
165+
166+
configs-disabled = {
167+
performance.byteCompileLua = {
168+
enable = true;
169+
configs = false;
170+
};
171+
172+
extraFiles."plugin/test1.lua".text = "vim.opt.tabstop = 2";
173+
174+
files."plugin/test2.lua".opts.tabstop = 2;
175+
176+
extraConfigLuaPost = ''
177+
${isByteCompiledFun}
178+
179+
-- extraFiles
180+
test_rtp_file("plugin/test1.lua", false)
181+
-- files
182+
test_rtp_file("plugin/test2.lua", false)
183+
'';
184+
};
139185
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
vim.opt.tabstop = 2

0 commit comments

Comments
 (0)