packages feed

HaTeX 3.10.0.0 → 3.11.0.0

raw patch · 12 files changed

+230/−29 lines, 12 filesdep +HaTeXdep +QuickCheckdep +tastydep ~basedep ~transformers

Dependencies added: HaTeX, QuickCheck, tasty, tasty-quickcheck, wl-pprint-extras

Dependency ranges changed: base, transformers

Files

Examples/beamer.hs view
@@ -35,4 +35,4 @@   block "The block" $ do
    pause
    "The content of the block appears after a pause."
-  uncover [FromSlide 6] $ center "And that's it!"+  uncover [FromSlide 6] $ center "And that's it!"
HaTeX.cabal view
@@ -1,5 +1,5 @@ Name: HaTeX
-Version: 3.10.0.0
+Version: 3.11.0.0
 Author: Daniel Díaz
 Category: Text, LaTeX
 Build-type: Simple
@@ -45,11 +45,14 @@   Default-language: Haskell2010
   Build-depends: base == 4.*
                , bytestring >= 0.9.2.1 && < 0.11
-               , transformers >= 0.2.2 && < 0.4
+               , transformers >= 0.2.2 && < 0.5
                , text >= 0.11.2.3 && < 2
                , attoparsec >= 0.10.2 && < 0.12
                , matrix
                , containers >= 0.4.2.1 && < 0.6
+               , QuickCheck
+                 -- For pretty-printing
+               , wl-pprint-extras >= 3.5
   Exposed-modules:
     Text.LaTeX
       -- Base (Core of the library)
@@ -57,6 +60,7 @@         Text.LaTeX.Base.Class
         Text.LaTeX.Base.Commands
         Text.LaTeX.Base.Parser
+        Text.LaTeX.Base.Pretty
         Text.LaTeX.Base.Render
         Text.LaTeX.Base.Syntax
         Text.LaTeX.Base.Texy
@@ -88,3 +92,13 @@   Default-extensions: OverloadedStrings
   Other-extensions: CPP
   ghc-options: -Wall -fno-warn-orphans
