diff --git a/modules/plugins/languages/haskell.nix b/modules/plugins/languages/haskell.nix index 32f45151..b392bcee 100644 --- a/modules/plugins/languages/haskell.nix +++ b/modules/plugins/languages/haskell.nix @@ -7,61 +7,17 @@ inherit (builtins) isList attrNames; inherit (lib.types) either package enum listOf str; inherit (lib.options) mkEnableOption mkOption literalExpression; - inherit (lib.strings) optionalString; inherit (lib.modules) mkIf mkMerge; - inherit (lib.nvim.types) mkGrammarOption; + inherit (lib.nvim.types) mkGrammarOption mkPluginSetupOption; inherit (lib.nvim.dag) entryAfter; inherit (lib.nvim.lua) toLuaObject; - inherit (lib.meta) getExe'; - inherit (lib.generators) mkLuaInline; + inherit (lib.nvim.custom) enumWithRename; inherit (pkgs) haskellPackages; cfg = config.vim.languages.haskell; - defaultServers = ["hls"]; - servers = { - hls = { - enable = false; - cmd = [(getExe' pkgs.haskellPackages.haskell-language-server "haskell-language-server-wrapper") "--lsp"]; - filetypes = ["haskell" "lhaskell"]; - on_attach = - mkLuaInline - /* - lua - */ - '' - function(client, bufnr) - local ht = require("haskell-tools") - local opts = { noremap = true, silent = true, buffer = bufnr } - vim.keymap.set('n', 'cl', vim.lsp.codelens.run, opts) - vim.keymap.set('n', 'hs', ht.hoogle.hoogle_signature, opts) - vim.keymap.set('n', 'ea', ht.lsp.buf_eval_all, opts) - vim.keymap.set('n', 'rr', ht.repl.toggle, opts) - vim.keymap.set('n', 'rf', function() - ht.repl.toggle(vim.api.nvim_buf_get_name(0)) - end, opts) - vim.keymap.set('n', 'rq', ht.repl.quit, opts) - end - ''; - root_dir = - mkLuaInline - /* - lua - */ - '' - function(bufnr, on_dir) - local fname = vim.api.nvim_buf_get_name(bufnr) - on_dir(util.root_pattern('hie.yaml', 'stack.yaml', 'cabal.project', '*.cabal', 'package.yaml')(fname)) - end - ''; - settings = { - haskell = { - formattingProvider = "ormolu"; - cabalFormattingProvider = "cabal-fmt"; - }; - }; - }; - }; + defaultServers = []; + servers = ["haskell-tools"]; in { options.vim.languages.haskell = { enable = mkEnableOption "Haskell support"; @@ -84,9 +40,23 @@ in { defaultText = literalExpression "config.vim.lsp.enable"; }; servers = mkOption { - type = listOf (enum (attrNames servers)); + type = listOf ( + enumWithRename + "vim.languages.haskell.lsp.servers" + (attrNames servers) + {hls = "haskell-tools";} + ); default = defaultServers; - description = "Haskell LSP server to use"; + description = '' + Haskell LSP server to use. Choosing `haskell-tools` will enable + {option}`vim.languages.haskell.extensions.haskell-tools-nvim.enable` + + > [!NOTE] + > + > HLS is extremely picky about your GHC version - most likely you'll + > have to install your specific HLS version in a devShell that matches + > your GHC version. + ''; }; }; @@ -103,6 +73,13 @@ in { description = "Haskell DAP package or command to run the Haskell DAP"; }; }; + + extensions = { + haskell-tools-nvim = { + enable = mkEnableOption "advanced tools for Haskell development"; + setupOpts = mkPluginSetupOption "haskell-tools.nvim" {}; + }; + }; }; config = mkIf cfg.enable (mkMerge [ @@ -113,33 +90,28 @@ in { }; }) - (mkIf (cfg.dap.enable || cfg.lsp.enable) { + (mkIf cfg.dap.enable { + vim.languages.haskell.extensions.haskell-tools-nvim = { + enable = true; + setupOpts = { + dap = { + cmd = + if isList cfg.dap.package + then toLuaObject cfg.dap.package + else ["${cfg.dap.package}/bin/haskell-debug-adapter"]; + }; + }; + }; + }) + + (mkIf cfg.extensions.haskell-tools-nvim.enable { vim = { startPlugins = ["haskell-tools-nvim"]; luaConfigRC.haskell-tools-nvim = entryAfter ["lsp-servers"] '' - vim.g.haskell_tools = { - ${optionalString cfg.lsp.enable '' - -- LSP - tools = { - hover = { - enable = true, - }, - }, - hls = ${toLuaObject servers.hls}, - ''} - ${optionalString cfg.dap.enable '' - dap = { - cmd = ${ - if isList cfg.dap.package - then toLuaObject cfg.dap.package - else ''{"${cfg.dap.package}/bin/haskell-debug-adapter"}'' - }, - }, - ''} - } + vim.g.haskell_tools = ${cfg.extensions.haskell-tools-nvim.setupOpts} ''; }; }) diff --git a/modules/plugins/lsp/presets/haskell-tools.nix b/modules/plugins/lsp/presets/haskell-tools.nix new file mode 100644 index 00000000..e94abb0f --- /dev/null +++ b/modules/plugins/lsp/presets/haskell-tools.nix @@ -0,0 +1,47 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib.meta) getExe'; + inherit (lib.modules) mkIf; + inherit (lib.nvim.types) mkLspPresetEnableOption; + inherit (lib.generators) mkLuaInline; + + cfg = config.vim.lsp.presets.haskell-tools; + haskell-toolsPackage = pkgs.haskellPackages.haskell-language-server; +in { + options.vim.lsp.presets.haskell-tools = { + enable = mkLspPresetEnableOption "haskell-tools-nvim" "Haskell" ["haskell"]; + }; + + config = mkIf cfg.enable { + vim.lsp.servers.haskell-tools = { + # The plugin will handle startup + enable = false; + # TODO: does this actually work? + cmd = [(getExe' haskell-toolsPackage "haskell-language-server-wrapper")]; + on_attach = mkLuaInline '' + function(client, bufnr) + local ht = require("haskell-tools") + local opts = { noremap = true, silent = true, buffer = bufnr } + vim.keymap.set('n', 'cl', vim.lsp.codelens.run, opts) + vim.keymap.set('n', 'hs', ht.hoogle.hoogle_signature, opts) + vim.keymap.set('n', 'ea', ht.lsp.buf_eval_all, opts) + vim.keymap.set('n', 'rr', ht.repl.toggle, opts) + vim.keymap.set('n', 'rf', function() + ht.repl.toggle(vim.api.nvim_buf_get_name(0)) + end, opts) + vim.keymap.set('n', 'rq', ht.repl.quit, opts) + end + ''; + settings = { + haskell = { + formattingProvider = "ormolu"; + cabalFormattingProvider = "cabal-fmt"; + }; + }; + }; + }; +}