packages feed

lambdatex 0.1.1.0 → 0.2.0.0

raw patch · 21 files changed

+439/−371 lines, 21 filesdep +filepathsetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: filepath

API changes (from Hackage documentation)

- Text.LaTeX.LambdaTeX: data GenerationConfig
- Text.LaTeX.LambdaTeX.Types: data ΛConfig
- Text.LaTeX.LambdaTeX.Types: data ΛState
+ Text.LaTeX.LambdaTeX: [projectBuildDir] :: ProjectConfig -> FilePath
+ Text.LaTeX.LambdaTeX: instance GHC.Classes.Eq Text.LaTeX.LambdaTeX.GenerationConfig
+ Text.LaTeX.LambdaTeX: instance GHC.Classes.Eq Text.LaTeX.LambdaTeX.ProjectConfig
+ Text.LaTeX.LambdaTeX: instance GHC.Show.Show Text.LaTeX.LambdaTeX.GenerationConfig
+ Text.LaTeX.LambdaTeX: instance GHC.Show.Show Text.LaTeX.LambdaTeX.ProjectConfig
+ Text.LaTeX.LambdaTeX: newtype GenerationConfig
+ Text.LaTeX.LambdaTeX.Types: newtype ΛConfig
+ Text.LaTeX.LambdaTeX.Types: newtype ΛState
- Text.LaTeX.LambdaTeX: ProjectConfig :: GenerationConfig -> String -> String -> ProjectConfig
+ Text.LaTeX.LambdaTeX: ProjectConfig :: GenerationConfig -> String -> String -> FilePath -> ProjectConfig
- Text.LaTeX.LambdaTeX: execLambdaTeXT :: Monad m => ΛTeXT m a -> GenerationConfig -> m ([ΛError], LaTeX, [Reference], [(String, IO ())])
+ Text.LaTeX.LambdaTeX: execLambdaTeXT :: Monad m => ΛTeXT m a -> GenerationConfig -> m ([ΛError], LaTeX, [Reference], [(String, FilePath -> IO ())])
- Text.LaTeX.LambdaTeX.Action: registerAction :: Monad m => String -> IO () -> ΛTeXT m ()
+ Text.LaTeX.LambdaTeX.Action: registerAction :: Monad m => String -> (FilePath -> IO ()) -> ΛTeXT m ()
- Text.LaTeX.LambdaTeX.Types: [outputActions] :: ΛOutput -> [(String, IO ())]
+ Text.LaTeX.LambdaTeX.Types: [outputActions] :: ΛOutput -> [(String, FilePath -> IO ())]
- Text.LaTeX.LambdaTeX.Types: runΛTeX :: ΛTeXT m a -> ΛConfig -> ΛState -> m ((a, LaTeX), ΛState, ΛOutput)
+ Text.LaTeX.LambdaTeX.Types: runΛTeX :: Monad m => ΛTeXT m a -> ΛConfig -> ΛState -> m ((a, LaTeX), ΛState, ΛOutput)
- Text.LaTeX.LambdaTeX.Types: ΛOutput :: Set PackageDep -> Set Reference -> Set Text -> Set Text -> [(String, IO ())] -> ΛOutput
+ Text.LaTeX.LambdaTeX.Types: ΛOutput :: Set PackageDep -> Set Reference -> Set Text -> Set Text -> [(String, FilePath -> IO ())] -> ΛOutput

Files

