    -- | This is a library which colourises Haskell code.
    --   It currently has five output formats:
    --
    -- * ANSI terminal codes
    --
    -- * LaTeX macros
    --
    -- * HTML with font tags
    --
    -- * HTML with CSS.
    --
    -- * mIRC chat client colour codes.
    --
    module Language.Haskell.HsColour (Output(..), ColourPrefs(..),
                                      hscolour) where

    import Language.Haskell.HsColour.Colourise (ColourPrefs(..))
    import qualified Language.Haskell.HsColour.TTY   as TTY
    import qualified Language.Haskell.HsColour.HTML  as HTML
    import qualified Language.Haskell.HsColour.CSS   as CSS
    import qualified Language.Haskell.HsColour.LaTeX as LaTeX
    import qualified Language.Haskell.HsColour.MIRC  as MIRC

    -- | The supported output formats.
    data Output = TTY   -- ^ ANSI terminal codes
                | LaTeX -- ^ TeX macros
                | HTML  -- ^ HTML with font tags
                | CSS   -- ^ HTML with CSS.
                | MIRC  -- ^ mIRC chat clients
      deriving (Eq,Show)

    -- | Colourise Haskell source code with the given output format.
    hscolour :: Output      -- ^ Output format.
             -> ColourPrefs -- ^ Colour preferences (for formats that support them).
             -> Bool        -- ^ Whether to include anchors.
             -> Bool        -- ^ Whether output document is partial or complete.
             -> Bool        -- ^ Whether input document is literate haskell or not
             -> String	-- ^ Title for output.
             -> String      -- ^ Haskell source code.
             -> String      -- ^ Coloured Haskell source code.
    hscolour output pref anchor partial literate title
        | literate  = concatMap chunk . joinL . map lhsClassify . inlines
        | otherwise = hscolour' output pref anchor partial title
      where
        chunk (Literate c) = c
        chunk (Code c)     = hscolour' output pref anchor True title c

    hscolour' :: Output      -- ^ Output format.
              -> ColourPrefs -- ^ Colour preferences (for formats that support them).
              -> Bool        -- ^ Whether to include anchors.
              -> Bool        -- ^ Whether output document is partial or complete.
              -> String      -- ^ Title for output.
              -> String      -- ^ Haskell source code.
              -> String      -- ^ Coloured Haskell source code.
    hscolour' TTY   pref _      _       _   = TTY.hscolour pref
    hscolour' MIRC  pref _      _       _   = MIRC.hscolour pref
    hscolour' LaTeX pref _      partial _   = LaTeX.hscolour pref partial
    hscolour' HTML  pref anchor partial top = HTML.hscolour pref anchor partial top
    hscolour' CSS   _    anchor partial top = CSS.hscolour anchor partial top

    -- | Separating literate files into code\/comment chunks.
    data Literate = Code {unL :: String} | Literate {unL :: String}

    -- Re-implementation of 'lines', for better efficiency (but decreased laziness).
    -- Also, importantly, accepts non-standard DOS and Mac line ending characters.
    -- And retains the trailing '\n' character in each resultant string.
    inlines :: String -> [String]
    inlines s = lines' s id
      where
      lines' []             acc = [acc []]
      lines' ('\^M':'\n':s) acc = acc ['\n'] : lines' s id	-- DOS
    --lines' ('\^M':s)      acc = acc ['\n'] : lines' s id	-- MacOS
      lines' ('\n':s)       acc = acc ['\n'] : lines' s id	-- Unix
      lines' (c:s)          acc = lines' s (acc . (c:))

    -- Note, I just pass the > symbol to the colouriser, which assumes that
    -- it's token based and not parse-based!!!
    lhsClassify :: String -> Literate
    lhsClassify ('>':xs)  = Code ('>':xs)
    lhsClassify xs        = Literate xs

    joinL :: [Literate] -> [Literate]
    joinL []                          = []
    joinL (Code c:Code c2:xs)         = joinL (Code (c++c2):xs)
    joinL (Literate c:Literate c2:xs) = joinL (Literate (c++c2):xs)
    joinL (any:xs)                    = any: joinL xs