{ 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" id; 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" ); descString = optionalString (desc != null) "desc = ${quote desc},"; in ''{ ${quote key}, ${cmdString}, mode = ${listToStringOneLine quote mode}, ${descString} }''; lazySpecFromPlugin = { plugin, dependencies, init, conf, lazy, event, enabled, cmd, ft, priority, keys }: listToStringMultiLine' ([ "dir = ${quote plugin}" "name = ${quote (getName plugin)}" ] ++ (optional (lazy != null) "lazy = ${boolToString lazy}") ++ (optional (!enabled) "enabled = ${boolToString enabled}") ++ (optional (dependencies != [ ]) "dependencies = ${listToStringMultiLine' (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' (map keybinding keys)}") ++ (optional (event != [ ]) "event = ${listToStringOneLine quote event}") ++ (optional (cmd != [ ]) "cmd = ${listToStringOneLine quote cmd}") ++ (optional (ft != [ ]) "ft = ${listToStringOneLine quote ft}") ++ (optional (priority != null) "priority = ${toString priority}") ); lazySpecs = listToStringMultiLine' (map lazySpecFromPlugin cfg.plugins); lazy = /* lua */ '' 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 function 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 = 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 { home-manager.users.moritz = { home.packages = with pkgs; [ ( if config.my.programs.hyprland.enable then neovide-hyprland else neovide ) ]; xdg.configFile."nvim/init.lua" = { source = let text = lib.concatLines [ (builtins.readFile ./options.lua) lazy ]; in pkgs.runCommand "init.lua" { inherit text; } '' touch $out echo -n "$text" > $out ${getExe pkgs.stylua} $out ''; }; programs.neovim = { enable = true; package = pkgs.neovim-nightly; vimAlias = true; vimdiffAlias = true; withNodeJs = true; withPython3 = true; 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 ]; }; }; }; }