From a2f01876f721d3361f33845397de77ca19e5734a Mon Sep 17 00:00:00 2001 From: Quentin Boyer Date: Thu, 30 Jan 2025 22:53:55 +0100 Subject: [PATCH] lib: Harmonize package options which may not exist in nixpkgs --- lib/default.nix | 2 + lib/options.nix | 38 +++++++++++++++++++ plugins/by-name/none-ls/_mk-source-plugin.nix | 27 +++---------- plugins/lsp/language-servers/_mk-lsp.nix | 20 ++-------- tests/lsp-servers.nix | 5 ++- .../plugins/by-name/none-ls/default.nix | 7 ++-- 6 files changed, 57 insertions(+), 42 deletions(-) diff --git a/lib/default.nix b/lib/default.nix index ea2c143d..448d2f8d 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -54,6 +54,7 @@ lib.makeExtensible ( mkCompositeOption mkCompositeOption' mkLazyLoadOption + mkMaybeUnpackagedOption mkNullOrLua mkNullOrLua' mkNullOrLuaFn @@ -69,6 +70,7 @@ lib.makeExtensible ( mkPackageOption mkPluginPackageOption mkSettingsOption + mkUnpackagedOption pluginDefaultText ; diff --git a/lib/options.nix b/lib/options.nix index d8382662..668a6c42 100644 --- a/lib/options.nix +++ b/lib/options.nix @@ -403,5 +403,43 @@ rec { if cfg ? lazyLoad then lib.literalMD "`false` when lazy-loading is enabled." else true; example = false; }; + + /** + Create an option for a package not currently available in nixpkgs. + + The option will throw an error if a value is not explicitly set by the end user. + */ + mkUnpackagedOption = + optionName: packageName: + lib.mkOption { + type = types.nullOr types.package; + description = '' + Package to use for ${packageName}. + Nixpkgs does not include this package, and as such an external derivation or null must be provided. + ''; + default = throw '' + Nixvim (${optionName}): No package is known for ${packageName}, to resolve this either: + - install externally and set this option to `null` + - or provide a derviation to install this package + ''; + defaultText = lib.literalMD "No package, throws when undefined"; + }; + + /** + Create an option for a package that may not be currently available in nixpkgs. + + See `mkUnpackagedOption` + */ + mkMaybeUnpackagedOption = + optionName: pkgs: packageName: package: + if lib.isOption package then + package + else if package != null then + lib.mkPackageOption pkgs packageName { + nullable = true; + default = package; + } + else + mkUnpackagedOption optionName packageName; } // removed diff --git a/plugins/by-name/none-ls/_mk-source-plugin.nix b/plugins/by-name/none-ls/_mk-source-plugin.nix index 0239c68e..aab1e7f0 100644 --- a/plugins/by-name/none-ls/_mk-source-plugin.nix +++ b/plugins/by-name/none-ls/_mk-source-plugin.nix @@ -9,7 +9,6 @@ sourceType: sourceName: let inherit (import ./packages.nix lib) packaged; pkg = packaged.${sourceName}; - loc = lib.toList pkg; cfg = config.plugins.none-ls; cfg' = config.plugins.none-ls.sources.${sourceType}.${sourceName}; @@ -41,27 +40,11 @@ in } # Only declare a package option if a package is required // lib.optionalAttrs (packaged ? ${sourceName}) { - package = lib.mkOption ( - { - type = lib.types.nullOr lib.types.package; - description = - "Package to use for ${sourceName}." - + (lib.optionalString (pkg == null) ( - "\n\n" - + '' - Currently not packaged in nixpkgs. - Either set this to `null` and install ${sourceName} outside of nix, - or set this to a custom nix package. - '' - )); - } - // lib.optionalAttrs (pkg != null) { - default = - lib.attrByPath loc (lib.warn "${lib.concatStringsSep "." loc} cannot be found in pkgs!" null) - pkgs; - defaultText = lib.literalExpression "pkgs.${lib.concatStringsSep "." loc}"; - } - ); + package = + lib.nixvim.mkMaybeUnpackagedOption "plugins.none-ls.sources.${sourceType}.${sourceName}.package" + pkgs + sourceName + pkg; }; # TODO: Added 2024-07-16; remove after 24.11 diff --git a/plugins/lsp/language-servers/_mk-lsp.nix b/plugins/lsp/language-servers/_mk-lsp.nix index 7df1b107..230e09d7 100644 --- a/plugins/lsp/language-servers/_mk-lsp.nix +++ b/plugins/lsp/language-servers/_mk-lsp.nix @@ -37,7 +37,8 @@ in { meta.nixvimInfo = { # TODO: description - url = args.url or opts.package.default.meta.homepage or null; + # The package default can throw when the server is unpackaged, so use tryEval + url = args.url or (builtins.tryEval opts.package.default).value.meta.homepage or null; path = [ "plugins" "lsp" @@ -51,21 +52,8 @@ in enable = lib.mkEnableOption description; package = - if lib.isOption package then - package - else if args ? package then - lib.mkPackageOption pkgs name { - nullable = true; - default = package; - } - else - # If we're not provided a package, we should provide a no-default option - lib.mkOption { - type = types.nullOr types.package; - description = '' - The package to use for ${name}. Has no default, but can be set to null. - ''; - }; + lib.nixvim.mkMaybeUnpackagedOption "plugins.lsp.servers.${name}.package" pkgs name + package; cmd = mkOption { type = with types; nullOr (listOf str); diff --git a/tests/lsp-servers.nix b/tests/lsp-servers.nix index 11bece89..562dc8a9 100644 --- a/tests/lsp-servers.nix +++ b/tests/lsp-servers.nix @@ -82,7 +82,10 @@ let { enable = !(lib.elem server disabled); } - // lib.optionalAttrs (opts ? package && !(opts.package ? default)) { package = null; } + # Some servers are defined using mkUnpackagedOption whose default will throw + // lib.optionalAttrs (opts ? package && !(builtins.tryEval opts.package.default).success) { + package = null; + } )) (lib.filterAttrs (server: _: !(lib.elem server renamed))) ]; diff --git a/tests/test-sources/plugins/by-name/none-ls/default.nix b/tests/test-sources/plugins/by-name/none-ls/default.nix index bd1acdfd..9850082b 100644 --- a/tests/test-sources/plugins/by-name/none-ls/default.nix +++ b/tests/test-sources/plugins/by-name/none-ls/default.nix @@ -100,7 +100,6 @@ with-sources = { - config, options, lib, pkgs, @@ -158,8 +157,10 @@ # Enable unless disabled above enable = !(lib.elem sourceName disabled); } - # Some sources have a package option with no default - // lib.optionalAttrs (opts ? package && !(opts.package ? default)) { package = null; } + # Some sources are defined using mkUnpackagedOption whose default will throw + // lib.optionalAttrs (opts ? package && !(builtins.tryEval opts.package.default).success) { + package = null; + } ) ) options.plugins.none-ls.sources; };