From 6a054de04dd2b0a3cc5fed1adab8e9f76c050b45 Mon Sep 17 00:00:00 2001 From: sportshead Date: Sun, 8 Jun 2025 23:30:08 +0100 Subject: [PATCH] plugins/lsp: add packageFallback option https://github.com/nix-community/nixvim/pull/3445#pullrequestreview-2908615597 --- plugins/lsp/language-servers/_mk-lsp.nix | 13 ++++- plugins/lsp/language-servers/hls.nix | 5 +- .../lsp/language-servers/rust-analyzer.nix | 11 ++-- tests/test-sources/plugins/lsp/_lsp.nix | 54 +++++++++++++++++++ 4 files changed, 77 insertions(+), 6 deletions(-) diff --git a/plugins/lsp/language-servers/_mk-lsp.nix b/plugins/lsp/language-servers/_mk-lsp.nix index fb694c6e..f80fd6e9 100644 --- a/plugins/lsp/language-servers/_mk-lsp.nix +++ b/plugins/lsp/language-servers/_mk-lsp.nix @@ -55,6 +55,16 @@ in lib.nixvim.mkMaybeUnpackagedOption "plugins.lsp.servers.${name}.package" pkgs name package; + packageFallback = mkOption { + type = types.bool; + default = false; + description = '' + When enabled, the language server package will be added to the end of the `PATH` _(suffix)_ instead of the beginning _(prefix)_. + + This can be useful if you want local versions of the language server (e.g. from a devshell) to override the nixvim version. + ''; + }; + cmd = mkOption { type = with types; nullOr (listOf str); default = @@ -148,7 +158,8 @@ in }; config = lib.mkIf enabled { - extraPackages = [ cfg.package ]; + extraPackages = lib.optional (!cfg.packageFallback) cfg.package; + extraPackagesAfter = lib.optional cfg.packageFallback cfg.package; plugins.lsp.enabledServers = [ { diff --git a/plugins/lsp/language-servers/hls.nix b/plugins/lsp/language-servers/hls.nix index 9dee38af..8a7af9d8 100644 --- a/plugins/lsp/language-servers/hls.nix +++ b/plugins/lsp/language-servers/hls.nix @@ -7,6 +7,8 @@ let cfg = config.plugins.lsp.servers.hls; inherit (lib) types; + + ghcPackage = lib.optional (cfg.installGhc == true) cfg.ghcPackage; in { options.plugins.lsp.servers.hls = { @@ -32,6 +34,7 @@ in ''; }; - extraPackages = lib.optional (cfg.installGhc == true) cfg.ghcPackage; + extraPackages = lib.optionals (!cfg.packageFallback) ghcPackage; + extraPackagesAfter = lib.optionals cfg.packageFallback ghcPackage; }; } diff --git a/plugins/lsp/language-servers/rust-analyzer.nix b/plugins/lsp/language-servers/rust-analyzer.nix index 767c5bbb..b89a123b 100644 --- a/plugins/lsp/language-servers/rust-analyzer.nix +++ b/plugins/lsp/language-servers/rust-analyzer.nix @@ -9,6 +9,11 @@ let inherit (lib) mkPackageOption types; inherit (lib.nixvim) mkNullOrOption'; + extraPackages = + lib.optional (cfg.installCargo == true) cfg.cargoPackage + ++ lib.optional (cfg.installRustc == true) cfg.rustcPackage + ++ lib.optional (cfg.installRustfmt == true) cfg.rustfmtPackage; + in { options.plugins.lsp.servers.rust_analyzer = { @@ -72,9 +77,7 @@ in } ]; - extraPackages = - lib.optional (cfg.installCargo == true) cfg.cargoPackage - ++ lib.optional (cfg.installRustc == true) cfg.rustcPackage - ++ lib.optional (cfg.installRustfmt == true) cfg.rustfmtPackage; + extraPackages = lib.optionals (!cfg.packageFallback) extraPackages; + extraPackagesAfter = lib.optionals cfg.packageFallback extraPackages; }; } diff --git a/tests/test-sources/plugins/lsp/_lsp.nix b/tests/test-sources/plugins/lsp/_lsp.nix index 2891842b..cd30548e 100644 --- a/tests/test-sources/plugins/lsp/_lsp.nix +++ b/tests/test-sources/plugins/lsp/_lsp.nix @@ -265,4 +265,58 @@ } ]; }; + + package-fallback = + { config, ... }: + { + test.buildNixvim = false; + + plugins.lsp = { + enable = true; + servers = { + nil_ls = { + enable = true; + + packageFallback = true; + }; + rust_analyzer = { + enable = true; + + installCargo = true; + installRustc = true; + + packageFallback = true; + }; + hls = { + enable = true; + + installGhc = true; + packageFallback = true; + }; + }; + }; + + assertions = + let + assertAfter = name: pkg: [ + { + assertion = lib.all (x: x != pkg) config.extraPackages; + message = "Expected `${name}` not to be in extraPackages"; + } + { + assertion = lib.any (x: x == pkg) config.extraPackagesAfter; + message = "Expected `${name}` to be in extraPackagesAfter"; + } + ]; + in + with config.plugins.lsp.servers; + ( + assertAfter "nil" nil_ls.package + ++ assertAfter "rust-analyzer" rust_analyzer.package + ++ assertAfter "cargo" rust_analyzer.cargoPackage + ++ assertAfter "rustc" rust_analyzer.rustcPackage + ++ assertAfter "haskell-language-server" hls.package + ++ assertAfter "ghc" hls.ghcPackage + ); + }; }