1module Options.Applicative.Help.Pretty
2  ( module Text.PrettyPrint.ANSI.Leijen
3  , (.$.)
4  , groupOrNestLine
5  , altSep
6  ) where
7
8import           Control.Applicative
9import           Data.Semigroup ((<>))
10
11import           Text.PrettyPrint.ANSI.Leijen hiding ((<$>), (<>), columns)
12import           Text.PrettyPrint.ANSI.Leijen.Internal (Doc (..), flatten)
13import qualified Text.PrettyPrint.ANSI.Leijen as PP
14
15import           Prelude
16
17(.$.) :: Doc -> Doc -> Doc
18(.$.) = (PP.<$>)
19
20
21-- | Apply the function if we're not at the
22--   start of our nesting level.
23ifNotAtRoot :: (Doc -> Doc) -> Doc -> Doc
24ifNotAtRoot f doc =
25  Nesting $ \i ->
26    Column $ \j ->
27      if i == j
28        then doc
29        else f doc
30
31
32-- | Render flattened text on this line, or start
33--   a new line before rendering any text.
34--
35--   This will also nest subsequent lines in the
36--   group.
37groupOrNestLine :: Doc -> Doc
38groupOrNestLine =
39  Union
40    <$> flatten
41    <*> ifNotAtRoot (line <>) . nest 2
42
43
44-- | Separate items in an alternative with a pipe.
45--
46--   If the first document and the pipe don't fit
47--   on the line, then mandatorily flow the next entry
48--   onto the following line.
49--
50--   The (<//>) softbreak ensures that if the document
51--   does fit on the line, there is at least a space,
52--   but it's possible for y to still appear on the
53--   next line.
54altSep :: Doc -> Doc -> Doc
55altSep x y =
56  group (x <+> char '|' <> line) <//> y
57