diff --git a/CHANGELOG.develop b/CHANGELOG.develop index 6eab41798..db0eb4425 100644 --- a/CHANGELOG.develop +++ b/CHANGELOG.develop @@ -1357,6 +1357,7 @@ Other: (thanks to Magnus Therning) - Fixed jump handlers conflict for haskell and intero (thanks to CthulhuDen) - Fix haskell jump handler for dante (thanks to cjay) +- Enable LSP mode using HIE. **** Helm - Limited =ripgrep= results to 512 columns by default, and added =spacemacs-helm-rg-max-column-number= layer variable to configure the above diff --git a/layers/+lang/haskell/README.org b/layers/+lang/haskell/README.org index f2fb38e63..4dc4dfd45 100644 --- a/layers/+lang/haskell/README.org +++ b/layers/+lang/haskell/README.org @@ -14,6 +14,7 @@ - [[#intero][=intero=]] - [[#dante][=dante=]] - [[#ghc-mod][=ghc-mod=]] + - [[#lsp][=lsp=]] - [[#optional-extras][Optional extras]] - [[#structured-haskell-mode][structured-haskell-mode]] - [[#hindent][hindent]] @@ -77,6 +78,7 @@ This layer requires some [[https://www.haskell.org/cabal/][cabal]] packages: - =hoogle= (optional for =haskell-mode= and =helm-hoogle=) - =ghc-mod= (optional for completion) - =intero= (optional for completion) +- =hie= (optional for completion) To install them, use the following command (or the =stack= equivalent): @@ -100,8 +102,8 @@ For information about setting up =$PATH=, check out the corresponding section in the FAQ (~SPC h SPC $PATH RET~). ** Completion support -This layer provides several completion backends - =intero=, =dante=, =ghci= and -=ghc-mod=. =ghci= (=company-ghci=) is used by default, because it doesn’t +This layer provides several completion backends - =intero=, =dante=, =ghci=, +=ghc-mod=, and =lsp=. =ghci= (=company-ghci=) is used by default, because it doesn’t require any dependencies, and it works with both =stack= and pure =cabal= projects. The completion backend can be changed manually, by setting the value of the =haskell-completion-backend= variable. Note that in order to enable @@ -152,6 +154,14 @@ Also note that =ghc-mod= only works with the =GHC= version that was used to build =ghc-mod=. You can check which version was used by calling =ghc-mod --version=. +*** =lsp= +=lsp= requires an appropriate installation of =hie= to provide the Haskell language server. +=hie= is built on =ghc-mod=, so many of the same considerations apply. + +Enabling the =lsp= backend requires the =lsp= layer to be enabled, and provides access to +all the additional =lsp-mode= keybindings. As such it is more of a full backend than just +a completion backend. + ** Optional extras The Haskell layer supports some extra features, which can be enabled through the layer variables. diff --git a/layers/+lang/haskell/config.el b/layers/+lang/haskell/config.el index 3ae6bd663..85cafac78 100644 --- a/layers/+lang/haskell/config.el +++ b/layers/+lang/haskell/config.el @@ -17,7 +17,7 @@ (defvar haskell-completion-backend 'ghci "Completion backend used by company. -Available options are `ghci', `intero', `dante', and `ghc-mod'. Default is +Available options are `ghci', `intero', `dante', `lsp' and `ghc-mod'. Default is `ghci'.") (defvar haskell-enable-hindent nil diff --git a/layers/+lang/haskell/funcs.el b/layers/+lang/haskell/funcs.el index 81942a6fe..60235189f 100644 --- a/layers/+lang/haskell/funcs.el +++ b/layers/+lang/haskell/funcs.el @@ -28,6 +28,7 @@ "Conditionally setup haskell backend." (pcase haskell-completion-backend (`ghci (spacemacs-haskell//setup-ghci)) + (`lsp (spacemacs-haskell//setup-lsp)) (`intero (spacemacs-haskell//setup-intero)) (`dante (spacemacs-haskell//setup-dante)) (`ghc-mod (spacemacs-haskell//setup-ghc-mod)))) @@ -36,6 +37,7 @@ "Conditionally setup haskell backend." (pcase haskell-completion-backend (`ghci (spacemacs-haskell//setup-ghci-company)) + (`lsp (spacemacs-haskell//setup-lsp-company)) (`intero (spacemacs-haskell//setup-intero-company)) (`dante (spacemacs-haskell//setup-dante-company)) (`ghc-mod (spacemacs-haskell//setup-ghc-mod-company)))) @@ -50,6 +52,31 @@ :backends (company-ghci company-dabbrev-code company-yasnippet) :modes haskell-mode)) +;; LSP functions + +(defun spacemacs-haskell//setup-lsp () + "Setup lsp backend" + (if (configuration-layer/layer-used-p 'lsp) + (progn + ;; The functionality we require from this is not an autoload, but rather some + ;; top-level code that registers a LSP server type. So we need to load it + ;; directly and can't rely on it being autoloaded. + (require 'lsp-haskell) + (lsp)) + (message "`lsp' layer is not installed, please add `lsp' layer to your dotfile."))) + +(defun spacemacs-haskell//setup-lsp-company () + "Setup lsp auto-completion" + (if (configuration-layer/layer-used-p 'lsp) + (progn + (spacemacs|add-company-backends + :backends company-lsp + :modes haskell-mode + :append-hooks nil + :call-hooks t) + (company-mode)) + (message "`lsp' layer is not installed, please add `lsp' layer to your dotfile."))) + ;; ghc-mod functions (defun spacemacs-haskell//setup-ghc-mod () diff --git a/layers/+lang/haskell/packages.el b/layers/+lang/haskell/packages.el index 454f28c9b..c55d2ac61 100644 --- a/layers/+lang/haskell/packages.el +++ b/layers/+lang/haskell/packages.el @@ -28,6 +28,8 @@ ;; dante completion backend (dante :requires company) + lsp-haskell + flycheck (flycheck-haskell :requires flycheck) ggtags @@ -40,6 +42,10 @@ hlint-refactor )) +(defun haskell/init-lsp-haskell() + (use-package lsp-haskell + :defer t)) + (defun haskell/init-cmm-mode () (use-package cmm-mode :defer t))