Setup.hs view
@@ -1,2 +1,3 @@ import Distribution.Simple+ main = defaultMain
lambdatex.cabal view
@@ -1,68 +1,69 @@-name:                lambdatex-version:             0.1.1.0-synopsis:            Type-Safe LaTeX EDSL-description:         -  ΛTeX, pronounced 'LambdaTeX' is a Haskell EDSL that adds type-safety to LaTeX.-  ΛTeX-generated LaTeX code should compile without errors.+name: lambdatex+version: 0.2.0.0+cabal-version: >=1.10+build-type: Simple+license: GPL+license-file: LICENSE+copyright: 2015 Tom Sydney Kerckhove+maintainer: syd.kerckhove@gmail.com+homepage: http://github.com/NorfairKing/lambdatex+synopsis: Type-Safe LaTeX EDSL+description:+    ΛTeX, pronounced 'LambdaTeX' is a Haskell EDSL that adds type-safety to LaTeX.+    ΛTeX-generated LaTeX code should compile without errors.+    TODO(kerckhove) big fancy example+category: Text+author: Tom Sydney Kerckhove -  TODO(kerckhove) big fancy example-homepage:            http://github.com/NorfairKing/lambdatex-license:             GPL-license-file:        LICENSE-author:              Tom Sydney Kerckhove-maintainer:          syd.kerckhove@gmail.com-copyright:           2015 Tom Sydney Kerckhove-category:            Text-build-type:          Simple--- extra-source-files:-cabal-version:       >=1.10+source-repository head+    type: git+    location: https://github.com/NorfairKing/lambdatex  library-  hs-source-dirs:      src-  exposed-modules:     Text.LaTeX.LambdaTeX-                       Text.LaTeX.LambdaTeX.Action-                       Text.LaTeX.LambdaTeX.Error-                       Text.LaTeX.LambdaTeX.Package-                       Text.LaTeX.LambdaTeX.Package.Internal-                       Text.LaTeX.LambdaTeX.Package.Types-                       Text.LaTeX.LambdaTeX.Part-                       Text.LaTeX.LambdaTeX.Reference-                       Text.LaTeX.LambdaTeX.Reference.Internal-                       Text.LaTeX.LambdaTeX.Reference.Types-                       Text.LaTeX.LambdaTeX.Selection-                       Text.LaTeX.LambdaTeX.Selection.Internal-                       Text.LaTeX.LambdaTeX.Selection.Types-                       Text.LaTeX.LambdaTeX.Types-                       Text.LaTeX.LambdaTeX.Utils-  build-depends:       base             >= 4.8      && < 5.0-                     , HaTeX            >= 3.16     && < 3.18-                     , mtl              >= 2.2      && < 2.3-                     , text             >= 1.2      && < 1.3-                     , containers       >= 0.5      && < 0.6-                     , transformers     >= 0.4      && < 0.6-                     , directory        >= 1.2      && < 1.3-                     , async            >= 2.0      && < 2.2-  ghc-options:        -Wall-                      -fwarn-unused-imports-                      -fwarn-incomplete-patterns-                      -fno-warn-unused-do-bind-                      -fno-warn-name-shadowing-                      -fno-warn-orphans-  default-language:    Haskell2010+    exposed-modules:+        Text.LaTeX.LambdaTeX+        Text.LaTeX.LambdaTeX.Action+        Text.LaTeX.LambdaTeX.Error+        Text.LaTeX.LambdaTeX.Package+        Text.LaTeX.LambdaTeX.Package.Internal+        Text.LaTeX.LambdaTeX.Package.Types+        Text.LaTeX.LambdaTeX.Part+        Text.LaTeX.LambdaTeX.Reference+        Text.LaTeX.LambdaTeX.Reference.Internal+        Text.LaTeX.LambdaTeX.Reference.Types+        Text.LaTeX.LambdaTeX.Selection+        Text.LaTeX.LambdaTeX.Selection.Internal+        Text.LaTeX.LambdaTeX.Selection.Types+        Text.LaTeX.LambdaTeX.Types+        Text.LaTeX.LambdaTeX.Utils+    build-depends:+        base >=4.8 && <5.0,+        HaTeX >=3.16 && <3.18,+        mtl >=2.2 && <2.3,+        text >=1.2 && <1.3,+        containers >=0.5 && <0.6,+        transformers >=0.4 && <0.6,+        directory >=1.2 && <1.4,+        async >=2.0 && <2.2,+        filepath >=1.4 && <1.5+    default-language: Haskell2010+    hs-source-dirs: src+    ghc-options: -Wall -fwarn-unused-imports -fwarn-incomplete-patterns -fno-warn-unused-do-bind -fno-warn-name-shadowing -fno-warn-orphans  test-suite lambdatex-test-  type:                exitcode-stdio-1.0-  hs-source-dirs:      test-  main-is:             MainTest.hs-  build-depends:       base-                     , lambdatex-                     , hspec-                     , QuickCheck-                     , text             >= 1.2      && < 1.3-                     , quickcheck-text  >= 0.1      && < 0.2-  ghc-options:         -threaded -rtsopts -with-rtsopts=-N-  default-language:    Haskell2010--source-repository head-  type:     git-  location: https://github.com/NorfairKing/lambdatex+    type: exitcode-stdio-1.0+    main-is: MainTest.hs+    build-depends:+        base -any,+        lambdatex -any,+        hspec -any,+        QuickCheck -any,+        text >=1.2 && <1.3,+        quickcheck-text >=0.1 && <0.2+    default-language: Haskell2010+    hs-source-dirs: test+    other-modules:+        Text.LaTeX.LambdaTeX.Part.Arbitrary+        Text.LaTeX.LambdaTeX.Selection.Arbitrary+        Text.LaTeX.LambdaTeX.Selection.InternalSpec+    ghc-options: -threaded -rtsopts -with-rtsopts=-N
src/Text/LaTeX/LambdaTeX.hs view
@@ -2,47 +2,41 @@ -- TODO(kerckhove) big example here! -- {-# LANGUAGE OverloadedStrings #-}-module Text.LaTeX.LambdaTeX (-    -- * Building ΛTeX-      module Text.LaTeX.LambdaTeX +module Text.LaTeX.LambdaTeX+    ( module Text.LaTeX.LambdaTeX     -- ** Selections     , module Text.LaTeX.LambdaTeX.Selection-     -- ** References     , module Text.LaTeX.LambdaTeX.Reference-     -- ** Packages dependencies     , module Text.LaTeX.LambdaTeX.Package-     -- ** IO dependencies     , module Text.LaTeX.LambdaTeX.Action-     -- ** Re-exports     , module Text.LaTeX.LambdaTeX.Types-     ) where -import           Control.Monad                           (forM_, void)-import           Control.Monad.IO.Class                  (MonadIO (..))+import Control.Monad (forM_, void)+import Control.Monad.IO.Class (MonadIO(..)) -import           Control.Concurrent.Async                (async, wait)+import Control.Concurrent.Async (async, wait)+import System.FilePath -import qualified Data.Set                                as S-import qualified Data.Text.IO                            as T+import qualified Data.Set as S+import qualified Data.Text.IO as T -import           Text.LaTeX.Base                         (LaTeX, renderFile)+import Text.LaTeX.Base (LaTeX, renderFile) -import           Text.LaTeX.LambdaTeX.Action-import           Text.LaTeX.LambdaTeX.Package-import           Text.LaTeX.LambdaTeX.Package.Internal-import           Text.LaTeX.LambdaTeX.Reference-import           Text.LaTeX.LambdaTeX.Reference.Internal-import           Text.LaTeX.LambdaTeX.Reference.Types-import           Text.LaTeX.LambdaTeX.Selection-import           Text.LaTeX.LambdaTeX.Selection.Types-import           Text.LaTeX.LambdaTeX.Types-import           Text.LaTeX.LambdaTeX.Utils+import Text.LaTeX.LambdaTeX.Action+import Text.LaTeX.LambdaTeX.Package+import Text.LaTeX.LambdaTeX.Package.Internal+import Text.LaTeX.LambdaTeX.Reference+import Text.LaTeX.LambdaTeX.Reference.Internal+import Text.LaTeX.LambdaTeX.Reference.Types+import Text.LaTeX.LambdaTeX.Selection+import Text.LaTeX.LambdaTeX.Selection.Types+import Text.LaTeX.LambdaTeX.Types  -- | Build all the files for a LaTeX project given by a ΛTeXT generator --   This either returns Left with an error or Right () to signify success.@@ -53,33 +47,31 @@ --      * Automatic bibtex file generation --      * All safety provided by 'execLambdaTeXT' (in the form of textual errors) --      * Automatic asynchronic resolution of IO dependencies for graphviz or tikz figures-buildLaTeXProject :: MonadIO m => ΛTeXT m a -> ProjectConfig -> m (Either [ΛError] ())+buildLaTeXProject ::+       MonadIO m => ΛTeXT m a -> ProjectConfig -> m (Either [ΛError] ()) buildLaTeXProject func conf = do-    (errs, latex, refs, actions) <- execLambdaTeXT func $ projectGenerationConfig conf--+    (errs, latex, refs, actions) <-+        execLambdaTeXT func $ projectGenerationConfig conf     -- Render tex file     let renderTex = do             let mainTexFile = projectTexFileName conf ++ ".tex"-            renderFile mainTexFile latex-+            renderFile (projectBuildDir conf </> mainTexFile) latex     -- Render bib file     let renderMain = do             let mainBibFile = projectBibFileName conf ++ ".bib"-            removeIfExists mainBibFile-            T.appendFile mainBibFile $ renderReferences refs-+            T.writeFile (projectBuildDir conf </> mainBibFile) $+                renderReferences refs     let performAction (name, action) = do-            void action+            void $ action $ projectBuildDir conf             putStrLn $ "Job " ++ name ++ " done."-     -- Perform all the IO actions asynchronously-    as <- liftIO $ mapM async $ renderTex : renderMain : map performAction actions+    as <-+        liftIO $ mapM async $ renderTex : renderMain : map performAction actions     liftIO $ forM_ as wait--    return $ if null errs-        then Right ()-        else Left errs+    return $+        if null errs+            then Right ()+            else Left errs  -- | Execute a ΛTeXT generation --   This either returns a tuple of the errors and a tuple of the resulting LaTeX value and a list of external references that need to be put into a bibtex file.@@ -91,60 +83,62 @@ --      * Internal dependency safety. No more '??' for external references in the internal pdf. --      * Package dependency resolution, TODO(kerckhove) with packages in the right order --      * Dependency selection of figure dependencies on graphviz or tikz figures-execLambdaTeXT :: Monad m => ΛTeXT m a -> GenerationConfig -> m ([ΛError], LaTeX, [Reference], [(String, IO ())])+execLambdaTeXT ::+       Monad m+    => ΛTeXT m a+    -> GenerationConfig+    -> m ([ΛError], LaTeX, [Reference], [(String, FilePath -> IO ())]) execLambdaTeXT func conf = do-    ((_,latex), _, output) <- runΛTeX func (ΛConfig $ generationSelection conf) initState--    let mresult = injectPackageDependencies (S.toList $ outputPackageDependencies output) latex-    let (extraErrs, result) = case mresult of-            Nothing -> ([IncompatibleDependencies], latex)-            Just res -> ([], res)-+    ((_, latex), _, output) <-+        runΛTeX func (ΛConfig $ generationSelection conf) initState+    let mresult =+            injectPackageDependencies+                (S.toList $ outputPackageDependencies output)+                latex+    let (extraErrs, result) =+            case mresult of+                Nothing -> ([IncompatibleDependencies], latex)+                Just res -> ([], res)     let refs = S.toList $ outputExternalReferences output     let actions = outputActions output-     -- Check reference errors     let made = outputLabelsMade output         needed = outputLabelsNeeded output         diff = S.difference needed made-     let referss = map ReferenceMissing $ S.toList diff-     return (extraErrs ++ referss, result, refs, actions)-   where     initState :: ΛState-    initState = ΛState { stateCurrentPart = emptyPart }-+    initState = ΛState {stateCurrentPart = emptyPart}  -- * Configuration- -- | Configuration of a ΛTeX project-data ProjectConfig = ProjectConfig {-      projectGenerationConfig :: GenerationConfig-    , projectBibFileName      :: String-    , projectTexFileName      :: String-    }+data ProjectConfig = ProjectConfig+    { projectGenerationConfig :: GenerationConfig+    , projectBibFileName :: String+    , projectTexFileName :: String+    , projectBuildDir :: FilePath+    } deriving (Show, Eq)  -- | Default project configuration. -- --  Modify this instead of building your own 'ProjectConfig' defaultProjectConfig :: ProjectConfig-defaultProjectConfig = ProjectConfig {-      projectGenerationConfig = defaultGenerationConfig+defaultProjectConfig =+    ProjectConfig+    { projectGenerationConfig = defaultGenerationConfig     , projectBibFileName = "main"     , projectTexFileName = "main"+    , projectBuildDir = "."     }  -- | Configuration of ΛTeX generation-data GenerationConfig = GenerationConfig {-      generationSelection :: Selection-    }+newtype GenerationConfig = GenerationConfig+    { generationSelection :: Selection+    } deriving (Show, Eq)  -- | Default generation config. -- --  Modify this instead of building your own 'GenerationConfig' defaultGenerationConfig :: GenerationConfig-defaultGenerationConfig = GenerationConfig {-      generationSelection = [All]-    }+defaultGenerationConfig = GenerationConfig {generationSelection = [All]}
src/Text/LaTeX/LambdaTeX/Action.hs view
@@ -1,12 +1,15 @@ {-# LANGUAGE OverloadedStrings #-}+ module Text.LaTeX.LambdaTeX.Action where -import           Text.LaTeX.LambdaTeX.Types+import Text.LaTeX.LambdaTeX.Types  -- | Register an IO action (with a given name) that needs to be completed before the pdf can be built. -- -- Use this to generate and build external resources that are included with @includegraphics@ for example.-registerAction :: Monad m => String -- ^ Name of the job-                          -> IO () -- ^ Job-                          -> ΛTeXT m ()-registerAction name func = λtell $ mempty { outputActions = [(name, func)] }+registerAction ::+       Monad m+    => String -- ^ Name of the job+    -> (FilePath -> IO ()) -- ^ Job, it takes the project directory as an argument+    -> ΛTeXT m ()+registerAction name func = λtell $ mempty {outputActions = [(name, func)]}
src/Text/LaTeX/LambdaTeX/Error.hs view
@@ -1,6 +1,6 @@ module Text.LaTeX.LambdaTeX.Error where -import           Data.Text (Text)+import Data.Text (Text)  data ΛError     = ReferenceMissing Text
src/Text/LaTeX/LambdaTeX/Package.hs view
@@ -3,19 +3,23 @@ -- Note: If you want different arguments to a package, you have to specify this by making a 'manual' 'packageDep' declaration before your document. module Text.LaTeX.LambdaTeX.Package where -import           Text.LaTeX.Base.Syntax+import Text.LaTeX.Base.Syntax -import qualified Data.Set                           as S+import qualified Data.Set as S -import           Text.LaTeX.LambdaTeX.Package.Types-import           Text.LaTeX.LambdaTeX.Types+import Text.LaTeX.LambdaTeX.Package.Types+import Text.LaTeX.LambdaTeX.Types  -- | Declare a dependency to a package, with given arguments-packageDep :: Monad m => [LaTeX] -- ^ Arguments-                      -> Text -- ^ Name of the LaTeX package-                      -> ΛTeXT m ()-packageDep args name = λtell $ mempty { outputPackageDependencies = S.singleton (PackageDep name args) }+packageDep ::+       Monad m+    => [LaTeX] -- ^ Arguments+    -> Text -- ^ Name of the LaTeX package+    -> ΛTeXT m ()+packageDep args name =+    λtell $+    mempty {outputPackageDependencies = S.singleton (PackageDep name args)}  -- | Declare a dependency to a package without any arguments packageDep_ :: Monad m => Text -> ΛTeXT m ()-packageDep_ name = packageDep [] name+packageDep_ = packageDep []
src/Text/LaTeX/LambdaTeX/Package/Internal.hs view
@@ -1,67 +1,73 @@ {-# LANGUAGE OverloadedStrings #-}+ module Text.LaTeX.LambdaTeX.Package.Internal where -import           Control.Monad-import           Data.List+import Control.Monad+import Data.List -import           Text.LaTeX.Base.Syntax+import Text.LaTeX.Base.Syntax -import           Text.LaTeX.LambdaTeX.Package.Types-import           Text.LaTeX.LambdaTeX.Types+import Text.LaTeX.LambdaTeX.Package.Types+import Text.LaTeX.LambdaTeX.Types  -- | Inject package dependencies into a given LaTeX document. --   This is done by top-level functions in @Text.LaTeX.LambdaTeX@ automatically injectPackageDependencies :: [PackageDep] -> LaTeX -> Maybe LaTeX injectPackageDependencies packages latex = do     ps <- reorderPackages packages-    let packageDecs = mconcat $ map (\(PackageDep name args) -> usepackage args name) ps+    let packageDecs =+            mconcat $ map (\(PackageDep name args) -> usepackage args name) ps     pure (inject packageDecs latex)   where     inject ps = go-      where         -- We're looking for this: TeXComm "documentclass" ...         -- We have to go looking through the LaTeX :(+      where         go t@(TeXComm "documentclass" _) = TeXSeq t ps         go (TeXSeq t1 t2) = TeXSeq (go t1) (go t2)         go c = c -- reorderPackages :: [PackageDep] -> Maybe [PackageDep] reorderPackages deps = do     bestEffort <- foldM (flip reorderToSatisfy) deps allPackageCombinationRules     if all (`ruleIsSatisfied` bestEffort) allPackageCombinationRules-    then Just bestEffort-    else Nothing+        then Just bestEffort+        else Nothing -data PackageRule-    = PackageOrder Text Text+data PackageRule =+    PackageOrder Text+                 Text     deriving (Show, Eq)  -- Yes it's dumb, but it works for now. reorderToSatisfy :: PackageRule -> [PackageDep] -> Maybe [PackageDep]-reorderToSatisfy (PackageOrder n1 n2) ps = Just $+reorderToSatisfy (PackageOrder n1 n2) ps =+    Just $     case (,) <$> elemIndex n1 names <*> elemIndex n2 names of         Nothing -> ps         Just (ix1, ix2) ->             if ix1 < ix2-            then ps-            else (ps !! ix1)-                : (ps !! ix2)-                : map snd (filter (\(ix, _) -> ix /= ix1 && ix /= ix2) (zip [0..] ps))-  where names = map packageDepName ps+                then ps+                else (ps !! ix1) :+                     (ps !! ix2) :+                     map+                         snd+                         (filter+                              (\(ix, _) -> ix /= ix1 && ix /= ix2)+                              (zip [0 ..] ps))+  where+    names = map packageDepName ps  ruleIsSatisfied :: PackageRule -> [PackageDep] -> Bool-ruleIsSatisfied (PackageOrder n1 n2) ps-    = case (<) <$> elemIndex n1 names <*> elemIndex n2 names of+ruleIsSatisfied (PackageOrder n1 n2) ps =+    case (<) <$> elemIndex n1 names <*> elemIndex n2 names of         Just False -> False         _ -> True-  where names = map packageDepName ps+  where+    names = map packageDepName ps  allPackageCombinationRules :: [PackageRule]-allPackageCombinationRules =-    [ mintedLibertineRule-    ]+allPackageCombinationRules = [mintedLibertineRule]  mintedLibertineRule :: PackageRule mintedLibertineRule = PackageOrder "minted" "libertine"@@ -70,4 +76,3 @@ --   Don't use this directly, use the packageDep instead! usepackage :: [LaTeX] -> Text -> LaTeX usepackage ls pn = TeXComm "usepackage" [MOptArg ls, FixArg $ TeXRaw pn]-
src/Text/LaTeX/LambdaTeX/Package/Types.hs view
@@ -1,14 +1,14 @@ module Text.LaTeX.LambdaTeX.Package.Types where -import           Data.Ord               (comparing)-import           Data.Text              (Text)+import Data.Ord (comparing)+import Data.Text (Text) -import           Text.LaTeX.Base.Syntax (LaTeX)+import Text.LaTeX.Base.Syntax (LaTeX) -data PackageDep = PackageDep {-      packageDepName    :: Text+data PackageDep = PackageDep+    { packageDepName :: Text     , packageDepOptions :: [LaTeX]-  } deriving (Show, Eq)+    } deriving (Show, Eq)  instance Ord PackageDep where     compare = comparing packageDepName
src/Text/LaTeX/LambdaTeX/Part.hs view
@@ -1,16 +1,16 @@ module Text.LaTeX.LambdaTeX.Part where -import           Data.Text (Text)+import Data.Text (Text) -newtype Part = Part { unPart :: [Text] }-    deriving Show+newtype Part = Part+    { unPart :: [Text]+    } deriving (Show)  emptyPart :: Part-emptyPart = Part { unPart = [] }+emptyPart = Part {unPart = []}  pushPart :: Part -> Text -> Part-pushPart p t = Part { unPart = unPart p ++ [t] }+pushPart p t = Part {unPart = unPart p ++ [t]}  popPart :: Part -> Part-popPart p = Part { unPart = init $ unPart p }-+popPart p = Part {unPart = init $ unPart p}
src/Text/LaTeX/LambdaTeX/Reference.hs view
@@ -1,15 +1,16 @@ {-# LANGUAGE OverloadedStrings #-}+ module Text.LaTeX.LambdaTeX.Reference where -import           Text.LaTeX.Base.Class-import           Text.LaTeX.Base.Syntax+import Text.LaTeX.Base.Class+import Text.LaTeX.Base.Syntax -import qualified Text.LaTeX.Base.Commands                as H (label, pageref,-                                                               ref)+import qualified Text.LaTeX.Base.Commands as H+       (label, pageref, ref) -import           Text.LaTeX.LambdaTeX.Reference.Internal-import           Text.LaTeX.LambdaTeX.Reference.Types-import           Text.LaTeX.LambdaTeX.Types+import Text.LaTeX.LambdaTeX.Reference.Internal+import Text.LaTeX.LambdaTeX.Reference.Types+import Text.LaTeX.LambdaTeX.Types  -- * Internal references -- An internal references point is defined by a label@@ -17,9 +18,7 @@ -- -- ΛTeX automatically ensures that those references are always internally consistent -- BUT you have to make sure that you use these functions instead of the regular ones.- -- ** Labels- -- | Label a part label :: Monad m => Text -> ΛTeXT m () label l = do@@ -40,27 +39,24 @@  -- * External references -- ** Defining references- -- TODO(kerckhove) Check for duplicate fields?- -- | Define an external reference. --   Use 'cite' or 'nocite' to use this in your document. makeReference :: ReferenceType -> Text -> [(Text, Text)] -> Reference makeReference = Reference  -- ** Using references- -- | Refer to an external reference. cite :: Monad m => Reference -> ΛTeXT m ()-cite ref = do-  fromLaTeX $ comm1 "cite" $ TeXRaw $ referenceName ref-  addReference ref+cite rf = do+    fromLaTeX $ comm1 "cite" $ TeXRaw $ referenceName rf+    addReference rf  -- | Put an external reference in your list of references without using it. nocite :: Monad m => Reference -> ΛTeXT m ()-nocite ref = do-  fromLaTeX $ comm1 "nocite" $ TeXRaw $ referenceName ref-  addReference ref+nocite rf = do+    fromLaTeX $ comm1 "nocite" $ TeXRaw $ referenceName rf+    addReference rf  -- ** Reference Types --@@ -78,4 +74,3 @@  article :: ReferenceType article = "article"-
src/Text/LaTeX/LambdaTeX/Reference/Internal.hs view
@@ -1,43 +1,42 @@ {-# LANGUAGE OverloadedStrings #-}+ module Text.LaTeX.LambdaTeX.Reference.Internal where -import qualified Data.Set                             as S-import qualified Data.Text                            as T+import qualified Data.Set as S+import qualified Data.Text as T -import           Text.LaTeX.LambdaTeX.Reference.Types-import           Text.LaTeX.LambdaTeX.Types+import Text.LaTeX.LambdaTeX.Reference.Types+import Text.LaTeX.LambdaTeX.Types  -- * Internal references- -- | Declare that a label has been made-addLabelMade ::  Monad m => Text -> ΛTeXT m ()-addLabelMade label = λtell $ mempty { outputLabelsMade = S.singleton label }+addLabelMade :: Monad m => Text -> ΛTeXT m ()+addLabelMade label = λtell $ mempty {outputLabelsMade = S.singleton label}  -- | Declare that a label is needed-addLabelNeeded ::  Monad m => Text -> ΛTeXT m ()-addLabelNeeded label = λtell $ mempty { outputLabelsNeeded = S.singleton label }+addLabelNeeded :: Monad m => Text -> ΛTeXT m ()+addLabelNeeded label = λtell $ mempty {outputLabelsNeeded = S.singleton label}  -- * External references- -- | Render references to bib(La)TeX format renderReferences :: [Reference] -> Text-renderReferences rs = (`mappend` "\n\n") . T.intercalate ",\n\n" $ map showRef rs+renderReferences rs =+    (`mappend` "\n\n") . T.intercalate ",\n\n" $ map showRef rs   where     showRef :: Reference -> Text-    showRef r = mconcat-        [-          "@"-        , referenceType r-        , "{"-        , referenceName r-        , ",\n"-        , T.intercalate ",\n" (map showField $ referenceFields r)-        , "\n}"-        ]-+    showRef r =+        mconcat+            [ "@"+            , referenceType r+            , "{"+            , referenceName r+            , ",\n"+            , T.intercalate ",\n" (map showField $ referenceFields r)+            , "\n}"+            ]     showField :: (Text, Text) -> Text     showField (a, b) = mconcat ["  ", a, " = {", b, "}"]  -- | Add a reference to a ΛTeX generator addReference :: Monad m => Reference -> ΛTeXT m ()-addReference ref = λtell $ mempty { outputExternalReferences = S.singleton ref }+addReference ref = λtell $ mempty {outputExternalReferences = S.singleton ref}
src/Text/LaTeX/LambdaTeX/Reference/Types.hs view
@@ -1,16 +1,15 @@ module Text.LaTeX.LambdaTeX.Reference.Types where -import           Data.Ord  (comparing)-import           Data.Text (Text)+import Data.Ord (comparing)+import Data.Text (Text)  type ReferenceType = Text-data Reference = Reference {-      referenceType   :: ReferenceType-    , referenceName   :: Text++data Reference = Reference+    { referenceType :: ReferenceType+    , referenceName :: Text     , referenceFields :: [(Text, Text)]-  } deriving (Show, Eq)+    } deriving (Show, Eq)  instance Ord Reference where     compare = comparing referenceName--
src/Text/LaTeX/LambdaTeX/Selection.hs view
@@ -1,15 +1,14 @@ module Text.LaTeX.LambdaTeX.Selection where -import           Control.Monad                           (when)+import Control.Monad (when) -import qualified Data.Text                               as T+import qualified Data.Text as T -import           Text.LaTeX.LambdaTeX.Selection.Internal-import           Text.LaTeX.LambdaTeX.Selection.Types-import           Text.LaTeX.LambdaTeX.Types+import Text.LaTeX.LambdaTeX.Selection.Internal+import Text.LaTeX.LambdaTeX.Selection.Types+import Text.LaTeX.LambdaTeX.Types  -- * Making selections- -- | Construct a selection from a space-separated list of strings representing selectors -- -- > constructSelection = map constructSelector . words@@ -36,11 +35,10 @@ constructSelector s = Match $ map T.pack $ split s  -- * Using selections- -- | Declare a sub-part of the document with a name. --   This allows you to use the subset-selection feature later. note :: Monad m => Text -> ΛTeXT m () -> ΛTeXT m ()-note partname func = inPart partname $ do-    s <- isSelected-    when s func-+note partname func =+    inPart partname $ do+        s <- isSelected+        when s func
src/Text/LaTeX/LambdaTeX/Selection/Internal.hs view
@@ -1,9 +1,9 @@ module Text.LaTeX.LambdaTeX.Selection.Internal where -import           Data.List                            (isPrefixOf)+import Data.List (isPrefixOf) -import           Text.LaTeX.LambdaTeX.Selection.Types-import           Text.LaTeX.LambdaTeX.Types+import Text.LaTeX.LambdaTeX.Selection.Types+import Text.LaTeX.LambdaTeX.Types  -- | Whether a part is selected by a given list of selectors. --@@ -12,18 +12,20 @@ -- All parts are selected or -- It it is matched and not ignored. selects :: Part -> [Selector] -> Bool-selects (Part ps) ss = go ps ss False-    where-        go :: [Text] -> [Selector] -> Bool -> Bool-        go _ [] b                       = b-        go ps (All:ss) _                = go ps ss True-        go ps ((Match s):ss) b          = if (ps `isPrefixOf` s || s `isPrefixOf` ps)-                                          then go ps ss True-                                          else go ps ss b-        go ps ((Ignore s):ss) True      = if s `isPrefixOf` ps-                                          then go ps ss False-                                          else go ps ss True-        go ps ((Ignore _):ss) False     = go ps ss False+selects (Part parts) selectors = go parts selectors False+  where+    go :: [Text] -> [Selector] -> Bool -> Bool+    go _ [] b = b+    go ps (All:ss) _ = go ps ss True+    go ps (Match s:ss) b =+        if ps `isPrefixOf` s || s `isPrefixOf` ps+            then go ps ss True+            else go ps ss b+    go ps (Ignore s:ss) True =+        if s `isPrefixOf` ps+            then go ps ss False+            else go ps ss True+    go ps (Ignore _:ss) False = go ps ss False  -- | Whether the current part is selected to be generated isSelected :: Monad m => ΛTeXT m Bool@@ -33,7 +35,6 @@     return $ selects part sels  -- * Current part Helpers- -- | Returns the current part from the ΛTeX state currentPart :: Monad m => ΛTeXT m Part currentPart = λgets stateCurrentPart@@ -49,17 +50,18 @@ -- -- WARNING: This should never be used outside of 'inPart' pushCurrentPart :: Monad m => Text -> ΛTeXT m ()-pushCurrentPart partname = λmodify (\s -> s { stateCurrentPart = pushPart (stateCurrentPart s) partname})+pushCurrentPart partname =+    λmodify+        (\s -> s {stateCurrentPart = pushPart (stateCurrentPart s) partname})  -- | Pop a part name off the current part stack -- -- WARNING: This should never be used outside of 'inPart' popCurrentPart :: Monad m => ΛTeXT m ()-popCurrentPart = λmodify (\s -> s { stateCurrentPart = popPart $ stateCurrentPart s })-+popCurrentPart =+    λmodify (\s -> s {stateCurrentPart = popPart $ stateCurrentPart s})  -- * Text Helpers- -- | Split a string on a dot. -- This can be useful to convert from a 'Selector's textual representation back to a selector --@@ -69,11 +71,10 @@  -- | Split a string on a specific character splitOn :: Char -> String -> [String]-splitOn c s = go s []+splitOn c str = go str []   where     go :: String -> String -> [String]     go [] s = [s]-    go (sc:ss) acc | sc == c   = acc : go ss []-                   | otherwise = go ss (acc ++ [sc])--+    go (sc:ss) acc+        | sc == c = acc : go ss []+        | otherwise = go ss (acc ++ [sc])
src/Text/LaTeX/LambdaTeX/Selection/Types.hs view
@@ -1,10 +1,11 @@ module Text.LaTeX.LambdaTeX.Selection.Types where -import           Data.Text (Text)+import Data.Text (Text)  type Selection = [Selector]-data Selector = All-              | Match [Text]-              | Ignore [Text]-    deriving (Show, Eq) +data Selector+    = All+    | Match [Text]+    | Ignore [Text]+    deriving (Show, Eq)
src/Text/LaTeX/LambdaTeX/Types.hs view
@@ -1,65 +1,54 @@-{-# LANGUAGE CPP                        #-}-{-# LANGUAGE FlexibleInstances          #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE UndecidableInstances       #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-} -module Text.LaTeX.LambdaTeX.Types (-      module Text.LaTeX.LambdaTeX.Types+module Text.LaTeX.LambdaTeX.Types+    ( module Text.LaTeX.LambdaTeX.Types     , module Text.LaTeX.LambdaTeX.Part     , module Text.LaTeX.LambdaTeX.Error     , module Text.LaTeX.LambdaTeX.Package.Types     , module Text.LaTeX.LambdaTeX.Reference.Types     , module Text.LaTeX.LambdaTeX.Selection.Types--#if !MIN_VERSION_base(4,8,0)-    , module Control.Applicative-    , module Data.Monoid-#endif     , Text     ) where -#if !MIN_VERSION_base(4,8,0)-import           Control.Applicative-import           Data.Monoid                          hiding (All)-#endif--import           Control.Monad                        (liftM)-import           Control.Monad.IO.Class               (MonadIO, liftIO)-import           Control.Monad.Reader                 (MonadReader (..), asks)-import           Control.Monad.RWS                    (RWST (..))-import           Control.Monad.State                  (MonadState (..), gets,-                                                       modify)-import           Control.Monad.Trans                  (MonadTrans (..), lift)-import           Control.Monad.Writer                 (MonadWriter (..))+import Control.Monad.IO.Class (MonadIO, liftIO)+import Control.Monad.RWS (RWST(..))+import Control.Monad.Reader (MonadReader(..), asks)+import Control.Monad.State (MonadState(..), gets, modify)+import Control.Monad.Trans (MonadTrans(..), lift)+import Control.Monad.Writer (MonadWriter(..)) -import           Data.Set                             (Set)-import qualified Data.Set                             as S-import           Data.String                          (IsString (..))-import           Data.Text                            (Text)+import Data.Set (Set)+import qualified Data.Set as S+import Data.String (IsString(..))+import Data.Text (Text) -import           Text.LaTeX.Base                      (LaTeX, LaTeXT, runLaTeXT)-import           Text.LaTeX.Base.Class                (LaTeXC (..), fromLaTeX)-import           Text.LaTeX.Base.Writer               (extractLaTeX, textell)+import Text.LaTeX.Base (LaTeX, LaTeXT, runLaTeXT)+import Text.LaTeX.Base.Class (LaTeXC(..), fromLaTeX)+import Text.LaTeX.Base.Writer (extractLaTeX, textell) -import           Text.LaTeX.Packages.AMSMath          ()+import Text.LaTeX.Packages.AMSMath () -import           Text.LaTeX.LambdaTeX.Error-import           Text.LaTeX.LambdaTeX.Package.Types-import           Text.LaTeX.LambdaTeX.Part-import           Text.LaTeX.LambdaTeX.Reference.Types-import           Text.LaTeX.LambdaTeX.Selection.Types+import Text.LaTeX.LambdaTeX.Error+import Text.LaTeX.LambdaTeX.Package.Types+import Text.LaTeX.LambdaTeX.Part+import Text.LaTeX.LambdaTeX.Reference.Types+import Text.LaTeX.LambdaTeX.Selection.Types  -- * The ΛTeX Monad type LambdaTeXT = ΛTeXT+ type LambdaTeXT_ m = ΛTeXT_ m  type ΛTeXT_ m = ΛTeXT m () -newtype ΛTeXT m a =-    ΛTeXT { unwrapΛTeXT :: LaTeXT (RWST ΛConfig ΛOutput ΛState m) a }-    deriving (Functor, Applicative, Monad)+newtype ΛTeXT m a = ΛTeXT+    { unwrapΛTeXT :: LaTeXT (RWST ΛConfig ΛOutput ΛState m) a+    } deriving (Functor, Applicative, Monad)  -- TODO(kerckhove) Move and add amsmath dependency instance (Monad m, a ~ ()) => Num (ΛTeXT m a) where@@ -72,16 +61,19 @@     -- Non-defined methods     signum = ΛTeXT . signum . unwrapΛTeXT - -- TODO(kerckhove) Move and add amsmath dependency instance (Monad m, a ~ ()) => Fractional (ΛTeXT m a) where     (/) a b = ΛTeXT $ unwrapΛTeXT a / unwrapΛTeXT b     fromRational = fromLaTeX . fromRational  -- TODO(kerckhove) Also instantiate floating?--runΛTeX :: ΛTeXT m a -> ΛConfig -> ΛState -> m ((a, LaTeX), ΛState, ΛOutput)-runΛTeX func conf state = runRWST (runLaTeXT $ unwrapΛTeXT func) conf state+runΛTeX ::+       Monad m+    => ΛTeXT m a+    -> ΛConfig+    -> ΛState+    -> m ((a, LaTeX), ΛState, ΛOutput)+runΛTeX func = runRWST (runLaTeXT $ unwrapΛTeXT func)  instance MonadTrans ΛTeXT where     lift = ΛTeXT . lift . lift@@ -122,64 +114,60 @@  -- | This function run a 'LaTeXT' computation, -- lifting the result again in the monad.-extractΛLaTeX :: Monad m => ΛTeXT m a -> ΛTeXT m (a,LaTeX)+extractΛLaTeX :: Monad m => ΛTeXT m a -> ΛTeXT m (a, LaTeX) extractΛLaTeX = ΛTeXT . extractLaTeX . unwrapΛTeXT  -- | Like 'extractΛLaTeX' but without the result extractΛLaTeX_ :: Monad m => ΛTeXT m a -> ΛTeXT m LaTeX-extractΛLaTeX_ = liftM snd . extractΛLaTeX+extractΛLaTeX_ = fmap snd . extractΛLaTeX  -- | Internal ΛTeXT configration-data ΛConfig    = ΛConfig {-      configSelection :: Selection+newtype ΛConfig = ΛConfig+    { configSelection :: Selection     }  -- | Internal ΛTeXT configration output-data ΛOutput    = ΛOutput {-      outputPackageDependencies :: Set PackageDep-    , outputExternalReferences  :: Set Reference-    , outputLabelsMade          :: Set Text-    , outputLabelsNeeded        :: Set Text-    , outputActions             :: [(String, IO ())]+data ΛOutput = ΛOutput+    { outputPackageDependencies :: Set PackageDep+    , outputExternalReferences :: Set Reference+    , outputLabelsMade :: Set Text+    , outputLabelsNeeded :: Set Text+    , outputActions :: [(String, FilePath -> IO ())]     }  instance Monoid ΛOutput where-    mempty = ΛOutput {-            outputPackageDependencies   = S.empty-          , outputExternalReferences    = S.empty-          , outputLabelsMade            = S.empty-          , outputLabelsNeeded          = S.empty-          , outputActions               = []+    mempty =+        ΛOutput+        { outputPackageDependencies = S.empty+        , outputExternalReferences = S.empty+        , outputLabelsMade = S.empty+        , outputLabelsNeeded = S.empty+        , outputActions = []         }--    mappend o1 o2 = ΛOutput {-            outputPackageDependencies =-                S.union-                    (outputPackageDependencies o1)-                    (outputPackageDependencies o2)-          , outputExternalReferences =-                S.union-                    (outputExternalReferences o1)-                    (outputExternalReferences o2)-          , outputLabelsMade =-                S.union-                    (outputLabelsMade o1)-                    (outputLabelsMade o2)-          , outputLabelsNeeded =-                S.union-                    (outputLabelsNeeded o1)-                    (outputLabelsNeeded o2)-          , outputActions = outputActions o1 ++ outputActions o2+    mappend o1 o2 =+        ΛOutput+        { outputPackageDependencies =+              S.union+                  (outputPackageDependencies o1)+                  (outputPackageDependencies o2)+        , outputExternalReferences =+              S.union+                  (outputExternalReferences o1)+                  (outputExternalReferences o2)+        , outputLabelsMade = S.union (outputLabelsMade o1) (outputLabelsMade o2)+        , outputLabelsNeeded =+              S.union (outputLabelsNeeded o1) (outputLabelsNeeded o2)+        , outputActions = outputActions o1 ++ outputActions o2         }  -- | Internal ΛTeXT configration state-data ΛState = ΛState {-      stateCurrentPart :: Part+newtype ΛState = ΛState+    { stateCurrentPart :: Part     }  -- Orphan Monad Transformer instances for LaTeXT instance MonadReader r m => MonadReader r (LaTeXT m) where-    ask   = lift ask+    ask = lift ask     local = local     reader = lift . reader @@ -193,10 +181,9 @@     listen = listen     pass = pass - -- Monad Transformer instances for ΛTeXT instance MonadReader r m => MonadReader r (ΛTeXT m) where-    ask   = lift ask+    ask = lift ask     local = local     reader = lift . reader @@ -209,4 +196,3 @@     tell = lift . tell     listen = listen     pass = pass-
src/Text/LaTeX/LambdaTeX/Utils.hs view
@@ -1,14 +1,14 @@ -- | ΛTeX utilities module Text.LaTeX.LambdaTeX.Utils where -import           Control.Exception-import           System.Directory  (removeFile)-import           System.IO.Error   (isDoesNotExistError)+import Control.Exception+import System.Directory (removeFile)+import System.IO.Error (isDoesNotExistError)  -- | Remove the given file if it exists removeIfExists :: FilePath -> IO () removeIfExists fileName = removeFile fileName `catch` handleExists-  where handleExists e-          | isDoesNotExistError e = return ()-          | otherwise = throwIO e-+  where+    handleExists e+        | isDoesNotExistError e = return ()+        | otherwise = throwIO e
test/MainTest.hs view
@@ -1,9 +1,10 @@ {-# OPTIONS_GHC -F -pgmF hspec-discover #-}+ module MainTest where  import qualified Spec-import           Test.Hspec.Formatters-import           Test.Hspec.Runner+import Test.Hspec.Formatters+import Test.Hspec.Runner  main :: IO () main = hspecWith defaultConfig {configFormatter = Just progress} Spec.spec
+ test/Text/LaTeX/LambdaTeX/Part/Arbitrary.hs view
@@ -0,0 +1,11 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Text.LaTeX.LambdaTeX.Part.Arbitrary where++import Test.QuickCheck++import Data.Text.Arbitrary ()+import Text.LaTeX.LambdaTeX.Part++instance Arbitrary Part where+    arbitrary = Part <$> arbitrary
+ test/Text/LaTeX/LambdaTeX/Selection/Arbitrary.hs view
@@ -0,0 +1,11 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Text.LaTeX.LambdaTeX.Selection.Arbitrary where++import Test.QuickCheck++import Data.Text.Arbitrary ()+import Text.LaTeX.LambdaTeX.Selection.Types++instance Arbitrary Selector where+    arbitrary = oneof [pure All, Match <$> arbitrary, Ignore <$> arbitrary]
+ test/Text/LaTeX/LambdaTeX/Selection/InternalSpec.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE OverloadedStrings #-}++module Text.LaTeX.LambdaTeX.Selection.InternalSpec where++import Test.Hspec+import Test.QuickCheck++import Text.LaTeX.LambdaTeX.Part+import Text.LaTeX.LambdaTeX.Part.Arbitrary ()+import Text.LaTeX.LambdaTeX.Selection+import Text.LaTeX.LambdaTeX.Selection.Arbitrary ()+import Text.LaTeX.LambdaTeX.Selection.Internal+import Text.LaTeX.LambdaTeX.Selection.Types++spec :: Spec+spec =+    describe "selects" $ do+        it "is false for the empty selection" $+            property $ \p -> selects p [] `shouldBe` False+        it "is true for the 'match all' selection" $+            property $ \p -> selects p [All] `shouldBe` True+        it "is true for the empty part and this nonempty selection" $+            selects emptyPart [Match ["part"]] `shouldBe` True+        it "matches explicitly matched parts" $+            property $ \p -> selects (Part p) [Match p] `shouldBe` True+        it "ignore expicitly ignored parts" $+            property $ \p -> selects (Part p) [All, Ignore p] `shouldBe` False+        it "matches the right part for these simple test cases" $ do+            let p = Part ["this", "part"]+            selects p [Match ["this"]] `shouldBe` True+            selects p [Match ["this", "part"]] `shouldBe` True+            selects p [Match ["this", "part", "should"]] `shouldBe` True+            selects p [Match ["this", "part", "should", "be"]] `shouldBe` True+            selects p [Match ["this", "part", "should", "be", "matched"]] `shouldBe`+                True+            selects p [Match ["something"]] `shouldBe` False+            selects p [Match ["something", "else"]] `shouldBe` False+        it "ignores the right part for these simple test cases" $ do+            let p = Part ["this", "part"]+            selects p [All, Ignore ["this"]] `shouldBe` False+            selects p [All, Ignore ["this", "part"]] `shouldBe` False+            selects p [All, Ignore ["this", "part", "but", "it", "should"]] `shouldBe`+                True+            selects+                p+                [All, Ignore ["this", "part", "but", "it", "should", "be"]] `shouldBe`+                True+            selects+                p+                [ All+                , Ignore+                      ["this", "part", "but", "it", "should", "be", "matched"]+                ] `shouldBe`+                True+        it+            "constructs this selection that's more than three subparts long correctly" $+            constructSelector "something.in.four.subparts" `shouldBe`+            Match ["something", "in", "four", "subparts"]