# Haskell contribution layer for Spacemacs
![logo](img/haskell.png)
**Table of Contents**
- [Haskell contribution layer for Spacemacs](#haskell-contribution-layer-for-spacemacs)
- [Description](#description)
- [Install](#install)
- [Layer](#layer)
- [Cabal packages](#cabal-packages)
- [OS X](#os-x)
- [Optional extras](#optional-extras)
- [GHCi-ng support](#ghci-ng-support)
- [structured-haskell-mode](#structured-haskell-mode)
- [hindent](#hindent)
- [Key bindings](#key-bindings)
- [Haskell source code:](#haskell-source-code)
- [Haskell commands:](#haskell-commands)
- [Documentation commands:](#documentation-commands)
- [Cabal commands:](#cabal-commands)
- [Debug commands:](#debug-commands)
- [REPL commands:](#repl-commands)
- [Cabal files:](#cabal-files)
## Description
This layer adds support for the [Haskell][] language.
Features:
- auto-completion with [company-ghc][],
- auto-indentation with [hi2][].
**This layer is in construction, it needs your contributions and bug reports.**
## Install
### Layer
To use this contribution add it to your `~/.spacemacs`
```elisp
(setq-default dotspacemacs-configuration-layers '(haskell))
```
### Cabal packages
This layer requires some [cabal][] packages:
- `ghc-mod`
- `hlint`
- `stylish-haskell`
To install them, use the following command:
```sh
cabal install stylish-haskell hlint ghc-mod
```
Next Emacs needs to know where to find these binaries, you can locate them with
the following shell command:
```sh
dirname $(which ghc-mod)
```
Then you have to add this path to your system `$PATH` (preferred):
```sh
export PATH=~/.cabal/bin/:$PATH
```
_or_ to the Emacs `exec-path` variable in the `dotspacemacs/init` function of
your `.spacemacs` file:
```elisp
(add-to-list 'exec-path "~/.cabal/bin/")
```
**Note:** it is important to add the path in the `dotspacemacs/init` function,
so that the path is added before any layers is loaded.
### 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.
#### 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:
```elisp
(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 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 hi2 (and any other
Haskell-indentation modes) and adds some nice functionality.
To enable shm, run `cabal install structured-haskell-mode` and set the layer
variable:
```elisp
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-enable-shm-support t)))
```
After shm has been enabled, some of the evil normal-mode 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`.
To enable it you have to set the variable `haskell-enable-hindent-support`
to a supported style. The available styles are:
- fundamental
- johan-tibell
- chris-done
- andrew-gibiansky
See examples [here][hindent-examples]
```elisp
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-enable-hindent-support "johan-tibell")))
```
By default it uses the style called `fundamental`, if you want to use
another, `johan-tibell`, run `M-x customize-variable
hindent-style`.
## Key bindings
All Haskell specific bindings are prefixed with SPC m
### Haskell source code:
#### Haskell commands:
Top-level commands are prefixed by SPC m:
Key Binding | Description
----------------------|------------------------------------------------------------
SPC m t | gets the type of the identifier under the cursor
SPC m i | gets information for the identifier under the cursor
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 commands:
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 y | do a Hayoo lookup
#### 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
#### Debug commands:
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 commands:
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 files:
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
[Haskell]: https://www.haskell.org/
[cabal]: https://www.haskell.org/cabal/
[company-ghc]: https://github.com/iquiw/company-ghc
[hi2]: https://github.com/nilcons/hi2
[ghci-ng]: https://github.com/chrisdone/ghci-ng
[structured-haskell-mode]: https://github.com/chrisdone/structured-haskell-mode
[hindent]: https://github.com/chrisdone/hindent
[hindent-examples]: https://github.com/chrisdone/hindent#example