From 901363d1acfbe584e2e652633891f84d9244454f Mon Sep 17 00:00:00 2001 From: diniamo <55629891+diniamo@users.noreply.github.com> Date: Fri, 12 Jul 2024 00:49:44 +0200 Subject: [PATCH] treewide: refactor custom lib, merge lists in hm/nixos module (#323) * treewide: refactor custom lib, merge lists in hm/nixos module * lib/types(custom): clarify anythingConcatLists code --------- Co-authored-by: raf --- configuration.nix | 418 ++++++++++++++++----------------- docs/default.nix | 2 +- flake.nix | 25 +- flake/modules/home-manager.nix | 8 +- flake/modules/nixos.nix | 8 +- flake/overlays.nix | 8 +- flake/packages.nix | 3 +- lib/configuration.nix | 18 ++ lib/default.nix | 1 + lib/stdlib-extended.nix | 4 +- lib/types/custom.nix | 53 +++++ lib/types/default.nix | 2 + modules/default.nix | 13 +- 13 files changed, 307 insertions(+), 256 deletions(-) create mode 100644 lib/configuration.nix create mode 100644 lib/types/custom.nix diff --git a/configuration.nix b/configuration.nix index b0e6132..a581b65 100644 --- a/configuration.nix +++ b/configuration.nix @@ -1,260 +1,240 @@ -inputs: let - modulesWithInputs = import ./modules inputs; - - neovimConfiguration = { - modules ? [], - pkgs, - lib ? pkgs.lib, - check ? true, - extraSpecialArgs ? {}, - extraModules ? [], - ... - }: - modulesWithInputs { - inherit pkgs lib check extraSpecialArgs extraModules; - configuration.imports = modules; +isMaximal: { + config.vim = { + viAlias = true; + vimAlias = true; + debugMode = { + enable = false; + level = 16; + logFile = "/tmp/nvim.log"; }; - mainConfig = isMaximal: { - config.vim = { - viAlias = true; - vimAlias = true; - debugMode = { - enable = false; - level = 16; - logFile = "/tmp/nvim.log"; - }; + spellcheck = { + enable = isMaximal; + }; - spellcheck = { + lsp = { + formatOnSave = true; + lspkind.enable = false; + lightbulb.enable = true; + lspsaga.enable = false; + nvimCodeActionMenu.enable = isMaximal; + trouble.enable = true; + lspSignature.enable = true; + lsplines.enable = isMaximal; + nvim-docs-view.enable = isMaximal; + }; + + debugger = { + nvim-dap = { + enable = true; + ui.enable = true; + }; + }; + + languages = { + enableLSP = true; + enableFormat = true; + enableTreesitter = true; + enableExtraDiagnostics = true; + + # Nim LSP is broken on Darwin and therefore + # should be disabled by default. Users may still enable + # `vim.languages.vim` to enable it, this does not restrict + # that. + # See: + nim.enable = false; + + nix.enable = true; + + markdown.enable = isMaximal; + html.enable = isMaximal; + css.enable = isMaximal; + sql.enable = isMaximal; + java.enable = isMaximal; + ts.enable = isMaximal; + svelte.enable = isMaximal; + go.enable = isMaximal; + elixir.enable = isMaximal; + zig.enable = isMaximal; + ocaml.enable = isMaximal; + python.enable = isMaximal; + dart.enable = isMaximal; + bash.enable = isMaximal; + tailwind.enable = isMaximal; + typst.enable = isMaximal; + clang = { enable = isMaximal; + lsp.server = "clangd"; }; - lsp = { - formatOnSave = true; - lspkind.enable = false; - lightbulb.enable = true; - lspsaga.enable = false; - nvimCodeActionMenu.enable = isMaximal; - trouble.enable = true; - lspSignature.enable = true; - lsplines.enable = isMaximal; - nvim-docs-view.enable = isMaximal; + rust = { + enable = isMaximal; + crates.enable = isMaximal; }; + }; - debugger = { - nvim-dap = { - enable = true; - ui.enable = true; - }; - }; + visuals = { + enable = true; + nvimWebDevicons.enable = true; + scrollBar.enable = isMaximal; + smoothScroll.enable = true; + cellularAutomaton.enable = false; + fidget-nvim.enable = true; + highlight-undo.enable = true; - languages = { - enableLSP = true; - enableFormat = true; - enableTreesitter = true; - enableExtraDiagnostics = true; - - # Nim LSP is broken on Darwin and therefore - # should be disabled by default. Users may still enable - # `vim.languages.vim` to enable it, this does not restrict - # that. - # See: - nim.enable = false; - - nix.enable = true; - - markdown.enable = isMaximal; - html.enable = isMaximal; - css.enable = isMaximal; - sql.enable = isMaximal; - java.enable = isMaximal; - ts.enable = isMaximal; - svelte.enable = isMaximal; - go.enable = isMaximal; - elixir.enable = isMaximal; - zig.enable = isMaximal; - ocaml.enable = isMaximal; - python.enable = isMaximal; - dart.enable = isMaximal; - bash.enable = isMaximal; - tailwind.enable = isMaximal; - typst.enable = isMaximal; - clang = { - enable = isMaximal; - lsp.server = "clangd"; - }; - - rust = { - enable = isMaximal; - crates.enable = isMaximal; - }; - }; - - visuals = { + indentBlankline = { enable = true; - nvimWebDevicons.enable = true; - scrollBar.enable = isMaximal; - smoothScroll.enable = true; - cellularAutomaton.enable = false; - fidget-nvim.enable = true; - highlight-undo.enable = true; - - indentBlankline = { - enable = true; - fillChar = null; - eolChar = null; - scope = { - enabled = true; - }; - }; - - cursorline = { - enable = true; - lineTimeout = 0; + fillChar = null; + eolChar = null; + scope = { + enabled = true; }; }; - statusline = { - lualine = { - enable = true; - theme = "catppuccin"; - }; - }; - - theme = { + cursorline = { enable = true; - name = "catppuccin"; - style = "mocha"; - transparent = false; + lineTimeout = 0; }; + }; - autopairs.enable = true; - - autocomplete = { + statusline = { + lualine = { enable = true; - type = "nvim-cmp"; + theme = "catppuccin"; }; + }; - filetree = { - nvimTree = { - enable = true; - }; - }; + theme = { + enable = true; + name = "catppuccin"; + style = "mocha"; + transparent = false; + }; - tabline = { - nvimBufferline.enable = true; - }; + autopairs.enable = true; - treesitter.context.enable = true; + autocomplete = { + enable = true; + type = "nvim-cmp"; + }; - binds = { - whichKey.enable = true; - cheatsheet.enable = true; - }; - - telescope.enable = true; - - git = { + filetree = { + nvimTree = { enable = true; - gitsigns.enable = true; - gitsigns.codeActions.enable = false; # throws an annoying debug message + }; + }; + + tabline = { + nvimBufferline.enable = true; + }; + + treesitter.context.enable = true; + + binds = { + whichKey.enable = true; + cheatsheet.enable = true; + }; + + telescope.enable = true; + + git = { + enable = true; + gitsigns.enable = true; + gitsigns.codeActions.enable = false; # throws an annoying debug message + }; + + minimap = { + minimap-vim.enable = false; + codewindow.enable = isMaximal; # lighter, faster, and uses lua for configuration + }; + + dashboard = { + dashboard-nvim.enable = false; + alpha.enable = isMaximal; + }; + + notify = { + nvim-notify.enable = true; + }; + + projects = { + project-nvim.enable = isMaximal; + }; + + utility = { + ccc.enable = isMaximal; + vim-wakatime.enable = false; + icon-picker.enable = isMaximal; + surround.enable = isMaximal; + diffview-nvim.enable = true; + motion = { + hop.enable = true; + leap.enable = true; }; - minimap = { - minimap-vim.enable = false; - codewindow.enable = isMaximal; # lighter, faster, and uses lua for configuration + images = { + image-nvim.enable = false; }; + }; - dashboard = { - dashboard-nvim.enable = false; - alpha.enable = isMaximal; + notes = { + obsidian.enable = false; # FIXME: neovim fails to build if obsidian is enabled + orgmode.enable = false; + mind-nvim.enable = isMaximal; + todo-comments.enable = true; + }; + + terminal = { + toggleterm = { + enable = true; + lazygit.enable = true; }; + }; - notify = { - nvim-notify.enable = true; + ui = { + borders.enable = true; + noice.enable = true; + colorizer.enable = true; + modes-nvim.enable = false; # the theme looks terrible with catppuccin + illuminate.enable = true; + breadcrumbs = { + enable = isMaximal; + navbuddy.enable = isMaximal; }; - - projects = { - project-nvim.enable = isMaximal; - }; - - utility = { - ccc.enable = isMaximal; - vim-wakatime.enable = false; - icon-picker.enable = isMaximal; - surround.enable = isMaximal; - diffview-nvim.enable = true; - motion = { - hop.enable = true; - leap.enable = true; - }; - - images = { - image-nvim.enable = false; + smartcolumn = { + enable = true; + setupOpts.custom_colorcolumn = { + # this is a freeform module, it's `buftype = int;` for configuring column position + nix = "110"; + ruby = "120"; + java = "130"; + go = ["90" "130"]; }; }; + }; - notes = { - obsidian.enable = false; # FIXME: neovim fails to build if obsidian is enabled - orgmode.enable = false; - mind-nvim.enable = isMaximal; - todo-comments.enable = true; + assistant = { + chatgpt.enable = false; + copilot = { + enable = false; + cmp.enable = isMaximal; }; + }; - terminal = { - toggleterm = { - enable = true; - lazygit.enable = true; - }; - }; + session = { + nvim-session-manager.enable = false; + }; - ui = { - borders.enable = true; - noice.enable = true; - colorizer.enable = true; - modes-nvim.enable = false; # the theme looks terrible with catppuccin - illuminate.enable = true; - breadcrumbs = { - enable = isMaximal; - navbuddy.enable = isMaximal; - }; - smartcolumn = { - enable = true; - setupOpts.custom_colorcolumn = { - # this is a freeform module, it's `buftype = int;` for configuring column position - nix = "110"; - ruby = "120"; - java = "130"; - go = ["90" "130"]; - }; - }; - }; + gestures = { + gesture-nvim.enable = false; + }; - assistant = { - chatgpt.enable = false; - copilot = { - enable = false; - cmp.enable = isMaximal; - }; - }; + comments = { + comment-nvim.enable = true; + }; - session = { - nvim-session-manager.enable = false; - }; - - gestures = { - gesture-nvim.enable = false; - }; - - comments = { - comment-nvim.enable = true; - }; - - presence = { - neocord.enable = false; - }; + presence = { + neocord.enable = false; }; }; -in { - inherit neovimConfiguration mainConfig; } diff --git a/docs/default.nix b/docs/default.nix index 5d521d6..b48daf5 100644 --- a/docs/default.nix +++ b/docs/default.nix @@ -1,7 +1,7 @@ { inputs, pkgs, - lib ? import ../lib/stdlib-extended.nix pkgs.lib inputs, + lib, manpageUrls ? pkgs.path + "/doc/manpage-urls.json", ... }: let diff --git a/flake.nix b/flake.nix index a10cd43..ea66b53 100644 --- a/flake.nix +++ b/flake.nix @@ -1,12 +1,18 @@ { description = "A neovim flake with a modular configuration"; outputs = { - nixpkgs, flake-parts, self, ... - } @ inputs: - flake-parts.lib.mkFlake {inherit inputs;} { + } @ inputs: let + # call the extedended library with `inputs` + # inputs is used to get the original standard library, and to pass inputs to the plugin autodiscovery function + lib = import ./lib/stdlib-extended.nix inputs; + in + flake-parts.lib.mkFlake { + inherit inputs; + specialArgs = {inherit lib;}; + } { # provide overridable systems # https://github.com/nix-systems/nix-systems systems = import inputs.systems; @@ -17,36 +23,33 @@ ./flake/packages.nix ]; - _module.args = {inherit (nixpkgs) lib;}; - flake = { lib = { - inherit (import ./lib/stdlib-extended.nix nixpkgs.lib inputs) nvim; - inherit (import ./configuration.nix inputs) neovimConfiguration; + inherit (lib) nvim neovimConfiguration; }; homeManagerModules = { neovim-flake = - nixpkgs.lib.warn '' + lib.warn '' homeManagerModules.neovim-flake has been deprecated. Plese use the homeManagerModules.nvf instead '' self.homeManagerModules.nvf; - nvf = import ./flake/modules/home-manager.nix self.packages inputs; + nvf = import ./flake/modules/home-manager.nix self.packages lib; default = self.homeManagerModules.nvf; }; nixosModules = { neovim-flake = - nixpkgs.lib.warn '' + lib.warn '' nixosModules.neovim-flake has been deprecated. Please use the nixosModules.nvf instead '' self.nixosModules.nvf; - nvf = import ./flake/modules/nixos.nix self.packages inputs; + nvf = import ./flake/modules/nixos.nix self.packages lib; default = self.nixosModules.nvf; }; diff --git a/flake/modules/home-manager.nix b/flake/modules/home-manager.nix index 81662ed..66a3552 100644 --- a/flake/modules/home-manager.nix +++ b/flake/modules/home-manager.nix @@ -1,8 +1,7 @@ # Home Manager module -packages: inputs: { +packages: lib: { config, pkgs, - lib ? pkgs.lib, ... }: let inherit (lib) maintainers; @@ -10,9 +9,10 @@ packages: inputs: { inherit (lib.lists) optional; inherit (lib.options) mkOption mkEnableOption literalExpression; inherit (lib.types) attrsOf anything bool; + inherit (lib.nvim) neovimConfiguration; + inherit (lib.nvim.types) anythingConcatLists; cfg = config.programs.nvf; - inherit (import ../../configuration.nix inputs) neovimConfiguration; neovimConfigured = neovimConfiguration { inherit pkgs; @@ -55,7 +55,7 @@ in { }; settings = mkOption { - type = attrsOf anything; + type = attrsOf anythingConcatLists; default = {}; description = "Attribute set of nvf preferences."; example = literalExpression '' diff --git a/flake/modules/nixos.nix b/flake/modules/nixos.nix index 2b1f6d7..e1e81f1 100644 --- a/flake/modules/nixos.nix +++ b/flake/modules/nixos.nix @@ -1,8 +1,7 @@ # NixOS module -packages: inputs: { +packages: lib: { config, pkgs, - lib ? pkgs.lib, ... }: let inherit (lib) maintainers; @@ -10,9 +9,10 @@ packages: inputs: { inherit (lib.lists) optional; inherit (lib.options) mkOption mkEnableOption literalExpression; inherit (lib.types) attrsOf anything bool; + inherit (lib.nvim) neovimConfiguration; + inherit (lib.nvim.types) anythingConcatLists; cfg = config.programs.nvf; - inherit (import ../../configuration.nix inputs) neovimConfiguration; neovimConfigured = neovimConfiguration { inherit pkgs; @@ -55,7 +55,7 @@ in { }; settings = mkOption { - type = attrsOf anything; + type = attrsOf anythingConcatLists; default = {}; description = "Attribute set of nvf preferences."; example = literalExpression '' diff --git a/flake/overlays.nix b/flake/overlays.nix index 3c5434d..1381e7b 100644 --- a/flake/overlays.nix +++ b/flake/overlays.nix @@ -1,14 +1,14 @@ { - inputs, pkgs, + lib, ... }: let - inherit (import ../configuration.nix inputs) neovimConfiguration mainConfig; + inherit (lib.nvim) neovimConfiguration; buildPkg = pkgs: modules: (neovimConfiguration {inherit pkgs modules;}).neovim; - nixConfig = mainConfig false; - maximalConfig = mainConfig true; + nixConfig = import ../configuration.nix false; + maximalConfig = import ../configuration.nix true; in { flake.overlays.default = _final: prev: { inherit neovimConfiguration; diff --git a/flake/packages.nix b/flake/packages.nix index 36f660a..f8ad3c2 100644 --- a/flake/packages.nix +++ b/flake/packages.nix @@ -2,9 +2,10 @@ perSystem = { config, pkgs, + lib, ... }: let - docs = import ../docs {inherit pkgs inputs;}; + docs = import ../docs {inherit pkgs inputs lib;}; in { packages = { # Documentation diff --git a/lib/configuration.nix b/lib/configuration.nix new file mode 100644 index 0000000..1f3c59a --- /dev/null +++ b/lib/configuration.nix @@ -0,0 +1,18 @@ +{ + inputs, + lib, +}: let + modulesWithInputs = import ../modules inputs; +in + { + modules ? [], + pkgs, + check ? true, + extraSpecialArgs ? {}, + extraModules ? [], + ... + }: + modulesWithInputs { + inherit pkgs lib check extraSpecialArgs extraModules; + configuration.imports = modules; + } diff --git a/lib/default.nix b/lib/default.nix index eade2e2..35485b7 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -12,4 +12,5 @@ lists = import ./lists.nix {inherit lib;}; lua = import ./lua.nix {inherit lib;}; vim = import ./vim.nix; + neovimConfiguration = import ./configuration.nix {inherit inputs lib;}; } diff --git a/lib/stdlib-extended.nix b/lib/stdlib-extended.nix index 4bd63b9..0f30815 100644 --- a/lib/stdlib-extended.nix +++ b/lib/stdlib-extended.nix @@ -1,7 +1,7 @@ # Convenience function that returns the given Nixpkgs standard library # extended with our functions using `lib.extend`. -nixpkgsLib: inputs: -nixpkgsLib.extend (self: super: { +inputs: +inputs.nixpkgs.lib.extend (self: super: { # WARNING: New functions should not be added here, but to files # imported by `./default.nix` under their own categories. If your # function does not fit to any of the existing categories, create diff --git a/lib/types/custom.nix b/lib/types/custom.nix new file mode 100644 index 0000000..f406515 --- /dev/null +++ b/lib/types/custom.nix @@ -0,0 +1,53 @@ +{lib}: let + inherit (lib) isStringLike showOption showFiles getFiles mergeOneOption mergeEqualOption; + inherit (lib.types) anything attrsOf; + inherit (lib.nvim.types) anythingConcatLists; + inherit (builtins) typeOf isAttrs any head concatLists; +in { + # HACK: Does this break anything in our case? + # A modified version of the nixpkgs anything type that concatenates lists + # This isn't the default because the order in which the lists are concatenated depends on the order in which the modules are imported, + # which makes it non-deterministic + anythingConcatLists = + anything + // { + merge = loc: defs: let + getType = value: + if isAttrs value && isStringLike value + then "stringCoercibleSet" + else typeOf value; + + # Throw an error if not all defs have the same type + checkType = getType (head defs).value; + commonType = + if any (def: getType def.value != checkType) defs + then throw "The option `${showOption loc}' has conflicting option types in ${showFiles (getFiles defs)}" + else checkType; + + mergeFunctions = { + # Recursively merge attribute sets + set = (attrsOf anythingConcatLists).merge; + + # Overridden behavior for lists, that concatenates lists + list = _: defs: concatLists (map (e: e.value) defs); + + # This means it's a package, only accept a single definition + stringCoercibleSet = mergeOneOption; + + # This works by passing the argument to the functions, + # and merging their returns values instead + lambda = loc: defs: arg: + anythingConcatLists.merge + (loc ++ [""]) + (map (def: { + inherit (def) file; + value = def.value arg; + }) + defs); + }; + in + # Merge the defs with the correct function from above, if available + # otherwise only allow equal values + (mergeFunctions.${commonType} or mergeEqualOption) loc defs; + }; +} diff --git a/lib/types/default.nix b/lib/types/default.nix index 8f02073..9e3f17b 100644 --- a/lib/types/default.nix +++ b/lib/types/default.nix @@ -6,8 +6,10 @@ typesDag = import ./dag.nix {inherit lib;}; typesPlugin = import ./plugins.nix {inherit inputs lib;}; typesLanguage = import ./languages.nix {inherit lib;}; + typesCustom = import ./custom.nix {inherit lib;}; in { inherit (typesDag) dagOf; inherit (typesPlugin) pluginsOpt extraPluginType mkPluginSetupOption luaInline pluginType; inherit (typesLanguage) diagnostics mkGrammarOption; + inherit (typesCustom) anythingConcatLists; } diff --git a/modules/default.nix b/modules/default.nix index 5c23e53..941c18f 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -1,7 +1,7 @@ inputs: { configuration, pkgs, - lib ? pkgs.lib, + lib, check ? true, extraSpecialArgs ? {}, extraModules ? [], @@ -15,23 +15,16 @@ inputs: { inherit (lib.attrsets) recursiveUpdate; inherit (lib.asserts) assertMsg; - # call the extedended library with `lib` and `inputs` as arguments - # lib is used to provide the standard library functions to the extended library - # but it can be overridden while this file is being called - # inputs is used to pass inputs to the plugin autodiscovery function - extendedLib = import ../lib/stdlib-extended.nix lib inputs; - # import modules.nix with `check`, `pkgs` and `lib` as arguments # check can be disabled while calling this file is called # to avoid checking in all modules nvimModules = import ./modules.nix { - inherit pkgs check; - lib = extendedLib; + inherit pkgs check lib; }; # evaluate the extended library with the modules # optionally with any additional modules passed by the user - module = extendedLib.evalModules { + module = lib.evalModules { specialArgs = recursiveUpdate {modulesPath = toString ./.;} extraSpecialArgs; modules = concatLists [[configuration] nvimModules extraModules]; };