merge: pull request #5337 from iyefrat/haskell

Improve `:lang haskell`
This commit is contained in:
Henrik Lissner 2021-09-15 00:58:52 +02:00 committed by GitHub
commit 7265fecd19
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 67 additions and 192 deletions

View file

@ -172,7 +172,7 @@ following properties:
:path [STRING] path to category root directory :path [STRING] path to category root directory
Example: Example:
(doom-module-set :lang 'haskell :flags '(+dante))" (doom-module-set :lang 'haskell :flags '(+lsp))"
(puthash (cons category module) plist doom-modules)) (puthash (cons category module) plist doom-modules))
(defun doom-module-path (category module &optional file) (defun doom-module-path (category module &optional file)

View file

@ -117,7 +117,7 @@ Modules that bring support for a language or group of languages to Emacs.
+ [[file:../modules/lang/fstar/README.org][fstar]] - F* support + [[file:../modules/lang/fstar/README.org][fstar]] - F* support
+ [[file:../modules/lang/gdscript/README.org][gdscript]] =+lsp= - TODO + [[file:../modules/lang/gdscript/README.org][gdscript]] =+lsp= - TODO
+ [[file:../modules/lang/go/README.org][go]] =+lsp= - TODO + [[file:../modules/lang/go/README.org][go]] =+lsp= - TODO
+ [[file:../modules/lang/haskell/README.org][haskell]] =+dante +ghcide +lsp= - TODO + [[file:../modules/lang/haskell/README.org][haskell]] =+lsp= - TODO
+ hy - TODO + hy - TODO
+ [[file:../modules/lang/idris/README.org][idris]] - TODO + [[file:../modules/lang/idris/README.org][idris]] - TODO
+ java =+meghanada +eclim +lsp= - TODO + java =+meghanada +eclim +lsp= - TODO

View file

@ -132,7 +132,7 @@
;;fstar ; (dependent) types and (monadic) effects and Z3 ;;fstar ; (dependent) types and (monadic) effects and Z3
;;gdscript ; the language you waited for ;;gdscript ; the language you waited for
;;(go +lsp) ; the hipster dialect ;;(go +lsp) ; the hipster dialect
;;(haskell +dante) ; a language that's lazier than I am ;;(haskell +lsp) ; a language that's lazier than I am
;;hy ; readability of scheme w/ speed of python ;;hy ; readability of scheme w/ speed of python
;;idris ; a language you can depend on ;;idris ; a language you can depend on
;;json ; At least it ain't XML ;;json ; At least it ain't XML

View file

@ -1,41 +0,0 @@
;;; lang/haskell/+dante.el -*- lexical-binding: t; -*-
;;;###if (featurep! +dante)
(use-package! dante
:hook (haskell-mode-local-vars . dante-mode)
:init
(setq dante-load-flags '(;; defaults:
"+c"
"-Wwarn=missing-home-modules"
"-fno-diagnostics-show-caret"
;; necessary to make attrap-attrap useful:
"-Wall"
;; necessary to make company completion useful:
"-fdefer-typed-holes"
"-fdefer-type-errors"))
:config
(when (featurep! :checkers syntax)
(flycheck-add-next-checker 'haskell-dante '(warning . haskell-hlint)))
(set-company-backend! 'dante-mode #'dante-company)
(defadvice! +haskell--restore-modified-state-a (fn &rest args)
"Marks the buffer as falsely modified.
Dante quietly saves the current buffer (without triggering save hooks) before
invoking flycheck, unexpectedly leaving the buffer in an unmodified state. This
is annoying if we depend on save hooks to do work on the buffer (like
reformatting)."
:around #'dante-async-load-current-buffer
(let ((modified-p (buffer-modified-p)))
(apply fn args)
(if modified-p (set-buffer-modified-p t))))
(when (featurep 'evil)
(add-hook 'dante-mode-hook #'evil-normalize-keymaps))
(map! :map dante-mode-map
:localleader
"t" #'dante-type-at
"i" #'dante-info
"l" #'haskell-process-load-file
"e" #'dante-eval-block
"a" #'attrap-attrap))

View file

@ -1,11 +0,0 @@
;;; lang/haskell/+lsp.el -*- lexical-binding: t; -*-
(use-package! lsp-haskell
:after lsp-mode
:preface (add-hook 'haskell-mode-local-vars-hook #'lsp!)
:config
(when (featurep! +ghcide)
(setq lsp-haskell-server-path "ghcide"
lsp-haskell-server-args nil))
;; Does some strange indentation if it pastes in the snippet
(setq-hook! 'haskell-mode-hook yas-indent-line 'fixed))

View file

@ -5,152 +5,69 @@
* Table of Contents :TOC: * Table of Contents :TOC:
- [[#description][Description]] - [[#description][Description]]
- [[#external-resources][External resources]] - [[#maintainers][Maintainers]]
- [[#module-flags][Module Flags]] - [[#module-flags][Module Flags]]
- [[#plugins][Plugins]] - [[#plugins][Plugins]]
- [[#prerequisites][Prerequisites]] - [[#prerequisites][Prerequisites]]
- [[#cabal][Cabal]] - [[#features][Features]]
- [[#lsp-haskell-language-server][LSP (haskell-language-server)]]
- [[#lsp-ghcide][LSP (ghcide)]]
- [[#stack][Stack]]
- [[#haskell-packages][Haskell packages]]
- [[#configuration][Configuration]] - [[#configuration][Configuration]]
- [[#using-the-new-style-cabal-repl][Using the new-style cabal REPL]]
- [[#troubleshooting][Troubleshooting]]
* Description * Description
This module adds [[https://www.haskell.org/][Haskell]] support, powered by either [[https://github.com/jyp/dante][dante]] (the default) or LSP Adds Haskell support to Doom Emacs.
(haskell-language-server or ghcide).
+ Code completion (~company-ghc~) ** Maintainers
+ Look up documentation (~hoogle~) This module has no dedicated maintainers.
+ eldoc support (~dante~)
+ REPL (~ghci~)
+ Syntax-checking (~flycheck~)
+ Code navigation (~dante~)
+ [[https://github.com/hlissner/doom-snippets/tree/master/haskell-mode][Snippets]]
** External resources
Here are a few resources I've found indispensable in my Haskell adventures:
+ [[http://learnyouahaskell.com/][Learn you a haskell for great good]]
+ [[http://haskellbook.com/][Haskell Programming from first principles]]
+ [[https://github.com/krispo/awesome-haskell][Awesome Haskell]]: an extensive list of haskell resources
+ [[https://docs.haskellstack.org/en/stable/README/][The Haskell Tool Stack docs]]
** Module Flags ** Module Flags
+ =+dante= Enables dante; a fork of intero aimed at lightweightedness. It + =+lsp= Enable LSP support with for [[https://github.com/haskell/haskell-language-server][haskell-language-server]] (requires the =:tools lsp= module).
doesn't depend on =stack=, supports both ~cabal~-only and ~stack~ projects,
but lacks eldoc support.
+ =+ghcide= Enables LSP support with ghcide (requires the ~:tools lsp~ module).
+ =+lsp= Enables LSP support with haskell-language-server (requires the ~:tools lsp~
module).
** Plugins ** Plugins
+ [[https://github.com/haskell/haskell-mode][haskell-mode]] + [[https://github.com/haskell/haskell-mode][haskell-mode]]
+ =+dante= + [[https://github.com/emacs-lsp/lsp-haskell][lsp-haskell]] (=+lsp=, =:tools lsp=)
+ [[https://github.com/jyp/dante][dante]]
+ [[https://github.com/jyp/attrap][attrap]]
+ =+lsp=
+ [[https://github.com/emacs-lsp/lsp-haskell][lsp-haskell]]
* Prerequisites * Prerequisites
Depending on whether you use Dante, haskell-language-server or ghcide, your It is recommended to install the haskell tooling using [[https://www.haskell.org/ghcup/][ghcup]]. Only ghc is needed
dependencies will differ: for basic functionality:
+ Dante users need =cabal=, =ghc= and =ghc-mod= #+BEGIN_SRC bash
+ LSP users need the =haskell-language-server= LSP server OR =ghcide= ghcup install ghc
+ All users will need the =hoogle= package
** Cabal
To use Dante, you need =cabal= (the haskell package builder) and =ghci= (the
compiler, syntax checker & repl):
*** MacOS
#+BEGIN_SRC sh
brew install cabal-install ghc
#+END_SRC #+END_SRC
*** Arch Linux but =+lsp= users should also install the language server:
#+BEGIN_SRC sh
sudo pacman -S cabal-install ghc
#+END_SRC
*** openSUSE
#+BEGIN_SRC sh :dir /sudo::
sudo zypper install cabal-install ghc
#+END_SRC
** LSP (haskell-language-server)
You will need =stack= and =git= installed.
You will find a comprehensive [[https://github.com/haskell/haskell-language-server#installation][instructions for haskell-language-server on its project page]], but if you are using [[https://www.haskell.org/ghcup/][ghcup]]:
#+BEGIN_SRC bash #+BEGIN_SRC bash
ghcup install hls ghcup install hls
#+END_SRC #+END_SRC
** LSP (ghcide) Installing [[https://www.haskell.org/cabal/][cabal]] or [[https://docs.haskellstack.org/en/stable/README/][stack]] as well is recommended, and can be done through
See https://github.com/digital-asset/ghcide for install instructions. =ghcup=.
** Stack =haskell-mode= provides support for [[https://github.com/ndmitchell/hoogle][hoogle]], which can be installed through
To use LSP, you need =stack=: system package manager, cabal, or stack.
*** MacOS =haskell-language-server= provides support for [[https://github.com/ndmitchell/hlint/][hlint]], and haskell code
#+BEGIN_SRC sh formatters such as [[https://github.com/lspitzner/brittany][brittany]], [[https://github.com/ennocramer/floskell][floskell]], [[https://github.com/tweag/ormolu][ormolu]], [[https://github.com/fourmolu/fourmolu][fourmolu]], and [[https://github.com/haskell/stylish-haskell][stylish-haskell]],
brew install haskell-stack which can be installed through system package manager, cabal, or stack.
stack setup
#+END_SRC
*** Arch Linux
#+BEGIN_SRC sh
sudo pacman -S stack
# Replace pacaur with your AUR package manager of choice
pacaur -S ncurses5-compat-lib
stack setup
#+END_SRC
*** openSUSE * Features
#+BEGIN_SRC sh :dir /sudo:: This module intergrates the haskell packages into Doom by providing things such
sudo zypper install stack as repl support, project root recognition, etc. It also provide the following
stack setup keybindings:
#+END_SRC
** Haskell packages | Keybinding | Description |
You'll need to install the following packages using ~stack~ or ~cabal~: |-------------------+-----------------------------------------------|
| =<localleader> b= | Build the current cabal project |
+ (Dante users) =ghc-mod= | =<localleader> c= | Visit the =.cabal= file of the current buffer |
#+BEGIN_SRC sh | =<localleader> h= | Toggle visibility of the form at point |
stack install ghc-mod | =<localleader> H= | hides all top level functions |
# or
cabal install ghc-mod
#+END_SRC
+ =hoogle=
#+BEGIN_SRC sh
cabal update
cabal install happy haskell-src-exts # ghc-mod/hoogle dependencies
cabal ghc-mod hoogle
# or
stack install ghc-mod
stack install hoogle
#+END_SRC
And ensure the binaries for these packages are in your ~PATH~, e.g.
#+BEGIN_SRC sh
# place this in your profile file, like ~/.bash_profile or ~/.zshenv
export PATH="~/.local/bin:$PATH"
#+END_SRC
* Configuration * Configuration
** Using the new-style cabal REPL After installing your preferred formatter, make sure to set
=haskell-mode= will typically detect what REPL to run based on your project =lsp-haskell-formatting-provider= to it.
(e.g. stack, (old-style) cabal or ghc). If you want the new-style cabal REPL you
must set ~haskell-process-type~ manually:
#+BEGIN_SRC emacs-lisp Make sure to configure the lsp to use your perfered formatter, e.g.:
(setq haskell-process-type 'cabal-new-repl) #+BEGIN_SRC elisp
;; ~/.doom.d/config.el
(after!
(setq lsp-haskell-formatting-provider "brittany"))
#+END_SRC #+END_SRC
* Troubleshooting
+ Stack users: a ~dist/setup-config~ file in your project may cause [[https://github.com/DanielG/ghc-mod/wiki#known-issues-related-to-stack][ghc-mod to
not work]].

View file

@ -43,10 +43,10 @@
"H" #'haskell-hide-toggle-all)) "H" #'haskell-hide-toggle-all))
;; (use-package! lsp-haskell
;;; Backends :when (featurep! +lsp)
:after lsp-mode
(cond ((featurep! +dante) (load! "+dante")) :preface (add-hook 'haskell-mode-local-vars-hook #'lsp!)
((or (featurep! +lsp) :config
(featurep! +ghcide)) ;; Does some strange indentation if it pastes in the snippet
(load! "+lsp"))) (setq-hook! 'haskell-mode-hook yas-indent-line 'fixed))

View file

@ -5,8 +5,22 @@
(featurep! :tools lsp)) (featurep! :tools lsp))
"This module requires (:tools lsp)") "This module requires (:tools lsp)")
(when (featurep! +dante) (unless (executable-find "cabal")
(unless (executable-find "cabal") (warn! "Couldn't find cabal. haskell-mode may have issues."))
(warn! "Couldn't find cabal, haskell-mode may have issues"))
(unless (executable-find "hlint") (unless (executable-find "hoogle")
(warn! "Couldn't find hlint. Flycheck may have issues in haskell-mode"))) (warn! "Couldn't find hoogle. Documentation searching will not work."))
(unless (or (featurep! +lsp)
(executable-find "hlint"))
(warn! "Couldn't find hlint. Flycheck may have issues in haskell-mode.
Install it or enable +lsp."))
(when (and (featurep! :editor format)
(not (executable-find "brittany")))
(warn! "Couldn't find brittany. Code formatting will not work.
Install it or enable +lsp."))
(when (and (featurep! +lsp)
(not (executable-find "haskell-language-server-wrapper")))
(warn! "Couldn't find haskell-language-server."))

View file

@ -3,10 +3,6 @@
(package! haskell-mode :pin "98ba3922360199d5260d47f417f096730ad057c5") (package! haskell-mode :pin "98ba3922360199d5260d47f417f096730ad057c5")
(when (featurep! +dante) (when (and (featurep! +lsp)
(package! dante :pin "8741419333fb85ed2c1d71f5902688f5201b0a40") (not (featurep! :tools lsp +eglot)))
(package! attrap :pin "a5bc695af27349ae6fe4541a581e6fd449d2a026"))
(when (or (and (featurep! +lsp)
(not (featurep! :tools lsp +eglot)))
(featurep! +ghcide))
(package! lsp-haskell :pin "4e62cf897dd9e9fcef25c6e8e483490a07a5d439")) (package! lsp-haskell :pin "4e62cf897dd9e9fcef25c6e8e483490a07a5d439"))