hindent
Extensible Haskell pretty printer
https://github.com/mihaimaruseac/hindent
Version on this page: | 6.1.1 |
LTS Haskell 23.1: | 6.2.1 |
Stackage Nightly 2024-12-09: | 6.2.1 |
Latest on Hackage: | 6.2.1 |
hindent-6.1.1@sha256:455807f5de591d43a015f29b60d5afb56ee28966c909bb6943dd1cb8a618d59f,5435
Module documentation for 6.1.1
hindent
Haskell pretty printer
Install
$ stack install hindent
Usage
$ hindent --help
hindent - Reformat Haskell source code
Usage: hindent [--version | [--line-length ARG]
[--indent-size ARG | --tab-size ARG] [--no-force-newline]
[--sort-imports | --no-sort-imports] [--style STYLE]
[-X GHCEXT] [--validate] [FILENAMES]]
Available options:
--version Print the version
--line-length ARG Desired length of lines (default: 80)
--indent-size ARG Indentation size in spaces (default: 2)
--tab-size ARG Same as --indent-size, for compatibility
--no-force-newline Don't force a trailing newline
--sort-imports Sort imports in groups
--no-sort-imports Don't sort imports
--style STYLE Style to print with (historical, now ignored)
-X GHCEXT Language extension
--validate Check if files are formatted without changing them
-h,--help Show this help text
hindent is used in a pipeline style
$ cat path/to/sourcefile.hs | hindent
The default indentation size is 2
spaces. Configure indentation size with --indent-size
:
$ echo 'example = case x of Just p -> foo bar' | hindent --indent-size 2; echo
example =
case x of
Just p -> foo bar
$ echo 'example = case x of Just p -> foo bar' | hindent --indent-size 4; echo
example =
case x of
Just p -> foo bar
Customization
Create a .hindent.yaml
file in your project directory or in your
~/
home directory. The following fields are accepted and are the
default:
indent-size: 2
line-length: 80
force-trailing-newline: true
sort-imports: true
line-breaks: []
extensions: []
By default, hindent preserves the newline or lack of newline in your input. With force-trailing-newline
, it will make sure there is always a trailing newline.
hindent can be forced to insert a newline before specific operators and tokens with line-breaks
. This is especially useful when utilizing libraries like servant
which use long type aliases.
Using extensions
, hindent can be made aware of valid syntactic compiler extensions that would normally be considered invalid syntax.
It is also possible to specify which extensions HIndent runs
with in your .hindent.yaml
:
extensions:
- MagicHash
- RecursiveDo
Emacs
In
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 standardM-q
.C-M-\
reformats the current region.
To enable it, add the following to your init file:
(add-to-list 'load-path "/path/to/hindent/elisp")
(require 'hindent)
(add-hook 'haskell-mode-hook #'hindent-mode)
Vim
The 'formatprg'
option lets you use an external program (like
hindent) to format your text. Put the following line into
~/.vim/ftplugin/haskell.vim to set this option for Haskell files:
setlocal formatprg=hindent
Then you can format with hindent using gq
. Read :help gq
and help 'formatprg'
for more details.
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 which provides a text object for top level bindings.
In order to format an entire source file execute:
:%!hindent
Alternatively you could use the vim-hindent plugin which runs hindent automatically when a Haskell file is saved.
IntelliJ / other JetBrains IDEs
- Install the “HaskForce” Haskell plugin (this is so we get the language type recognized in the file watcher)
- Install the “File Watchers” plugin under “Browse Repositories”
- Add a File Watcher with
- File type: Haskell Language
- Program:
/path/to/hindent
- Arguments:
$FilePath$
- Immediate file synchronization: off
- Show console: Error
Now whenever you save a file, hindent
should autoformat it.
Changes
Changelog
Unreleased
Added
- Support for GHC 9.8 (#775).
Changed
Fixed
- Wrong default HIndent configuration in
README.md
(#750). - Fix the bug of panicking when the given source code has CPP lines and space-prefixed lines (#780).
- Fix not pretty-printing multiple signatures in a
SPECIALISE
(#784).
Removed
6.1.0 - 2023-05-17
Added
Changed
reformat
now takes a list ofExtension
s instead of aMaybe
value containing the list (#712).reformat
andtestAst
now return aParseError
on error (#715).reformat
now returns the formatted code as aByteString
instead of aBuilder
. (#720).- HIndent now assumes no extensions are enabled by default (#728).
- All modules except for
HIndent
are now private, and the minimum necessary definitions are exposed from the module (#729). - HIndent now prints all
do
expressions in a unified style (#739). - HIndent now formats operators based on their fixities (#741, #742).
Fixed
- Fixed module names being removed from uses of qualified
do
(#696). - Misplaced haddocks for class declarations (#706).
- Misplaced comments in do expressions (#707).
- Misplaced comments in case expressions (#708).
- The bug of extensions specified via pragmas not enabling implied ones (#727).
- Language extensions enabled via pragmas were not effective across CPP boundaries (#731).
Removed
6.0.0 - 2023-02-20
Added
- The getConfig function is exported.
Changed
- Switched the parser from
haskell-src-exts
toghc-lib-parser
. This switch causes changes in the formatting results in some cases. - Changed how to format a data type with a record constructor to follow the Johan Tibell’s Haskell Style Guide. (#662).
- A newline is no longer inserted after a pattern signature (#663).
- A type with many type applications are now broken into multiple lines. (#664).
- A long type-level list is broken into multiple lines. (#665).
- Spaces around typed expression brackets are removed (#666).
- HIndent no longer breaks short class constraints in function signautres into multiple lines (#669).
Fixed
- Fixed the wrong formatting of data family instances inside class instances (#667).
- Fixed the bug of removing the space before the enclosing parenthesis of a record syntax in a signature in a GADT declaration (#670).
- Fixed the bug of inserting unnecessary empty lines if a file contains only comments (#672).
Removed
- Test functions except
testAst
. - Atom support (#671).
5.3.4 - 2022-07-07
This version is accidentally pushlished, and is the same as 5.3.3.
5.3.3 - 2022-07-07
Added
- Support for GHC 9.2.2.
- Test CI with GitHub Actions (WIP).
Fixed
- Fixed a broken link to Servant by @mattfbacon in #579.
- Fixed a build with Cabal 3.6 by @uhbif19 in #584.
- Fixed a compile error for GHC 9.2.2 by @toku-sa-n in #588.
5.3.2 - 2022-02-02
Fixed
MonadFix
issues to support newer GHC versions.
5.3.1 - 2019-06-28
Fixed
- Comment relocations in where clauses of top-level function declarations.
5.3.0 - 2019-04-29
Added
- Allow batch processing of multiple files.
- You can now specify default extensions in the configuration file.
Fixed
- Handle multiple deriving clauses in the
DerivingStrategies
scenario. - Ignore non-files in
findCabalFiles
. - Prevent HIndent from trying to open non-files when searching for
.cabal
files. - Fix the bad output for
[p|Foo|]
pattern quasi-quotes. - Fix pretty-printing of
'(:)
. - Fix parsing C preprocessor line continuations.
- Add parentheses around symbols
(:|)
when required. - Support
$p
pattern splices. - Fix formatting of associated type families.
- Fix formatting of non-dependent record constructors.
5.2.7 - 2019-03-16
Fixed
- A bug in the
-X
option
5.2.6 - 2019-03-16
Changed
- Switched to
optparse-applicative
.
5.2.5 - 2018-01-04
Added
- Support getting extensions from a
.cabal
file
Changed
- Improved the indentation with record constructions and updates
- Updated
haskell-src-exts
dependency to version>= 1.20.0
Fixed
- Fix the
let ... in
bug - Fix formatting top-level lambda expressions in
TemplateHaskell
slices
5.2.4 - 2017-10-20
Added
- Improved pretty-printing unboxed tuples.
- Support the
--validate
option for checking the format without reformatting - Support parsing
#include
,#error
, and#warning
directives. - Support reading
LANGUAGE
pragmas and parse the declared extensions from sources. - Support the
EmptyCases
extension - Optimize pretty-printing for many functional dependencies.
Changed
- The
TypeApplications
extension is now disabled-by-default due to the@
symbol
Fixed
- Fixed pretty-printing imports
- Fixed pretty-printing string literals for
DataKinds
- Fixed many issues related to infix operators including TH name quotes,
INLINE
/NOINLINE
pragmas, infix type operators, and infix constructors. - Fix extra linebreaks after short identifiers.
5.2.3 - 2017-05-07
Added
- HIndent now reports where a parse happened.
- Added
--line-breaks
parameter to support custom line breaks. - Added the
RecStmt
support
Changed
- Explicit import lists are now sorted.
- Improved pretty-printing long type signatures.
- Improved pretty-printing GADT records.
- Improved pretty-printing data declaration records.
- The
RecursiveDo
andDoRec
extensions are now disabled-by-default.
Fixed
- Fixed pretty-printing for infix data constructors.
- Fixed pretty-printing of quasi-quoter names.
- Fixed pretty-printing of complicated type aliases.
- Fixed pretty-printing of complicated type signatures.
5.2.2 - 2017-01-16
Changed
- HIndent now leaves
do
, lambda (\x->
), and lambda-case (\case->
) on the previous line of$
.
Fixed
- Fixed pretty-printing of parallel list comprehensions.
- Miscellaneous fixes.
5.2.1 - 2016-09-01
Changed
- The
--tab-size
option is renamed to--indent-size
. - The
PatternSynonyms
extension is now disabled by default. - HIndent now puts a newline before the closing bracket on a list.
Fixed
- Fixed handling of paragraph overhang when using large constraints.
- Fixed pretty-printing of multi-line comments.
- Fixed bug resulting in adding a spurious space for comments at the end of a file.
- Fixed bug which results in adding a trailing white space on
<-
5.2.0 - 2016-08-30
Added
- Support the
.hindent.yaml
file to specify alternative tab width and max column numbers. - Implement the tab-size support in Emacs Lisp.
Changed
- The default number of spaces for a tab is changed to 2.
5.1.1 - 2016-08-29
Added
- Add shebang support (Fixes #208).
- Output the filename for parse errors (Fixes #179).
- Added a document of the
-X
option (Fixes #212).
Changed
- HIndent now preserves spaces between groups of imports (Fixes #200).
- HIndent now preserves the last newline if the input ends with one (Fixes #211).
- HIndent now puts the last parenthesis of an export list on a new line (Fixes #227).
Fixed
- Fixed pretty-printing explicit
forall
s in instances (Fixes #218).
5.1.0 - 2016-08-25
Added
- Add
--tab-size
parameter to control indentation spaces.
Changed
- Rewrote comment association for more reliability.
Fixed
- Some miscellaneous bugs.
5.0.1 - 2016-08-20
Added
- Made HIndent compatible with GHC 7.8 through GHC 8.0
- Added test suites and benchmarks in
TESTS.md
andBENCHMARKS.md
Changed
- Re-implement using
bytestring
instead oftext
5.0.0 - 2016-08-11
Removed
- Support for styles
4.6.4 - 2016-07-15
Changed
- The formatted file is now created by coping/deleting a file instead of renaming.
4.6.3 - 2016-04-18
Added
- Accept a filename to reformat.
Fixed
- Fixed the whole module printer.
4.5.4 - 2015-06-22
Added
- Improvements to Tibell style.
- 6x speed up on rendering operators.
4.4.5 - 2015-11-10
Fixed
- Fixed a bug in infix patterns.
4.4.2 - 2015-04-05
Added
- Support for CPP.
Fixed
- Bunch of Gibiansky style bugs.
- Tibell style bugs.
4.3.8 - 2015-02-06
Fixed
- A bug in printing operators in statements.