1
1
mirror of https://github.com/tweag/ormolu.git synced 2024-09-17 16:17:14 +03:00
A formatter for Haskell source code
Go to file
2019-05-31 14:43:15 +02:00
.circleci Build the project with Nix and switct to GHC 8.6.4 2019-05-31 14:43:15 +02:00
app Implement more precise comment placement without ‘ghc-exactprint’ 2019-05-08 22:03:21 +02:00
data Build the project with Nix and switct to GHC 8.6.4 2019-05-31 14:43:15 +02:00
nix/nixpkgs Build the project with Nix and switct to GHC 8.6.4 2019-05-31 14:43:15 +02:00
src Build the project with Nix and switct to GHC 8.6.4 2019-05-31 14:43:15 +02:00
tests Implement rendering of simplest value-level constructs 2019-05-18 18:47:53 +02:00
.gitignore Initial commit 2018-11-25 20:51:22 +07:00
CHANGELOG.md Initial commit 2018-11-25 20:51:22 +07:00
default.nix Build the project with Nix and switct to GHC 8.6.4 2019-05-31 14:43:15 +02:00
DESIGN.md Minor corrections to the design document 2019-02-14 22:12:13 +01:00
EXAMPLES.md Add examples of comments. 2019-01-08 12:37:42 -03:00
LICENSE.md Fix the link to license file and years there 2019-05-23 19:57:32 +02:00
ormolu.cabal Build the project with Nix and switct to GHC 8.6.4 2019-05-31 14:43:15 +02:00
README.md Update the readme 2019-05-31 14:43:15 +02:00
Setup.hs Initial commit 2018-11-25 20:51:22 +07:00

Ormolu

CircleCI

Ormolu is a formatter for Haskell source code. The projects was created with the following features in mind:

  • Using GHC's own parser to avoid parsing problems caused by haskell-src-exts.
  • Let some whitespace be programmable. The layout of the input influence the layout choices in the output. This means that the choices between single-line/multi-line layouts in each particular situation are made by the user, not by an algorithm. This makes the implementation simpler and leaves some control to the user while still guaranteeing that the formatted code is stylistically consistent.
  • Writing code in such a way so it's easy to modify and maintain. Roughly, it means that the project follows the path of hindent and is very much about printing AST in a particular way.
  • Implementing one “true” formatting style which admits no configuration.
  • That formatting style aims to result in minimal diffs while still remaining very close to “conventional” Haskell formatting people use.
  • Idempotency: formatting already formatted code doesn't change it.
  • Be well-tested and robust to the point that it can be used in large projects without exposing unfortunate, disappointing bugs here and there.

Building

The easiest way to build the project is with Nix:

$ nix-build

Or with cabal-install from the Nix shell:

$ nix-shell --run "cabal new-build"

Alternatively, stack could be used with a stack.yaml file as follows.

$ cat stack.yaml
resolver: lts-13.19
packages:
- '.'

$ stack build

Usage

The following will print the formatted output to the standard output.

$ ormolu Module.hs

Add --mode inplace to replace the contents of the input file with the formatted output.

$ ormolu --mode inplace Module.hs

A configuration file can specify the language extensions to use by default.

$ cat ormolu.yaml
ghc-opts:
  - -XLambdaCase
unsafe: False
debug: False

$ ormolu -c ormolu.yaml Module.hs

Contribution

Issues (bugs, feature requests or otherwise feedback) may be reported in the GitHub issue tracker for this project. Pull requests are also welcome.

What to hack on?

Right now there are two options for people who want to contribute:

  • Implementing rendering of AST. This is the main focus right now because we want to have a MVP which can render all syntactical constructions found in Haskell source code. Once that is achieved we'll polish the tool iteratively.
  • Fixing bugs. If this seems more interesting than implementing rendering of AST, you are welcome to do this as well.

Implementing rendering of AST

The Ormolu.Printer.Combinators module provides a DSL for rendering of GHC AST. You'll probably only need this one module for writing new rendering functions. The module documents how to use the printing combinators it provides. Consult the Haddocks to learn more about them.

Create new modules corresponding to the things you want to render under Ormolu.Printer.Meat. For example, there are Ormolu.Printer.Meat.Type and Ormolu.Printer.Meat.Declaration.Data.

Concrete rendering functions get their names by appending p_ to the name of the type which describes a particular part of AST. For example, the function for rendering types is correspondingly:

p_hsType :: HsType GhcPs -> R ()

In general rendering functions like this take 1 or more arguments and produce R () which is a rendering action.

Testing

Testing has been taken good care of and now it amounts to just adding examples under data/examples. Each example is a pair of files: <example-name>.hs for input and <example-name>-out.hs for corresponding expected output.

Testing is performed as following:

  • Given snippet of source code is parsed and pretty-printed.
  • The result of printing is parsed back again and the AST is compared to the AST obtained from the original file. They should match.
  • The output of printer is checked against the expected output.
  • Idempotency property is verified: formatting already formatted code results in exactly the same output.

Examples can be organized in sub-directories, see the existing ones for inspiration.

License

See LICENSE.

Copyright © 20182019 Tweag I/O