| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Ormolu.Printer.Combinators
Description
Printing combinators. The definitions here are presented in such an order so you can just go through the Haddocks and by the end of the file you should have a pretty good idea how to program rendering logic.
Synopsis
- data R a
- runR :: R () -> SpanStream -> CommentStream -> SourceType -> EnumSet Extension -> ModuleFixityMap -> Bool -> Text
- getEnclosingSpan :: R (Maybe RealSrcSpan)
- getEnclosingSpanWhere :: (RealSrcSpan -> Bool) -> R (Maybe RealSrcSpan)
- getEnclosingComments :: R [LComment]
- isExtensionEnabled :: Extension -> R Bool
- txt :: Text -> R ()
- atom :: Outputable a => a -> R ()
- space :: R ()
- newline :: R ()
- inci :: R () -> R ()
- inciIf :: Bool -> R () -> R ()
- askSourceType :: R SourceType
- askModuleFixityMap :: R ModuleFixityMap
- askDebug :: R (Choice "debug")
- located :: HasLoc l => GenLocated l a -> (a -> R ()) -> R ()
- encloseLocated :: HasLoc l => GenLocated l [a] -> ([a] -> R ()) -> R ()
- located' :: HasLoc l => (a -> R ()) -> GenLocated l a -> R ()
- switchLayout :: [SrcSpan] -> R () -> R ()
- data Layout
- vlayout :: R a -> R a -> R a
- getLayout :: R Layout
- breakpoint :: R ()
- breakpoint' :: R ()
- sep :: R () -> (a -> R ()) -> [a] -> R ()
- sepSemi :: (a -> R ()) -> [a] -> R ()
- canUseBraces :: R Bool
- useBraces :: R () -> R ()
- dontUseBraces :: R () -> R ()
- data BracketStyle
- sitcc :: R () -> R ()
- backticks :: R () -> R ()
- banana :: BracketStyle -> R () -> R ()
- braces :: BracketStyle -> R () -> R ()
- brackets :: BracketStyle -> R () -> R ()
- parens :: BracketStyle -> R () -> R ()
- parensHash :: BracketStyle -> R () -> R ()
- pragmaBraces :: R () -> R ()
- pragma :: Text -> R () -> R ()
- comma :: R ()
- commaDel :: R ()
- equals :: R ()
- data SpanMark
- spanMarkSpan :: SpanMark -> RealSrcSpan
- data HaddockStyle
- setSpanMark :: SpanMark -> R ()
- getSpanMark :: R (Maybe SpanMark)
- data Placement
- placeHanging :: Placement -> R () -> R ()
The R monad
The R monad hosts combinators that allow us to describe how to render
AST.
Arguments
| :: R () | Monad to run |
| -> SpanStream | Span stream |
| -> CommentStream | Comment stream |
| -> SourceType | Whether the source is a signature or a regular module |
| -> EnumSet Extension | Enabled extensions |
| -> ModuleFixityMap | Module fixity map |
| -> Bool | Resulting rendition |
| -> Text |
Run R monad.
getEnclosingSpan :: R (Maybe RealSrcSpan) #
Get the immediately enclosing RealSrcSpan.
Arguments
| :: (RealSrcSpan -> Bool) | Predicate to use |
| -> R (Maybe RealSrcSpan) |
Get the first enclosing RealSrcSpan that satisfies given predicate.
getEnclosingComments :: R [LComment] #
Get the comments contained in the enclosing span.
isExtensionEnabled :: Extension -> R Bool #
Combinators
Basic
Output a fixed Text fragment. The argument may not contain any line
breaks. txt is used to output all sorts of “fixed” bits of syntax like
keywords and pipes | in functional dependencies.
To separate various bits of syntax with white space use space instead
of . To output txt " "Outputable Haskell entities like numbers use
atom.
atom :: Outputable a => a -> R () #
Output Outputable fragment of AST. This can be used to output numeric
literals and similar. Everything that doesn't have inner structure but
does have an Outputable instance.
This primitive does not necessarily output a space. It just ensures that the next thing that will be printed on the same line will be separated by a single space from the previous output. Using this combinator twice results in at most one space.
In practice this design prevents trailing white space and makes it hard to output more than one delimiting space in a row, which is what we usually want.
Output a newline. First time newline is used after some non-newline
output it gets inserted immediately. Second use of newline does not
output anything but makes sure that the next non-white space output will
be prefixed by a newline. Using newline more than twice in a row has no
effect. Also, using newline at the very beginning has no effect, this
is to avoid leading whitespace.
Similarly to space, this design prevents trailing newlines and makes it
hard to output more than one blank newline in a row.
Increase indentation level by one indentation step for the inner
computation. inci should be used when a part of code must be more
indented relative to the parts outside of inci in order for the output
to be valid Haskell. When layout is single-line there is no obvious
effect, but with multi-line layout correct indentation levels matter.
Indent the inner expression if the first argument is True.
askSourceType :: R SourceType #
Return the source type.
askModuleFixityMap :: R ModuleFixityMap #
Retrieve the module fixity map.
askDebug :: R (Choice "debug") #
Retrieve whether we should print out certain debug information while printing.
Arguments
| :: HasLoc l | |
| => GenLocated l a | Thing to enter |
| -> (a -> R ()) | How to render inner value |
| -> R () |
Enter a GenLocated entity. This combinator handles outputting comments
and sets layout (single-line vs multi-line) for the inner computation.
Roughly, the rule for using located is that every time there is a
Located wrapper, it should be “discharged” with a corresponding
located invocation.
encloseLocated :: HasLoc l => GenLocated l [a] -> ([a] -> R ()) -> R () #
Similar to located, but when the "payload" is an empty list, print
virtual elements at the start and end of the source span to prevent comments
from "floating out".
Arguments
| :: HasLoc l | |
| => (a -> R ()) | How to render inner value |
| -> GenLocated l a | Thing to enter |
| -> R () |
A version of located with arguments flipped.
Set layout according to combination of given SrcSpans for a given.
Use this only when you need to set layout based on e.g. combined span of
several elements when there is no corresponding Located wrapper
provided by GHC AST. It is relatively rare that this one is needed.
Given empty list this function will set layout to single line.
Layout options.
Constructors
| SingleLine | Put everything on single line |
| MultiLine | Use multiple lines |
Do one or another thing depending on current Layout.
breakpoint :: R () #
Insert a space if enclosing layout is single-line, or newline if it's multiline.
breakpoint = vlayout space newline
breakpoint' :: R () #
Similar to breakpoint but outputs nothing in case of single-line
layout.
breakpoint' = vlayout (return ()) newline
Formatting lists
Render a collection of elements inserting a separator between them.
Render a collection of elements layout-sensitively using given printer,
inserting semicolons if necessary and respecting useBraces and
dontUseBraces combinators.
useBraces $ sepSemi txt ["foo", "bar"]
== vlayout (txt "{ foo; bar }") (txt "foo\nbar")dontUseBraces $ sepSemi txt ["foo", "bar"] == vlayout (txt "foo; bar") (txt "foo\nbar")
canUseBraces :: R Bool #
Return True if we can use braces in this context.
dontUseBraces :: R () -> R () #
Make the inner computation omit braces around single-line layouts.
Wrapping
data BracketStyle #
BracketStyle controlling how closing bracket is rendered.
Instances
| Show BracketStyle # | |
Defined in Ormolu.Printer.Combinators Methods showsPrec :: Int -> BracketStyle -> ShowS # show :: BracketStyle -> String # showList :: [BracketStyle] -> ShowS # | |
| Eq BracketStyle # | |
Defined in Ormolu.Printer.Combinators | |
Set indentation level for the inner computation equal to current column. This makes sure that the entire inner block is uniformly "shifted" to the right.
banana :: BracketStyle -> R () -> R () #
Surround given entity by banana brackets (i.e., from arrow notation.)
braces :: BracketStyle -> R () -> R () #
Surround given entity by curly braces { and }.
brackets :: BracketStyle -> R () -> R () #
Surround given entity by square brackets [ and ].
parens :: BracketStyle -> R () -> R () #
Surround given entity by parentheses ( and ).
parensHash :: BracketStyle -> R () -> R () #
Surround given entity by (# and #).
pragmaBraces :: R () -> R () #
Braces as used for pragmas: {-# and #-}.
Surround the body with a pragma name and pragmaBraces.
Literals
Stateful markers
An auxiliary marker for keeping track of last output element.
Constructors
| HaddockSpan HaddockStyle RealSrcSpan | Haddock comment |
| CommentSpan RealSrcSpan | Non-haddock comment |
| StatementSpan RealSrcSpan | A statement in a do-block and such span |
spanMarkSpan :: SpanMark -> RealSrcSpan #
Project RealSrcSpan from SpanMark.
data HaddockStyle #
Haddock string style.
getSpanMark :: R (Maybe SpanMark) #
Get span of last output comment.
Placement
Expression placement. This marks the places where expressions that implement handing forms may use them.
Constructors
| Normal | Multi-line layout should cause insertion of a newline and indentation bump |
| Hanging | Expressions that have hanging form should use it and avoid bumping one level of indentation |
placeHanging :: Placement -> R () -> R () #
Place a thing that may have a hanging form. This function handles how to separate it from preceding expressions and whether to bump indentation depending on what sort of expression we have.