    {-# LANGUAGE CPP #-}
    module Options.Applicative.Help.Pretty
      ( module Prettyprinter
      , module Prettyprinter.Render.Terminal
      , Doc
      , SimpleDoc

      , (.$.)
      , (</>)

      , groupOrNestLine
      , altSep
      , hangAtIfOver

      , prettyString
      ) where

    #if !MIN_VERSION_base(4,11,0)
    import           Data.Semigroup ((<>), mempty)
    #endif
    import qualified Data.Text.Lazy as Lazy

    import           Prettyprinter hiding (Doc)
    import qualified Prettyprinter as PP
    import           Prettyprinter.Render.Terminal

    import           Prelude

    type Doc = PP.Doc AnsiStyle
    type SimpleDoc = SimpleDocStream AnsiStyle

    linebreak :: Doc
    linebreak :: Doc
    linebreak = Doc -> Doc -> Doc
    forall ann. Doc ann -> Doc ann -> Doc ann
    flatAlt Doc
    forall ann. Doc ann
    line Doc
    forall a. Monoid a => a
    mempty

    (.$.) :: Doc -> Doc -> Doc
    Doc
    x .$. :: Doc -> Doc -> Doc
    .$. Doc
    y = Doc
    x Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Doc
    forall ann. Doc ann
    line Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Doc
    y
    (</>) :: Doc -> Doc -> Doc
    Doc
    x </> :: Doc -> Doc -> Doc
    </> Doc
    y = Doc
    x Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Doc
    forall ann. Doc ann
    softline Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Doc
    y

    -- | Apply the function if we're not at the
    --   start of our nesting level.
    ifNotAtRoot :: (Doc -> Doc) -> Doc -> Doc
    ifNotAtRoot :: (Doc -> Doc) -> Doc -> Doc
    ifNotAtRoot =
      (Doc -> Doc) -> (Doc -> Doc) -> Doc -> Doc
    ifElseAtRoot Doc -> Doc
    forall a. a -> a
    id

    -- | Apply the function if we're not at the
    --   start of our nesting level.
    ifAtRoot :: (Doc -> Doc) -> Doc -> Doc
    ifAtRoot :: (Doc -> Doc) -> Doc -> Doc
    ifAtRoot =
      ((Doc -> Doc) -> (Doc -> Doc) -> Doc -> Doc)
    -> (Doc -> Doc) -> (Doc -> Doc) -> Doc -> Doc
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip (Doc -> Doc) -> (Doc -> Doc) -> Doc -> Doc
    ifElseAtRoot Doc -> Doc
    forall a. a -> a
    id

    -- | Apply the function if we're not at the
    --   start of our nesting level.
    ifElseAtRoot :: (Doc -> Doc) -> (Doc -> Doc) -> Doc -> Doc
    ifElseAtRoot :: (Doc -> Doc) -> (Doc -> Doc) -> Doc -> Doc
    ifElseAtRoot Doc -> Doc
    f Doc -> Doc
    g Doc
    doc =
      (Int -> Doc) -> Doc
    forall ann. (Int -> Doc ann) -> Doc ann
    nesting ((Int -> Doc) -> Doc) -> (Int -> Doc) -> Doc
    forall a b. (a -> b) -> a -> b
    $ \Int
    i ->
        (Int -> Doc) -> Doc
    forall ann. (Int -> Doc ann) -> Doc ann
    column ((Int -> Doc) -> Doc) -> (Int -> Doc) -> Doc
    forall a b. (a -> b) -> a -> b
    $ \Int
    j ->
          if Int
    i Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    j
            then Doc -> Doc
    f Doc
    doc
            else Doc -> Doc
    g Doc
    doc

    -- | Render flattened text on this line, or start
    --   a new line before rendering any text.
    --
    --   This will also nest subsequent lines in the
    --   group.
    groupOrNestLine :: Doc -> Doc
    groupOrNestLine :: Doc -> Doc
    groupOrNestLine =
      Doc -> Doc
    forall ann. Doc ann -> Doc ann
    group (Doc -> Doc) -> (Doc -> Doc) -> Doc -> Doc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Doc -> Doc) -> Doc -> Doc
    ifNotAtRoot (Doc
    linebreak Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <>) (Doc -> Doc) -> (Doc -> Doc) -> Doc -> Doc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Doc -> Doc
    forall ann. Int -> Doc ann -> Doc ann
    nest Int
    2

    -- | Separate items in an alternative with a pipe.
    --
    --   If the first document and the pipe don't fit
    --   on the line, then mandatorily flow the next entry
    --   onto the following line.
    --
    --   The (<//>) softbreak ensures that if the document
    --   does fit on the line, there is at least a space,
    --   but it's possible for y to still appear on the
    --   next line.
    altSep :: Doc -> Doc -> Doc
    altSep :: Doc -> Doc -> Doc
    altSep Doc
    x Doc
    y =
      Doc -> Doc
    forall ann. Doc ann -> Doc ann
    group (Doc
    x Doc -> Doc -> Doc
    forall ann. Doc ann -> Doc ann -> Doc ann
    <+> Char -> Doc
    forall ann. Char -> Doc ann
    forall a ann. Pretty a => a -> Doc ann
    pretty Char
    '|' Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Doc
    forall ann. Doc ann
    line) Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> Doc -> Doc
    forall ann. Doc ann -> Doc ann
    group Doc
    linebreak Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <>  Doc
    y

    -- | Printer hacks to get nice indentation for long commands
    --   and subcommands.
    --
    --   If we're starting this section over the desired width
    --   (usually 1/3 of the ribbon), then we will make a line
    --   break, indent all of the usage, and go.
    --
    --   The ifAtRoot is an interesting clause. If this whole
    --   operation is put under a `group` then the linebreak
    --   will disappear; then item d will therefore not be at
    --   the starting column, and it won't be indented more.
    hangAtIfOver :: Int -> Int -> Doc -> Doc
    hangAtIfOver :: Int -> Int -> Doc -> Doc
    hangAtIfOver Int
    i Int
    j Doc
    d =
      (Int -> Doc) -> Doc
    forall ann. (Int -> Doc ann) -> Doc ann
    column ((Int -> Doc) -> Doc) -> (Int -> Doc) -> Doc
    forall a b. (a -> b) -> a -> b
    $ \Int
    k ->
        if Int
    k Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    j then
          Doc -> Doc
    forall ann. Doc ann -> Doc ann
    align Doc
    d
        else
          Doc
    linebreak Doc -> Doc -> Doc
    forall a. Semigroup a => a -> a -> a
    <> (Doc -> Doc) -> Doc -> Doc
    ifAtRoot (Int -> Doc -> Doc
    forall ann. Int -> Doc ann -> Doc ann
    indent Int
    i) Doc
    d

    renderPretty :: Double -> Int -> Doc -> SimpleDocStream AnsiStyle
    renderPretty :: Double -> Int -> Doc -> SimpleDocStream AnsiStyle
    renderPretty Double
    ribbonFraction Int
    lineWidth
      = LayoutOptions -> Doc -> SimpleDocStream AnsiStyle
    forall ann. LayoutOptions -> Doc ann -> SimpleDocStream ann
    layoutPretty LayoutOptions
          { layoutPageWidth :: PageWidth
    layoutPageWidth = Int -> Double -> PageWidth
    AvailablePerLine Int
    lineWidth Double
    ribbonFraction }

    prettyString :: Double -> Int -> Doc -> String
    prettyString :: Double -> Int -> Doc -> String
    prettyString Double
    ribbonFraction Int
    lineWidth
      = SimpleDocStream AnsiStyle -> String
    streamToString
      (SimpleDocStream AnsiStyle -> String)
    -> (Doc -> SimpleDocStream AnsiStyle) -> Doc -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Double -> Int -> Doc -> SimpleDocStream AnsiStyle
    renderPretty Double
    ribbonFraction Int
    lineWidth

    streamToString :: SimpleDocStream AnsiStyle -> String
    streamToString :: SimpleDocStream AnsiStyle -> String
    streamToString SimpleDocStream AnsiStyle
    sdoc =
      let
        rendered :: Text
    rendered =
          SimpleDocStream AnsiStyle -> Text
    Prettyprinter.Render.Terminal.renderLazy SimpleDocStream AnsiStyle
    sdoc
      in
        Text -> String
    Lazy.unpack Text
    rendered