{ config , lib , pkgs , ... }: with lib; let cfg = config.my.programs.nvim; boolToString = bool: if bool then "true" else "false"; quote = str: ''"${toString str}"''; id = x: x; listToString = sep: f: list: ''{ ${concatStringsSep sep (map f list)} }''; listToStringOneLine = listToString ", "; listToStringMultiLine = listToString ",\n"; keybinding = { key , cmd , func , mode , desc }: let cmdString = if cmd != null then quote cmd else ( if func != null then func else abort "Either cmd or function must be set" ); in ''{ ${quote key}, ${cmdString}, mode = ${quote mode}, ${optionalString (desc != null) "desc = ${quote desc},"} }''; lazySpecFromPlugin = { plugin , dependencies , init , conf , lazy , event , enabled , cmd , ft , priority , keys }: listToStringMultiLine id ([ "dir = ${quote plugin}" "name = ${quote (getName plugin)}" ] ++ (optional (!lazy) "lazy = ${boolToString lazy}") ++ (optional (!enabled) "enabled = ${boolToString enabled}") ++ (optional (dependencies != [ ]) "dependencies = ${listToStringMultiLine id (map lazySpecFromPlugin dependencies)}") ++ (optional (init != null) "init = function(plugin)\n${toString init}\nend") ++ (optional (conf != null) "config = function(plugin, opts)\n${toString conf}\nend") ++ (optional (keys != [ ]) "keys = ${listToStringMultiLine id (map keybinding keys)}") ++ (optional (event != [ ]) "event = ${listToStringOneLine quote event}") ++ (optional (cmd != [ ]) "cmd = ${listToStringOneLine quote cmd}") ++ (optional (ft != [ ]) "ft = ${listToStringOneLine quote ft}") ++ (optional (priority != 50) "priority = ${toString priority}") ); lazySpecs = listToStringMultiLine id (map lazySpecFromPlugin cfg.plugins); lazy = '' require("lazy").setup({ ${lazySpecs} }) ''; in { imports = [ ./plugins ]; options.my.programs.nvim = { enable = mkEnableOption "nvim"; 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 code to be executed when the plugin is loaded. ''; }; 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 = bool; default = true; 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 = int; default = 50; 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 = 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 { home-manager.users.moritz = { home.packages = with pkgs; [ ( if config.my.programs.hyprland.enable then neovide-hyprland else neovide ) ]; programs.neovim = { enable = true; package = pkgs.neovim-nightly; vimAlias = true; vimdiffAlias = true; withNodeJs = true; withPython3 = true; extraLuaConfig = lib.concatLines [ (builtins.readFile ./options.lua) 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; extraPackages = with pkgs; [ alejandra black deadnix isort jq nil nixpkgs-fmt nodePackages.bash-language-server rustfmt shellcheck shfmt statix stylua sumneko-lua-language-server taplo typst typst-lsp yamlfmt ]; plugins = [ pkgs.vimPlugins.lazy-nvim ]; }; }; }; }