haskintex 0.7.0.1 → 0.8.0.3
raw patch · 7 files changed
Files
- Haskintex.hs +137/−27
- LICENSE +1/−1
- README.md +0/−10
- Setup.hs +0/−2
- changelog.md +8/−0
- haskintex.cabal +9/−20
- readme.md +7/−0
Haskintex.hs view
@@ -4,7 +4,7 @@ module Haskintex (haskintex) where -- System-import System.Process (readProcess)+import System.Process (readProcess, readCreateProcess, shell) import System.FilePath import System.Directory import System.IO (hFlush,stdout)@@ -36,7 +36,7 @@ -- Lists import Data.List (intersperse, isSuffixOf) -- GHC-import Language.Haskell.Interpreter hiding (get)+import Language.Haskell.Interpreter hiding (get, modName) import Language.Haskell.Interpreter.Unsafe (unsafeRunInterpreterWithArgs) import Data.Typeable import qualified Language.Haskell.Exts.Pretty as H@@ -88,6 +88,28 @@ -- Configuration +-- | Possible sources of package DBs. The value of the type is constructed from+-- CLI argument and tells haskintex which strategy to use for package DB selection.+--+-- If no CLI argument is presented, haskintex tries to guess from local environment+-- which package DB to use.+data PackageDB =+ CabalSandboxDB -- ^ Pick package-db from `.cabal-sandbox` folder+ | StackDB -- ^ Pick package-db from `stack path`+ deriving Show++-- | True if the input value is cabal sandbox package-db+isCabalSandboxDB :: PackageDB -> Bool+isCabalSandboxDB v = case v of+ CabalSandboxDB -> True+ _ -> False++-- | True if the input value is stack package-db+isStackDB :: PackageDB -> Bool+isStackDB v = case v of+ StackDB -> True+ _ -> False+ data Conf = Conf { keepFlag :: Bool , visibleFlag :: Bool@@ -102,6 +124,8 @@ , memocleanFlag :: Bool , autotexyFlag :: Bool , nosandboxFlag :: Bool+ , packageDb :: Maybe PackageDB+ , werrorFlag :: Bool , unknownFlags :: [String] , inputs :: [FilePath] , memoTree :: MemoTree@@ -122,10 +146,13 @@ , ("memoclean" , memocleanFlag) , ("autotexy" , autotexyFlag) , ("nosandbox" , nosandboxFlag)+ , ("cabaldb" , maybe False isCabalSandboxDB . packageDb)+ , ("stackdb" , maybe False isStackDB . packageDb)+ , ("werror" , werrorFlag) ] readConf :: [String] -> Conf-readConf = go $ Conf False False False False False False False False False False False False False [] [] M.empty+readConf = go $ Conf False False False False False False False False False False False False False Nothing False [] [] M.empty where go c [] = c go c (x:xs) =@@ -146,6 +173,9 @@ "memoclean" -> go (c {memocleanFlag = True}) xs "autotexy" -> go (c {autotexyFlag = True}) xs "nosandbox" -> go (c {nosandboxFlag = True}) xs+ "cabaldb" -> go (c {packageDb = Just CabalSandboxDB}) xs+ "stackdb" -> go (c {packageDb = Just StackDB}) xs+ "werror" -> go (c {werrorFlag = True}) xs _ -> go (c {unknownFlags = unknownFlags c ++ [flag]}) xs -- Otherwise, an input file. _ -> go (c {inputs = inputs c ++ [x]}) xs@@ -207,7 +237,7 @@ auto <- lift $ autotexyFlag <$> get let v = H.Var () . H.UnQual () . H.Ident () f = if auto then H.App () $ if isIO then H.App () (v "fmap") (v "texy")- else v "texy" + else v "texy" else id cons b <$> processExp f (pack h) @@ -273,6 +303,84 @@ -- | A 'MemoTree' maps each expression to its reduced form. type MemoTree = M.Map Text Text +-- | Search in current directory and all parents dirs for given file.+-- Return 'True' if found such file, 'False' either way. Search is performed+-- until root folder is not hit.+doesFileExistsUp :: FilePath -> IO Bool+doesFileExistsUp fname = do+ parents <- getAllParents <$> getCurrentDirectory+ checks <- mapM (doesFileExist . (</> fname)) parents+ pure $ or checks++-- | Generate list of all parents of the given path including the path itself.+getAllParents :: FilePath -> [FilePath]+getAllParents = go . reverse . splitDirectories+ where+ go [] = []+ go segs = let+ parent = joinPath $ reverse segs+ in parent : go (drop 1 segs)++-- | Try to detect cabal sandbox or stack project and get pathes to package DBs.+--+-- If ambigous situation is presented (both stack and cabal sandbox is found),+-- then fail with descriptive message.+autoDetectSandbox :: Haskintex (Maybe [String])+autoDetectSandbox = do+ noSandbox <- nosandboxFlag <$> get+ if noSandbox+ then do+ outputStr "Ignoring sandbox."+ pure Nothing+ else do inSandbox <- lift $ doesDirectoryExist ".cabal-sandbox"+ hasStackFile <- lift $ doesFileExistsUp "stack.yaml"+ case (inSandbox, hasStackFile) of+ (True, False) -> do+ outputStr "Detected cabal sandbox."+ loadCabalSandboxDBPaths+ (False, True) -> do+ outputStr "Detected stack sandbox."+ loadStackDBPaths+ (True, True) -> fail $ "Found both cabal sandbox and stack project. Please, specify which package DB to use with either "+ ++ " '-cabaldb' or '-stackdb' flags."+ (False, False) -> do+ outputStr "No sandbox or stack project detected."+ pure Nothing++-- | Generate CLI arguments for GHC for package DB using cabal sandbox+loadCabalSandboxDBPaths :: Haskintex (Maybe [String])+loadCabalSandboxDBPaths = do+ outputStr "Using cabal sandbox for package db"+ sand <- lift $ getDirectoryContents ".cabal-sandbox"+ let pkgdbs = filter (isSuffixOf "packages.conf.d") sand+ case pkgdbs of+ pkgdb : _ -> do+ outputStr $ "Using sandbox package db: " ++ pkgdb+ pure . Just $ [".cabal-sandbox/" ++ pkgdb]+ _ -> do+ outputStr "Don't use sandbox. Empty .cabal-sandbox"+ pure Nothing++-- | Generate CLI arguments for GHC for package DB using stack environment+loadStackDBPaths :: Haskintex (Maybe [String])+loadStackDBPaths = do+ outputStr "Using stack environment for package db"+ let getDBPath s = fmap (filter (/= '\n')) . lift $ readCreateProcess (shell $ "stack path --" ++ s) ""+ pkgdbSnapshot <- getDBPath "snapshot-pkg-db"+ pkgdbGlobal <- getDBPath "global-pkg-db"+ pkgdbLocal <- getDBPath "local-pkg-db"+ outputStr $ "Using sandbox package db: \n" ++ unlines [pkgdbSnapshot, pkgdbGlobal, pkgdbLocal]+ pure . Just $ [pkgdbSnapshot, pkgdbGlobal, pkgdbLocal]++-- | Try to detect cabal sandbox and use stack's ones if user specifies the 'stackdb' flag.+getSandbox :: Haskintex (Maybe [String])+getSandbox = do+ pkgDbConf <- packageDb <$> get+ case pkgDbConf of+ Nothing -> autoDetectSandbox+ Just CabalSandboxDB -> loadCabalSandboxDBPaths+ Just StackDB -> loadStackDBPaths+ memoreduce :: Typeable t => String -- ^ Auxiliar module name -> Bool -- ^ Is this expression memorized?@@ -292,26 +400,16 @@ setTopLevelModules [modName] setImports ["Prelude"] interpret e ty- -- Sandbox recognition- inSandbox <- lift $ doesDirectoryExist ".cabal-sandbox"- r <- if inSandbox- then do outputStr "Sandbox detected."- noSandbox <- nosandboxFlag <$> get- if noSandbox- then do outputStr "Ignoring sandbox."- runInterpreter int- else do sand <- lift $ getDirectoryContents ".cabal-sandbox"- let pkgdbs = filter (isSuffixOf "packages.conf.d") sand- case pkgdbs of- pkgdb : _ -> do- outputStr $ "Using sandbox package db: " ++ pkgdb- unsafeRunInterpreterWithArgs ["-package-db .cabal-sandbox/" ++ pkgdb] int- _ -> runInterpreter int- else runInterpreter int+ -- Sandbox recognition and executing interpreter+ r <- maybe (runInterpreter int) (\pkgdbs -> unsafeRunInterpreterWithArgs (("-package-db " ++) <$> pkgdbs) int) =<< getSandbox case r of Left err -> do- outputStr $ "Warning: Error while evaluating the expression.\n"+ shouldFail <- werrorFlag <$> get+ if shouldFail+ then fail $ "Error: failed while evaluating the expression: \n" ++ errorString err+ else outputStr $ "Warning: Error while evaluating the expression.\n"+ ++ errorString err return mempty Right x -> do -- Render result@@ -415,7 +513,7 @@ d <- liftIO $ getAppUserDataDirectory "haskintex" let fp = d </> "memotree" b <- liftIO $ doesFileExist fp- when b $ do + when b $ do liftIO $ removeFile fp outputStr "Info: memotree removed." @@ -466,13 +564,21 @@ let p = if isMemo then M.lookup t memt else Nothing case p of Nothing -> do+ useStack <- fmap (maybe False isStackDB . packageDb) get -- Run GHC externally and read the result.- r <- lift $ pack . init <$> readProcess "ghc" + r <- if useStack+ then lift $ pack . init <$> readProcess "stack" -- Disable reading of .ghci files.- [ "-ignore-dot-ghci"+ ["ghc", "--", "-ignore-dot-ghci", -- Evaluation loading the temporal module.- , "-e", e, modName ++ ".hs"- ] []+ modName ++ ".hs"+ , "-e", e ] []+ else lift $ pack . init <$> readProcess "ghc"+ -- Disable reading of .ghci files.+ ["-ignore-dot-ghci", + -- Evaluation loading the temporal module.+ modName ++ ".hs"+ , "-e", e ] [] -- If the expression is marked to be memorized, we do so. when isMemo $ do modify $ \st -> st { memoTree = M.insert t r $ memoTree st }@@ -674,7 +780,11 @@ , " expressions in types other than LaTeX and have haskintex to perform" , " the required transformation." , ""- , " -nosandbox Do not use the sandbox package db even in the presence of one."+ , " -nosandbox Do not use a sandbox package db even in the presence of one."+ , ""+ , " -cabaldb Use local cabal sandbox."+ , ""+ , " -stackdb Use local stackage db." , "" , "Any unsupported flag will be ignored." ]
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2013, Daniel Díaz+Copyright (c) 2017, Daniel Díaz All rights reserved.
− README.md
@@ -1,10 +0,0 @@-# 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
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
+ changelog.md view
@@ -0,0 +1,8 @@+## 0.8.0.3+* Metadata update.+* Increase upper-bound on filepath to `< 1.6`.+* Drop GitLab CI.++## 0.8.0.2+* Metadata update.+* Allow more recent versions of `text`.
haskintex.cabal view
@@ -1,32 +1,21 @@ name: haskintex-version: 0.7.0.1+version: 0.8.0.3 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 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.+ extension and, in summary, anything you can do within Haskell. Additionally, it is possible to include expressions of 'LaTeX' type (see /HaTeX/ package) and render them as LaTeX code. 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.- .- Additions from last version:- .- * /haskintex/ is now able to detect that is running on a cabal sandbox, and will use the sandbox package- db if this is the case. Unless the flag @-nosandbox@ is given, in which case the sandbox will be ignored.- .- * New flag @-nosandbox@. Ignore sandbox if /haskintex/ runs on one.- .-homepage: http://daniel-diaz.github.io/projects/haskintex-bug-reports: https://github.com/Daniel-Diaz/haskintex/issues+bug-reports: https://codeberg.org/daniel-casanueva/haskintex/issues license: BSD3 license-file: LICENSE-author: Daniel Díaz-maintainer: dhelta.diaz@gmail.com+maintainer: Daniel Casanueva (coding `at` danielcasanueva.eu) category: LaTeX build-type: Simple-extra-source-files: README.md- -- examples- examples/fact.htex+extra-doc-files: readme.md, changelog.md+extra-source-files: examples/fact.htex examples/hatex.htex examples/sine.htex examples/io.htex@@ -34,7 +23,7 @@ examples/string.htex examples/threaded.htex examples/memo.htex-cabal-version: >=1.10+cabal-version: 1.18 executable haskintex hs-source-dirs: main@@ -48,10 +37,10 @@ default-language: Haskell2010 build-depends: base >= 4.7 && < 5 , transformers >= 0.3.0.0- , text >= 0.11.2.3 && < 2+ , text >= 0.11.2.3 , bytestring >= 0.10.4 , directory >= 1.2.0 && < 1.4- , filepath >= 1.1.0 && < 1.5+ , filepath >= 1.1.0 && < 1.6 , process >= 1.2.0 , HaTeX >= 3.9.0.0 , parsec >= 3.1.2
+ readme.md view
@@ -0,0 +1,7 @@+# 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.