Based on #3292
12 KiB
Haskell contribution layer for Spacemacs
Table of Contents TOC@4
Description
This layer adds support for the Haskell language.
Features:
- auto-completion with company-ghc,
- syntax highlighting for C– source.
This layer is in construction, it needs your contributions and bug reports.
Install
Layer
To use this contribution add it to your ~/.spacemacs
(setq-default dotspacemacs-configuration-layers '(haskell))
Dependencies
This layer requires some cabal packages:
hlint
stylish-haskell
hasktags
You can install them using cabal
or stack
. Cabal
users should use
following command:
$ cabal install stylish-haskell hlint hasktags
Stack
users should use following command:
$ stack install stylish-haskell hlint hasktags
Setup PATH
First of all make sure that your $PATH
contains installation path for Haskell
tools like ghc
, ghci
etc. It depends on how you have installed ghc
. But
you can always check it by calling $ which ghc
in your terminal. Stack
users
should add only installation path of stack
itself, usually it's
~/.local/bin
.
Then make sure that your $PATH
contains installation path for cabal
packages. If you are using cabal
it should be ~/.cabal/bin
or
/Users/<username>/Library/Haskell/bin
(for 'Haskell for Mac' users). If you
are using stack
then it should be ~/.local/bin
.
If you are using bash
, sh
or zsh
, you could update your $PATH
by using
following command:
$ export PATH=~/.local/bin:$PATH
If you are using fish
, you could update your $PATH
by using following
command:
$ set -x PATH ~/.local/bin $PATH
After you setup your $PATH
, emacs should automatically pick it's value (after
restart).
Alternatively, you can add path to the Emacs exec-path
variable in the
dotspacemacs/user-config
function of your .spacemacs
file:
(add-to-list 'exec-path "~/.cabal/bin/")
Or for stack
users:
(add-to-list 'exec-path "~/.local/bin/")
OS X
Note that emacs.app
for OS X does not pick up $PATH
from ~/.bashrc
or
~/.zshrc
when launched from outside a terminal.
Optional extras
The Haskell layer supports some extra features that can be enabled through layer variables.
ghc-mod support
ghc-mod enhances haskell-mode
with for example templates, case-splitting and
much more. In order to use it you need to install the executable with
$ cabal install ghc-mod
Stack
users should use following command:
$ stack install ghc-mod --resolver nightly-2015-10-07
and set the layer variable:
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-enable-ghc-mod-support t)))
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 document.
GHCi-ng support
ghci-ng adds some nice features to haskell-mode
, and is supported in
Spacemacs by a layer variable:
Follow the instructions to install ghci-ng (remember to add :set +c
in ~/.ghci
, next set the layer variable:
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-enable-ghci-ng-support t)))
Once ghci-ng is enabled, two of the old keybindings are overriden with improved versions from ghci-ng, and a new keybinding available:
Key Binding | Description |
---|---|
SPC m h t |
gets the type of the identifier under the cursor or for the active region |
SPC m g g |
go to definition |
SPC m u |
finds uses of identifier |
structured-haskell-mode
structured-haskell-mode, or shm, replaces default haskell-mode auto-indentation and adds some nice functionalities.
To Install shm
with cabal run following command:
$ cabal install structured-haskell-mode
Stack
users should use following command:
$ stack install structured-haskell-mode
To enable shm
set the layer variable:
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-enable-shm-support t)))
After shm has been enabled, some of the evil normal state bindings are overridden:
Key Binding | Description |
---|---|
D |
shm/kill-line |
R |
shm/raise |
P |
shm/yank |
( |
shm/forward-node |
) |
shm/backward-node |
For a nice visualization of these functions, please refer to the github page for structured-haskell-mode.
hindent
hindent is an extensible Haskell pretty printer, which let's you
reformat your code. You need to install the executable with cabal
install hindent
or stack install hindent
To enable it you have to set the variable haskell-enable-hindent-style
to a supported style. The available styles are:
- fundamental
- johan-tibell
- chris-done
- gibiansky
See examples here
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-enable-hindent-style "johan-tibell")))
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 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 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 d |
start debug process, needs to be run first |
SPC m d b |
insert breakpoint at function |
SPC m d n |
next breakpoint |
SPC m d N |
previous breakpoint |
SPC m d B |
delete breakpoint |
SPC m d c |
continue current process |
SPC m d a |
abandon current process |
SPC m d r |
refresh process buffer |
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 the REPL |
SPC m s S |
show and switch to the REPL |
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
This 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 libary section |
SPC m n |
go to next subsection |
SPC m p |
go to previous subsection |
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 |
FAQ
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 you can help
haskell-mode
by setting haskell-process-type
as in following code:
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-process-type 'stack-ghci)))
Available options are:
- ghci
- cabal-repl
- cabal-dev
- cabal-ghci
- stack-ghci
REPL is stuck
Make sure that when you are typing anything in REPL there is a space between
what you type and λ>
. When there is no space - REPL will behave as it's stuck.
Usually, when you enter normal state, cursor is moved back, so there is no
required space when you switch to insert mode. There is possible workaround -
just add following snippet to your dotspacemacs/user-config
function:
(when (configuration-layer/layer-usedp 'haskell)
(add-hook 'haskell-interactive-mode-hook
(lambda ()
(setq-local evil-move-cursor-back nil))))
It will make cursor stay at 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 REPL in insert mode. For this to happen you
could place following snippet in your dotspacemacs/user-config
function:
(when (configuration-layer/layer-usedp 'haskell)
(defadvice haskell-interactive-switch (after spacemacs/haskell-interactive-switch-advice activate)
(when (eq dotspacemacs-editing-style 'vim)
(call-interactively 'evil-insert))))
I am using stack
and ghc-mod
, but ghc-mod
doesn't work
Make sure that dist
directory doesn't exist in your project root. So if it
exists, just remove it and try again.