nixvim
nixvim copied to clipboard
Combine `files` and `extraFiles`
Status quo
Currently we have files for building a nixvim config as an extra file and extraFiles for directly writing text as an extra file.
There is also no way to add a path as an extra file (without using readFile to get the text).
Simple option
If we make an option with the type attrsOf (oneOf [ str path fileModuleType ]), then we could combine the two existing options by making one of them into a rename-alias.
Better option
It may be better to have a new option with a slightly different type, more in line with what nixos & home-manager use:
type = attrsOf (submodule (
{ name, config, options, ... }:
{
options = {
target = /* default to `name` */;
source = /* path to a file */;
text = /* alternatively, file content */;
module = /* alternatively, a nixvim module to build */;
};
config = mkIf (config.source == null) (mkMerge [
{ source = mkIf (config.text != null) (pkgs.writeText "" config.text); }
{ source = mkIf (config.module != null) config.module.plugin; }
]);
}
))
The config block ensures the option will always have a .source file path, along with .target that is where the file should be symlinked from when used in xdg/etc.
Heavily based on nixos's environment.etc.* option type: https://github.com/NixOS/nixpkgs/blob/7dca15289a1c2990efbe4680f0923ce14139b042/nixos/modules/system/etc/etc.nix#L123-L215
Also similar to home-manager's file-type.
Type coercion
We can transition extraFiles type from str to submodule using types.coercedTo, which takes a coerced type, a coercion function, and a final type.
The coercion function is essentially the same as an option's apply function.
The description is "X or Y convertible to it", but we could override that to just "X" if/when we wanted to.
We could print a deprecation warning in the type's merge function, thanks to @infinisil for explaining this to me:
Details
# Extend lib.types.coercedTo with a deprecation warning for the coerced type
deprecateType = coercedType: coerceFunc: finalType:
lib.types.coercedTo coercedType coerceFunc finalType
// {
# Override description
inherit (finalType) description;
# Override merge so we can print a warning
merge = loc: defs:
let
coerceVal = val:
if coercedType.check val then
lib.warn "Passing a ${coercedType.description} for ${showOption loc} is deprecated, use ${finalType.description} instead. Definitions: ${showDefs defs}"
(coerceFunc val)
else val;
in finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
};
User's perspective
extraFiles = {
"ftplugin/markdown.lua".text = "print('lua here')";
"after/some_file.lua".source = ./some/lua-file.nix;
"ftplugin/lua.lua".module = {
extraConfigLua = "print('module built by nixvim')";
};
"ftplugin/nix.lua".module = ({config, options, ...}: {
extraConfigLua = "print('fancy module built by nixvim')";
});
}