+
+Test-Suite matrix-test
+  type: exitcode-stdio-1.0
+  hs-source-dirs: test
+  main-is: Main.hs
+  build-depends: base == 4.*
+               , HaTeX
+               , tasty
+               , QuickCheck
+               , tasty-quickcheck
README.md view
@@ -25,6 +25,8 @@ In the other hand, this package follows the [_Package Versioning Policy_](http://www.haskell.org/haskellwiki/Package_versioning_policy),
 so it is unlikely to suffer from API breakages if you follow it too when importing the library.
 
+See the [Hackage page of HaTeX](http://hackage.haskell.org/package/HaTeX) to browse older versions.
+
 ## Travis automatic build
 
 [![Build Status](https://travis-ci.org/Daniel-Diaz/HaTeX.png?branch=master)](https://travis-ci.org/Daniel-Diaz/HaTeX)
@@ -57,10 +59,6 @@   This includes adding more test cases to the [parsertest folder](https://github.com/Daniel-Diaz/HaTeX/tree/master/parsertest).
 * Add more documentation.
 * BibTeX support.
-
-## Packages to be implemented
-
-* geometry
 
 ## Related projects
 
Text/LaTeX/Base/Commands.hs view
@@ -848,7 +848,7 @@  -- | Column separator. (&) :: LaTeXC l => l -> l -> l-(&) = liftL2 $ TeXOp "&"+(&) = between "&"  -- | Horizontal line. hline :: LaTeXC l => l
+ Text/LaTeX/Base/Pretty.hs view
@@ -0,0 +1,77 @@++-- | 'LaTeX' values pretty printer.+--+--   Still experimental. Give it a try and send us your feedback! :)+module Text.LaTeX.Base.Pretty (+    -- * @LaTeX@ pretty printer+    prettyLaTeX+    -- * Configurable printer+  , docLaTeX+  ) where++import Text.LaTeX.Base.Syntax+import Text.LaTeX.Base.Render+import Text.PrettyPrint.Free+  ( Doc, text, char+  , backslash, hardline+  , braces, brackets+  , indent, align, vsep+  , list, encloseSep+  , renderSmart, displayS+    )+import Data.Text (unpack,lines)+import Data.Monoid (mconcat,mempty)++-- | This function transforms a value of type 'LaTeX' to a 'Doc'.+--   You can then choose how to print this 'Doc' value using+--   the function from the "Text.PrettyPrint.Free" module.+docLaTeX :: LaTeX -> Doc ()+docLaTeX (TeXRaw t) = text $ unpack t+docLaTeX (TeXComm n as) = backslash <> text n <> align (mconcat (fmap docTeXArg as)) <> hardline+docLaTeX (TeXCommS n) = backslash <> text n <> hardline+docLaTeX (TeXEnv n as b) =+  let a = FixArg $ fromString n+  in  mconcat+       [ hardline+       , docLaTeX $ TeXComm "begin" $ a : as+       , indent 4 $ docLaTeX b+       , hardline+       , docLaTeX $ TeXComm "end" [a]+         ]+docLaTeX (TeXMath t b) =+  let (l,r) =+        case t of+          Parentheses -> ("\\(","\\)")+          Square -> ("\\[","\\]")+          Dollar -> ("$","$")+  in  text l <> docLaTeX b <> text r+docLaTeX (TeXLineBreak m b) =+  text "\\\\" <> maybe mempty (brackets . text . unpack . render) m <> ( if b then text "*" else mempty )+docLaTeX (TeXBraces b) = braces $ docLaTeX b+docLaTeX (TeXComment t) =+  let ls = Data.Text.lines t+  in  if null ls+         then char '%' <> hardline+         else align $ vsep $ fmap (text . ("% "++) . unpack) ls+docLaTeX (TeXSeq l1 l2) = docLaTeX l1 <> docLaTeX l2+docLaTeX TeXEmpty = mempty++docTeXArg :: TeXArg -> Doc ()+docTeXArg (FixArg l) = braces $ docLaTeX l+docTeXArg (OptArg l) = brackets $ docLaTeX l+docTeXArg (MOptArg ls) =+  if null ls then mempty+             else list $ fmap docLaTeX ls+docTeXArg (SymArg l) = docTeXArg $ MSymArg [l]+docTeXArg (MSymArg ls) = encloseSep (char '<') (char '>') (char ',') $ fmap docLaTeX ls++-- | Pretty print a 'LaTeX' value. It produces a more human-friendly output than 'render'.+--+--   This function should be used only for debugging purposes since it may change+--   the semantics of the input in order to create a prettier output.+--   In other words, running a LaTeX compiler in the output file of @renderFile fp l@ may+--   produce a different document than running it in the output of @writeFile fp (prettyLaTeX l)@.+--   You should use 'renderFile' unless you really need to read the LaTeX file.+--+prettyLaTeX :: LaTeX -> String+prettyLaTeX l = displayS (renderSmart 60 (docLaTeX l)) []
Text/LaTeX/Base/Render.hs view
@@ -129,8 +129,6 @@ 
   render (TeXLineBreak m b) = "\\\\" <> maybe mempty (\x -> "[" <> render x <> "]") m <> ( if b then "*" else mempty )
 
-  render (TeXOp sym l1 l2) = render l1 <> fromString sym <> render l2
-
   render (TeXBraces l) = "{" <> render l <> "}"
 
   render (TeXComment c) =
Text/LaTeX/Base/Syntax.hs view
@@ -26,13 +26,15 @@  , getPreamble
    ) where
 
-import Data.Text (Text)
+import Data.Text (Text,pack)
 import qualified Data.Text
 import Data.Monoid
 import Data.String
 import Control.Applicative
+import Control.Monad (replicateM)
 import Data.Functor.Identity (runIdentity)
 import Data.Typeable
+import Test.QuickCheck
 
 -- | Measure units defined in LaTeX. Use 'CustomMeasure' to use commands like 'textwidth'.
 --   For instance:
@@ -62,13 +64,14 @@                            -- First argument is the name of the command.
                            -- Second, its arguments.
  | TeXCommS String -- ^ Constructor for commands with no arguments.
+                   --   When rendering, no space or @{}@ will be added at
+                   --   the end.
  | TeXEnv String [TeXArg] LaTeX -- ^ Constructor for environments.
                                 -- First argument is the name of the environment.
                                 -- Second, its arguments.
                                 -- Third, its content.
  | TeXMath MathType LaTeX -- ^ Mathematical expressions.
  | TeXLineBreak (Maybe Measure) Bool -- ^ Line break command.
- | TeXOp String LaTeX LaTeX -- ^ Operators.
  | TeXBraces LaTeX -- ^ A expression between braces.
  | TeXComment Text -- ^ Comments.
  | TeXSeq LaTeX LaTeX -- ^ Sequencing of 'LaTeX' expressions.
@@ -161,7 +164,6 @@   let xs = concatMap (matchCommandArg f) as
   in  xs ++ matchCommand f l
 matchCommand f (TeXMath _ l) = matchCommand f l
-matchCommand f (TeXOp _ l1 l2) = matchCommand f l1 ++ matchCommand f l2
 matchCommand f (TeXBraces l) = matchCommand f l
 matchCommand f (TeXSeq l1 l2) = matchCommand f l1 ++ matchCommand f l2
 matchCommand _ _ = []
@@ -193,7 +195,6 @@       zs = xs ++ ys
   in  if f str then (str,as,l) : zs else zs
 matchEnv f (TeXMath _ l) = matchEnv f l
-matchEnv f (TeXOp _ l1 l2) = matchEnv f l1 ++ matchEnv f l2
 matchEnv f (TeXBraces l) = matchEnv f l
 matchEnv f (TeXSeq l1 l2) = matchEnv f l1 ++ matchEnv f l2
 matchEnv _ _ = []
@@ -224,7 +225,6 @@    go l@(TeXComm str as)  = if c l then f l else TeXComm str <$> mapM go' as
    go l@(TeXEnv str as b) = if c l then f l else TeXEnv str <$> mapM go' as <*> go b
    go l@(TeXMath t b)     = if c l then f l else TeXMath t <$> go b
-   go l@(TeXOp str l1 l2) = if c l then f l else liftA2 (TeXOp str) (go l1) (go l2)
    go l@(TeXBraces b)     = if c l then f l else TeXBraces <$> go b
    go l@(TeXSeq l1 l2)    = if c l then f l else liftA2 TeXSeq (go l1) (go l2)
    go l = if c l then f l else pure l
@@ -248,3 +248,67 @@ getPreamble (TeXEnv "document" _ _) = mempty
 getPreamble (TeXSeq l1 l2) = getPreamble l1 <> getPreamble l2
 getPreamble l = l
+
+---------------------------------------
+-- LaTeX Arbitrary instance
+
+arbitraryChar :: Gen Char
+arbitraryChar = elements $
+     ['A'..'Z']
+  ++ ['a'..'z']
+  ++ "\n-+*/!\"$%&()[]{}^_.,:;'#@<>?\\ "
+
+-- | Utility for the instance of 'LaTeX' to 'Arbitrary'.
+--   We generate a short sequence of characters and
+--   escape reserved characters with 'protectText'.
+arbitraryRaw :: Gen Text
+arbitraryRaw = do
+  n <- choose (1,20)
+  protectText . pack <$> replicateM n arbitraryChar
+
+-- | Generator for names of command and environments.
+--   We use only alphabetical characters.
+arbitraryName :: Gen String
+arbitraryName = do
+  n <- choose (1,10)
+  replicateM n $ elements $ ['a' .. 'z'] ++ ['A' .. 'Z']
+
+instance Arbitrary Measure where
+  arbitrary = do
+     n <- choose (0,5)
+     let f = [Pt,Mm,Cm,In,Ex,Em] !! n
+     f <$> arbitrary
+
+instance Arbitrary LaTeX where
+  arbitrary = do
+     -- We give more chances to 'TeXRaw'.
+     -- This results in arbitrary 'LaTeX' values
+     -- not getting too large.
+     n <- choose (0,16 :: Int)
+     case n of
+       0 -> pure TeXEmpty
+       1 -> do m <- choose (0,5)
+               TeXComm <$> arbitraryName <*> vectorOf m arbitrary
+       2 -> TeXCommS <$> arbitraryName
+       3 -> do m <- choose (0,5)
+               TeXEnv <$> arbitraryName <*> vectorOf m arbitrary <*> arbitrary
+       4 -> do m <- choose (0,2)
+               let t = [Parentheses,Square,Dollar] !! m
+               TeXMath <$> pure t <*> arbitrary
+       5 -> TeXLineBreak <$> arbitrary <*> arbitrary
+       6 -> TeXBraces <$> arbitrary
+       7 -> TeXComment <$> arbitraryRaw
+       8 -> TeXSeq <$> arbitrary <*> arbitrary
+       _ -> TeXRaw <$> arbitraryRaw
+
+instance Arbitrary TeXArg where
+  arbitrary = do
+     n <- choose (0,4 :: Int)
+     case n of
+       0 -> OptArg <$> arbitrary
+       1 -> do m <- choose (1,5)
+               MOptArg <$> vectorOf m arbitrary
+       2 -> SymArg <$> arbitrary
+       3 -> do m <- choose (1,5)
+               MSymArg <$> vectorOf m arbitrary
+       _ -> FixArg <$> arbitrary
Text/LaTeX/Base/Warnings.hs view
@@ -110,7 +110,6 @@   _ -> return ()
 labcheck (TeXEnv _ _ l) = labcheck l
 labcheck (TeXMath _ l) = labcheck l
-labcheck (TeXOp _ l1 l2) = labcheck l1 >> labcheck l2
 labcheck (TeXBraces l) = labcheck l
 labcheck (TeXSeq l1 l2) = labcheck l1 >> labcheck l2
 labcheck _ = return ()
Text/LaTeX/Base/Writer.hs view
@@ -34,9 +34,14 @@ module Text.LaTeX.Base.Writer
  ( -- * @LaTeXT@ writer
    LaTeXT
- , LaTeXT_
  , runLaTeXT
  , execLaTeXT
+   -- ** Synonyms
+ , LaTeXT_
+ , LaTeXM
+ , runLaTeXM
+ , execLaTeXM
+   -- * Utils
  , execLaTeXTWarn
  , extractLaTeX
  , extractLaTeX_
@@ -47,25 +52,27 @@    -- * Errors
  , throwError
  , merror
-   -- * Re-export
+   -- * Re-exports
  , lift
  , liftIO
    ) where
 
-import Control.Monad.Trans.Writer
-import Control.Monad.IO.Class
-import Control.Monad.Trans.Class
+-- base
 import Control.Applicative
+import Control.Monad (liftM)
 import Control.Arrow
 import Data.String
 import Data.Monoid
---
+-- transformers
+import Control.Monad.Trans.Writer
+import Control.Monad.IO.Class
+import Control.Monad.Trans.Class
+import Data.Functor.Identity
+-- HaTeX
 import Text.LaTeX.Base.Syntax
 import Text.LaTeX.Base.Class
 import Text.LaTeX.Base.Render
 import Text.LaTeX.Base.Warnings (Warning,checkAll,check)
---
-import Control.Monad (liftM)
 
 -- | 'WriterT' monad transformer applied to 'LaTeX' values.
 newtype LaTeXT m a =
@@ -84,6 +91,23 @@ 
 -- | Type synonym for empty 'LaTeXT' computations.
 type LaTeXT_ m = LaTeXT m ()
+
+-- | The 'LaTeXT' monad transformed applied to 'Identity'.
+type LaTeXM = LaTeXT Identity
+
+-- | A particular case of 'runLaTeXT'.
+--
+-- > runLaTeXM = runIdentity . runLaTeXT
+--
+runLaTeXM :: LaTeXM a -> (Either String a, LaTeX)
+runLaTeXM = runIdentity . runLaTeXT
+
+-- | A particular case of 'execLaTeXT'.
+--
+-- > execLaTeXM = runIdentity . execLaTeXT
+--
+execLaTeXM :: LaTeXM a -> LaTeX
+execLaTeXM = runIdentity . execLaTeXT
 
 instance MonadTrans LaTeXT where
  lift = LaTeXT . liftM pairNoth . lift
Text/LaTeX/Packages/AMSMath.hs view
@@ -137,8 +137,8 @@ -- | Careful! Method 'signum' is undefined. Don't use it!
 --   This instance is defined in the "Text.LaTeX.Packages.AMSMath" module.
 instance Num LaTeX where
- (+) = TeXOp "+"
- (-) = TeXOp "-"
+ (+) = between "+"
+ (-) = between "-"
  (*) = (<>)
  negate = (TeXEmpty -)
  fromInteger = rendertex
@@ -491,7 +491,7 @@ --
 -- > infixr 4 =:
 (=:) :: LaTeXC l => l -> l -> l
-(=:)  = liftL2 $ TeXOp "="
+(=:)  = between "="
 
 -- | Not equal (≠).
 --
@@ -501,7 +501,7 @@ 
 -- | Greater.
 (>:) :: LaTeXC l => l -> l -> l
-(>:) = liftL2 $ TeXOp ">"
+(>:) = between ">"
 
 -- | Greater or equal (≥).
 (>=:) :: LaTeXC l => l -> l -> l
@@ -509,7 +509,7 @@ 
 -- | Lesser.
 (<:) :: LaTeXC l => l -> l -> l
-(<:) = liftL2 $ TeXOp "<"
+(<:) = between "<"
 
 -- | Lesser or equal (≤).
 (<=:) :: LaTeXC l => l -> l -> l
Text/LaTeX/Packages/Hyperref.hs view
@@ -45,6 +45,8 @@ 
 createURL :: String -> URL
 createURL = URL
+-- TODO: This function should check that the input
+-- String is a valid URL.
 
 -- | 'fromString' = 'createURL'.
 instance IsString URL where
+ test/Main.hs view
@@ -0,0 +1,25 @@++import Text.LaTeX+import Text.LaTeX.Base.Parser++import Test.Tasty+import qualified Test.Tasty.QuickCheck as QC+import Test.QuickCheck++main :: IO ()+main = defaultMain $ testGroup "HaTeX"+  [ testGroup "LaTeX"+    [ QC.testProperty "LaTeX mempty" $+         \l -> (mempty <> l) == (l <> mempty)+            && (mempty <> l) == (l :: LaTeX)+    , QC.testProperty "LaTeX mappend" $+         \l1 l2 l3 -> render (l1 <> (l2 <> l3)) == render ((l1 <> l2) <> (l3 :: LaTeX))+    ]+  , testGroup "Parser"+    [ QC.testProperty "render . parse = id" $+         \l0 -> let t = render (l0 :: LaTeX)+                in case parseLaTeX t of+                     Left _ -> False+                     Right l -> render l == t+    ]+  ]