{ config, lib, pkgs, ... }: with lib; with import ./lib.nix { inherit lib; }; let cfg = config.programs.neovim.lazy; luaList = values: "{" + (concatStringsSep ", " values) + "}"; keybinding = { key, cmd, func, mode, desc }: let cmdString = if cmd != null then toLua cmd else if func != null then func else abort "Either cmd or function must be set"; descString = optionalString (desc != null) "desc = ${toLua desc},"; in ''{ ${toLua key}, ${cmdString}, mode = ${toLua mode}, ${descString} }''; lazySpecFromPlugin = { cmd , conf , dependencies , enabled , event , ft , init , keys , lazy , opts , plugin , priority }: luaList ([ "dir = ${string plugin}" "name = ${toLua (getName plugin)}" ] ++ (optional (opts != null) "opts = ${toLua opts}") ++ (optional (lazy != null) "lazy = ${toLua lazy}") ++ (optional (!enabled) "enabled = ${toLua enabled}") ++ (optional (dependencies != [ ]) "dependencies = ${luaList (map lazySpecFromPlugin dependencies)}") ++ (optional (init != null) "init = function(spec)\n${init}\nend") ++ (optional (conf != null) "config = function(spec, opts)\n${conf}\nend") ++ (optional (keys != [ ]) "keys = ${luaList (map keybinding keys)}") ++ (optional (event != [ ]) "event = ${toLua event}") ++ (optional (cmd != [ ]) "cmd = ${toLua cmd}") ++ (optional (ft != [ ]) "ft = ${toLua ft}") ++ (optional (priority != null) "priority = ${toLua priority}") ); lazySpecs = luaList (map lazySpecFromPlugin cfg.plugins); text = /* lua */ '' require("lazy").setup(${lazySpecs}) ''; formatted = pkgs.runCommand "lazy.lua" { inherit text; } '' touch $out echo -n "$text" > $out ${getExe pkgs.stylua} $out ''; lazy = if cfg.format then readFile formatted else text; in { options.programs.neovim.lazy = { enable = mkEnableOption "lazy.nvim"; format = mkEnableOption "format"; plugins = mkOption { default = [ ]; description = '' List of plugins with config. ''; type = with types; listOf ( let sub = submodule { options = { conf = mkOption { type = nullOr str; default = null; description = '' Lua function to be executed when the plugin is loaded. ''; }; opts = mkOption { type = let valueType = nullOr (oneOf [ str bool int float (listOf valueType) (attrsOf valueType) ]) // { description = "Lua value"; }; in nullOr (attrsOf valueType); default = null; description = '' Lua table to be passed to te plugin config function. ''; }; dependencies = mkOption { type = listOf sub; default = [ ]; description = '' List of plugins this plugin depends on. ''; }; init = mkOption { type = nullOr str; default = null; description = '' Lua code to be executed when the plugin is initialized. ''; }; event = mkOption { type = listOf str; default = [ ]; description = '' Event to load the plugin on. ''; }; lazy = mkOption { type = nullOr bool; default = null; description = '' Whether to load the plugin lazily. ''; }; plugin = mkOption { type = package; description = '' The plugin package. ''; }; enabled = mkOption { type = bool; default = true; description = '' Whether to enable the plugin. ''; }; cmd = mkOption { type = listOf str; default = [ ]; description = '' Command to load the plugin. ''; }; ft = mkOption { type = listOf str; default = [ ]; description = '' Filetype to load the plugin on. ''; }; priority = mkOption { type = nullOr int; default = null; description = '' Priority to load the plugin. ''; }; keys = mkOption { default = [ ]; description = '' List of keybindings. ''; type = listOf (submodule { options = { key = mkOption { type = str; description = '' Key to bind. ''; }; cmd = mkOption { type = nullOr str; default = null; description = '' Command to execute. ''; }; func = mkOption { type = nullOr str; default = null; description = '' Function to execute. ''; }; mode = mkOption { type = listOf str; default = [ "n" ]; description = '' Mode to bind the key in. ''; }; desc = mkOption { type = nullOr str; default = null; description = '' Description of the keybinding. ''; }; }; }); }; }; }; in sub ); }; }; config = mkIf cfg.enable { programs.neovim = { extraLuaConfig = lazy; extraPython3Packages = ps: let plugins = map (getAttr "plugin") cfg.plugins; depAttrName = "python3Dependencies"; filtered = filter (hasAttr depAttrName) plugins; funcs = map (getAttr depAttrName) filtered; in foldl (list: f: list ++ (f ps)) [ ] funcs; plugins = [ pkgs.vimPlugins.lazy-nvim ]; }; }; }