packages feed

haskintex 0.4.1.0 → 0.5.0.0

raw patch · 2 files changed

+351/−166 lines, 2 filesdep +binarydep +bytestringdep +containersdep ~HaTeXdep ~basedep ~directoryPVP ok

version bump matches the API change (PVP)

Dependencies added: binary, bytestring, containers, haskell-src-exts

Dependency ranges changed: HaTeX, base, directory, filepath, hint, parsec, process

API changes (from Hackage documentation)

Files

Haskintex.hs view
@@ -12,27 +12,40 @@ import Data.Text (pack,unpack) import qualified Data.Text as T import qualified Data.Text.IO as T+import Data.Text.Encoding -- Parser--- import Data.Attoparsec.Text import Text.Parsec hiding (many,(<|>))-import Text.Parsec.Text+import Text.Parsec.Text () -- Transformers-import Control.Monad (when,unless)+import Control.Monad (when,unless,replicateM) import Control.Monad.Trans.Class-import Control.Monad.Trans.Reader+import Control.Monad.Trans.State -- LaTeX import Text.LaTeX hiding (version)+import qualified Text.LaTeX as Hatex import Text.LaTeX.Base.Syntax -- Utils import Control.Applicative import Data.Foldable (foldMap)+import Numeric (showFFloat) -- Paths-import Paths_haskintex+import Paths_haskintex (version) import Data.Version (showVersion) -- Lists import Data.List (intersperse) -- GHC-import Language.Haskell.Interpreter+import Language.Haskell.Interpreter hiding (get)+import Data.Typeable+import qualified Language.Haskell.Exts.Pretty as H+import qualified Language.Haskell.Exts.Parser as H+-- Map+import qualified Data.Map as M+-- Binary+import Data.Binary.Put+import Data.Binary.Get hiding (lookAhead)+import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString.Lazy as LB+import qualified Data.ByteString as SB  -- Syntax @@ -56,58 +69,148 @@ -- data Syntax =     WriteLaTeX   Text-  | WriteHaskell Bool Bool Text -- First Bool: False for Hidden, True for Visible.-                                -- Second Bool: True for Header, False for Body.-  | InsertHaTeX  Text-  | InsertHaTeXIO Text-  | EvalHaskell  Bool Text -- False for Command, True for Environment+  | WriteHaskell Bool -- Visibility: False for Hidden, True for Visible+                 Bool -- Location: True for Header, False for Body+                 Text+  | InsertHaTeX  Bool -- Memorized expression?+                 Text+  | InsertHaTeXIO Bool -- Memorized expression?+                  Text+  | EvalHaskell  Bool -- Type: False for Command, True for Environment+                 Bool -- Memorized expression?+                 Text   | Sequence     [Syntax]     deriving Show -- Show instance for debugging. +-- Configuration++data Conf = Conf+  { keepFlag      :: Bool+  , visibleFlag   :: Bool+  , verboseFlag   :: Bool+  , manualFlag    :: Bool+  , helpFlag      :: Bool+  , lhs2texFlag   :: Bool+  , stdoutFlag    :: Bool+  , overwriteFlag :: Bool+  , debugFlag     :: Bool+  , memoFlag      :: Bool+  , memocleanFlag :: Bool+  , unknownFlags  :: [String]+  , inputs        :: [FilePath]+  , memoTree      :: MemoTree+    }++supportedFlags :: [(String,Conf -> Bool)]+supportedFlags =+  [ ("keep"      , keepFlag)+  , ("visible"   , visibleFlag)+  , ("verbose"   , verboseFlag)+  , ("manual"    , manualFlag)+  , ("help"      , helpFlag)+  , ("lhs2tex"   , lhs2texFlag)+  , ("stdout"    , stdoutFlag)+  , ("overwrite" , overwriteFlag)+  , ("debug"     , debugFlag)+  , ("memo"      , memoFlag)+  , ("memoclean" , memocleanFlag)+    ]++readConf :: [String] -> Conf+readConf = go $ Conf False False False False False False False False False False False [] [] M.empty+  where+    go c [] = c+    go c (x:xs) =+       case x of+        -- Arguments starting with '-' are considered a flag.+        ('-':flag) ->+           case flag of+             "keep"      -> go (c {keepFlag      = True}) xs+             "visible"   -> go (c {visibleFlag   = True}) xs+             "verbose"   -> go (c {verboseFlag   = True}) xs+             "manual"    -> go (c {manualFlag    = True}) xs+             "help"      -> go (c {helpFlag      = True}) xs+             "lhs2tex"   -> go (c {lhs2texFlag   = True}) xs+             "stdout"    -> go (c {stdoutFlag    = True}) xs+             "overwrite" -> go (c {overwriteFlag = True}) xs+             "debug"     -> go (c {debugFlag     = True}) xs+             "memo"      -> go (c {memoFlag      = True}) xs+             "memoclean" -> go (c {memocleanFlag = True}) xs+             _           -> go (c {unknownFlags = unknownFlags c ++ [flag]}) xs+        -- Otherwise, an input file.+        _ -> go (c {inputs = inputs c ++ [x]}) xs++-- Haskintex monad++type Haskintex = StateT Conf IO++outputStr :: String -> Haskintex ()+outputStr str = do+  b <- verboseFlag <$> get+  when b $ lift $ putStrLn str+ -- PARSING -parseSyntax :: Bool -> Parser Syntax-parseSyntax v = do-  s <- fmap Sequence $ many $ choice $ fmap try [ p_writehaskell v, p_inserthatex, p_inserthatexio , p_evalhaskell, p_writelatex ]+type Parser = ParsecT Text () Haskintex++parseSyntax :: Parser Syntax+parseSyntax = do+  s <- fmap Sequence $ many $ choice [ p_writehaskell, p_inserthatex False , p_inserthatex True , p_evalhaskell, p_writelatex ]   eof   return s -p_writehaskell :: Bool -> Parser Syntax-p_writehaskell v = do+p_writehaskell :: Parser Syntax+p_writehaskell = do   isH <- (try $ string "\\begin{writehaskell}" >> return False)-           <|> (string "\\begin{haskellpragmas}" >> return True)+           <|> (try $ string "\\begin{haskellpragmas}" >> return True)   b <- choice $ fmap try [ string "[hidden]"  >> return False                          , string "[visible]" >> return True-                         , return v ] -- When no option is given, take the default.+                         , lift $ visibleFlag <$> get ] -- When no option is given, take the default.   h <- manyTill anyChar $ try $ string $ if isH then "\\end{haskellpragmas}" else "\\end{writehaskell}"   return $ WriteHaskell b isH $ pack h -p_inserthatex :: Parser Syntax-p_inserthatex = do-  _ <- string "\\hatex{"-  h <- p_haskell 0-  return $ InsertHaTeX $ pack h+readMemo :: Parser Bool+readMemo = (char '[' *> choice xs <* char ']') <|> lift (memoFlag <$> get)+  where+    xs = [ string "memo" >> return True+         , string "notmemo" >> return False ] -p_inserthatexio :: Parser Syntax-p_inserthatexio = do-  _ <- string "\\iohatex{"+processExp :: Text -> Text+processExp t =+  case H.parseExp (unpack t) of+    H.ParseOk e -> pack $ H.prettyPrint e +    _ -> t++p_inserthatex :: Bool -- False for pure, True for IO+              -> Parser Syntax+p_inserthatex isIO = do+  --+  let iden = if isIO then "iohatex" else "hatex"+      cons = if isIO then InsertHaTeXIO else InsertHaTeX+  --+  _ <- try $ string $ '\\' : iden+  b <- readMemo+  _ <- char '{'   h <- p_haskell 0-  return $ InsertHaTeXIO $ pack h+  return $ cons b $ processExp $ pack h  p_evalhaskell :: Parser Syntax-p_evalhaskell = choice $ fmap try [ p_evalhaskellenv, p_evalhaskellcomm ]+p_evalhaskell = choice [ p_evalhaskellenv, p_evalhaskellcomm ]  p_evalhaskellenv :: Parser Syntax p_evalhaskellenv = do-  _ <- string "\\begin{evalhaskell}"+  _ <- try $ string "\\begin{evalhaskell}"+  b <- readMemo   h <- manyTill anyChar $ try $ string "\\end{evalhaskell}"-  return $ EvalHaskell True $ pack h+  return $ EvalHaskell True b $ processExp $ pack h  p_evalhaskellcomm :: Parser Syntax p_evalhaskellcomm = do-  _  <- string "\\evalhaskell{"+  _  <- try $ string "\\evalhaskell"+  b <- readMemo+  _ <- char '{'   h  <- p_haskell 0-  return $ EvalHaskell False $ pack h+  return $ EvalHaskell False b $ processExp $ pack h  p_haskell :: Int -> Parser String p_haskell n = choice [@@ -146,6 +249,146 @@              , return True              ] +----------------------------------------------------------+----------------------------------------------------------+-- MEMO TREE++-- | A 'MemoTree' maps each expression to its reduced form.+type MemoTree = M.Map Text Text++memoreduce :: Typeable t+           => String -- ^ Auxiliar module name+           -> Bool -- ^ Is this expression memorized?+           -> Text -- ^ Input+           -> t -- ^ Type+           -> (t -> Haskintex Text) -- ^ Rendering function+           -> Haskintex Text+memoreduce modName isMemo t ty f = do+  let e = unpack t+  outputStr $ "Evaluation (" ++ showsTypeRep (typeRep $ Just t) "" ++ "): " ++ e+  memt <- memoTree <$> get+  let p = if isMemo then M.lookup t memt else Nothing+  case p of+    Nothing -> do+      let int = do+             loadModules [modName]+             setTopLevelModules [modName]+             setImports ["Prelude"]+             interpret e ty+      r <- runInterpreter int+      case r of+        Left err -> do+          outputStr $ "Warning: Error while evaluating the expression.\n"+                   ++ errorString err+          return mempty+        Right x -> do+          -- Render result+          t' <- f x+          -- If the expression is marked to be memorized, store it in the 'MemoTree'.+          when isMemo $ do+            modify $ \st -> st { memoTree = M.insert t t' $ memoTree st }+            outputStr $ "-> Result has been memorized."+          -- Return result+          return t'+    Just o -> do+      outputStr "-> Result of the evaluation recovered from memo tree."+      return o++{- Memo Tree Format++A memo tree is stored as a list of (key,value) in key ascending order.+Keys and values are encoded in UTF-8.++| offset |   description        | size (in bytes) |+---------------------------------------------------+| 00     | Number of blocks     | 2               |+| 02     | Zero or more blocks  | variable        |++Each block has the following structure:++| offset |   description        | size (in bytes) |+---------------------------------------------------+| 00     | Length of key (k)    | 2               |+| 02     | Length of value (v)  | 2               |+| 04     | Key                  | k               |+| 04+k   | Value                | v               |++-}++memoTreeToBinary :: MemoTree -> ByteString+memoTreeToBinary memt = runPut $ do+  putWord16le $ fromIntegral $ M.size memt+  mapM_ (\(t,t') -> do+    let b  = encodeUtf8 t+        b' = encodeUtf8 t'+    putWord16le $ fromIntegral $ SB.length b+    putWord16le $ fromIntegral $ SB.length b'+    putByteString b+    putByteString b'+    ) $ M.toAscList memt++memoTreeFromBinary :: ByteString -> Either String MemoTree+memoTreeFromBinary b =+  case runGetOrFail getMemoTree b of+    Left (_,_,err) -> Left err+    Right (_,_,memt) -> Right memt++getMemoTree :: Get MemoTree+getMemoTree = do+  n <- fromIntegral <$> getWord16le+  fmap M.fromAscList $ replicateM n $ do+    l  <- getWord16le+    l' <- getWord16le+    b  <- getByteString $ fromIntegral l+    b' <- getByteString $ fromIntegral l'+    return (decodeUtf8 b, decodeUtf8 b')++memoTreeOpen :: Haskintex ()+memoTreeOpen = do+  d <- liftIO $ getAppUserDataDirectory "haskintex"+  let fp = d </> "memotree"+  b <- liftIO $ doesFileExist fp+  if b then do t <- liftIO $ LB.readFile fp+               case memoTreeFromBinary t of+                 Left err -> do+                   outputStr $ "Error: memotree failed to read: " ++ err+                   outputStr "-> Using empty memotree."+                   modify $ \st -> st { memoTree = M.empty }+                 Right memt -> do+                   modify $ \st -> st { memoTree = memt }+                   let n = LB.length t+                       kbs :: Double+                       kbs = fromIntegral n / 1024+                       s = if kbs < 1 then show n ++ " Bs"+                                      else showFFloat (Just 2) kbs " KBs"+                   outputStr $ "Info: memotree loaded (" ++ s ++ ")."+       else do outputStr "Info: memotree does not exist."+               outputStr "-> Using empty memotree."+               modify $ \st -> st { memoTree = M.empty }++memoTreeSave :: Haskintex ()+memoTreeSave = do+  memt <- memoTree <$> get+  unless (M.null memt) $ do+    outputStr "Saving memotree..."+    liftIO $ do+      d <- getAppUserDataDirectory "haskintex"+      createDirectoryIfMissing True d+      let fp = d </> "memotree"+      LB.writeFile fp $ memoTreeToBinary memt+    outputStr "Info: memotree saved."++memoTreeClean :: Haskintex ()+memoTreeClean = do+  d <- liftIO $ getAppUserDataDirectory "haskintex"+  let fp = d </> "memotree"+  b <- liftIO $ doesFileExist fp+  when b $ do +    liftIO $ removeFile fp+    outputStr "Info: memotree removed."++----------------------------------------------------------+ -- PASS 1: Extract code from processed Syntax.  extractCode :: Syntax -> (Text,Text)@@ -156,70 +399,57 @@ -- PASS 2: Evaluate Haskell expressions from processed Syntax.  evalCode :: String -- ^ Auxiliary module name-         -> Bool   -- ^ Is manual flag on?-         -> Bool   -- ^ Is lhs2tex flag on?          -> Syntax -> Haskintex Text-evalCode modName mFlag lhsFlag = go+evalCode modName = go   where     go (WriteLaTeX t) = return t-    go (WriteHaskell b _ t) =+    go (WriteHaskell b _ t) = do+         mFlag <- manualFlag <$> get+         lhsFlag <- lhs2texFlag <$> get          let f :: Text -> LaTeX              f x | not b = mempty                  | mFlag = raw x                  | lhsFlag = TeXEnv "code" [] $ raw x                  | otherwise = verbatim x-         in return $ render $ f t-    go (InsertHaTeX t) = do-         let e = unpack $ T.strip t-             int = do-               loadModules [modName]-               setTopLevelModules [modName]-               setImports ["Prelude"]-               interpret e (as :: LaTeX)-         outputStr $ "Evaluation (LaTeX): " ++ e-         r <- runInterpreter int-         case r of-           Left err -> do-             outputStr $ "Warning: Error while evaluating the expression.\n"-               ++ errorString err-             return mempty-           Right l -> return $ render l-    go (InsertHaTeXIO t) = do-         let e = unpack $ T.strip t-             int = do-               loadModules [modName]-               setTopLevelModules [modName]-               setImports ["Prelude"]-               interpret e (as :: IO LaTeX)-         outputStr $ "Evaluation (IO LaTeX): " ++ e-         r <- runInterpreter int-         case r of-           Left err -> do-             outputStr $ "Warning: Error while evaluating the expression.\n"-               ++ errorString err-             return mempty-           Right l -> liftIO $ render <$> l-    go (EvalHaskell env t) =+         return $ render $ f t+    go (InsertHaTeX   isMemo t) = memoreduce modName isMemo t (as ::    LaTeX) (return .      render)+    go (InsertHaTeXIO isMemo t) = memoreduce modName isMemo t (as :: IO LaTeX) (liftIO . fmap render)+    go (EvalHaskell env isMemo t) = do+         mFlag <- manualFlag <$> get+         lhsFlag <- lhs2texFlag <$> get          let f :: Text -> LaTeX              f x | mFlag = raw x -- Manual flag overrides lhs2tex flag behavior                  | env && lhsFlag = TeXEnv "code" [] $ raw x                  | lhsFlag = raw $ "|" <> x <> "|"                  | env = verbatim $ layout x                  | otherwise = verb x-         in (render . f . pack) <$> ghc modName t+         (render . f) <$> ghc modName isMemo t     go (Sequence xs) = mconcat <$> mapM go xs -ghc :: String -> Text -> Haskintex String-ghc modName e = do-  let e' = unpack $ T.strip e-  outputStr $ "Evaluation: " ++ e'-  lift $ init <$> readProcess "ghc" -     -- Disable reading of .ghci files.-     [ "-ignore-dot-ghci"-     -- Evaluation loading the temporal module.-     -- The expression is stripped.-     , "-e", e', modName ++ ".hs"-       ] []+ghc :: String -> Bool -> Text -> Haskintex Text+ghc modName isMemo t = do+  let e = unpack t+  outputStr $ "Evaluation: " ++ e+  memt <- memoTree <$> get+  let p = if isMemo then M.lookup t memt else Nothing+  case p of+    Nothing -> do+      -- Run GHC externally and read the result.+      r <- lift $ pack . init <$> readProcess "ghc" +                -- Disable reading of .ghci files.+                [ "-ignore-dot-ghci"+                -- Evaluation loading the temporal module.+                , "-e", e, modName ++ ".hs"+                  ] []+      -- If the expression is marked to be memorized, we do so.+      when isMemo $ do+         modify $ \st -> st { memoTree = M.insert t r $ memoTree st }+         outputStr "-> Result has been memorized."+      -- Return result+      return r+    Just o -> do+      outputStr "-> Result of the evaluation recovered from memo tree."+      return o  maxLineLength :: Int maxLineLength = 60@@ -243,78 +473,20 @@ errorString (NotAllowed e) = "Not allowed:" ++ e errorString (GhcException e) = "GHC exception: " ++ e --- Configuration--data Conf = Conf-  { keepFlag      :: Bool-  , visibleFlag   :: Bool-  , verboseFlag   :: Bool-  , manualFlag    :: Bool-  , helpFlag      :: Bool-  , lhs2texFlag   :: Bool-  , stdoutFlag    :: Bool-  , overwriteFlag :: Bool-  , debugFlag     :: Bool-  , unknownFlags  :: [String]-  , inputs        :: [FilePath]-    }--supportedFlags :: [(String,Conf -> Bool)]-supportedFlags =-  [ ("keep"      , keepFlag)-  , ("visible"   , visibleFlag)-  , ("verbose"   , verboseFlag)-  , ("manual"    , manualFlag)-  , ("help"      , helpFlag)-  , ("lhs2tex"   , lhs2texFlag)-  , ("stdout"    , stdoutFlag)-  , ("overwrite" , overwriteFlag)-  , ("debug"     , debugFlag)-    ]--readConf :: [String] -> Conf-readConf = go $ Conf False False False False False False False False False [] []-  where-    go c [] = c-    go c (x:xs) =-       case x of-        -- Arguments starting with '-' are considered a flag.-        ('-':flag) ->-           case flag of-             "keep"      -> go (c {keepFlag      = True}) xs-             "visible"   -> go (c {visibleFlag   = True}) xs-             "verbose"   -> go (c {verboseFlag   = True}) xs-             "manual"    -> go (c {manualFlag    = True}) xs-             "help"      -> go (c {helpFlag      = True}) xs-             "lhs2tex"   -> go (c {lhs2texFlag   = True}) xs-             "stdout"    -> go (c {stdoutFlag    = True}) xs-             "overwrite" -> go (c {overwriteFlag = True}) xs-             "debug"     -> go (c {debugFlag     = True}) xs-             _           -> go (c {unknownFlags = unknownFlags c ++ [flag]}) xs-        -- Otherwise, an input file.-        _ -> go (c {inputs = inputs c ++ [x]}) xs---- Haskintex--type Haskintex = ReaderT Conf IO--outputStr :: String -> Haskintex ()-outputStr str = do-  b <- verboseFlag <$> ask-  when b $ lift $ putStrLn str+-- Haskintex main function  -- | Run haskintex with the given arguments. For example: -- -- > haskintex ["-visible","-overwrite","foo.htex"] -- --   Useful if you want to call /haskintex/ from another program.---   This function does /not/ do any system call.+-- haskintex :: [String] -> IO ()-haskintex = runReaderT haskintexmain . readConf+haskintex = evalStateT haskintexmain . readConf  haskintexmain :: Haskintex () haskintexmain = do-  flags <- ask+  flags <- get   if -- If the help flag is passed, ignore everything else      -- and just print the help.      helpFlag flags@@ -322,14 +494,17 @@      else let xs = inputs flags           in  if null xs                  then lift $ putStr noFiles-                 else mapM_ haskintexFile xs+                 else do memoTreeOpen+                         mapM_ haskintexFile xs+                         willClean <- memocleanFlag <$> get+                         if willClean then memoTreeClean else memoTreeSave  commas :: [String] -> String commas = concat . intersperse ", "  showEnabledFlags :: Haskintex () showEnabledFlags = do-  c <- ask+  c <- get   outputStr $ "Enabled flags: "            ++ commas (foldr (\(str,f) xs -> if f c then str : xs else xs) [] supportedFlags)            ++ "."@@ -337,8 +512,8 @@ reportWarnings :: Haskintex () reportWarnings = do   -- Combination of manual and lhs2tex flags.-  manFlag <- manualFlag  <$> ask-  lhsFlag <- lhs2texFlag <$> ask+  manFlag <- manualFlag  <$> get+  lhsFlag <- lhs2texFlag <$> get   when (manFlag && lhsFlag) $     outputStr "Warning: lhs2tex flag is useless in presence of manual flag." @@ -352,20 +527,18 @@   -- Warnings   reportWarnings   -- Other unknown flags passed.-  uFlags <- unknownFlags <$> ask+  uFlags <- unknownFlags <$> get   unless (null uFlags) $     outputStr $ "Unsupported flags: " ++ commas uFlags ++ "."   -- File parsing.   outputStr $ "Reading " ++ fp ++ "..."-  vFlag <- visibleFlag <$> ask   t <- lift $ T.readFile fp-  -- case parseOnly (parseSyntax vFlag) t of-    -- Left err -> outputStr $ "Reading of " ++ fp ++ " failed: " ++ err-  case parse (parseSyntax vFlag) fp t of+  pres <- runParserT parseSyntax () fp t+  case pres of     Left err -> outputStr $ "Reading of " ++ fp ++ " failed:\n" ++ show err     Right s -> do       -- Zero pass: In case of debugging, write down the parsed AST.-      dbugFlag <- debugFlag <$> ask+      dbugFlag <- debugFlag <$> get       when dbugFlag $ do         let debugfp = dropExtension (takeFileName fp) ++ ".debughtex"         outputStr $ "Writing file " ++ debugfp ++ " with debugging output..."@@ -378,15 +551,13 @@       lift $ T.writeFile (modName ++ ".hs") $ hsH <> moduleHeader <> hs       -- Second pass: Evaluate expressions using 'evalCode'.       outputStr $ "Evaluating expressions in " ++ fp ++ "..."-      mFlag <- manualFlag <$> ask-      lhsFlag <- lhs2texFlag <$> ask-      l <- evalCode modName mFlag lhsFlag s+      l <- evalCode modName s       -- Write final output.       let fp' = dropExtension (takeFileName fp) ++ ".tex"           writeit = do outputStr $ "Writing final file at " ++ fp' ++ "..."                        lift $ T.writeFile fp' l-      outFlag <- stdoutFlag <$> ask-      overFlag <- overwriteFlag <$> ask+      outFlag <- stdoutFlag <$> get+      overFlag <- overwriteFlag <$> get       nonew <- lift $ doesFileExist fp'       let finalOutput            | outFlag = do outputStr "Sending final output to stdout..."@@ -402,7 +573,7 @@            | otherwise = writeit       finalOutput       -- If the keep flag is not set, remove the haskell source file.-      kFlag <- keepFlag <$> ask+      kFlag <- keepFlag <$> get       unless kFlag $ do         outputStr $ "Removing Haskell source file " ++ modName ++ ".hs "                   ++ "(use -keep to avoid this)..."@@ -417,6 +588,8 @@     "You are using haskintex version " ++ showVersion version ++ "."   , "http://daniel-diaz.github.io/projects/haskintex"   , ""+  , "The underlying HaTeX version is " ++ showVersion Hatex.version ++ "."+  , ""   , "Usage and flags:"   , "Any argument passed to haskintex that starts with '-' will be considered"   , "a flag. Otherwise, it will be considered an input file. Every input file"@@ -456,6 +629,13 @@   , "  -debug      Only for debugging purposes. It writes a file with extension"   , "              .debughtex with the AST of the internal representation of the"   , "              input file haskintex uses."+  , ""+  , "  -memo       Unless otherwise specified, every evalhaskell, hatex or iohatex"+  , "              command (or environment) will be called with the memo option."+  , ""+  , "  -memoclean  Cleans the memo tree after the execution of haskintex. If "+  , "              several files are processed, the memo tree will be cleaned"+  , "              after processing all of them."   , ""   , "Any unsupported flag will be ignored."   ]
haskintex.cabal view
@@ -1,5 +1,5 @@ name:                haskintex-version:             0.4.1.0+version:             0.5.0.0 synopsis:            Haskell Evaluation inside of LaTeX code. description:   The /haskintex/ (Haskell in LaTeX) program is a tool that reads a LaTeX file and evaluates Haskell expressions contained@@ -37,14 +37,19 @@  library   default-language: Haskell2010-  build-depends: base == 4.*+  build-depends: base >= 4.7 && < 5                , transformers == 0.3.*                , text >= 0.11.2.3 && < 2-               , directory >= 1.2.0.0 && < 1.3-               , filepath >= 1.1.0.0 && < 1.4-               , process-               , HaTeX >= 3.9.0.0 && < 4-               , parsec >= 3.1.2 && < 3.2-               , hint >= 0.3.3.5 && < 0.5+               , bytestring >= 0.10.4+               , directory >= 1.2.0 && < 1.3+               , filepath >= 1.1.0 && < 1.4+               , process >= 1.2.0+               , HaTeX >= 3.9.0.0+               , parsec >= 3.1.2+               , hint >= 0.3.3 && < 0.5+               , containers >= 0.5.5+               , binary >= 0.7.1+               , haskell-src-exts >= 1.15.0   exposed-modules: Haskintex   other-modules: Paths_haskintex+  ghc-options: -Wall