diff --git a/modules/plugins/languages/haskell.nix b/modules/plugins/languages/haskell.nix index 737b511d..f670b805 100644 --- a/modules/plugins/languages/haskell.nix +++ b/modules/plugins/languages/haskell.nix @@ -6,14 +6,14 @@ ... }: let inherit (builtins) attrNames; - inherit (lib) genAttrs; - inherit (lib.types) either package enum listOf str nullOr; + inherit (lib) genAttrs optional; + inherit (lib.types) either package enum listOf str nullOr attrsOf anything; inherit (lib.options) mkEnableOption mkOption literalExpression; - inherit (lib.modules) mkIf mkMerge; + inherit (lib.modules) mkIf mkMerge mkDefault; inherit (config.vim.lib) mkMappingOption; inherit (lib.nvim.lua) toLuaObject; inherit (lib.nvim.binds) addDescriptionsToMappings; - inherit (lib.nvim.types) mkGrammarOption deprecatedSingleOrListOf mkPluginSetupOption luaInline; + inherit (lib.nvim.types) mkGrammarOption mkPluginSetupOption luaInline; inherit (lib.nvim.attrsets) mapListToAttrs; inherit (lib.meta) getExe; inherit (lib.generators) mkLuaInline; @@ -31,6 +31,12 @@ stylish-haskell = {command = getExe haskellPackages.stylish-haskell;}; floskell = {command = getExe haskellPackages.floskell;}; }; + + defaultCabalFormat = "cabal-fmt"; + cabalFormats = { + cabal-fmt = haskellPackages.cabal-fmt; + cabal-gild = haskellPackages.cabal-gild; + }; in { options.vim.languages.haskell = { enable = mkEnableOption "Haskell support"; @@ -67,12 +73,26 @@ in { defaultText = literalExpression "config.vim.languages.enableFormat"; }; type = mkOption { - type = deprecatedSingleOrListOf "vim.languages.haskell.format.type" (enum (attrNames formats)); + type = listOf (enum (attrNames formats)); default = defaultFormat; description = "Haskell formatter to use"; }; }; + cabalFormat = { + enable = + mkEnableOption "Haskell cabal file formatting via HLS" + // { + default = config.vim.languages.enableFormat; + defaultText = literalExpression "config.vim.languages.enableFormat"; + }; + type = mkOption { + type = enum (attrNames cabalFormats); + default = defaultCabalFormat; + description = "Haskell cabal file formatter to use via HLS"; + }; + }; + dap = { enable = mkEnableOption "DAP support for Haskell" @@ -105,7 +125,7 @@ in { cmd = mkOption { type = nullOr (listOf str); default = [ - "${pkgs.haskellPackages.haskell-language-server}/bin/haskell-language-server" + "${pkgs.haskellPackages.haskell-language-server}/bin/haskell-language-server-wrapper" "--lsp" ]; description = '' @@ -126,6 +146,12 @@ in { default = null; defaultText = literalExpression "Generated from vim.languages.haskell.extensions.haskell-tools.mappings"; }; + + settings = mkOption { + type = nullOr (attrsOf anything); + default = null; + description = "Settings passed to HLS. When null, generated from vim.languages.haskell.cabalFormat."; + }; }; dap = { @@ -198,7 +224,7 @@ in { (mkIf cfg.extensions.haskell-tools.enable { vim = { - extraPackages = [haskellPackages.cabal-fmt]; + extraPackages = optional cfg.cabalFormat.enable cabalFormats.${cfg.cabalFormat.type}; startPlugins = ["haskell-tools-nvim"]; globals.haskell_tools = cfg.extensions.haskell-tools.setupOpts; languages.haskell.extensions.haskell-tools.setupOpts = { @@ -223,6 +249,12 @@ in { ${mkBinding mappings.replQuit "function() vim.cmd('Haskell repl quit') end"} end ''; + settings = mkIf cfg.cabalFormat.enable (mkDefault { + haskell = { + cabalFormattingProvider = cfg.cabalFormat.type; + plugin.${cfg.cabalFormat.type}.config.path = getExe cabalFormats.${cfg.cabalFormat.type}; + }; + }); }; }; }; diff --git a/modules/plugins/lsp/presets/haskell-language-server.nix b/modules/plugins/lsp/presets/haskell-language-server.nix index 572ed13f..967b1cd4 100644 --- a/modules/plugins/lsp/presets/haskell-language-server.nix +++ b/modules/plugins/lsp/presets/haskell-language-server.nix @@ -4,11 +4,16 @@ pkgs, ... }: let - inherit (lib.meta) getExe'; + inherit (lib.meta) getExe getExe'; inherit (lib.modules) mkIf; inherit (lib.nvim.types) mkLspPresetEnableOption; cfg = config.vim.lsp.presets.haskell-language-server; + cabalFmtCfg = config.vim.languages.haskell.cabalFormat; + cabalFormats = { + cabal-fmt = pkgs.haskellPackages.cabal-fmt; + cabal-gild = pkgs.haskellPackages.cabal-gild; + }; in { options.vim.lsp.presets.haskell-language-server = { enable = mkLspPresetEnableOption "haskell-language-server" "Haskell" []; @@ -23,18 +28,16 @@ in { paths = [pkgs.haskellPackages.haskell-language-server]; meta.mainProgram = "haskell-language-server-wrapper"; buildInputs = [pkgs.makeBinaryWrapper]; - postBuild = '' - wrapProgram $out/bin/haskell-language-server-wrapper \ - --prefix PATH : ${pkgs.haskellPackages.cabal-fmt}/bin - ''; }) "haskell-language-server-wrapper") "--lsp" ]; root_markers = ["hie.yaml" "stack.yaml" "cabal.project" "*.cabal" "package.yaml"]; - settings = { + settings = mkIf cabalFmtCfg.enable { haskell = { - # cabal-fmt is an external tool; it is wrapped into the LSP binary's PATH above - cabalFormattingProvider = "cabal-fmt"; + cabalFormattingProvider = cabalFmtCfg.type; + # This option is undocumented in the haskell-language-server docs, but it does exist in the plugin API + # https://github.com/haskell/haskell-language-server/blob/f158128ec034bec1667c440262641086bbb4d359/plugins/hls-cabal-fmt-plugin/src/Ide/Plugin/CabalFmt.hs#L51 + plugin.${cabalFmtCfg.type}.config.path = getExe cabalFormats.${cabalFmtCfg.type}; }; }; };