texbuilder-0.1.0.1: TexBuilder/ChooseEngine.hs
{-# LANGUAGE LambdaCase #-}
module TexBuilder.ChooseEngine
( chooseEngine
, readUseEngine
, showUseEngine
, UseEngine(..)
, UseLatexMk(..) )
where
import TexBuilder.Utils.File
import TexBuilder.Engine
import qualified Text.PrettyPrint.ANSI.Leijen as PP
import Control.Applicative
import Control.Monad
import Control.Monad.Extra
import System.Exit
import Data.Monoid
data UseEngine =
UseLuaLaTex
| UsePdfLaTex
| UseXeLaTex
deriving (Enum,Bounded)
readUseEngine :: String -> Maybe UseEngine
readUseEngine s
| s == "lualatex" = Just UseLuaLaTex
| s == "xelatex" = Just UseXeLaTex
| s == "pdflatex" = Just UsePdfLaTex
| otherwise = Nothing
showUseEngine :: UseEngine -> String
showUseEngine = enginePath
data UseLatexMk = UseLatexMk | UseNoLatexMk
chooseEngine :: UseEngine -> UseLatexMk -> IO Engine
chooseEngine useEngine useLatexmk = do
engine <- chooseLatexEngine useEngine
texmk <- chooseLatexMk useLatexmk
pure $ case (engine,texmk) of
(UseLuaLaTex,UseLatexMk) -> LuaLaTexMk
(UseLuaLaTex,UseNoLatexMk) -> LuaLaTex
(UsePdfLaTex,UseLatexMk) -> PdfLaTexMk
(UsePdfLaTex,UseNoLatexMk) -> PdfLaTex
(UseXeLaTex,UseLatexMk) -> XeLaTexMk
(UseXeLaTex,UseNoLatexMk) -> XeLaTex
chooseLatexEngine :: UseEngine -> IO UseEngine
chooseLatexEngine = fallback . \case
UseLuaLaTex -> UseLuaLaTex : [UsePdfLaTex,UseXeLaTex]
UsePdfLaTex -> UsePdfLaTex : [UseXeLaTex,UseLuaLaTex]
UseXeLaTex -> UseXeLaTex : [UsePdfLaTex,UseLuaLaTex]
where
numEngines = fromEnum ( maxBound :: UseEngine )
chooseLatexMk :: UseLatexMk -> IO UseLatexMk
chooseLatexMk = \case
UseLatexMk -> useMk
UseNoLatexMk -> pure UseNoLatexMk
haveMk :: IO Bool
haveMk = haveExe "latexmk"
useMk :: IO UseLatexMk
useMk = ifM haveMk (pure UseLatexMk) $ do
warn "No latexmk in PATH, using engine directly."
pure UseNoLatexMk
enginePath :: UseEngine -> FilePath
enginePath = \case
UseLuaLaTex -> "lualatex"
UsePdfLaTex -> "pdflatex"
UseXeLaTex -> "xelatex"
haveEngine :: UseEngine -> IO Bool
haveEngine = haveExe . enginePath
fallback :: [UseEngine] -> IO UseEngine
fallback = \case
[] -> errorNoEngine
useEng:useEngines ->
ifM (haveEngine useEng) (pure useEng) $ do
warn (enginePath useEng <> " not in PATH.")
warnFallback useEngines
fallback useEngines
where
warnFallback [] = pure ()
warnFallback (useEng:_) =
warn ("Falling back to " <> enginePath useEng <> ".")
warn :: String -> IO ()
warn s = PP.putDoc . PP.yellow
$ PP.string s <> PP.hardline
errorNoEngine = do
PP.putDoc . PP.red
$ PP.string "No latex engine found!"
exitWith $ ExitFailure 2