559 lines
26 KiB
Org Mode
559 lines
26 KiB
Org Mode
#+TITLE: Haskell layer
|
||
|
||
[[file:img/haskell.png]]
|
||
|
||
* Table of Contents :TOC_4_gh:noexport:
|
||
- [[#description][Description]]
|
||
- [[#features][Features:]]
|
||
- [[#install][Install]]
|
||
- [[#layer][Layer]]
|
||
- [[#dependencies][Dependencies]]
|
||
- [[#setup-path][Setup PATH]]
|
||
- [[#completion-support][Completion support]]
|
||
- [[#company-ghci][=company-ghci=]]
|
||
- [[#intero][=intero=]]
|
||
- [[#dante][=dante=]]
|
||
- [[#ghc-mod][=ghc-mod=]]
|
||
- [[#lsp][=lsp=]]
|
||
- [[#optional-extras][Optional extras]]
|
||
- [[#structured-haskell-mode][structured-haskell-mode]]
|
||
- [[#hindent][hindent]]
|
||
- [[#key-bindings][Key bindings]]
|
||
- [[#documentation][Documentation]]
|
||
- [[#debug][Debug]]
|
||
- [[#debug-buffer][Debug Buffer]]
|
||
- [[#repl][REPL]]
|
||
- [[#intero-repl][Intero REPL]]
|
||
- [[#cabal-commands][Cabal commands]]
|
||
- [[#cabal-files][Cabal files]]
|
||
- [[#refactor][Refactor]]
|
||
- [[#ghc-mod-1][Ghc-mod]]
|
||
- [[#insert-template][Insert template]]
|
||
- [[#intero-1][Intero]]
|
||
- [[#syntax-checking][Syntax checking]]
|
||
- [[#flycheck][Flycheck]]
|
||
- [[#hlint][HLint]]
|
||
- [[#ghc-mod-2][ghc-mod]]
|
||
- [[#interactive-haskell-mode][Interactive haskell-mode]]
|
||
- [[#flymake][Flymake]]
|
||
- [[#troubleshooting][Troubleshooting]]
|
||
- [[#faq][FAQ]]
|
||
- [[#the-repl-doesnt-work][The REPL doesn't work]]
|
||
- [[#the-repl-is-stuck][The REPL is stuck]]
|
||
- [[#i-am-using-stack-and-ghc-mod-but-ghc-mod-doesnt-work][I am using =stack= and =ghc-mod=, but =ghc-mod= doesn't work]]
|
||
- [[#ghc-mod-doesnt-work][=ghc-mod= doesn't work]]
|
||
- [[#indentation-doesnt-reset-when-pressing-return-after-an-empty-line][Indentation doesn't reset when pressing return after an empty line]]
|
||
- [[#flycheck-displays-hlint-warnings-but-not-errors][Flycheck displays HLint warnings but not errors]]
|
||
- [[#i-can-see-highlighted-errors-but-they-dont-appear-in-the-error-list][I can see highlighted errors but they don't appear in the error list]]
|
||
- [[#flycheck-doesnt-work][Flycheck doesn't work]]
|
||
- [[#flycheck-doesnt-work-with-stack][Flycheck doesn't work with =stack=]]
|
||
- [[#the-stack-build-directory-is-wrong][The =stack= build directory is wrong]]
|
||
- [[#the-project-root-directory-is-not-set-properly][The Project root directory is not set properly]]
|
||
- [[#haskell-mode-commands-dont-work][haskell-mode commands don't work]]
|
||
- [[#ghc-mod-and-haskell-mode-commands-overlap-how-do-i-know-which-command-belongs-to-what][=ghc-mod= and =haskell-mode= commands overlap. How do I know which command belongs to what?]]
|
||
- [[#some-commands-start-with-ghc--and-some-with-haskell--what-does-that-mean][Some commands start with =ghc-= and some with =haskell-=. What does that mean?]]
|
||
|
||
* Description
|
||
This layer adds support for the [[https://www.haskell.org/][Haskell]] language.
|
||
|
||
** Features:
|
||
- syntax highlighting for [[https://github.com/haskell/haskell-mode][haskell source]], [[https://github.com/haskell/haskell-mode][cabal files]], [[https://github.com/bgamari/cmm-mode][C-- source]],
|
||
- auto-completion with one of the selected backends (=intero=, =dante=, =ghci= or
|
||
=ghc-mod=).
|
||
|
||
*This layer is under construction, it needs your contributions and bug reports.*
|
||
|
||
* Install
|
||
** Layer
|
||
To use this configuration layer, add it to your =~/.spacemacs=. You will need to
|
||
add =haskell= to the existing =dotspacemacs-configuration-layers= list in this
|
||
file.
|
||
|
||
** Dependencies
|
||
This layer requires some [[https://www.haskell.org/cabal/][cabal]] packages:
|
||
- =apply-refact= (required by =hlint-refactor=)
|
||
- =hlint= (required by =hlint-refactor=)
|
||
- =stylish-haskell= (optional for =haskell-mode=)
|
||
- =hasktags= (optional)
|
||
- =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):
|
||
|
||
#+BEGIN_SRC sh
|
||
$ cabal install apply-refact hlint stylish-haskell hasktags hoogle
|
||
#+END_SRC
|
||
|
||
** Setup PATH
|
||
First of all, make sure that your =$PATH= contains the installation path for
|
||
Haskell tools like =ghc=, =ghci= etc. It depends on how you have installed
|
||
=ghc=, but you can always check it by running =which ghc= in your terminal.
|
||
=Stack= users should only add the installation path of =stack= itself. Usually
|
||
it’s =~/.local/bin=.
|
||
|
||
Then make sure that your =$PATH= contains the installation path for the =cabal=
|
||
packages. If you are using =cabal= it should be =~/.cabal/bin= or
|
||
=~/Library/Haskell/bin= (for ’Haskell for Mac’ users). If you are using =stack=
|
||
then it should be =~/.local/bin=.
|
||
|
||
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=,
|
||
=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
|
||
completion, you’ll have to enable the =auto-completion= layer as well.
|
||
|
||
#+BEGIN_SRC emacs-lisp
|
||
(setq-default dotspacemacs-configuration-layers
|
||
'(auto-completion
|
||
(haskell :variables haskell-completion-backend 'intero)))
|
||
#+END_SRC
|
||
|
||
Backend can be chosen on a per project basis using directory local variables
|
||
(files named =.dir-locals.el= at the root of a project), an example to use the
|
||
=intero= backend:
|
||
|
||
#+BEGIN_SRC elisp
|
||
;;; Directory Local Variables
|
||
;;; For more information see (info "(emacs) Directory Variables")
|
||
|
||
((haskell-mode (haskell-completion-backend . intero)))
|
||
#+END_SRC
|
||
|
||
*Note:* you can easily add a directory local variable with ~SPC f v d~.
|
||
|
||
*** =company-ghci=
|
||
[[https://github.com/juiko/company-ghci][company-ghci]] communicates directly with =ghci=, in order to provide completion.
|
||
To use it, you have to call =haskell-process-load-or-reload= (=SPC s b=).
|
||
|
||
*** =intero=
|
||
=Intero= only works for =stack= users. You can install the =intero= executable
|
||
manually, by calling =stack install intero=, but this step is optional as
|
||
=Intero= installs itself.
|
||
|
||
*** =dante=
|
||
=dante= works for =cabal=, =nix=, =sytx=, and =stack= users.
|
||
=dante= requires Emacs 25.
|
||
|
||
*** =ghc-mod=
|
||
[[http://www.mew.org/~kazu/proj/ghc-mod/][ghc-mod]] enhances =haskell-mode=, with for example code completion, templates,
|
||
case-splitting and much more. In order to use it, you need to install the
|
||
executable with =cabal install ghc-mod= (or the =stack= equivalent).
|
||
|
||
=Stack= users also should make sure that =dist/setup-config= doesn’t exist in
|
||
the project root. As it will confuse =ghc-mod=. For more troubleshooting,
|
||
checkout this [[https://github.com/DanielG/ghc-mod/wiki#user-content-known-issues-related-to-stack][document]].
|
||
|
||
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= key bindings. 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.
|
||
|
||
*** structured-haskell-mode
|
||
Currently there is no support for [[https://github.com/chrisdone/structured-haskell-mode][structured-haskell-mode]], since it doesn’t play
|
||
very well with non-emacs editing styles ([[https://github.com/chrisdone/structured-haskell-mode/issues/81][structured-haskell-mode/#81]]). Emacs
|
||
editing style users can easily enable it by adding =structured-haskell-mode= to
|
||
the list of =dotspacemacs-additional-packages= in your =.spacemacs= file. For
|
||
more installation instructions, please refer to the official documentation at
|
||
the [[https://github.com/chrisdone/structured-haskell-mode#features][structured-haskell-mode]] page. In case you are a non-emacs editing style user
|
||
and still want to use =structured-haskell-mode= - use it at your own risk.
|
||
|
||
Any contributions that will help to solve issues with =structured-haskell-mode=
|
||
are warmly welcome!
|
||
|
||
*** hindent
|
||
[[https://github.com/commercialhaskell/hindent][hindent]] is an extensible Haskell pretty printer, which lets you reformat your
|
||
code. You need to install the executable with =cabal install hindent= or
|
||
=stack install hindent=.
|
||
|
||
To enable it you have to toggle the variable =haskell-enable-hindent=.
|
||
|
||
See examples [[https://github.com/commercialhaskell/hindent/blob/master/TESTS.md][here]].
|
||
|
||
#+BEGIN_SRC emacs-lisp
|
||
(setq-default dotspacemacs-configuration-layers
|
||
'((haskell :variables haskell-enable-hindent t)))
|
||
#+END_SRC
|
||
|
||
* Key bindings
|
||
All Haskell specific bindings are prefixed with the major-mode leader ~SPC m~.
|
||
|
||
Top-level commands are prefixed by ~SPC m~:
|
||
|
||
| Key binding | Description |
|
||
|-------------+---------------------------------------------------------------------|
|
||
| ~SPC m g g~ | go to definition or tag |
|
||
| ~SPC m g i~ | cycle the Haskell import lines or return to point (with prefix arg) |
|
||
| ~SPC m F~ | format buffer using haskell-stylish |
|
||
| ~SPC m f~ | format declaration using hindent (if enabled) |
|
||
|
||
** Documentation
|
||
Documentation commands are prefixed by ~SPC m h~
|
||
|
||
| Key binding | Description |
|
||
|-------------+----------------------------------------------------------------------------|
|
||
| ~SPC m h d~ | find or generate Haddock documentation for the identifier under the cursor |
|
||
| ~SPC m h f~ | do a helm-hoogle lookup |
|
||
| ~SPC m h h~ | do a Hoogle lookup |
|
||
| ~SPC m h H~ | do a local Hoogle lookup |
|
||
| ~SPC m h i~ | gets information for the identifier under the cursor |
|
||
| ~SPC m h t~ | gets the type of the identifier under the cursor |
|
||
| ~SPC m h y~ | do a Hayoo lookup |
|
||
|
||
** Debug
|
||
Debug commands are prefixed by ~SPC m d~:
|
||
|
||
| Key binding | Description |
|
||
|-------------+--------------------------------------------|
|
||
| ~SPC m d a~ | abandon current process |
|
||
| ~SPC m d b~ | insert breakpoint at function |
|
||
| ~SPC m d B~ | delete breakpoint |
|
||
| ~SPC m d c~ | continue current process |
|
||
| ~SPC m d d~ | start debug process, needs to be run first |
|
||
| ~SPC m d n~ | next breakpoint |
|
||
| ~SPC m d N~ | previous breakpoint |
|
||
| ~SPC m d p~ | previous breakpoint |
|
||
| ~SPC m d r~ | refresh process buffer |
|
||
| ~SPC m d s~ | step into the next function |
|
||
| ~SPC m d t~ | trace the expression |
|
||
|
||
** Debug Buffer
|
||
|
||
| Key binding | Description |
|
||
|-------------+---------------------------------------------|
|
||
| ~RET~ | select object at the point |
|
||
| ~a~ | abandon current computation |
|
||
| ~b~ | break on function |
|
||
| ~c~ | continue the current computation |
|
||
| ~d~ | delete object at the point |
|
||
| ~i~ | step into the next function |
|
||
| ~r~ | refresh the debugger buffer |
|
||
| ~s~ | go to next step to inspect bindings |
|
||
| ~S~ | go to previous step to inspect the bindings |
|
||
| ~t~ | trace the expression |
|
||
|
||
** REPL
|
||
REPL commands are prefixed by ~SPC m s~:
|
||
|
||
| Key binding | Description |
|
||
|-------------+-------------------------------------------------|
|
||
| ~SPC m s b~ | load or reload the current buffer into the REPL |
|
||
| ~SPC m s c~ | clear the REPL |
|
||
| ~SPC m s s~ | show and switch to the REPL |
|
||
| ~SPC m s S~ | show the REPL without switching to it |
|
||
|
||
** Intero REPL
|
||
Intero REPL commands are prefixed by ~SPC m i~:
|
||
|
||
| Key binding | Description |
|
||
|-------------+---------------------------------------------------------------|
|
||
| ~SPC m i c~ | change directory in the backend process |
|
||
| ~SPC m i d~ | reload the module =DevelMain= and then run =DevelMain.update= |
|
||
| ~SPC m i k~ | stop the current worker process and kill its associated |
|
||
| ~SPC m i l~ | list hidden process buffers created by =intero= |
|
||
| ~SPC m i r~ | restart the process with the same configuration as before |
|
||
| ~SPC m i t~ | set the targets to use for stack =ghci= |
|
||
|
||
** Cabal commands
|
||
Cabal commands are prefixed by ~SPC m c~:
|
||
|
||
| Key binding | Description |
|
||
|-------------+------------------------------------------------------------|
|
||
| ~SPC m c a~ | cabal actions |
|
||
| ~SPC m c b~ | build the current cabal project, i.e. invoke =cabal build= |
|
||
| ~SPC m c c~ | compile the current project, i.e. invoke =ghc= |
|
||
| ~SPC m c v~ | visit the cabal file |
|
||
|
||
** Cabal files
|
||
These commands are available in a cabal file.
|
||
|
||
| Key binding | Description |
|
||
|-------------+---------------------------------------------|
|
||
| ~SPC m d~ | add a dependency to the project |
|
||
| ~SPC m b~ | go to benchmark section |
|
||
| ~SPC m e~ | go to executable section |
|
||
| ~SPC m t~ | go to test-suite section |
|
||
| ~SPC m m~ | go to exposed modules |
|
||
| ~SPC m l~ | go to library section |
|
||
| ~SPC m n~ | go to next subsection |
|
||
| ~SPC m p~ | go to previous subsection |
|
||
| ~SPC m s c~ | clear the REPL |
|
||
| ~SPC m s s~ | show the REPL without switching to it |
|
||
| ~SPC m s S~ | show and switch to the REPL |
|
||
| ~SPC m N~ | go to next section |
|
||
| ~SPC m P~ | go to previous section |
|
||
| ~SPC m f~ | find or create source-file under the cursor |
|
||
|
||
** Refactor
|
||
Refactor commands are prefixed by ~SPC m r~:
|
||
|
||
| Key binding | Description |
|
||
|-------------+---------------------------------------------------|
|
||
| ~SPC m r b~ | apply all HLint suggestions in the current buffer |
|
||
| ~SPC m r i~ | reformat imports from anywhere in the buffer |
|
||
| ~SPC m r r~ | apply the HLint suggestion under the cursor |
|
||
| ~SPC m r s~ | list all Intero suggestions |
|
||
|
||
Only some of the HLint suggestions can be applied.
|
||
|
||
To apply the Intero suggestions, press `C-c C-c` when the window is open.
|
||
|
||
Both the HLint and Intero suggestions appear in the same window.
|
||
|
||
** Ghc-mod
|
||
These commands are only available when ghc-mod is enabled.
|
||
|
||
For more info, see
|
||
[[http://www.mew.org/~kazu/proj/ghc-mod/en/emacs.html]]
|
||
|
||
ghc-mod commands are prefixed by ~SPC m m~:
|
||
|
||
| Key binding | Description |
|
||
|-------------+-------------------------------------------|
|
||
| ~SPC t~ | insert template |
|
||
| ~SPC m m u~ | insert template with holes |
|
||
| ~SPC m m a~ | select one of possible cases (=ghc-auto=) |
|
||
| ~SPC m m f~ | replace a hole (=ghc-refine=) |
|
||
| ~SPC m m e~ | expand template haskell |
|
||
| ~SPC m m n~ | go to next type hole |
|
||
| ~SPC m m p~ | go to previous type hole |
|
||
| ~SPC m m >~ | make indent deeper |
|
||
| ~SPC m m <~ | make indent shallower |
|
||
|
||
*** Insert template
|
||
~SPC m m t~ inserts a template. What this means is that in the beginning of a
|
||
buffer, =module Foo where= is inserted. On a function without signature, the
|
||
inferred type is inserted. On a symbol =foo= without definition, =foo =
|
||
undefined= is inserted or a proper module is imported. ~SPC m m u~ inserts a
|
||
hole in this case. On a variable, the case is split. When checking with hlint,
|
||
the original code is replaced with hlint’s suggestion if possible.
|
||
|
||
** Intero
|
||
This command is only available when intero is enabled.
|
||
|
||
This top-level command is prefixed by ~SPC m~:
|
||
|
||
| Key binding | Description |
|
||
|-------------+------------------------|
|
||
| ~SPC m g b~ | return from definition |
|
||
|
||
* Syntax checking
|
||
At the moment there are four components, which can check the syntax and indicate
|
||
errors and warnings in the code. Those components are:
|
||
- flycheck
|
||
- hlint (via flycheck)
|
||
- ghc-mod
|
||
- haskell-mode interactive
|
||
|
||
Since all of these components can be active at the same time, it can be tricky to
|
||
know which component is displaying which message, especially when they disagree,
|
||
or if one isn’t working. Only flycheck errors (ghc and hlint) are displayed in
|
||
the error list and can be navigated between, using the standard Spacemacs key
|
||
bindings (under ~SPC e~) even though errors from other modes might highlight the
|
||
actual buffer.
|
||
|
||
** Flycheck
|
||
This is the standard Spacemacs way of syntax checking, and it’s also the most
|
||
elaborate. You need to install the syntax-checking layer first. Please read the
|
||
layer’s [[https://github.com/syl20bnr/spacemacs/tree/develop/layers/+checkers/syntax-checking][documentation]] on how to interact with flycheck.
|
||
|
||
Flycheck has different Haskell checkers: =haskell-ghc=, =haskell-stack-ghc= and
|
||
=haskell-hlint=. Normally it can detect the best one to use automatically, but
|
||
if it doesn’t work, then you can change it with ~SPC e s~.
|
||
|
||
** HLint
|
||
HLint is a linter for Haskell. It doesn’t detect errors (as long as it can parse
|
||
the file) but bad coding style and code smell. The HLint checker is called
|
||
*after* the flycheck GHC checker.
|
||
|
||
** ghc-mod
|
||
Ghc-mod, when enabled, also does syntax checking. It doesn’t highlight errors,
|
||
but instead displays an exclamation point in the fringe. You can navigate
|
||
between errors using =ghc-goto-next-error= (~M-n~) and =ghc-goto-prev-error=
|
||
(~M-p~).
|
||
|
||
** Interactive haskell-mode
|
||
Finally, interactive haskell-mode (~SPC m s b~) also displays errors. These
|
||
errors can be navigated to, from the interactive buffer (by clicking on the
|
||
error) or using =haskell-goto-next-error= (~M-n~) and =haskell-goto-prev-error=
|
||
(~M-p~).
|
||
|
||
** Flymake
|
||
An alternative to syntax checking is to build your projects with
|
||
=flymake-compile=. It doesn’t highlight errors in the buffer, but it’s more
|
||
reliable. The error navigation is similar to interactive haskell-mode.
|
||
|
||
** Troubleshooting
|
||
Flycheck and ghc-mod can fail silently for miscellaneous reasons. See the [[#faq][FAQ]]
|
||
for troubleshooting.
|
||
|
||
* FAQ
|
||
** The REPL doesn't work
|
||
Usually =haskell-mode= is great at figuring out which interactive process to
|
||
bring up. But if you are experiencing problems with it, then you can help
|
||
=haskell-mode= by setting =haskell-process-type= as in following code:
|
||
|
||
#+BEGIN_SRC emacs-lisp
|
||
(setq-default dotspacemacs-configuration-layers
|
||
'((haskell :variables haskell-process-type 'stack-ghci)))
|
||
#+END_SRC
|
||
|
||
Available options are:
|
||
- ghci
|
||
- cabal-repl
|
||
- cabal-new-repl
|
||
- cabal-dev
|
||
- cabal-ghci
|
||
- stack-ghci
|
||
|
||
** The REPL is stuck
|
||
Make sure that there’s a space between the REPL’s =λ>= prompt and the cursor.
|
||
When there is no space, then the REPL will behave as if it’s stuck. Usually,
|
||
when you enter normal state, the cursor moves backwards by one character, so there
|
||
is no required space when you switch to insert mode. There is a possible
|
||
workaround - just add the following snippet to your =dotspacemacs/user-config=
|
||
function:
|
||
|
||
#+BEGIN_SRC emacs-lisp
|
||
(when (configuration-layer/package-used-p 'haskell)
|
||
(add-hook 'haskell-interactive-mode-hook
|
||
(lambda ()
|
||
(setq-local evil-move-cursor-back nil))))
|
||
#+END_SRC
|
||
|
||
It makes the cursor stay in the right place in the REPL buffer when you enter
|
||
normal state. Which in most cases helps you to avoid the problem with ’stuck’
|
||
REPL.
|
||
|
||
Also, some users might want to start the REPL in insert mode. This is done by
|
||
placing the following snippet in your =dotspacemacs/user-config= function:
|
||
|
||
#+BEGIN_SRC emacs-lisp
|
||
(when (configuration-layer/package-used-p 'haskell)
|
||
(defadvice haskell-interactive-switch (after spacemacs/haskell-interactive-switch-advice activate)
|
||
(when (eq dotspacemacs-editing-style 'vim)
|
||
(call-interactively 'evil-insert))))
|
||
#+END_SRC
|
||
|
||
** I am using =stack= and =ghc-mod=, but =ghc-mod= doesn't work
|
||
Make sure that a =dist= directory doesn’t exist in your project root. If it
|
||
exists, just remove it and try again.
|
||
|
||
** =ghc-mod= doesn't work
|
||
First of all - make sure that the version of =ghc= matches the version of =ghc=
|
||
that was used to build =ghc-mod=. To get the latter, call =ghc-mod --version= in
|
||
the terminal. If they don’t match then you’ll have to rebuild =ghc-mod=.
|
||
|
||
=Stack= provides the ability to use different =ghc= versions across different
|
||
projects. If you’re using this feature, then you’ll have to rebuild =ghc-mod=
|
||
quite often. If you only use =ghc-mod= for completion, and don’t want to rebuild
|
||
=ghc-mod= every time you switch projects, then you’d better disable =ghc-mod=
|
||
support, so that =company-ghci= will be used for completion.
|
||
|
||
The second thing to do if it’s still not working - is to call =ghc-mod debug= in
|
||
the root of the project that you’re currently working on. Make sure that it
|
||
doesn’t show any errors. If there are errors that you can’t solve - then it’s
|
||
better to report them [[https://github.com/DanielG/ghc-mod][upstream]].
|
||
|
||
** Indentation doesn't reset when pressing return after an empty line
|
||
This is the intended behavior in =haskell-indentation-mode=. If you want to
|
||
reset the indentation when pressing return after an empty line, add the
|
||
following snippet into your =dotspacemacs/user-config= function.
|
||
|
||
#+BEGIN_SRC emacs-lisp
|
||
(defun haskell-indentation-advice ()
|
||
(when (and (< 1 (line-number-at-pos))
|
||
(save-excursion
|
||
(forward-line -1)
|
||
(string= "" (s-trim (buffer-substring (line-beginning-position) (line-end-position))))))
|
||
(delete-region (line-beginning-position) (point))))
|
||
|
||
(advice-add 'haskell-indentation-newline-and-indent
|
||
:after 'haskell-indentation-advice)
|
||
#+END_SRC
|
||
|
||
** Flycheck displays HLint warnings but not errors
|
||
The HLint checker is called *after* the normal flycheck checker, even if the
|
||
checker fails. Check the [[#flycheck-doesnt-work][Flycheck doesn’t work]] section.
|
||
|
||
** I can see highlighted errors but they don't appear in the error list
|
||
The error list is only set by flycheck. You are probably seeing errors
|
||
highlighted by either ghc-mode or haskell-mode. Check the [[#flycheck-doesnt-work][Flycheck doesn’t work]]
|
||
section.
|
||
|
||
** Flycheck doesn't work
|
||
You can use the =flycheck-compile= command to check what’s wrong with flycheck.
|
||
This will show you the exact command line that’s used, and its output.
|
||
|
||
If you are using =stack=, check the [[#flycheck-doesnt-work-with-stack][Flycheck doesn’t work with =stack=]] section.
|
||
|
||
** Flycheck doesn't work with =stack=
|
||
First check that flycheck uses the correct checker, and all the paths are
|
||
properly configured using =flycheck-verify-setup= (~SPC e v~). You can force the
|
||
checker with =flycheck-select-checker= (~SPC e s~) to ensure that it uses
|
||
=haskell-stack-ghc=. If it still doesn’t work, then it could be one of the
|
||
following problems:
|
||
- The =stack= build directory is wrong
|
||
- The project root is not set properly
|
||
|
||
*** The =stack= build directory is wrong
|
||
The path to the build directory, which contains some generated files, is
|
||
normally under =.stack-work/install/<os>/Cabal-<version>/build=.
|
||
|
||
However the version of the cabal library that’s used by =stack= to generate the
|
||
directory name is not the version of the cabal library that’s installed by
|
||
=stack= but rather the version of cabal that’s associated to the GHC version.
|
||
This error can happen after upgrading cabal or cabal-install. To check if this
|
||
is the problem, compare the path name of the build path that’s used by flycheck
|
||
using =flycheck-compile= and compare it to the actual path in the =.stack-work=
|
||
directory. If they are different, then you’ll need to reinstall ghc using the
|
||
command =stack setup --upgrade-cabal=.
|
||
|
||
*** The Project root directory is not set properly
|
||
Flycheck launches the GHC command, not from the project root directory, but from
|
||
the directory of the file that’s being checked. This is normally not a problem,
|
||
as all the paths are set properly, however it could be a problem if some
|
||
template Haskell functions use relative paths (e.g. in Yesod scaffolded
|
||
projects).
|
||
|
||
Until it’s fixed in flycheck, the workaround is to wrap the =stack= command in
|
||
order to run all subcommands from the project’s root directory. You can do so
|
||
with the following script:
|
||
|
||
#+BEGIN_SRC bash
|
||
#!/bin/bash
|
||
cd `stack --project-root`
|
||
stack $*
|
||
#+END_SRC
|
||
|
||
Make sure you set =flycheck-haskell-stack-ghc-executable= to this script.
|
||
|
||
** haskell-mode commands don't work
|
||
Some (most) of the haskell-mode commands only work when haskell-mode is in
|
||
interactive mode, i.e. has an interactive session associated with it. Load it
|
||
using ~SPC m s b~.
|
||
|
||
** =ghc-mod= and =haskell-mode= commands overlap. How do I know which command belongs to what?
|
||
ghc-mod commands are prefixed with =ghc-=, haskell-mode ones are prefixed with
|
||
=haskell-=.
|
||
|
||
** Some commands start with =ghc-= and some with =haskell-=. What does that mean?
|
||
Commands starting with =ghc-= are ghc-mod commands. Commands starting with
|
||
=haskell-= are haskell-mode commands.
|