packages feed

HaTeX 3.8.0.0 → 3.9.0.0

raw patch · 16 files changed

+460/−349 lines, 16 filesdep ~base

Dependency ranges changed: base

Files

+ Examples/parser.hs view
@@ -0,0 +1,31 @@++{-# LANGUAGE OverloadedStrings #-}++import Text.LaTeX+import Text.LaTeX.Base.Parser+import Data.Text (unlines)+import qualified Data.Text.IO as T++main :: IO ()+main = case parseLaTeX example of+  Left err -> putStrLn err+  Right l  -> do+    putStrLn "Printing LaTeX AST..."+    print l+    putStrLn "Checking that (render . parse == id)..."+    let t = render l+    print $ example == t+    putStrLn "All done."++example :: Text+example = Data.Text.unlines+  [ "\\documentclass{article}"+  , "\\usepackage[utf8]{inputenc}"+  , "\\author{Daniel Díaz}"+  , "\\title{LaTeX parser}"+  , "\\begin{document}"+  , "\\maketitle"+  , "This is an example of how to parse LaTeX using the"+  , "\\HaTeX library."+  , "\\end{document}"+    ]
Examples/tikzsimple.hs view
@@ -21,16 +21,16 @@ myFigure :: Figure myFigure = Scale 3 $ Figures  [ RectangleFilled (0,0) 1 1- , Colored Green $ RectangleFilled (-1,1) 1 1- , Colored Red   $ RectangleFilled ( 0,2) 1 1- , Colored Blue  $ RectangleFilled ( 1,1) 1 1+ , Colored (BasicColor Green) $ RectangleFilled (-1,1) 1 1+ , Colored (BasicColor Red)   $ RectangleFilled ( 0,2) 1 1+ , Colored (BasicColor Blue)  $ RectangleFilled ( 1,1) 1 1    ]  myFigure2 :: Figure myFigure2 = Scale 2 $ Figures- [ Colored Blue $ PolygonFilled [(-2,-1),(0,1),(2,-1)]+ [ Colored (RGBColor 100 35 150) $ PolygonFilled [(-2,-1),(0,1),(2,-1)]  , Text (0,1.4) $ "Is this a " <> textit "blue" <> " triangle?"- , Rotate (pi/9) $ Colored Yellow $ Text (-0.2,-0.2) "Yes, it is!"+ , Rotate (pi/9) $ Colored (BasicColor Yellow) $ Text (-0.2,-0.2) "Yes, it is!"    ]  myFigure3 :: Figure
HaTeX.cabal view
@@ -1,5 +1,5 @@ Name: HaTeX
-Version: 3.8.0.0
+Version: 3.9.0.0
 Author: Daniel Díaz
 Category: Text, LaTeX
 Build-type: Simple
@@ -7,26 +7,30 @@ License-file: license
 Maintainer: Daniel Díaz (dhelta `dot` diaz `at` gmail `dot` com)
 Bug-reports: https://github.com/Daniel-Diaz/HaTeX/issues
+homepage: http://daniel-diaz.github.io/projects/hatex
 Synopsis: The Haskell LaTeX library.
-Description: The LaTeX project site states: \"LaTeX is a high-quality typesetting system\". This library provides
-             a bridge between LaTeX and Haskell, implementing the LaTeX syntax in Haskell.
+Description: This library provides a bridge between LaTeX and Haskell, implementing the LaTeX /syntax/
+             in Haskell.
              .
-             Some of the things you can do are:
+             Some of the things you can do with HaTeX are:
              .
              Write LaTeX documents with all the advantages you already have in Haskell (recursion,
              type system, high order functions, ...), create a LaTeX backend for your own program,
-             make analysis of LaTeX code through its Abstract Syntax Tree (AST), pretty-print Haskell
+             parse a LaTeX file and obtain its Abstract Syntax Tree (AST), pretty-print Haskell
              values in LaTeX, generate TikZ scripts easily, ...
              .
              See the @examples@ directory in the source distribution to look some simple examples.
              It would be good to get you started. The HaTeX User's Guide is available at
-             <https://github.com/Daniel-Diaz/hatex-guide>.
+             <https://github.com/Daniel-Diaz/hatex-guide/blob/master/README.md>.
 Cabal-version: >= 1.10
 Extra-source-files:
   ReleaseNotes
   README.md
   -- Examples
   Examples/*.hs
+  -- Tests
+  parsertest/*.tex
+  parsertest/parsertest.hs
 Extra-doc-files:
   -- TikZ
   docfiles/tikz/*.png
README.md view
@@ -1,10 +1,10 @@-# HaTeX ReadMe
+# The HaTeX library
 
 HaTeX is a Haskell library that implements the *LaTeX syntax*.
 
-Check a list of examples of usage in the [examples](Examples/) directory.
-A good starting point may be [simple.hs](Examples/simple.hs).
-Run the script using the ``main`` function.
+Check a list of examples of usage in the [Examples](https://github.com/Daniel-Diaz/HaTeX/tree/master/Examples) directory.
+A good starting point may be [simple.hs](https://github.com/Daniel-Diaz/HaTeX/blob/master/Examples/simple.hs).
+Run any example script executing the ``main`` function.
 
 ## Installation notes
 
@@ -39,16 +39,22 @@ To be sure that you are reading the last version, go to the github repository of the guide and follow instructions
 to build it. It is fairly easy.
 
-## Contributing
+## Community and Contributions
 
-To contribute to HaTeX, please, visit our code repository in GitHub:
+There are many ways to get involved in the HaTeX project.
 
-https://github.com/Daniel-Diaz/HaTeX
+* Fork the [GitHub repository](https://github.com/Daniel-Diaz/HaTeX).
+* Report bugs or make suggestions opening a ticket in the [Issue Tracker](https://github.com/Daniel-Diaz/HaTeX/issues).
+* Help us to improve and extend our [hatex-guide](https://github.com/Daniel-Diaz/hatex-guide).
+* Join the [Mailing List](http://projects.haskell.org/cgi-bin/mailman/listinfo/hatex) for help or announcements of the
+last developments.
+* Drop by the IRC channel at `#hatex`.
 
 ## TODO list
 
 * Add more examples.
 * More testing on the parser (See [#15](https://github.com/Daniel-Diaz/HaTeX/issues/15)).
+  This includes adding more test cases to the [parsertest folder](https://github.com/Daniel-Diaz/HaTeX/tree/master/parsertest).
 * Add more documentation.
 * BibTeX support.
 
@@ -60,3 +66,5 @@ 
 * [TeX-my-math](https://github.com/leftaroundabout/Symbolic-math-HaTeX): Experimental library to ease the production
 of mathematical expressions using HaTeX.
+* [haskintex](http://daniel-diaz.github.io/projects/haskintex): Tool to use Haskell and in particular the HaTeX library
+within a LaTeX file.
Text/LaTeX/Base.hs view
@@ -34,14 +34,12 @@  , module Text.LaTeX.Base.Commands
  , module Text.LaTeX.Base.Writer
  , module Text.LaTeX.Base.Texy
-   -- * External re-exports
+   -- * Monoids
    --
    -- | Since the 'Monoid' instance is the only way to append 'LaTeX'
-   --   values, a re-export of "Data.Monoid" is given here.
- , module Data.Monoid
-#if __GLASGOW_HASKELL__ < 704
+   --   values, a re-export of the 'Monoid' class is given here for convenience.
+ , Monoid (..)
  , (<>)
-#endif
    ) where
 
 -- Internal modules
Text/LaTeX/Base/Parser.hs view
@@ -1,299 +1,286 @@-{-# LANGUAGE CPP #-}
-{-# LANGUAGE OverloadedStrings #-}
--------------------------------------------------------------------------------
--- |
--- Module     : Text/LaTeX/Base/Parser.hs
--- Copyright  : (c) Tobias Schoofs
--- License    : LGPL 
--- Stability  : experimental
--- Portability: portable
---
--- LaTeX Parser based on Attoparsec
--------------------------------------------------------------------------------
-module Text.LaTeX.Base.Parser (
-                        latexParser,
-                        latexBlockParser,
-                        latexAtOnce,
-                        latexDocParser,
-                        isMainDoc
-#ifdef _TEST
-                        , specials
-#endif
-                      )
-where
-
-  import           Data.Attoparsec.Text hiding (take, takeTill)
-  import qualified Data.Attoparsec.Text as A   (takeTill)
-  import           Data.Char (toLower)
-  import           Data.Monoid
-  import           Data.Maybe (fromMaybe)
-  import           Data.Text (Text)
-  import qualified Data.Text as T 
-
-  import           Control.Applicative ((<|>), (<$>))
-  import           Control.Monad (unless)
-
-  import           Text.LaTeX.Base.Syntax
-
-  ------------------------------------------------------------------------
-  -- | Parses a Text sequence at once;
-  --   may fail or conclude.
-  ------------------------------------------------------------------------
-  latexAtOnce :: Text -> Either String LaTeX
-  latexAtOnce t | T.null t  = return TeXEmpty
-                | otherwise = 
-    case parse latexParser t of
-      Fail _ _ e     -> Left e
-      Done _ r       -> Right r
-      rx@(Partial _) -> -- Left "incomplete input"
-                        case feed rx T.empty of
-                         Fail _ _ e -> Left e
-                         Partial _  -> Left "incomplete input"
-                         Done _ r   -> Right r
-
-  ------------------------------------------------------------------------
-  -- | The incremental LaTeX Parser
-  ------------------------------------------------------------------------
-  latexParser :: Parser LaTeX
-  latexParser = blocks 
-
-  ------------------------------------------------------------------------
-  -- | Incremental Parser for single blocks of LaTeX
-  ------------------------------------------------------------------------
-  latexBlockParser :: Parser LaTeX
-  latexBlockParser = block
-
-  ------------------------------------------------------------------------
-  -- | Incremental Parser that terminates after the /document/ envionment
-  ------------------------------------------------------------------------
-  latexDocParser :: Parser LaTeX
-  latexDocParser = blockTillDoc
-
-  ------------------------------------------------------------------------
-  -- Blocks
-  ------------------------------------------------------------------------
-  blocks :: Parser LaTeX
-  blocks = mconcat <$> block `manyTill` endOfInput 
-
-  blockTillDoc :: Parser LaTeX
-  blockTillDoc  = do
-    b <- block
-    if isMainDoc b then return  b
-                   else mappend b <$> blockTillDoc
-
-  -- | Test if a 'LaTeX' block is a @document@ environment.
-  isMainDoc :: LaTeX -> Bool
-  isMainDoc b = case b of
-                  TeXEnv "document" _ _ -> True
-                  _                     -> False
-
-  ------------------------------------------------------------------------
-  -- Block
-  -- Note: text stops on ']';
-  --       if the other parser fail on the rest
-  --          text2 handles it, starting with ']' 
-  ------------------------------------------------------------------------
-  block :: Parser LaTeX
-  block = foldr1 (<|>) [text, dolMath, comment, text2, command, environment]
-   
-  ------------------------------------------------------------------------
-  -- Text
-  ------------------------------------------------------------------------
-  text :: Parser LaTeX
-  text = do
-    mbC <- peekChar
-    case mbC of
-      Nothing -> return TeXEmpty
-      Just c | c `elem` "$%\\{]}" -> fail "not text"
-             | otherwise          -> TeXRaw <$> A.takeTill (`elem` "$%\\{]}")
-
-  ------------------------------------------------------------------------
-  -- Text without stopping on ']'
-  ------------------------------------------------------------------------
-  text2 :: Parser LaTeX
-  text2 = do
-    _ <- char ']'
-    t <- try (text <|> return (TeXRaw T.empty))
-    return $ TeXRaw (T.pack "]") <> t
-
-  ------------------------------------------------------------------------
-  -- Environment
-  ------------------------------------------------------------------------
-  environment :: Parser LaTeX
-  environment = anonym <|> env
-
-  anonym :: Parser LaTeX
-  anonym = char '{' >> 
-      TeXBraces . mconcat <$> block `manyTill` char '}'
-
-  env :: Parser LaTeX
-  env = do
-    _  <- char '\\'
-    n  <- envName "begin"
-    as <- fmap (fromMaybe []) cmdArgs
-    b  <- envBody n 
-    return $ TeXEnv (T.unpack n) as b
-
-  envName :: Text -> Parser Text
-  envName k = do
-    _ <- string k
-    _ <- char '{'
-    n <- A.takeTill (== '}')
-    _ <- char '}'
-    return n
-
-  envBody :: Text -> Parser LaTeX
-  envBody n = mconcat <$> (bodyBlock n) `manyTill` endenv
-    where endenv = try $ string ("\\end{" <> n <> "}")
-
-  bodyBlock :: Text -> Parser LaTeX
-  bodyBlock n = do
-    c <- peekChar
-    case c of 
-       Just _ -> block
-       _ -> fail $ "Environment '" <> T.unpack n <> "' not finalized."
-
-  ------------------------------------------------------------------------
-  -- Command
-  ------------------------------------------------------------------------
-  command :: Parser LaTeX
-  command = do
-    _    <- char '\\'
-    mbX  <- peekChar
-    case mbX of
-      Nothing -> return TeXEmpty
-      Just x  -> if isSpecial x
-                   then special
-                   else do
-                     c  <- A.takeTill endCmd
-                     if c `elem` ["begin","end"]
-                        then fail $ "Command not allowed: " ++ T.unpack c
-                        else maybe (TeXCommS $ T.unpack c) (TeXComm $ T.unpack c) <$> cmdArgs
-
-  ------------------------------------------------------------------------
-  -- Command Arguments
-  ------------------------------------------------------------------------
-  cmdArgs :: Parser (Maybe [TeXArg])
-  cmdArgs = try (string "{}" >> return (Just []))
-              <|> fmap Just (many1 cmdArg)
-              <|> return Nothing
-
-  cmdArg :: Parser TeXArg
-  cmdArg = do
-    c <- char '[' <|> char '{'
-    let e = case c of
-              '[' -> "]"
-              '{' -> "}"
-              _   -> error "this cannot happen!"
-    b <- mconcat <$> block `manyTill` string e
-    case c of  
-      '[' -> return $ OptArg b
-      '{' -> return $ FixArg b
-      _   -> error "this cannot happen!"
-
-  ------------------------------------------------------------------------
-  -- Special commands (consisting of one char)
-  ------------------------------------------------------------------------
-  special :: Parser LaTeX
-  special = do
-    x <- anyChar
-    case x of
-      '('  -> math Parentheses "\\)"
-      '['  -> math Square      "\\]"
-      '{'  -> lbrace
-      '}'  -> rbrace
-      '|'  -> vert
-      '\\' -> lbreak
-      _    -> commS [x]
-
-  ------------------------------------------------------------------------
-  -- line break
-  ------------------------------------------------------------------------
-  lbreak :: Parser LaTeX
-  lbreak = do
-    y <- try (char '[' <|> char '*' <|> return ' ')  
-    case y of
-      '[' -> linebreak False
-      '*' -> do z <- try (char '[' <|> return ' ')
-                case z of
-                 '[' -> linebreak True
-                 _   -> return (TeXLineBreak Nothing True)
-      _   -> return (TeXLineBreak Nothing False)
-
-  linebreak :: Bool -> Parser LaTeX
-  linebreak t = do m <- measure
-                   _ <- char ']'
-                   s <- try (char '*' <|> return ' ')
-                   return $ TeXLineBreak (Just m) (t || s == '*')
-
-  measure :: Parser Measure
-  measure = try  (double >>= unit)
-              <|> CustomMeasure <$> block
-
-  unit :: Double -> Parser Measure
-  unit f = do
-    u1 <- anyChar
-    u2 <- anyChar
-    case map toLower [u1, u2] of
-      "pt" -> return $ Pt f
-      "mm" -> return $ Mm f
-      "cm" -> return $ Cm f
-      "in" -> return $ In f
-      "ex" -> return $ Ex f
-      "em" -> return $ Em f
-      _    -> fail "NaN"
-
-  ------------------------------------------------------------------------
-  -- right or left brace or vertical
-  ------------------------------------------------------------------------
-  rbrace, lbrace,vert :: Parser LaTeX
-  lbrace = brace "{"
-  rbrace = brace "}"
-  vert   = brace "|"
-
-  brace :: String -> Parser LaTeX
-  brace = return . TeXCommS
-
-  commS :: String -> Parser LaTeX
-  commS = return . TeXCommS
-
-  ------------------------------------------------------------------------
-  -- Math
-  ------------------------------------------------------------------------
-  dolMath :: Parser LaTeX
-  dolMath = do
-    _ <- char '$' 
-    b <- mconcat <$> block `manyTill` char '$'
-    return $ TeXMath Dollar b -- []
-
-  math :: MathType -> Text -> Parser LaTeX
-  math t eMath = do
-     b <- mconcat <$> block `manyTill` try (string eMath)
-     return $ TeXMath t b -- []
-
-  ------------------------------------------------------------------------
-  -- Comment 
-  ------------------------------------------------------------------------
-  comment :: Parser LaTeX
-  comment = do
-    _  <- char '%'
-    c  <- A.takeTill (== '\n')
-    e  <- atEnd
-    unless e (char '\n' >>= \_ -> return ())
-    return $ TeXComment c
-
-  ------------------------------------------------------------------------
-  -- Helpers
-  ------------------------------------------------------------------------
-  isSpecial :: Char -> Bool
-  isSpecial = (`elem` specials)
-
-  endCmd :: Char -> Bool
-  endCmd c = notLowercaseAlph && notUppercaseAlph
-   where c' = fromEnum c
-         notLowercaseAlph = c' < fromEnum 'a' || c' > fromEnum 'z'
-         notUppercaseAlph = c' < fromEnum 'A' || c' > fromEnum 'Z'
-
-
-  specials :: String
-  specials = "'(),.-\"!^$&#{}%~|/:;=[]\\` "
+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+-------------------------------------------------------------------------------+-- |+-- Module     : Text/LaTeX/Base/Parser.hs+-- Copyright  : (c) Tobias Schoofs+-- License    : LGPL +-- Stability  : experimental+-- Portability: portable+--+-- LaTeX Parser based on Attoparsec+-------------------------------------------------------------------------------+module Text.LaTeX.Base.Parser (+    parseLaTeX+  , latexParser+  , latexBlockParser+  , latexAtOnce+  , latexDocParser+#ifdef _TEST+  , specials+#endif+    ) where++import           Data.Attoparsec.Text hiding (take, takeTill)+import qualified Data.Attoparsec.Text as A   (takeTill)+import           Data.Char (toLower)+import           Data.Monoid+import           Data.Maybe (fromMaybe)+import           Data.Text (Text)+import qualified Data.Text as T ++import           Control.Applicative ((<|>), (<$>))+import           Control.Monad (unless)++import           Text.LaTeX.Base.Syntax++-- | Parse a 'Text' sequence as a 'LaTeX' block. If it fails, it returns+--   an error string.+parseLaTeX :: Text -> Either String LaTeX+parseLaTeX t | T.null t  = return TeXEmpty+             | otherwise = +  case parse latexParser t of+    Fail _ _ e     -> Left e+    Done _ r       -> Right r+    rx@(Partial _) -> -- Left "incomplete input"+                      case feed rx T.empty of+                        Fail _ _ e -> Left e+                        Partial _  -> Left "incomplete input"+                        Done _ r   -> Right r++{-# DEPRECATED latexAtOnce "Use parseLaTeX instead." #-}++latexAtOnce :: Text -> Either String LaTeX+latexAtOnce = parseLaTeX++------------------------------------------------------------------------+-- | Incremental Parser that terminates after the /document/ envionment+------------------------------------------------------------------------+latexDocParser :: Parser LaTeX+latexDocParser = blockTillDoc++------------------------------------------------------------------------+-- | Incremental 'LaTeX' parser.+------------------------------------------------------------------------+latexParser :: Parser LaTeX+latexParser = mconcat <$> latexBlockParser `manyTill` endOfInput ++blockTillDoc :: Parser LaTeX+blockTillDoc = do+  b <- latexBlockParser+  if isMainDoc b then return  b+                 else mappend b <$> blockTillDoc++-- | Test if a 'LaTeX' block is a @document@ environment.+isMainDoc :: LaTeX -> Bool+isMainDoc (TeXEnv "document" _ _) = True+isMainDoc _ = False++-- | Parser of a single 'LaTeX' constructor, no appending blocks.+latexBlockParser :: Parser LaTeX+latexBlockParser = foldr1 (<|>) [text, dolMath, comment, text2, environment, command]+-- Note: text stops on ']'; if the other parsers fail on the rest+--       text2 handles it, starting with ']' +  +------------------------------------------------------------------------+-- Text+------------------------------------------------------------------------+text :: Parser LaTeX+text = do+  mbC <- peekChar+  case mbC of+    Nothing -> fail "text: Empty input."+    Just c | c `elem` "$%\\{]}" -> fail "not text"+           | otherwise          -> TeXRaw <$> A.takeTill (`elem` "$%\\{]}")++------------------------------------------------------------------------+-- Text without stopping on ']'+------------------------------------------------------------------------+text2 :: Parser LaTeX+text2 = do+  _ <- char ']'+  t <- try (text <|> return (TeXRaw T.empty))+  return $ TeXRaw (T.pack "]") <> t++------------------------------------------------------------------------+-- Environment+------------------------------------------------------------------------+environment :: Parser LaTeX+environment = anonym <|> env++anonym :: Parser LaTeX+anonym = char '{' >> +    TeXBraces . mconcat <$> latexBlockParser `manyTill` char '}'++env :: Parser LaTeX+env = do+  _  <- char '\\'+  n  <- envName "begin"+  skipSpace+  as <- fmap (fromMaybe []) cmdArgs+  b  <- envBody n +  return $ TeXEnv (T.unpack n) as b++envName :: Text -> Parser Text+envName k = do+  _ <- string k+  _ <- char '{'+  n <- A.takeTill (== '}')+  _ <- char '}'+  return n++envBody :: Text -> Parser LaTeX+envBody n = mconcat <$> (bodyBlock n) `manyTill` endenv+  where endenv = try $ string ("\\end") >> skipSpace >> string ("{" <> n <> "}")++bodyBlock :: Text -> Parser LaTeX+bodyBlock n = do+  c <- peekChar+  case c of +     Just _ -> latexBlockParser+     _ -> fail $ "Environment '" <> T.unpack n <> "' not finalized."++------------------------------------------------------------------------+-- Command+------------------------------------------------------------------------+command :: Parser LaTeX+command = do+  _    <- char '\\'+  mbX  <- peekChar+  case mbX of+    Nothing -> return TeXEmpty+    Just x  -> if isSpecial x+                  then special+                  else do+                    c  <- A.takeTill endCmd+                    -- if c `elem` ["begin","end"]+                    --    then fail $ "Command not allowed: " ++ T.unpack c+                    --    else maybe (TeXCommS $ T.unpack c) (TeXComm $ T.unpack c) <$> cmdArgs+                    maybe (TeXCommS $ T.unpack c) (TeXComm $ T.unpack c) <$> cmdArgs++------------------------------------------------------------------------+-- Command Arguments+------------------------------------------------------------------------+cmdArgs :: Parser (Maybe [TeXArg])+cmdArgs = try (string "{}" >> return (Just []))+            <|> fmap Just (many1 cmdArg)+            <|> return Nothing++cmdArg :: Parser TeXArg+cmdArg = do+  c <- char '[' <|> char '{'+  let e = case c of+            '[' -> "]"+            '{' -> "}"+            _   -> error "this cannot happen!"+  b <- mconcat <$> latexBlockParser `manyTill` string e+  case c of  +    '[' -> return $ OptArg b+    '{' -> return $ FixArg b+    _   -> error "this cannot happen!"++------------------------------------------------------------------------+-- Special commands (consisting of one char)+------------------------------------------------------------------------+special :: Parser LaTeX+special = do+  x <- anyChar+  case x of+    '('  -> math Parentheses "\\)"+    '['  -> math Square      "\\]"+    '{'  -> lbrace+    '}'  -> rbrace+    '|'  -> vert+    '\\' -> lbreak+    _    -> commS [x]++------------------------------------------------------------------------+-- Line break+------------------------------------------------------------------------+lbreak :: Parser LaTeX+lbreak = do+  y <- try (char '[' <|> char '*' <|> return ' ')  +  case y of+    '[' -> linebreak False+    '*' -> do z <- try (char '[' <|> return ' ')+              case z of+               '[' -> linebreak True+               _   -> return (TeXLineBreak Nothing True)+    _   -> return (TeXLineBreak Nothing False)++linebreak :: Bool -> Parser LaTeX+linebreak t = do m <- measure+                 _ <- char ']'+                 s <- try (char '*' <|> return ' ')+                 return $ TeXLineBreak (Just m) (t || s == '*')++measure :: Parser Measure+measure = try (double >>= unit) <|> CustomMeasure <$> latexBlockParser++unit :: Double -> Parser Measure+unit f = do+  u1 <- anyChar+  u2 <- anyChar+  case map toLower [u1, u2] of+    "pt" -> return $ Pt f+    "mm" -> return $ Mm f+    "cm" -> return $ Cm f+    "in" -> return $ In f+    "ex" -> return $ Ex f+    "em" -> return $ Em f+    _    -> fail "NaN"++------------------------------------------------------------------------+-- Right or left brace or vertical+------------------------------------------------------------------------+rbrace, lbrace,vert :: Parser LaTeX+lbrace = brace "{"+rbrace = brace "}"+vert   = brace "|"++brace :: String -> Parser LaTeX+brace = return . TeXCommS++commS :: String -> Parser LaTeX+commS = return . TeXCommS++------------------------------------------------------------------------+-- Math+------------------------------------------------------------------------+dolMath :: Parser LaTeX+dolMath = do+  _ <- char '$' +  b <- mconcat <$> latexBlockParser `manyTill` char '$'+  return $ TeXMath Dollar b++math :: MathType -> Text -> Parser LaTeX+math t eMath = do+   b <- mconcat <$> latexBlockParser `manyTill` try (string eMath)+   return $ TeXMath t b++------------------------------------------------------------------------+-- Comment +------------------------------------------------------------------------+comment :: Parser LaTeX+comment = do+  _  <- char '%'+  c  <- A.takeTill (== '\n')+  e  <- atEnd+  unless e (char '\n' >>= \_ -> return ())+  return $ TeXComment c++------------------------------------------------------------------------+-- Helpers+------------------------------------------------------------------------+isSpecial :: Char -> Bool+isSpecial = (`elem` specials)++endCmd :: Char -> Bool+endCmd c = notLowercaseAlph && notUppercaseAlph+ where c' = fromEnum c+       notLowercaseAlph = c' < fromEnum 'a' || c' > fromEnum 'z'+       notUppercaseAlph = c' < fromEnum 'A' || c' > fromEnum 'Z'+++specials :: String+specials = "'(),.-\"!^$&#{}%~|/:;=[]\\` "
Text/LaTeX/Base/Render.hs view
@@ -27,6 +27,7 @@ import Data.Text.Encoding
 import Data.List (intersperse)
 import qualified Data.ByteString as B
+import Data.Word (Word8)
 
 -- | Class of values that can be transformed to 'Text'.
 -- You mainly will use this to obtain the 'Text' output
@@ -151,6 +152,7 @@ instance Render Integer where
 instance Render Float where
 instance Render Double where
+instance Render Word8 where
 
 instance Render a => Render [a] where
  render xs = "[" <> renderCommas xs <> "]"
Text/LaTeX/Base/Syntax.hs view
@@ -32,6 +32,7 @@ import Data.String
 import Control.Applicative
 import Data.Functor.Identity (runIdentity)
+import Data.Typeable
 
 -- | Measure units defined in LaTeX. Use 'CustomMeasure' to use commands like 'textwidth'.
 --   For instance:
@@ -126,6 +127,9 @@ protectChar '\\' = "\\textbackslash{}"
 protectChar '_'  = "\\_{}"
 protectChar x = [x]
+
+instance Typeable LaTeX where
+  typeOf _ = mkTyConApp (mkTyCon3 "HaTeX" "Text.LaTeX.Base.Syntax" "LaTeX") []
 
 -- Syntax analysis
 
Text/LaTeX/Base/Warnings.hs view
@@ -4,7 +4,7 @@ -- | This module provides functionality for check a 'LaTeX' value for
 --   possibly undesired things (like the call to an undefined label),
 --   returning 'Warning's. These are called 'Warning's because they
---   never terminates the program execution.
+--   never terminate the program execution.
 module Text.LaTeX.Base.Warnings (
    -- * Warnings datatype
    Warning (..)
Text/LaTeX/Packages/AMSMath.hs view
@@ -89,6 +89,7 @@  , to , mapsto
  , forall , exists
  , dagger, ddagger
+ , infty
    -- * Fonts
  , mathdefault
  , mathbf
@@ -394,7 +395,8 @@ 
 ---- Sum/Integral symbols
 
--- | Sigma sumation symbol.
+-- | Sigma sumation symbol. Use 'sumFromTo' instead if you want to
+--   specify the limits of the sum.
 tsum :: LaTeXC l => l
 tsum = comm0 "sum"
 
@@ -403,9 +405,10 @@           => l -- ^ Expression below the sigma.
           -> l -- ^ Expression above the sigma.
           -> l
-sumFromTo x y = tsum !: x ^: y
+sumFromTo x y = commS "sum" !: x ^: y
 
--- | Pi product symbol.
+-- | Pi product symbol. Use 'prodFromTo' if you want to specify the
+--   limits of the product.
 prod :: LaTeXC l => l
 prod = comm0 "prod"
 
@@ -414,9 +417,10 @@            => l -- ^ Expression below the pi.
            -> l -- ^ Expression above the pi.
            -> l
-prodFromTo x y = prod !: x ^: y
+prodFromTo x y = commS "prod" !: x ^: y
 
--- | Integral symbol.
+-- | Integral symbol. Use 'integralFromTo' if you want to specify
+--   the limits of the integral.
 integral :: LaTeXC l => l
 integral = comm0 "int"
 
@@ -425,7 +429,7 @@                => l -- ^ Lower limit of integration.
                -> l -- ^ Upper limit of integration.
                -> l
-integralFromTo x y = integral !: x ^: y
+integralFromTo x y = commS "int" !: x ^: y
 
 ---- Operator symbols
 
@@ -437,7 +441,6 @@  \l1 l2 ->
    (l1 <> commS "not") `op` l2
 
-
 -- | Plus-or-minus operator (±).
 pm :: LaTeXC l => l -> l -> l
 pm  = between $ comm0 "pm"
@@ -528,7 +531,6 @@ equiv :: LaTeXC l => l -> l -> l
 equiv  = between $ comm0 "equiv"
 
-
 -- | Element-of (∈).
 in_ :: LaTeXC l => l -> l -> l
 in_ = between $ comm0 "in"
@@ -561,7 +563,6 @@ setminus :: LaTeXC l => l -> l -> l
 setminus  = between $ comm0 "setminus"
 
-
 -- | Angle pointing downwards (∨).
 vee :: LaTeXC l => l -> l -> l
 vee  = between $ comm0 "vee"
@@ -570,7 +571,6 @@ wedge :: LaTeXC l => l -> l -> l
 wedge  = between $ comm0 "wedge"
 
-
 -- | Circled plus operator (⊕).
 oplus :: LaTeXC l => l -> l -> l
 oplus  = between $ comm0 "oplus"
@@ -591,9 +591,6 @@ odot :: LaTeXC l => l -> l -> l
 odot  = between $ comm0 "odot"
 
-
-
-
 ---- Greek alphabet
 
 -- | /α/ symbol.
@@ -781,6 +778,10 @@ -- | Double dagger symbol, ‡.
 ddagger :: LaTeXC l => l
 ddagger = comm0 "ddagger"
+
+-- | Infinity symbol.
+infty :: LaTeXC l => l
+infty = comm0 "infty"
 
 -------------------------------------
 ------------ Math Fonts -------------
Text/LaTeX/Packages/Color.hs view
@@ -18,6 +18,10 @@  , ColorName (..)
  , ColorModel (..)
  , ColSpec (..)
+   -- * Words
+   -- | RGB255 colors are determined by three parameters of the 'Word8' type.
+   --   Values of type 'Word8' lie within 0 and 255.
+ , Word8
    -- * Commands
  , pagecolor
  , color
@@ -32,6 +36,7 @@ import Text.LaTeX.Base.Types
 --
 import Data.Text (toLower)
+import Data.Word (Word8)
 
 -- | The 'pcolor' package.
 --
@@ -75,8 +80,11 @@ -- | Specify your own color using one of the different color models.
 data ColorModel =
    RGB Float Float Float
- | RGB255 Int Int Int
+     -- ^ Each parameter determines the proportion of red, green and
+     --   blue, with a value within the [0,1] interval.
+ | RGB255 Word8 Word8 Word8
  | GrayM Float
+     -- ^ Grayscale, from 0 (black) to 1 (white).
  | HTML String
  | CMYK Float Float Float Float
    deriving Show
Text/LaTeX/Packages/TikZ/Simple.hs view
@@ -19,9 +19,9 @@ -- > myFigure :: Figure -- > myFigure = Scale 2 $ Figures -- >   [ RectangleFilled (0,0) 1 1--- >   , Colored Green $ RectangleFilled (-1,1) 1 1--- >   , Colored Red   $ RectangleFilled ( 0,2) 1 1--- >   , Colored Blue  $ RectangleFilled ( 1,1) 1 1+-- >   , Colored (BasicColor Green) $ RectangleFilled (-1,1) 1 1+-- >   , Colored (BasicColor Red)   $ RectangleFilled ( 0,2) 1 1+-- >   , Colored (BasicColor Blue)  $ RectangleFilled ( 1,1) 1 1 -- >     ] -- module Text.LaTeX.Packages.TikZ.Simple (@@ -30,8 +30,9 @@    -- * Figures  , Figure (..)  , Point-   -- | /In the future we will accept colors other than the basic ones./+ , TikZColor (..)  , Color (..)+ , Word8    -- * Additional functions  , pathImage    -- * Figure scripting@@ -42,7 +43,9 @@  import Text.LaTeX.Base.Syntax (LaTeX) import Text.LaTeX.Base.Types (Measure)-import Text.LaTeX.Packages.TikZ (TikZ,Color,tikzpicture,emptytikz,tikz)+import Text.LaTeX.Packages.TikZ+           ( TikZ, TikZColor, Color, Word8+           , tikzpicture, emptytikz, tikz ) import qualified Text.LaTeX.Packages.TikZ as T  -- | A point in the plane.@@ -64,7 +67,7 @@  | EllipseFilled Point Double Double -- ^ Same as 'Ellipse', but filled with some color.  | Text Point LaTeX -- ^ Insert some 'LaTeX' code, centered at the given 'Point'.                     --   The text should not be very complex to fit nicely in the picture.- | Colored Color Figure -- ^ Color for the given 'Figure'.+ | Colored TikZColor Figure -- ^ Color for the given 'Figure'.  | LineWidth Measure Figure -- ^ Line width for the given 'Figure'.  | Scale Double Figure -- ^ Scaling of the given 'Figure' by a factor.  | Rotate Double Figure -- ^ Rotate a 'Figure' by a given angle (in radians).
Text/LaTeX/Packages/TikZ/Syntax.hs view
@@ -27,7 +27,9 @@   , (->-)     -- * Parameters   , Parameter (..)+  , TikZColor (..)   , Color (..)+  , Word8     -- * TikZ   , TikZ   , emptytikz@@ -44,14 +46,14 @@ import Text.LaTeX.Base.Render import Text.LaTeX.Base.Syntax import Text.LaTeX.Packages.Color--- TODO: Extend colors to anything accepted in TikZ. import Data.Monoid import Data.Foldable (foldMap) import qualified Data.Sequence as S+import Numeric (showFFloat)  -- POINTS --- | A point in TikZ.+-- | A point in Ti/k/Z. data TPoint =     DimPoint Measure Measure   | XYPoint Double Double@@ -60,23 +62,35 @@   | RelPoint_ TPoint     deriving Show +-- | Newtype of double with a custom 'Show' instance.+newtype TikZDouble = TikZDouble Double++instance Show TikZDouble where+  show (TikZDouble x) = showFFloat (Just 5) x []++instance Render TikZDouble where+  render = fromString . show+ instance Render TPoint where  render (DimPoint x y) = "(" <> renderCommas [x,y] <> ")"- render (XYPoint x y) = "(" <> renderCommas [x,y] <> ")"- render (XYZPoint x y z) = "(" <> renderCommas [x,y,z] <> ")"+ render (XYPoint x y) = "(" <> renderCommas [TikZDouble x,TikZDouble y] <> ")"+ render (XYZPoint x y z) = "(" <> renderCommas [TikZDouble x,TikZDouble y,TikZDouble z] <> ")"  render (RelPoint p) = "++" <> render p  render (RelPoint_ p) = "+" <> render p +-- | Point using 'Measure's for coordinantes. pointAt :: Measure -> Measure -> TPoint pointAt = DimPoint +-- | Point using numbers as coordinates. pointAtXY :: Double -> Double -> TPoint pointAtXY = XYPoint +-- | Three-dimensional point. pointAtXYZ :: Double -> Double -> Double -> TPoint pointAtXYZ = XYZPoint --- | Makes a point relative to the previous one.+-- | Makes a point relative to the previous. relPoint :: TPoint -> TPoint relPoint (RelPoint x) = RelPoint x relPoint (RelPoint_ x) = RelPoint x@@ -206,11 +220,21 @@  -- Parameters +-- | Color models accepted by Ti/k/Z.+data TikZColor =+   BasicColor Color+ | RGBColor Word8 Word8 Word8+   deriving Show++instance Render TikZColor where+  render (BasicColor c) = render c+  render (RGBColor r g b) = "{rgb,255:red," <> render r <> ";green," <> render g <> ";blue," <> render b <> "}"+ -- | Parameters to use in a 'scope' to change how things --   are rendered within that scope. data Parameter =    TWidth Measure- | TColor Color+ | TColor TikZColor  | TScale Double  | TRotate Double -- ^ Angle is in degrees.      deriving Show
+ parsertest/example1.tex view
@@ -0,0 +1,7 @@+\documentclass{article}++\newenvironment{foo}{\begin{center}}{\end{center}}++\begin{document}++\end{document}
+ parsertest/example2.tex view
@@ -0,0 +1,8 @@+\documentclass{article}+\usepackage{amsmath}++\begin{document}++$A \\cap [j_n, \\omega)$++\end{document}
+ parsertest/parsertest.hs view
@@ -0,0 +1,26 @@++import Text.LaTeX+import Text.LaTeX.Base.Parser+import qualified Data.Text.IO as T++testNumbers :: [Int]+testNumbers = [1 .. 2]++testFile :: Int -> IO Bool+testFile i = do+  putStr $ "Parsing example " ++ show i ++ "... "+  t <- T.readFile $ "example" ++ show i ++ ".tex"+  case parseLaTeX t of+    Left err -> do putStrLn "Failed."+                   putStrLn $ "The error was: " ++ err+                   return False+    Right _  -> putStrLn "Succeed." >> return True+  +main :: IO ()+main = do+  putStrLn "Running Parser Test..."+  bs <- mapM testFile testNumbers+  let b = and bs+  putStrLn $ "Parser Test Passed: " ++ show b+  if b then return ()+       else putStrLn $ "Number of errors: " ++ show (length $ filter (==False) bs)