haskelldocumentation/content/ide-and-linters.md

240 lines
7.6 KiB
Markdown

---
title: IDEs and Linters
author: Kostiantyn Rybnikov <k-bx@k-bx.com>
description: Preparing your editor
first-written: 2015-03-05
last-updated: 2015-03-05
---
Incomplete. Need to add:
* Emacs:
* haskell-mode + hlint
* stylish-haskell
* Additional:
* multi-tags search
* projectile for projects
* Vim - expand, show simple usage of each without redoing the libraries' own documentation
* fpcomplete IDE
* other IDEs not listed here
## Emacs
Emacs is one of most popular Haskell editors out there. If you are
able to use it, you can get a very nice development environment.
### Prerequisites
#### Cask (or use-package)
It's assumed in this tutorial you have modern package manager Cask installed.
You can install it by following the
[cask user guide](http://cask.readthedocs.org/en/latest/index.html). For
older Emacs versions (< 24), please figure out other method of
package-installation.
Make sure a `Cask` file in your `.emacs.d` directory has marmelade
repo, ensure it looks something like this:
```elisp
(source gnu)
(source melpa)
(source marmalade)
```
And check that your `~/.emacs` file has:
```elisp
(require 'cask "~/.cask/cask.el")
(cask-initialize)
```
After adding dependencies to your `Cask` file, run `cask install` in
that directory.
If instead of `Cask` you are using [use-package](https://github.com/jwiegley/use-package)
to manage your packages, then make sure that you have this in your `init.el` file:
```elisp
(setq package-archives
'(("gnu" . "http://elpa.gnu.org/packages/")
("marmalade" . "http://marmalade-repo.org/packages/")
("melpa" . "http://melpa.milkbox.net/packages/")))
(package-initialize)
(require 'use-package)
```
Make sure that you install `use-package` from the package manager. Following tutorial
should be straightforward.
#### exec-path-from-shell
On MacOS X you will also need
[exec-path-from-shell](https://github.com/purcell/exec-path-from-shell)
in order to get your environment variables from your shell (bash or
zsh) into your emacs, so that it inherits your `$PATH` and sees proper
`~/.cabal/bin/cabal`, for example. To install, add following to your
`Cask` file:
```elisp
(depends-on "exec-path-from-shell")
```
and run `cask install` from `Cask`-file directory. Add following to your `~/.emacs`:
```elisp
(when (memq window-system '(mac ns))
(exec-path-from-shell-initialize))
```
### haskell-mode
First of all, you should use
[haskell-mode](https://github.com/haskell/haskell-mode) for editing
`.hs` and `.cabal` files. Add this line to your `Cask`:
```elisp
(depends-on "haskell-mode")
```
and run `cask install` in that file's directory. This should install a
fresh `haskell-mode` for you. Restart your emacs and you should be
ready to open any `.cabal` or `.hs` file for editing. You will see
syntax highlighted, you'll be able to run commands like `M-x
haskell-process-load-file`.
However, you can't yet use `haskell-mode` in full because you haven't
configured indentation mode and interaction. Go read
[haskell-mode tutorial on setting the indentation-mode you like](https://github.com/haskell/haskell-mode/wiki/Indentation)
and
[Haskell Interactive Mode Setup](https://github.com/haskell/haskell-mode/wiki/Haskell-Interactive-Mode-Setup)
pages, or just put something like this to your `.emacs` (if you
already have `custom-set-variables` in your `.emacs` -- extend it):
```elisp
(defun turn-on-subword-mode ()
(interactive)
(subword-mode 1))
(defun my-haskell-mode-hook ()
(define-key haskell-mode-map (kbd "C-c C-l") 'haskell-process-load-or-reload)
(define-key haskell-mode-map (kbd "C-`") 'haskell-interactive-bring)
(define-key haskell-mode-map (kbd "C-c C-t") 'haskell-process-do-type)
(define-key haskell-mode-map (kbd "C-c C-i") 'haskell-process-do-info)
(define-key haskell-mode-map (kbd "C-c C-c") 'haskell-process-cabal-build)
(define-key haskell-mode-map (kbd "C-c C-k") 'haskell-interactive-mode-clear)
(define-key haskell-mode-map (kbd "C-c c") 'haskell-process-cabal)
(define-key haskell-mode-map (kbd "SPC") 'haskell-mode-contextual-space))
(custom-set-variables
'(haskell-mode-hook
(quote
(interactive-haskell-mode
turn-on-haskell-indent
turn-on-subword-mode
turn-on-haskell-decl-scan
my-haskell-mode-hook)))
'(haskell-process-type 'cabal-repl))
```
Now you're more or less ready, but this is just a beginning. Go ahead,
open some `.hs` file and press `C-h ? b`. You will see list of
bindings available. Search for `haskell-` to see all haskell-related
bindings. Also, run `M-x haskell-` and press `TAB` for list of
available commands starting with `haskell-`. There's plenty of them!
Press `C-c C-l` to open a `cabal repl` shell with current module
loaded. You can easily play with your code like this. Also, pressing
`C-c C-i` will inspect symbol under cursor and show you some info. Neat!
### ghc-mod
[Ghc-mod](http://www.mew.org/~kazu/proj/ghc-mod/en/) is a tool that
helps your editor become more close to an IDE. It lets you do things
like blazingly-fast error-reporting upon save, autocompletion and more.
First, install ghc-mod itself:
```
cabal install ghc-mod
```
Then, add this to your `Cask` file:
```elisp
(depends-on "ghc")
```
And this to your `~/.emacs`:
```
(autoload 'ghc-init "ghc" nil t)
(autoload 'ghc-debug "ghc" nil t)
```
and extend your `my-haskell-mode-hook` with call to `(ghc-init)` like
this:
```elisp
(defun my-haskell-mode-hook ()
(ghc-init)
; ... all previous contents
)
```
After this is done, relaunch your Emacs (or re-eval config)
and open some `.hs`-file. Make a mistake and save the file, mistake
should now become underlined with red, and pressing `M-S-?` while
keeping curstor on top of it will show the error, and `M-n` `M-p`
should navigate between next/prev errors.
Check out
[ghc-mod homepage](http://www.mew.org/~kazu/proj/ghc-mod/en/) and
other resources to know more.
### TAGS
In order to get a "goto by name" functionality you can use standard
[Emacs TAGS support](https://www.gnu.org/software/emacs/manual/html_node/emacs/Tags.html). Haskell
has a special program, called `hasktags`:
```
cabal install hasktags
```
In order to generate tags, you can use `haskell-mode`'s `M-x
haskell-process-generate-tags`, or you can manually run `hasktags -e.`
in your project's root.
`haskell-mode` replaces standard `M-.` tag-search with it's own,
trying to search via ghci first, and only then via standard TAGS
mechanism.
### Auto-completion via company-ghc
Auto-completion via [company-ghc](https://github.com/iquiw/company-ghc) is pretty simple. Put this to your `Cask`:
```elisp
(depends-on "company")
(depends-on "company-ghc")
```
Then put this to your `.emacs`:
```elisp
(require 'company)
(add-hook 'after-init-hook 'global-company-mode)
(add-to-list 'company-backends 'company-ghc)
```
Voila! Beautiful auto-complete from `ghc-mod` works like a charm.
## Vim
Suggested plugins
* [Vimproc](https://github.com/Shougo/vimproc.vim) (required when installing ghcmod-vim)
* [ghcmod-vim](https://github.com/eagletmt/ghcmod-vim) - a wrapper for the multifaceted [ghc-mod](https://github.com/kazu-yamamoto/ghc-mod) command-line tool
* [vim2hs](https://github.com/dag/vim2hs) - A configurable collection of syntax highlighting and keyword shortcuts tailored for Haskell development
* [Syntastic](https://github.com/scrooloose/syntastic) - syntax checking and linting
* [neco-ghc](https://github.com/eagletmt/neco-ghc) - Haskell/GHC completion plugin
* [neocomplete](https://github.com/Shougo/neocomplete.vim) - General-purpose keyword completion engine, fed by neco-ghc
* [Cabal Context](https://github.com/timmytofu/vim-cabal-context) - Sets pwd to the directory of the nearest cabal file, useful for bouncing between different libraries