Skip to content
3 changes: 3 additions & 0 deletions lib/utils.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
}:
with lib;
{
# Whether a string contains something other than whitespace
hasContent = str: (builtins.match "[[:space:]]*" str) == null;

listToUnkeyedAttrs =
list:
builtins.listToAttrs (lib.lists.imap0 (idx: lib.nameValuePair "__unkeyed-${toString idx}") list);
Expand Down
88 changes: 65 additions & 23 deletions modules/output.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{ lib, config, ... }:
{
config,
lib,
helpers,
...
}:
with lib;
let
pluginWithConfigType = types.submodule {
Expand Down Expand Up @@ -74,20 +79,30 @@ in
"vim"
"lua"
];
default = "lua";
default = if lib.hasSuffix ".vim" config.target then "vim" else "lua";
defaultText = lib.literalMD ''`"lua"` unless `config.target` ends with `".vim"`'';
description = "Whether the generated file is a vim or a lua file";
readOnly = true;
};

path = mkOption {
target = mkOption {
type = types.str;
description = "Path of the file relative to the config directory";
default = "init.lua";
};

content = mkOption {
type = types.str;
type = types.lines;
description = "The content of the config file";
readOnly = true;
visible = false;
# FIXME: can't be readOnly because we prefix it in top-level modules
};

finalConfig = mkOption {
type = types.package;
description = "The config file written as a derivation";
readOnly = true;
internal = true;
};

extraLuaPackages = mkOption {
Expand All @@ -97,29 +112,56 @@ in
};
};

imports = [ (lib.mkRenamedOptionModule [ "path" ] [ "target" ]) ];

config =
let
contentLua = ''
${config.extraConfigLuaPre}
vim.cmd([[
${config.extraConfigVim}
]])
${config.extraConfigLua}
${config.extraConfigLuaPost}
'';
derivationName = "nvim-" + lib.replaceStrings [ "/" ] [ "-" ] config.target;

contentVim = ''
lua << EOF
${config.extraConfigLuaPre}
EOF
${config.extraConfigVim}
lua << EOF
${config.extraConfigLua}
${config.extraConfigLuaPost}
EOF
'';
writer = if config.type == "lua" then helpers.writeLua else pkgs.writeText;

concatConfig = parts: lib.concatStringsSep "\n" (lib.filter helpers.hasContent parts);

wrapConfig =
fn: parts:
let
s = concatConfig (toList parts);
in
optionalString (helpers.hasContent s) (fn s);

contentLua = concatConfig [
config.extraConfigLuaPre
(wrapConfig (s: ''
vim.cmd([[
${s}
]])
'') config.extraConfigVim)
config.extraConfigLua
config.extraConfigLuaPost
];

contentVim = concatConfig [
(wrapConfig (s: ''
lua << EOF
${s}
EOF
'') config.extraConfigLuaPre)
config.extraConfigVim
(wrapConfig
(s: ''
lua << EOF
${s}
EOF
'')
[
config.extraConfigLua
config.extraConfigLuaPost
]
)
];
in
{
content = if config.type == "lua" then contentLua else contentVim;
finalConfig = writer derivationName config.content;
};
}
4 changes: 2 additions & 2 deletions modules/top-level/files/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ in
extraFiles = lib.mkDerivedConfig options.files (
lib.mapAttrs' (
_: file: {
name = file.path;
value.source = file.plugin;
name = file.target;
value.source = file.finalConfig;
}
)
);
Expand Down
34 changes: 10 additions & 24 deletions modules/top-level/files/submodule.nix
Original file line number Diff line number Diff line change
@@ -1,27 +1,13 @@
{ name, lib, ... }:
{
name,
config,
lib,
helpers,
...
}:
{
options = {
plugin = lib.mkOption {
type = lib.types.package;
description = "A derivation with the content of the file in it";
readOnly = true;
internal = true;
};
imports = [
(lib.mkRenamedOptionModule [
"plugin"
"finalConfig"
])
];

config = {
target = lib.mkDefault name;
};
config =
let
derivationName = "nvim-" + lib.replaceStrings [ "/" ] [ "-" ] name;
in
{
path = lib.mkDefault name;
type = lib.mkDefault (if lib.hasSuffix ".vim" name then "vim" else "lua");
# No need to use mkDerivedConfig; this option is readOnly.
plugin = helpers.writeLua derivationName config.content;
};
}
100 changes: 36 additions & 64 deletions modules/top-level/output.nix
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,6 @@ with lib;
readOnly = true;
};

initPath = mkOption {
type = types.str;
description = "The path to the `init.lua` file.";
readOnly = true;
visible = false;
};

printInitPackage = mkOption {
type = types.package;
description = "A tool to show the content of the generated `init.lua` file.";
Expand All @@ -69,90 +62,69 @@ with lib;
};
};

