module Data.Text.ANSI
  ( -- $intro

    -- * Foreground color
    black,
    red,
    green,
    yellow,
    blue,
    magenta,
    cyan,
    white,
    brightBlack,
    brightRed,
    brightGreen,
    brightYellow,
    brightBlue,
    brightMagenta,
    brightCyan,
    brightWhite,
    rgb,

    -- * Background color
    blackBg,
    redBg,
    greenBg,
    yellowBg,
    blueBg,
    magentaBg,
    cyanBg,
    whiteBg,
    brightBlackBg,
    brightRedBg,
    brightGreenBg,
    brightYellowBg,
    brightBlueBg,
    brightMagentaBg,
    brightCyanBg,
    brightWhiteBg,
    rgbBg,

    -- * Style
    bold,
    faint,
    italic,
    underline,
    doubleUnderline,
    strikethrough,
    frame,
    encircle,
    overline,
  )
where

import Data.Text (Text)
import qualified Data.Text.Builder.ANSI as Builder.ANSI
import qualified Data.Text.Lazy as Text.Lazy
import Data.Text.Lazy.Builder (Builder)
import qualified Data.Text.Lazy.Builder as Builder
import Data.Word (Word8)

-- $intro
--
-- Text styling for ANSI terminals using SGR codes, as defined by the
-- <https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf ECMA-48>
-- standard.
--
-- Supports foreground\/background color, bold\/faint intensity, italic,
-- single\/double underline, strikethrough, frame, encircle, and overline escape
-- sequences. Some styles may not work on your terminal.
--
-- Also features terminal detection, so redirecting styled output to a file will
-- automatically strip the ANSI escape sequences.

