hindent-4.2.0: README.md
# hindent [](https://hackage.haskell.org/package/hindent)
Extensible Haskell pretty printer. Both a library and an
executable. Currently a work in progress (see
[FIXME items](https://github.com/chrisdone/hindent/blob/master/src/HIndent/Pretty.hs)).
[Haddock API documentation](http://chrisdone.github.io/hindent/).
## Install
$ cabal install hindent
You might need to `cabal install happy` if haskell-src-exts complains.
## Usage
$ hindent
hindent: arguments: --style [fundamental|chris-done|johan-tibell|gibiansky]
## Emacs
In
[elisp/hindent.el](https://github.com/chrisdone/hindent/blob/master/elisp/hindent.el)
there is `hindent-mode`, which provides keybindings to reindent parts of the
buffer:
- `M-q` reformats the current declaration. When inside a comment, it fills the
current paragraph instead, like the standard `M-q`.
- `C-M-\` reformats the current region.
To enable it, add the following to your init file:
```lisp
(add-hook 'haskell-mode-hook #'hindent-mode)
```
By default it uses the style called `fundamental`, if you want to use
another, `johan-tibell`, run `M-x customize-variable
hindent-style`. If you want to configure per-project, make a file
called `.dir-locals.el` in the project root directory like this:
``` lisp
((nil . ((hindent-style . "johan-tibell"))))
```
## Vim
Basic support is provided through [vim/hindent.vim](https://github.com/chrisdone/hindent/blob/master/vim/hindent.vim),
which sets hindent as the formatter used by `gq` for haskell files. The formatting style
defaults to `fundamental` but can be configured by setting `g:hindent_style` to the desired style.
Note that unlike in emacs you have to take care of selecting a sensible buffer region as input to
hindent yourself. If that is too much trouble you can try [vim-textobj-haskell](https://github.com/gilligan/vim-textobj-haskell) which provides a text object for top level bindings.
## Contributing your own printer style
This package comes with a basic fundamental pretty printer, which is
probably not desirable to use.
It comes with other styles implemented on top of this fundamental
printer, in the modules in `HIndent.Styles.*`.
Make a module `HIndent.Styles.YourName` in which to place the printer.
To define your own, see
[HIndent.Styles.Fundamental](https://github.com/chrisdone/hindent/blob/master/src/HIndent/Styles/Fundamental.hs)
for a starting point. This module defines a blank style, adds no
additional extensions. Customizations are specified via the
`styleExtenders` property. See
[HIndent.Styles.ChrisDone](https://github.com/chrisdone/hindent/blob/master/src/HIndent/Styles/ChrisDone.hs)
for an example of a non-trivial style.
Useful combinators can be found in
[HIndent.Pretty](https://github.com/chrisdone/hindent/blob/master/src/HIndent/Pretty.hs)
for defining printers. When you want to use a fundamental printer, use
`prettyNoExt` instead of `pretty`. Comments will still be inserted by
`prettyNoExt`.
If you want to contribute it to the package, add it to the list of
styles in
[HIndent](https://github.com/chrisdone/hindent/blob/master/src/HIndent.hs)
and export it, and open a pull request. Use
[the Erlang git commit guide](https://github.com/erlang/otp/wiki/Writing-good-commit-messages)
for your commits.
## Remaining issues
* Add test suite.
* Flesh out more obscure parts of the AST.
* Improve comment re-insertion.
* Possibly: Support formatting whole modules.
* Implement some operator-specific layouts: e.g.
Foo <$> foo
<*> bar
<*> mu
## Example
Input code:
``` haskell
foo = do print "OK, go"; foo (foo bar) -- Yep.
(if bar then bob else pif) (case mu {- cool -} zot of
Just x -> return (); Nothing -> do putStrLn "yay"; return 1) bill -- Etc
where potato Cakes {} = 2 * x foo * bar / 5
```
### Fundamental
This is an intentionally very dumb style that demands extension.
``` haskell
foo =
do print
"OK, go"
foo
(foo
bar)
(if bar
then bob
else pif)
(case mu {- cool -}
zot of
Just x ->
return
()
Nothing ->
do putStrLn
"yay"
return
1)
bill -- Etc
where potato Cakes{} =
2 * x
foo * bar / 5
```
### Johan Tibell
Documented in
[the style guide](https://github.com/tibbe/haskell-style-guide).
This printer style uses some simple heuristics in deciding when to go
to a new line or not, and custom handling of do, if, case alts, rhs,
etc.
``` haskell
foo = do
print "OK, go"
foo
(foo bar)
(if bar
then bob
else pif)
(case mu {- cool -} zot of
Just x ->
return ()
Nothing -> do
putStrLn "yay"
return 1)
bill -- Etc
where
potato Cakes{} =
2 * x foo * bar / 5
```
### Chris Done
My style is documented in
[the style guide](https://github.com/chrisdone/haskell-style-guide).
This printer style uses some simple heuristics in deciding when to go
to a new line or not.
``` haskell
foo =
do print "OK, go"
foo (foo bar)
(if bar
then bob
else pif)
(case mu {- cool -} zot of
Just x -> return ()
Nothing ->
do putStrLn "yay"
return 1)
bill -- Etc
where potato Cakes{} = 2 * x foo * bar / 5
```
### Andrew Gibiansky
``` haskell
foo = do
print "OK, go"
foo (foo bar) -- Yep.
(if bar
then bob
else pif) (case mu {- cool -} zot of
Just x -> return ()
Nothing -> do
putStrLn "yay"
return 1) bill -- Etc
where
potato Cakes{} = 2 * x foo * bar / 5
```