imports = [
(lib.mkRemovedOptionModule [ "initPath" ] ''
Use `finalConfig' instead.
'')
];

config =
let
defaultPlugin = {
plugin = null;
config = "";
optional = false;
neovimConfig = pkgs.neovimUtils.makeNeovimConfig {
inherit (config)
extraPython3Packages
extraLuaPackages
viAlias
vimAlias
withRuby
withNodeJs
;
plugins = config.extraPlugins;
# We handle `customRC` ourselves, to position it after `extraConfigLuaPre`
};

normalizedPlugins = map (
x: defaultPlugin // (if x ? plugin then x else { plugin = x; })
) config.extraPlugins;

neovimConfig = pkgs.neovimUtils.makeNeovimConfig (
{
inherit (config)
extraPython3Packages
extraLuaPackages
viAlias
vimAlias
withRuby
withNodeJs
;
# inherit customRC;
plugins = normalizedPlugins;
}
# Necessary to make sure the runtime path is set properly in NixOS 22.05,
# or more generally before the commit:
# cda1f8ae468 - neovim: pass packpath via the wrapper
// optionalAttrs (functionArgs pkgs.neovimUtils.makeNeovimConfig ? configure) {
configure.packages = {
nixvim = {
start = map (x: x.plugin) normalizedPlugins;
opt = [ ];
};
};
}
);

customRC =
let
hasContent = str: (builtins.match "[[:space:]]*" str) == null;
in
(optionalString (hasContent neovimConfig.neovimRcContent) ''
vim.cmd([[
${neovimConfig.neovimRcContent}
]])
'')
+ config.content;

init = helpers.writeLua "init.lua" customRC;

extraWrapperArgs = builtins.concatStringsSep " " (
(optional (config.extraPackages != [ ]) ''--prefix PATH : "${makeBinPath config.extraPackages}"'')
++ (optional config.wrapRc ''--add-flags -u --add-flags "${init}"'')
++ (optional config.wrapRc ''--add-flags -u --add-flags "${config.finalConfig}"'')
);

wrappedNeovim = pkgs.wrapNeovimUnstable config.package (
configPrefix =
if config.type == "lua" then
''
vim.cmd([[
${neovimConfig.neovimRcContent}
]])
''
else
neovimConfig.neovimRcContent;
in
{
content = lib.mkIf (helpers.hasContent neovimConfig.neovimRcContent) (lib.mkBefore configPrefix);

finalPackage = pkgs.wrapNeovimUnstable config.package (
neovimConfig
// {
wrapperArgs = lib.escapeShellArgs neovimConfig.wrapperArgs + " " + extraWrapperArgs;
# We handle wrapRc ourselves so we can control how init.lua is written
wrapRc = false;
}
);
in
{
type = lib.mkForce "lua";
finalPackage = wrappedNeovim;
initPath = "${init}";

printInitPackage = pkgs.writeShellApplication {
name = "nixvim-print-init";
runtimeInputs = [ pkgs.bat ];
text = ''
bat --language=lua "${init}"
bat --language=lua "${config.finalConfig}"
'';
};

extraConfigLuaPre = lib.optionalString config.wrapRc ''
extraConfigLuaPre = mkIf config.wrapRc ''
-- Ignore the user lua configuration
vim.opt.runtimepath:remove(vim.fn.stdpath('config')) -- ~/.config/nvim
vim.opt.runtimepath:remove(vim.fn.stdpath('config') .. "/after") -- ~/.config/nvim/after
vim.opt.runtimepath:remove(vim.fn.stdpath('data') .. "/site") -- ~/.local/share/nvim/site
'';

extraPlugins = if config.wrapRc then [ config.filesPlugin ] else [ ];
extraPlugins = mkIf config.wrapRc [ config.filesPlugin ];
};
}
5 changes: 1 addition & 4 deletions wrappers/_shared.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
filesOpt ? null,
# Filepath prefix to apply to extraFiles
filesPrefix ? "nvim/",
# Filepath to use when adding `cfg.initPath` to `filesOpt`
# Is prefixed with `filesPrefix`
initName ? "init.lua",
}:
{
pkgs,
Expand Down Expand Up @@ -59,7 +56,7 @@ in
) extraFiles
)
// {
${filesPrefix + initName}.source = cfg.initPath;
${filesPrefix + cfg.target}.source = cfg.finalConfig;
}
)
)
Expand Down
1 change: 1 addition & 0 deletions wrappers/modules/nixos.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@

config = {
wrapRc = lib.mkForce true;
target = lib.mkDefault "sysinit.lua";
};
}
1 change: 0 additions & 1 deletion wrappers/nixos.nix
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ in
"environment"
"etc"
];
initName = "sysinit.lua";
})
];

Expand Down