diff --git a/modules/neovim/init/lsp.nix b/modules/neovim/init/lsp.nix index b17c5554a..bce7b93d6 100644 --- a/modules/neovim/init/lsp.nix +++ b/modules/neovim/init/lsp.nix @@ -6,7 +6,7 @@ inherit (builtins) filter; inherit (lib.modules) mkIf mkMerge mkDefault; inherit (lib.options) mkOption mkEnableOption; - inherit (lib.types) attrsOf; + inherit (lib.types) attrsOf enum; inherit (lib.strings) concatLines; inherit (lib.attrsets) mapAttrsToList attrNames filterAttrs; inherit (lib.generators) mkLuaInline; @@ -70,6 +70,29 @@ in { on the underlying API. ''; }; + + vendorPrograms = mkOption { + type = enum ["path" "exact" "never"]; + default = "exact"; + description = '' + How NVF should install LSP packages. + + - "path": Append program paths to PATH, this means other programs on + your system or devshell will take precedence, so the vendored + package only acts as a fallback when you have none installed. + - "exact": Commands are passed as full path to the program in the nix + store. Programs on your PATH are never used. + - "never": Never vendor LSP packages. Language servers are searched + for in PATH + + "Exact" is generally preferred but for some languages/projects, you + may need a different version of your language server per-project, in + which case, "path" will allow you to do so. + + You can modify this behavior per-language by modifying + {option}`vim.lsp.servers.*.cmd`. + ''; + }; }; }; diff --git a/modules/plugins/lsp/presets/haskell-language-server.nix b/modules/plugins/lsp/presets/haskell-language-server.nix index 6a7371d76..874ba3f6c 100644 --- a/modules/plugins/lsp/presets/haskell-language-server.nix +++ b/modules/plugins/lsp/presets/haskell-language-server.nix @@ -6,8 +6,21 @@ }: let inherit (lib.modules) mkIf; inherit (lib.nvim.types) mkLspPresetEnableOption; + inherit (lib.lists) optional; inherit (lib.meta) getExe; + vendored = getExe (pkgs.symlinkJoin { + name = "haskell-language-server-wrapper"; + paths = [pkgs.haskellPackages.haskell-language-server]; + meta.mainProgram = "haskell-language-server-wrapper"; + buildInputs = [pkgs.makeBinaryWrapper]; + # wrap HLS-wrapper so it can find the actual binary + postBuild = '' + wrapProgram $out/bin/haskell-language-server-wrapper \ + --prefix PATH : ${pkgs.haskellPackages.haskell-language-server}/bin + ''; + }); + cfg = config.vim.lsp.presets.haskell-language-server; in { options.vim.lsp.presets.haskell-language-server = { @@ -21,20 +34,18 @@ in { vim.lsp.servers.haskell-language-server = { enable = true; cmd = [ - (getExe (pkgs.symlinkJoin { - name = "haskell-language-server-wrapper"; - paths = [pkgs.haskellPackages.haskell-language-server]; - meta.mainProgram = "haskell-language-server-wrapper"; - buildInputs = [pkgs.makeBinaryWrapper]; - # wrap HLS-wrapper so it can find the actual binary - postBuild = '' - wrapProgram $out/bin/haskell-language-server-wrapper \ - --prefix PATH : ${pkgs.haskellPackages.haskell-language-server}/bin - ''; - })) + ( + if config.vim.lsp.vendorPrograms == "exact" + then vendored + else "haskell-language-server-wrapper" + ) "--lsp" ]; root_markers = ["hie.yaml" "stack.yaml" "cabal.project" "*.cabal" "package.yaml"]; }; + + vim.extraPackages = + optional (config.vim.lsp.vendorPrograms == "path") + pkgs.haskellPackages.haskell-language-server; }; }