    module Language.Haskell.HsColour.ColourHighlight
      ( Colour(..)
      , Highlight(..)
      , base256, unbase
      , rgb24bit_to_xterm256
      ,   projectToBasicColour8
      , hlProjectToBasicColour8
      ) where

    import Data.Word

    -- | Colours supported by ANSI codes.
    data Colour = Black | Red | Green | Yellow | Blue | Magenta | Cyan | White | Rgb Word8 Word8 Word8
      deriving (Colour -> Colour -> Bool
    (Colour -> Colour -> Bool)
    -> (Colour -> Colour -> Bool) -> Eq Colour
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Colour -> Colour -> Bool
    == :: Colour -> Colour -> Bool
    $c/= :: Colour -> Colour -> Bool
    /= :: Colour -> Colour -> Bool
    Eq,Int -> Colour -> ShowS
    [Colour] -> ShowS
    Colour -> String
    (Int -> Colour -> ShowS)
    -> (Colour -> String) -> ([Colour] -> ShowS) -> Show Colour
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Colour -> ShowS
    showsPrec :: Int -> Colour -> ShowS
    $cshow :: Colour -> String
    show :: Colour -> String
    $cshowList :: [Colour] -> ShowS
    showList :: [Colour] -> ShowS
    Show,ReadPrec [Colour]
    ReadPrec Colour
    Int -> ReadS Colour
    ReadS [Colour]
    (Int -> ReadS Colour)
    -> ReadS [Colour]
    -> ReadPrec Colour
    -> ReadPrec [Colour]
    -> Read Colour
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS Colour
    readsPrec :: Int -> ReadS Colour
    $creadList :: ReadS [Colour]
    readList :: ReadS [Colour]
    $creadPrec :: ReadPrec Colour
    readPrec :: ReadPrec Colour
    $creadListPrec :: ReadPrec [Colour]
    readListPrec :: ReadPrec [Colour]
    Read)

    -- | Convert an integer in the range [0,2^24-1] to its base 256-triplet, passing the result to the given continuation (avoid unnecessary tupleism).
    base256 :: Integral int => (Word8 -> Word8 -> Word8 -> r) -> int -> r
    base256 :: forall int r.
    Integral int =>
    (Word8 -> Word8 -> Word8 -> r) -> int -> r
    base256 Word8 -> Word8 -> Word8 -> r
    kont int
    x =
        let
            (int
    r,int
    gb) = int -> int -> (int, int)
    forall a. Integral a => a -> a -> (a, a)
    divMod int
    x int
    256
            (int
    g,int
    b)  = int -> int -> (int, int)
    forall a. Integral a => a -> a -> (a, a)
    divMod int
    gb int
    256
            fi :: int -> Word8
    fi = int -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
        in
            Word8 -> Word8 -> Word8 -> r
    kont (int -> Word8
    fi int
    r) (int -> Word8
    fi int
    g) (int -> Word8
    fi int
    b)

    -- | Convert a three-digit numeral in the given (as arg 1) base to its integer value.
    unbase :: Integral int => int -> Word8 -> Word8 -> Word8 -> int
    unbase :: forall int. Integral int => int -> Word8 -> Word8 -> Word8 -> int
    unbase int
    base Word8
    r Word8
    g Word8
    b = (Word8 -> int
    fi Word8
    rint -> int -> int
    forall a. Num a => a -> a -> a
    *int
    baseint -> int -> int
    forall a. Num a => a -> a -> a
    +Word8 -> int
    fi Word8
    g)int -> int -> int
    forall a. Num a => a -> a -> a
    *int
    baseint -> int -> int
    forall a. Num a => a -> a -> a
    +Word8 -> int
    fi Word8
    b
        where fi :: Word8 -> int
    fi = Word8 -> int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    -- | Approximate a 24-bit Rgb colour with a colour in the xterm256 6x6x6 colour cube, returning its index.
    rgb24bit_to_xterm256 :: (Integral t) => Word8 -> Word8 -> Word8 -> t
    rgb24bit_to_xterm256 :: forall t. Integral t => Word8 -> Word8 -> Word8 -> t
    rgb24bit_to_xterm256 Word8
    r Word8
    g Word8
    b = let f :: Word8 -> Word8
    f = (Word8 -> Word8 -> Word8
    forall a. Integral a => a -> a -> a
    `div` Word8
    43)
                              in t
    16 t -> t -> t
    forall a. Num a => a -> a -> a
    + t -> Word8 -> Word8 -> Word8 -> t
    forall int. Integral int => int -> Word8 -> Word8 -> Word8 -> int
    unbase t
    6 (Word8 -> Word8
    f Word8
    r) (Word8 -> Word8
    f Word8
    g) (Word8 -> Word8
    f Word8
    b)

    -- | Ap\"proxi\"mate a 24-bit Rgb colour with an ANSI8 colour. Will leave other colours unchanged and will never return an 'Rgb' constructor value.
    projectToBasicColour8 ::  Colour -> Colour
    projectToBasicColour8 :: Colour -> Colour
    projectToBasicColour8 (Rgb Word8
    r Word8
    g Word8
    b) = let f :: Word8 -> Word8
    f = (Word8 -> Word8 -> Word8
    forall a. Integral a => a -> a -> a
    `div` Word8
    128)
                              in  Int -> Colour
    forall a. Enum a => Int -> a
    toEnum ( Int -> Word8 -> Word8 -> Word8 -> Int
    forall int. Integral int => int -> Word8 -> Word8 -> Word8 -> int
    unbase Int
    2 (Word8 -> Word8
    f Word8
    r) (Word8 -> Word8
    f Word8
    g) (Word8 -> Word8
    f Word8
    b) )
    projectToBasicColour8 Colour
    x = Colour
    x

    -- | Lift 'projectToBasicColour8' to 'Highlight's
    hlProjectToBasicColour8 ::  Highlight -> Highlight
    hlProjectToBasicColour8 :: Highlight -> Highlight
    hlProjectToBasicColour8 (Foreground Colour
    c) = Colour -> Highlight
    Foreground (Colour -> Colour
    projectToBasicColour8 Colour
    c)
    hlProjectToBasicColour8 (Background Colour
    c) = Colour -> Highlight
    Background (Colour -> Colour
    projectToBasicColour8 Colour
    c)
    hlProjectToBasicColour8 Highlight
    h = Highlight
    h

    instance Enum Colour where
        toEnum :: Int -> Colour
    toEnum Int
    0 = Colour
    Black
        toEnum Int
    1 = Colour
    Red
        toEnum Int
    2 = Colour
    Green
        toEnum Int
    3 = Colour
    Yellow
        toEnum Int
    4 = Colour
    Blue
        toEnum Int
    5 = Colour
    Magenta
        toEnum Int
    6 = Colour
    Cyan
        toEnum Int
    7 = Colour
    White
        -- Arbitrary extension; maybe just 'error' out instead
        toEnum Int
    x = (Word8 -> Word8 -> Word8 -> Colour) -> Int -> Colour
    forall int r.
    Integral int =>
    (Word8 -> Word8 -> Word8 -> r) -> int -> r
    base256 Word8 -> Word8 -> Word8 -> Colour
    Rgb (Int
    xInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -Int
    8)

        fromEnum :: Colour -> Int
    fromEnum Colour
    Black   = Int
    0
        fromEnum Colour
    Red     = Int
    1
        fromEnum Colour
    Green   = Int
    2
        fromEnum Colour
    Yellow  = Int
    3
        fromEnum Colour
    Blue    = Int
    4
        fromEnum Colour
    Magenta = Int
    5
        fromEnum Colour
    Cyan    = Int
    6
        fromEnum Colour
    White   = Int
    7
        -- Arbitrary extension; maybe just 'error' out instead
        fromEnum (Rgb Word8
    r Word8
    g Word8
    b) = Int
    8 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int -> Word8 -> Word8 -> Word8 -> Int
    forall int. Integral int => int -> Word8 -> Word8 -> Word8 -> int
    unbase Int
    256 Word8
    r Word8
    g Word8
    b

    -- | Types of highlighting supported by ANSI codes (and some extra styles).
    data Highlight =
        Normal
      | Bold
      | Dim
      | Underscore
      | Blink
      | ReverseVideo
      | Concealed
      | Foreground Colour
      | Background Colour
      -- The above styles are ANSI-supported, with the exception of the 'Rgb' constructor for 'Colour's.  Below are extra styles (e.g. for Html rendering).
      | Italic
      deriving (Highlight -> Highlight -> Bool
    (Highlight -> Highlight -> Bool)
    -> (Highlight -> Highlight -> Bool) -> Eq Highlight
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Highlight -> Highlight -> Bool
    == :: Highlight -> Highlight -> Bool
    $c/= :: Highlight -> Highlight -> Bool
    /= :: Highlight -> Highlight -> Bool
    Eq,Int -> Highlight -> ShowS
    [Highlight] -> ShowS
    Highlight -> String
    (Int -> Highlight -> ShowS)
    -> (Highlight -> String)
    -> ([Highlight] -> ShowS)
    -> Show Highlight
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Highlight -> ShowS
    showsPrec :: Int -> Highlight -> ShowS
    $cshow :: Highlight -> String
    show :: Highlight -> String
    $cshowList :: [Highlight] -> ShowS
    showList :: [Highlight] -> ShowS
    Show,ReadPrec [Highlight]
    ReadPrec Highlight
    Int -> ReadS Highlight
    ReadS [Highlight]
    (Int -> ReadS Highlight)
    -> ReadS [Highlight]
    -> ReadPrec Highlight
    -> ReadPrec [Highlight]
    -> Read Highlight
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS Highlight
    readsPrec :: Int -> ReadS Highlight
    $creadList :: ReadS [Highlight]
    readList :: ReadS [Highlight]
    $creadPrec :: ReadPrec Highlight
    readPrec :: ReadPrec Highlight
    $creadListPrec :: ReadPrec [Highlight]
    readListPrec :: ReadPrec [Highlight]
    Read)