packages feed

haskintex (empty) → 0.1.0.0

raw patch · 6 files changed

+278/−0 lines, 6 filesdep +HaTeXdep +attoparsecdep +basesetup-changed

Dependencies added: HaTeX, attoparsec, base, directory, filepath, process, text, transformers

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2013, Daniel Díaz++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Daniel Díaz nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Main.hs view
@@ -0,0 +1,188 @@++{-# LANGUAGE OverloadedStrings #-}++module Main (main) where++-- System+import System.Process+import System.Environment (getArgs)+import System.FilePath+import System.Directory+-- Text+import Data.Text (pack,unpack)+import qualified Data.Text as T+import qualified Data.Text.IO as T+-- Parser+import Data.Attoparsec.Text+-- Transformers+import Control.Monad (when,unless)+import Control.Monad.Trans.Class+import Control.Monad.Trans.Reader+-- LaTeX+import Text.LaTeX+-- Utils+import Control.Applicative+import Data.Foldable (foldMap)++-- Syntax++data Syntax =+    WriteLaTeX   Text+  | WriteHaskell Bool Text -- False for Hidden, True for Visible+  | EvalHaskell  Bool Text -- False for Command, True for Environment+  | Sequence     [Syntax]++-- Parsing++parseSyntax :: Bool -> Parser Syntax+parseSyntax v = fmap Sequence $ many $ choice [ p_writehaskell v, p_evalhaskell, p_writelatex ]++p_writehaskell :: Bool -> Parser Syntax+p_writehaskell v = do+  _ <- string "\\begin{writehaskell}"+  b <- choice [ string "[hidden]"  >> return False+              , string "[visible]" >> return True+              , return v ]+  h <- manyTill anyChar $ try $ string "\\end{writehaskell}"+  return $ WriteHaskell b $ pack h++p_evalhaskell :: Parser Syntax+p_evalhaskell = choice [ p_evalhaskellenv, p_evalhaskellcomm ]++p_evalhaskellenv :: Parser Syntax+p_evalhaskellenv = do+  _ <- string "\\begin{evalhaskell}"+  h <- manyTill anyChar $ try $ string "\\end{evalhaskell}"+  return $ EvalHaskell True $ pack h++p_evalhaskellcomm :: Parser Syntax+p_evalhaskellcomm = do+  _ <- string "\\evalhaskell{"+  h <- manyTill anyChar $ char '}'+  return $ EvalHaskell False $ pack h++p_writelatex :: Parser Syntax+p_writelatex = (WriteLaTeX . pack) <$>+  many1 (p_other >>= \b -> if b then anyChar else fail "stop write latex")+  where+    p_other =+      choice [ string "\\begin{writehaskell}" >> return False+             , string "\\begin{evalhaskell}"  >> return False+             , string "\\evalhaskell"         >> return False+             , return True+             ]++-- PASS 1: Extract code from processed Syntax.++extractCode :: Syntax -> Text+extractCode (WriteHaskell _ t) = t+extractCode (Sequence xs) = foldMap extractCode xs+extractCode _ = mempty++-- PASS 2: Evaluate Haskell expressions from processed Syntax.++evalCode :: String -> Syntax -> Haskintex Text+evalCode modName = go+  where+    go (WriteLaTeX t) = return t+    go (WriteHaskell b t) =+         return $ if b then render (verbatim t :: LaTeX)+                       else mempty+    go (EvalHaskell b t) =+         let f :: Text -> LaTeX+             f = if b then verbatim . layout else verb+         in (render . f . pack) <$> ghc modName 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" [ "-e", e', modName ++ ".hs" ] []++maxLineLength :: Int+maxLineLength = 60++-- | Break lines longer than 'maxLineLenght'.+layout :: Text -> Text+layout = T.unlines . go . T.lines+  where+    go [] = []+    go (t:ts) =+      if T.length t > maxLineLength+         then let (l,r) = T.splitAt maxLineLength t+              in  l : go (r:ts)+         else t : go ts++-- Configuration++data Conf = Conf+  { keepFlag :: Bool+  , visibleFlag :: Bool+  , verboseFlag :: Bool+  , inputs :: [FilePath]+    }++isArg :: String -> Bool+isArg [] = False+isArg (x:_) = x == '-'++readConf :: [String] -> Conf+readConf xs =+  Conf ("-keep" `elem` xs)+       ("-visible" `elem` xs)+       ("-verbose" `elem` xs)+       (filter (not . isArg) xs)++-- Haskintex++type Haskintex = ReaderT Conf IO++outputStr :: String -> Haskintex ()+outputStr str = do+  b <- verboseFlag <$> ask+  when b $ lift $ putStrLn str++-- MAIN++main :: IO ()+main = (readConf <$> getArgs) >>= runReaderT haskintex++haskintex :: Haskintex ()+haskintex = ask >>= mapM_ haskintexFile . inputs++haskintexFile :: FilePath -> Haskintex ()+haskintexFile fp_ = do+  -- If the given file does not exist, try adding '.tex'.+  b <- lift $ doesFileExist fp_+  let fp = if b then fp_ else fp_ ++ ".tex"+  -- Read visible flag. It will be required in the file parsing.+  vFlag <- visibleFlag <$> ask+  outputStr $ "Visible flag: " ++ (if vFlag then "enabled" else "disabled") ++ "."+  -- File parsing.+  outputStr $ "Reading " ++ fp ++ "..."+  t <- lift $ T.readFile fp+  case parseOnly (parseSyntax vFlag) t of+    Left err -> outputStr $ "Reading of " ++ fp ++ " failed: " ++ err+    Right s -> do+      -- First pass: Create haskell source from the code obtained with 'extractCode'.+      let modName = ("Haskintex_" ++) $ dropExtension $ takeFileName fp+      outputStr $ "Creating Haskell source file " ++ modName ++ ".hs..."+      let hs = extractCode s+          moduleHeader = pack $ "module " ++ modName ++ " where\n\n"+      lift $ T.writeFile (modName ++ ".hs") $ moduleHeader <> hs+      -- Second pass: Evaluate expressions using 'evalCode'.+      outputStr $ "Evaluating expressions in " ++ fp ++ "..."+      l <- evalCode modName s+      let fp' = "haskintex_" ++ fp+      -- Write final output.+      outputStr $ "Writing final file at " ++ fp' ++ "..."+      lift $ T.writeFile fp' l+      -- If the keep flag is not set, remove the haskell source file.+      kFlag <- keepFlag <$> ask+      unless kFlag $ do+        outputStr $ "Removing Haskell source file " ++ modName ++ ".hs "+                  ++ "(use -keep to avoid this)..."+        lift $ removeFile $ modName ++ ".hs"+      -- End.+      outputStr $ "End of processing of file " ++ fp ++ "."
+ README.md view
@@ -0,0 +1,10 @@+# The *haskintex* program++The *haskintex* program is a tool that reads a LaTeX file and evaluates Haskell expressions contained+in some specific commands and environments. It allows you to define your own functions, use any GHC Haskell language+extension and, in brief, anything you can do within Haskell. You can freely add any Haskell code you need, and make+this code appear *optionally* in the LaTeX output. It is a tiny program, and therefore, easy to understand, use and+predict.++For more details, read the+[homepage of the project](http://daniel-diaz.github.io/projects/haskintex).
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ examples/fact.tex view
@@ -0,0 +1,14 @@+\documentclass{article}+\begin{document}++Recursive definition of the factorial function in Haskell.++\begin{writehaskell}[visible]+fact :: Int -> Int+fact 0 = 1+fact n = n * fact (n-1)+\end{writehaskell}++The factorial function grows really fast. While 5 factorial is+\evalhaskell{fact 5}, 10 factorial is \evalhaskell{fact 10}.+\end{document}
+ haskintex.cabal view
@@ -0,0 +1,34 @@+name:                haskintex+version:             0.1.0.0+synopsis:            Haskell Evaluation inside of LaTeX code.+description:+  The /haskintex/ program is a tool that reads a LaTeX file and evaluates Haskell expressions contained+  in some specific commands and environments. It allows you to define your own functions, use any GHC Haskell language+  extension and, in brief, anything you can do within Haskell. You can freely add any Haskell code you need, and make+  this code appear /optionally/ in the LaTeX output. It is a tiny program, and therefore, easy to understand, use and+  predict.+homepage:            http://daniel-diaz.github.io/projects/haskintex+bug-reports:         https://github.com/Daniel-Diaz/haskintex/issues+license:             BSD3+license-file:        LICENSE+author:              Daniel Díaz+maintainer:          dhelta.diaz@gmail.com+category:            LaTeX+build-type:          Simple+extra-source-files:  README.md+                     -- examples+                     examples/fact.tex+cabal-version:       >=1.10++executable haskintex+  main-is:             Main.hs+  build-depends:       base >= 4.6 && < 4.7+               ,       transformers == 0.3.*+               ,       text >= 0.11.2.3 && < 0.12+               ,       directory >= 1.2.0.0 && < 1.3+               ,       filepath >= 1.1.0.0 && < 1.4+               ,       process >= 1.1.0.2 && < 1.2+               ,       HaTeX >= 3.6 && < 3.9+               ,       attoparsec >= 0.10.2.0 && < 0.11+  default-language:    Haskell2010+  ghc-options: -Wall