-- | Black foreground.
black :: Text -> Text
black :: Text -> Text
black =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.black
{-# INLINE black #-}

-- | Red foreground.
red :: Text -> Text
red :: Text -> Text
red =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.red
{-# INLINE red #-}

-- | Green foreground.
green :: Text -> Text
green :: Text -> Text
green =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.green
{-# INLINE green #-}

-- | Yellow foreground.
yellow :: Text -> Text
yellow :: Text -> Text
yellow =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.yellow
{-# INLINE yellow #-}

-- | Blue foreground.
blue :: Text -> Text
blue :: Text -> Text
blue =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.blue
{-# INLINE blue #-}

-- | Magenta foreground.
magenta :: Text -> Text
magenta :: Text -> Text
magenta =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.magenta
{-# INLINE magenta #-}

-- | Cyan foreground.
cyan :: Text -> Text
cyan :: Text -> Text
cyan =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.cyan
{-# INLINE cyan #-}

-- | White foreground.
white :: Text -> Text
white :: Text -> Text
white =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.white
{-# INLINE white #-}

-- | Bright black foreground.
brightBlack :: Text -> Text
brightBlack :: Text -> Text
brightBlack =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightBlack
{-# INLINE brightBlack #-}

-- | Bright red foreground.
brightRed :: Text -> Text
brightRed :: Text -> Text
brightRed =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightRed
{-# INLINE brightRed #-}

-- | Bright green foreground.
brightGreen :: Text -> Text
brightGreen :: Text -> Text
brightGreen =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightGreen
{-# INLINE brightGreen #-}

-- | Bright yellow foreground.
brightYellow :: Text -> Text
brightYellow :: Text -> Text
brightYellow =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightYellow
{-# INLINE brightYellow #-}

-- | Bright blue foreground.
brightBlue :: Text -> Text
brightBlue :: Text -> Text
brightBlue =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightBlue
{-# INLINE brightBlue #-}

-- | Bright magenta foreground.
brightMagenta :: Text -> Text
brightMagenta :: Text -> Text
brightMagenta =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightMagenta
{-# INLINE brightMagenta #-}

-- | Bright cyan foreground.
brightCyan :: Text -> Text
brightCyan :: Text -> Text
brightCyan =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightCyan
{-# INLINE brightCyan #-}

-- | Bright white foreground.
brightWhite :: Text -> Text
brightWhite :: Text -> Text
brightWhite =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightWhite
{-# INLINE brightWhite #-}

-- | RGB foreground.
rgb :: Word8 -> Word8 -> Word8 -> Text -> Text
rgb :: Word8 -> Word8 -> Word8 -> Text -> Text
rgb Word8
r Word8
g Word8
b =
  (Builder -> Builder) -> Text -> Text
lift (Word8 -> Word8 -> Word8 -> Builder -> Builder
Builder.ANSI.rgb Word8
r Word8
g Word8
b)
{-# INLINE rgb #-}

-- | Black background.
blackBg :: Text -> Text
blackBg :: Text -> Text
blackBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.blackBg
{-# INLINE blackBg #-}

-- | Red background.
redBg :: Text -> Text
redBg :: Text -> Text
redBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.redBg
{-# INLINE redBg #-}

-- | Green background.
greenBg :: Text -> Text
greenBg :: Text -> Text
greenBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.greenBg
{-# INLINE greenBg #-}

-- | Yellow background.
yellowBg :: Text -> Text
yellowBg :: Text -> Text
yellowBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.yellowBg
{-# INLINE yellowBg #-}

-- | Blue background.
blueBg :: Text -> Text
blueBg :: Text -> Text
blueBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.blueBg
{-# INLINE blueBg #-}

-- | Magenta background.
magentaBg :: Text -> Text
magentaBg :: Text -> Text
magentaBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.magentaBg
{-# INLINE magentaBg #-}

-- | Cyan background.
cyanBg :: Text -> Text
cyanBg :: Text -> Text
cyanBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.cyanBg
{-# INLINE cyanBg #-}

-- | White background.
whiteBg :: Text -> Text
whiteBg :: Text -> Text
whiteBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.whiteBg
{-# INLINE whiteBg #-}

-- | Bright black background.
brightBlackBg :: Text -> Text
brightBlackBg :: Text -> Text
brightBlackBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightBlackBg
{-# INLINE brightBlackBg #-}

-- | Bright red background.
brightRedBg :: Text -> Text
brightRedBg :: Text -> Text
brightRedBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightRedBg
{-# INLINE brightRedBg #-}

-- | Bright green background.
brightGreenBg :: Text -> Text
brightGreenBg :: Text -> Text
brightGreenBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightGreenBg
{-# INLINE brightGreenBg #-}

-- | Bright yellow background.
brightYellowBg :: Text -> Text
brightYellowBg :: Text -> Text
brightYellowBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightYellowBg
{-# INLINE brightYellowBg #-}

-- | Bright blue background.
brightBlueBg :: Text -> Text
brightBlueBg :: Text -> Text
brightBlueBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightBlueBg
{-# INLINE brightBlueBg #-}

-- | Bright magenta background.
brightMagentaBg :: Text -> Text
brightMagentaBg :: Text -> Text
brightMagentaBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightMagentaBg
{-# INLINE brightMagentaBg #-}

-- | Bright cyan background.
brightCyanBg :: Text -> Text
brightCyanBg :: Text -> Text
brightCyanBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightCyanBg
{-# INLINE brightCyanBg #-}

-- | Bright white background.
brightWhiteBg :: Text -> Text
brightWhiteBg :: Text -> Text
brightWhiteBg =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.brightWhiteBg
{-# INLINE brightWhiteBg #-}

-- | RGB background.
rgbBg :: Word8 -> Word8 -> Word8 -> Text -> Text
rgbBg :: Word8 -> Word8 -> Word8 -> Text -> Text
rgbBg Word8
r Word8
g Word8
b =
  (Builder -> Builder) -> Text -> Text
lift (Word8 -> Word8 -> Word8 -> Builder -> Builder
Builder.ANSI.rgbBg Word8
r Word8
g Word8
b)
{-# INLINE rgbBg #-}

-- | __Bold__ style (high intensity).
bold :: Text -> Text
bold :: Text -> Text
bold =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.bold
{-# INLINE bold #-}

-- | Faint style (low intensity).
faint :: Text -> Text
faint :: Text -> Text
faint =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.faint
{-# INLINE faint #-}

-- | /Italic/ style.
italic :: Text -> Text
italic :: Text -> Text
italic =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.italic
{-# INLINE italic #-}

-- | U̲n̲d̲e̲r̲l̲i̲n̲e̲ style.
underline :: Text -> Text
underline :: Text -> Text
underline =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.underline
{-# INLINE underline #-}

-- | D̳o̳u̳b̳l̳e̳ ̳u̳n̳d̳e̳r̳l̳i̳n̳e̳ style.
doubleUnderline :: Text -> Text
doubleUnderline :: Text -> Text
doubleUnderline =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.doubleUnderline
{-# INLINE doubleUnderline #-}

-- | S̶t̶r̶i̶k̶e̶t̶h̶r̶o̶u̶g̶h̶ style.
strikethrough :: Text -> Text
strikethrough :: Text -> Text
strikethrough =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.strikethrough
{-# INLINE strikethrough #-}

-- | Frame style.
frame :: Text -> Text
frame :: Text -> Text
frame =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.frame
{-# INLINE frame #-}

-- | Encircle style.
encircle :: Text -> Text
encircle :: Text -> Text
encircle =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.encircle
{-# INLINE encircle #-}

-- | O̅v̅e̅r̅l̅i̅n̅e̅ style.
overline :: Text -> Text
overline :: Text -> Text
overline =
  (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
Builder.ANSI.overline
{-# INLINE overline #-}

--

lift :: (Builder -> Builder) -> Text -> Text
lift :: (Builder -> Builder) -> Text -> Text
lift Builder -> Builder
f =
  Text -> Text
Text.Lazy.toStrict (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText (Builder -> Text) -> (Text -> Builder) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Builder
f (Builder -> Builder) -> (Text -> Builder) -> Text -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Builder
Builder.fromText
-- Don't inline before phase 2
{-# NOINLINE [2] lift #-}

-- Collapse lift/lift to a single lift before phase 2
{-# RULES
"lift/lift" [~2] forall f g s.
  lift f (lift g s) =
    lift (f . g) s
  #-}