Skip to content

Commit 9dfc40e

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 added. `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). To byte compile derivations `byteCompileLuaHook` is added to helpers. 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 also byte compiled.
1 parent f2f87d6 commit 9dfc40e

File tree

10 files changed

+231
-13
lines changed

10 files changed

+231
-13
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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,24 @@
4848
4949
${lib.getExe' pkgs.luajit "luajit"} -bd -- "$out" "$out"
5050
'';
51+
52+
# Setup hook to byte compile all lua files in output directory
53+
byteCompileLuaHook = pkgs.makeSetupHook { name = "byte-compile-lua-hook"; } (
54+
let
55+
luajit = lib.getExe' pkgs.luajit "luajit";
56+
in
57+
pkgs.writeText "byte-compile-lua-hook.sh" # bash
58+
''
59+
byteCompileLuaPostFixup() {
60+
while IFS= read -r -d "" file; do
61+
tmp=$(mktemp -u "$file.XXXX")
62+
if ${luajit} -bd -- "$file" "$tmp"; then
63+
mv "$tmp" "$file"
64+
fi
65+
done < <(find "$out" -type f,l -name "*.lua" -print0)
66+
}
67+
68+
postFixupHooks+=(byteCompileLuaPostFixup)
69+
''
70+
);
5171
}

modules/files.nix

Lines changed: 44 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,40 @@ 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, add byteCompileLuaHook to it
76+
(config.source.overrideAttrs (
77+
prev:
78+
{
79+
nativeBuildInputs = prev.nativeBuildInputs or [ ] ++ [ helpers.byteCompileLuaHook ];
80+
}
81+
// lib.optionalAttrs (prev ? buildCommand) {
82+
buildCommand = ''
83+
${prev.buildCommand}
84+
runHook postFixup
85+
'';
86+
}
87+
))
88+
else
89+
# Source is a path or string
90+
helpers.writeByteCompiledLua derivationName (builtins.readFile config.source)
91+
else
92+
config.source;
5793
};
58-
}
59-
);
94+
};
95+
96+
fileType = lib.types.submoduleWith {
97+
shorthandOnlyDefinesConfig = true;
98+
modules = [ fileTypeModule ];
99+
specialArgs.topConfig = config;
100+
};
60101

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

modules/performance.nix

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ in
1010
description = "Whether to byte compile init.lua.";
1111
default = true;
1212
};
13+
configs = lib.mkEnableOption "configs" // {
14+
description = "Whether to byte compile lua configuration files.";
15+
default = true;
16+
};
1317
};
1418

1519
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: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,27 @@ 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+
# Non-lua files
3550
"plugin/test.vim".text = "set tabstop=2";
3651
"plugin/test.json".text = builtins.toJSON { a = 1; };
52+
# Lua file with txt extension won't be byte compiled
53+
"test.txt".source = helpers.writeLua "test.txt" "vim.opt.tabstop = 2";
3754
};
3855

3956
files = {
@@ -64,14 +81,18 @@ in
6481
local init_content = vim.fn.system("${config.printInitPackage}/bin/nixvim-print-init")
6582
assert(init_content:find("VALIDATING_STRING"), "nixvim-print-init's output is byte compiled")
6683
67-
-- extraFiles
68-
test_rtp_file("plugin/file_text.lua", false)
69-
test_rtp_file("plugin/file_source.lua", false)
84+
-- lua extraFiles are byte compiled
85+
test_rtp_file("plugin/file_text.lua", true)
86+
test_rtp_file("plugin/file_source.lua", true)
87+
test_rtp_file("plugin/file_drv.lua", true)
88+
test_rtp_file("plugin/file_path.lua", true)
89+
test_rtp_file("plugin/file_string.lua", true)
7090
test_rtp_file("plugin/test.vim", false)
7191
test_rtp_file("plugin/test.json", false)
92+
test_rtp_file("test.txt", false)
7293
73-
-- files
74-
test_rtp_file("plugin/file.lua", false)
94+
-- lua files are byte compiled
95+
test_rtp_file("plugin/file.lua", true)
7596
test_rtp_file("plugin/file.vim", false)
7697
7798
-- Plugins and neovim runtime aren't byte compiled by default
@@ -136,4 +157,24 @@ in
136157
assert(not is_byte_compiled(init), "MYVIMRC is not expected to be byte compiled, but it is")
137158
'';
138159
};
160+
161+
configs-disabled = {
162+
performance.byteCompileLua = {
163+
enable = true;
164+
configs = false;
165+
};
166+
167+
extraFiles."plugin/test1.lua".text = "vim.opt.tabstop = 2";
168+
169+
files."plugin/test2.lua".opts.tabstop = 2;
170+
171+
extraConfigLuaPost = ''
172+
${isByteCompiledFun}
173+
174+
-- extraFiles
175+
test_rtp_file("plugin/test1.lua", false)
176+
-- files
177+
test_rtp_file("plugin/test2.lua", false)
178+
'';
179+
};
139180
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
vim.opt.tabstop = 2

wrappers/_shared.nix

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ in
5353
setAttrByPath filesOpt (
5454
listToAttrs (
5555
map (
56-
{ target, source, ... }:
56+
{ target, finalSource, ... }:
5757
{
5858
name = filesPrefix + target;
5959
value = {
60-
inherit source;
60+
source = finalSource;
6161
};
6262
}
6363
) extraFiles

0 commit comments

Comments
 (0)