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 +1/−1
- HaTeX.cabal +16/−2
- README.md +2/−4
- Text/LaTeX/Base/Commands.hs +1/−1
- Text/LaTeX/Base/Pretty.hs +77/−0
- Text/LaTeX/Base/Render.hs +0/−2
- Text/LaTeX/Base/Syntax.hs +69/−5
- Text/LaTeX/Base/Warnings.hs +0/−1
- Text/LaTeX/Base/Writer.hs +32/−8
- Text/LaTeX/Packages/AMSMath.hs +5/−5
- Text/LaTeX/Packages/Hyperref.hs +2/−0
- test/Main.hs +25/−0
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 [](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+ ]+ ]