mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			115 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Haskell
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Haskell
		
	
	
	
	
	
-- | This is a library which colourises Haskell code.
 | 
						|
--   It currently has six output formats:
 | 
						|
--
 | 
						|
-- * ANSI terminal codes
 | 
						|
--
 | 
						|
-- * LaTeX macros
 | 
						|
--
 | 
						|
-- * HTML 3.2 with font tags
 | 
						|
--
 | 
						|
-- * HTML 4.01 with external CSS.
 | 
						|
--
 | 
						|
-- * XHTML 1.0 with internal 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.ACSS       as ACSS 
 | 
						|
import qualified Language.Haskell.HsColour.InlineCSS  as ICSS
 | 
						|
import qualified Language.Haskell.HsColour.LaTeX      as LaTeX
 | 
						|
import qualified Language.Haskell.HsColour.MIRC       as MIRC
 | 
						|
import Data.List(mapAccumL, isPrefixOf)
 | 
						|
import Data.Maybe
 | 
						|
import Language.Haskell.HsColour.Output
 | 
						|
--import Debug.Trace
 | 
						|
 | 
						|
-- | 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.
 | 
						|
         -> String	-- ^ Title for output.
 | 
						|
         -> Bool        -- ^ Whether input document is literate haskell or not
 | 
						|
         -> String      -- ^ Haskell source code.
 | 
						|
         -> String      -- ^ Coloured Haskell source code.
 | 
						|
hscolour output pref anchor partial title False =
 | 
						|
        (if partial then id else top'n'tail output title) .
 | 
						|
        hscolour' output pref anchor
 | 
						|
hscolour output pref anchor partial title True  =
 | 
						|
        (if partial then id else top'n'tail output title) .
 | 
						|
        concatMap chunk . joinL . classify . inlines
 | 
						|
  where
 | 
						|
    chunk (Code c) = hscolour' output pref anchor c
 | 
						|
    chunk (Lit c)  = c
 | 
						|
 | 
						|
-- | The actual colourising worker, despatched on the chosen output format.
 | 
						|
hscolour' :: Output      -- ^ Output format.
 | 
						|
          -> ColourPrefs -- ^ Colour preferences (for formats that support them)
 | 
						|
          -> Bool        -- ^ Whether to include anchors.
 | 
						|
          -> String      -- ^ Haskell source code.
 | 
						|
          -> String      -- ^ Coloured Haskell source code.
 | 
						|
hscolour' TTY       pref _      = TTY.hscolour     pref
 | 
						|
hscolour' (TTYg tt) pref _      = TTY.hscolourG tt pref
 | 
						|
hscolour' MIRC      pref _      = MIRC.hscolour    pref
 | 
						|
hscolour' LaTeX     pref _      = LaTeX.hscolour   pref
 | 
						|
hscolour' HTML      pref anchor = HTML.hscolour    pref anchor
 | 
						|
hscolour' CSS       _    anchor = CSS.hscolour          anchor
 | 
						|
hscolour' ICSS      pref anchor = ICSS.hscolour    pref anchor
 | 
						|
hscolour' ACSS      _    anchor = ACSS.hscolour         anchor
 | 
						|
 | 
						|
-- | Choose the right headers\/footers, depending on the output format.
 | 
						|
top'n'tail :: Output           -- ^ Output format
 | 
						|
           -> String           -- ^ Title for output
 | 
						|
           -> (String->String) -- ^ Output transformer
 | 
						|
top'n'tail TTY   _     = id
 | 
						|
top'n'tail (TTYg _) _  = id
 | 
						|
top'n'tail MIRC  _     = id
 | 
						|
top'n'tail LaTeX title = LaTeX.top'n'tail title
 | 
						|
top'n'tail HTML  title = HTML.top'n'tail title
 | 
						|
top'n'tail CSS   title = CSS.top'n'tail  title
 | 
						|
top'n'tail ICSS  title = ICSS.top'n'tail title
 | 
						|
top'n'tail ACSS  title = CSS.top'n'tail  title
 | 
						|
 | 
						|
-- | Separating literate files into code\/comment chunks.
 | 
						|
data Lit = Code {unL :: String} | Lit {unL :: String} deriving (Show)
 | 
						|
 | 
						|
-- 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:))
 | 
						|
 | 
						|
 | 
						|
-- | The code for classify is largely stolen from Language.Preprocessor.Unlit.
 | 
						|
classify ::  [String] -> [Lit]
 | 
						|
classify []             = []
 | 
						|
classify (x:xs) | "\\begin{code}"`isPrefixOf`x
 | 
						|
                        = Lit x: allProg xs
 | 
						|
   where allProg []     = []  -- Should give an error message,
 | 
						|
                              -- but I have no good position information.
 | 
						|
         allProg (x:xs) | "\\end{code}"`isPrefixOf`x
 | 
						|
                        = Lit x: classify xs
 | 
						|
         allProg (x:xs) = Code x: allProg xs
 | 
						|
classify (('>':x):xs)   = Code ('>':x) : classify xs
 | 
						|
classify (x:xs)         = Lit x: classify xs
 | 
						|
 | 
						|
-- | Join up chunks of code\/comment that are next to each other.
 | 
						|
joinL :: [Lit] -> [Lit]
 | 
						|
joinL []                  = []
 | 
						|
joinL (Code c:Code c2:xs) = joinL (Code (c++c2):xs)
 | 
						|
joinL (Lit c :Lit c2 :xs) = joinL (Lit  (c++c2):xs)
 | 
						|
joinL (any:xs)            = any: joinL xs
 | 
						|
 |