As a practice for interacting with system commands, I wrote a Haskell program that compiles a .tex file specified by the argument.
When one execute this program:
- If no argument is specified, print
"Specify a file!"
then exit - If the specified file does not exist, print
"File not found."
then exit - If the specified file does not have the extension
.tex
, then print"Not a .tex file!"
then exit - If a
.tex
file is specified (report.tex
), execute the following commands$ uplatex report.tex -o report.dvi
$ dvipdfmx report.dvi
$ rm report.dvi
- The program does not have to handle errors in the execution of tex-related commands.
This is what I wrote:
import qualified Control.Shell as S
import Data.Char (toLower)
import Data.List (dropWhileEnd)
import qualified System.Environment as E
main = do
args <- E.getArgs
case args of
[] -> putStrLn "Specify a file!"
(filename:_) -> handler filename
isTeXFile :: S.FilePath -> Bool
isTeXFile = ( == ".tex") . map toLower . S.takeExtension
handler :: S.FilePath -> IO ()
handler f = do
(Right isfile) <- S.shell $ S.isFile f
if not isfile
then putStrLn "File not found."
else
if isTeXFile f
then do
result <- compile f
case result of
(Left l) -> putStrLn l
(Right _) -> return ()
else
putStrLn "Not a .tex file!"
compile :: S.FilePath -> IO (Either String ())
compile f = S.shell $ do
S.run_ "uplatex" [f, "-o", dvifile] ""
S.run_ "dvipdfmx" [dvifile] ""
S.rm dvifile
where
basename = dropWhileEnd (/= '.') f
dvifile = basename ++ "dvi"
I appreciate any kind of feedback. I'm especially concerned about:
- The body of
handler
seems unnecessarily complicated. How can I clean it up? - Am I using
Control.Shell
in the right way? Is there other function I should use instead? Maybe I should consider usingSystem.Process
?
Side note: I don't use pdflatex because it is not as good as uplatex at Japanese typesetting and I haven't been catching up with the latest LaTeX families.