From 418bd42df85b93016e50ba48042804e8f51341b5 Mon Sep 17 00:00:00 2001 From: Albert Krewinkel Date: Sat, 3 Nov 2018 07:33:04 +0100 Subject: App: extract output settings into module --- src/Text/Pandoc/App.hs | 229 +++------------------ src/Text/Pandoc/App/CommandLineOptions.hs | 5 +- src/Text/Pandoc/App/OutputSettings.hs | 317 ++++++++++++++++++++++++++++++ 3 files changed, 347 insertions(+), 204 deletions(-) create mode 100644 src/Text/Pandoc/App/OutputSettings.hs (limited to 'src/Text') diff --git a/src/Text/Pandoc/App.hs b/src/Text/Pandoc/App.hs index cf4c9173d..173c60a56 100644 --- a/src/Text/Pandoc/App.hs +++ b/src/Text/Pandoc/App.hs @@ -1,7 +1,6 @@ {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE CPP #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TupleSections #-} {- Copyright (C) 2006-2018 John MacFarlane @@ -44,12 +43,10 @@ module Text.Pandoc.App ( import Prelude import qualified Control.Exception as E import Control.Monad -import Control.Monad.Except (catchError, throwError) import Control.Monad.Trans import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as B import Data.Char (toLower) -import Data.List (find, isPrefixOf, isSuffixOf) import Data.Maybe (fromMaybe, isJust, isNothing) import qualified Data.Set as Set import Data.Text (Text) @@ -59,8 +56,6 @@ import qualified Data.Text.Lazy.Encoding as TE import qualified Data.Text.Encoding.Error as TE import qualified Data.YAML as YAML import Network.URI (URI (..), parseURI) -import Skylighting (defaultSyntaxMap) -import Skylighting.Parser (addSyntaxDefinition, parseSyntaxDefinition) import System.Directory (getAppUserDataDirectory) import System.Exit (exitSuccess) import System.FilePath @@ -68,7 +63,8 @@ import System.IO (nativeNewline, stdout) import qualified System.IO as IO (Newline (..)) import Text.Pandoc import Text.Pandoc.App.CommandLineOptions (Opt (..), LineEnding (..), - defaultOpts, engines, parseOptions, options) + defaultOpts, parseOptions, options) +import Text.Pandoc.App.OutputSettings (OutputSettings (..), optToOutputSettings) import Text.Pandoc.BCP47 (Lang (..), parseBCP47) import Text.Pandoc.Builder (setMeta, deleteMeta) import Text.Pandoc.Filter (Filter (JSONFilter, LuaFilter), applyFilters) @@ -83,41 +79,6 @@ import System.Posix.IO (stdOutput) import System.Posix.Terminal (queryTerminal) #endif -pdfIsNoWriterErrorMsg :: String -pdfIsNoWriterErrorMsg = - "To create a pdf using pandoc, use " ++ - "-t latex|beamer|context|ms|html5" ++ - "\nand specify an output file with " ++ - ".pdf extension (-o filename.pdf)." - -pdfWriterAndProg :: Maybe String -- ^ user-specified writer name - -> Maybe String -- ^ user-specified pdf-engine - -> IO (String, Maybe String) -- ^ IO (writerName, maybePdfEngineProg) -pdfWriterAndProg mWriter mEngine = do - let panErr msg = liftIO $ E.throwIO $ PandocAppError msg - case go mWriter mEngine of - Right (writ, prog) -> return (writ, Just prog) - Left err -> panErr err - where - go Nothing Nothing = Right ("latex", "pdflatex") - go (Just writer) Nothing = (writer,) <$> engineForWriter writer - go Nothing (Just engine) = (,engine) <$> writerForEngine (takeBaseName engine) - go (Just writer) (Just engine) = - case find (== (baseWriterName writer, takeBaseName engine)) engines of - Just _ -> Right (writer, engine) - Nothing -> Left $ "pdf-engine " ++ engine ++ - " is not compatible with output format " ++ writer - - writerForEngine eng = case [f | (f,e) <- engines, e == eng] of - fmt : _ -> Right fmt - [] -> Left $ - "pdf-engine " ++ eng ++ " not known" - - engineForWriter "pdf" = Left pdfIsNoWriterErrorMsg - engineForWriter w = case [e | (f,e) <- engines, f == baseWriterName w] of - eng : _ -> Right eng - [] -> Left $ - "cannot produce pdf output from " ++ w convertWithOpts :: Opt -> IO () convertWithOpts opts = do @@ -130,10 +91,6 @@ convertWithOpts opts = do mapM_ (UTF8.hPutStrLn stdout) (optInputFiles opts) exitSuccess - epubMetadata <- case optEpubMetadata opts of - Nothing -> return Nothing - Just fp -> Just <$> UTF8.readFile fp - let isPandocCiteproc (JSONFilter f) = takeBaseName f == "pandoc-citeproc" isPandocCiteproc _ = False -- --bibliography implies -F pandoc-citeproc for backwards compatibility: @@ -165,30 +122,6 @@ convertWithOpts opts = do let pdfOutput = map toLower (takeExtension outputFile) == ".pdf" - (writerName, maybePdfProg) <- - if pdfOutput - then pdfWriterAndProg (optWriter opts) (optPdfEngine opts) - else case optWriter opts of - Nothing -> - return (formatFromFilePaths "html" [outputFile], Nothing) - Just f -> return (f, Nothing) - - let format = map toLower $ baseWriterName - $ takeFileName writerName -- in case path to lua script - - -- disabling the custom writer for now - (writer, writerExts) <- - if ".lua" `isSuffixOf` format - then return (TextWriter - (\o d -> writeCustom writerName o d) - :: Writer PandocIO, mempty) - else case getWriter (map toLower writerName) of - Left e -> E.throwIO $ PandocAppError $ - if format == "pdf" - then e ++ "\n" ++ pdfIsNoWriterErrorMsg - else e - Right (w, es) -> return (w :: Writer PandocIO, es) - -- TODO: we have to get the input and the output into the state for -- the sake of the text2tags reader. (reader, readerExts) <- @@ -202,34 +135,6 @@ convertWithOpts opts = do "\nPandoc can convert from DOCX, but not from DOC.\nTry using Word to save your DOC file as DOCX, and convert that with pandoc." _ -> e - let standalone = optStandalone opts || not (isTextFormat format) || pdfOutput - let addStringAsVariable varname s vars = return $ (varname, s) : vars - - let addSyntaxMap existingmap f = do - res <- parseSyntaxDefinition f - case res of - Left errstr -> E.throwIO $ PandocSyntaxMapError errstr - Right syn -> return $ addSyntaxDefinition syn existingmap - - syntaxMap <- foldM addSyntaxMap defaultSyntaxMap - (optSyntaxDefinitions opts) - - -- We don't want to send output to the terminal if the user - -- does 'pandoc -t docx input.txt'; though we allow them to - -- force this with '-o -'. On posix systems, we detect - -- when stdout is being piped and allow output to stdout - -- in that case, but on Windows we can't. -#ifdef _WINDOWS - let istty = True -#else - istty <- queryTerminal stdOutput -#endif - when (not (isTextFormat format) && istty && isNothing ( optOutputFile opts)) $ - E.throwIO $ PandocAppError $ - "Cannot write " ++ format ++ " output to terminal.\n" ++ - "Specify an output file using the -o option, or " ++ - "use '-o -' to force output to stdout." - let convertTabs = tabFilter (if optPreserveTabs opts || readerName == "t2t" || readerName == "man" @@ -261,80 +166,41 @@ convertWithOpts opts = do LF -> IO.LF Native -> nativeNewline - -- note: this reverses the list constructed in option parsing, - -- which in turn was reversed from the command-line order, - -- so we end up with the correct order in the variable list: - let withList _ [] vars = return vars - withList f (x:xs) vars = f x vars >>= withList f xs - - let addContentsAsVariable varname fp vars = do - s <- UTF8.toString <$> readFileStrict fp - return $ (varname, s) : vars - runIO' $ do setUserDataDir datadir setInputFiles (optInputFiles opts) setOutputFile (optOutputFile opts) - variables <- - withList (addStringAsVariable "sourcefile") - (reverse $ optInputFiles opts) - (("outputfile", fromMaybe "-" (optOutputFile opts)) - : optVariables opts) - -- we reverse this list because, unlike - -- the other option lists here, it is - -- not reversed when parsed from CLI arguments. - -- See withList, above. - >>= - withList (addContentsAsVariable "include-before") - (optIncludeBeforeBody opts) - >>= - withList (addContentsAsVariable "include-after") - (optIncludeAfterBody opts) - >>= - withList (addContentsAsVariable "header-includes") - (optIncludeInHeader opts) - >>= - withList (addStringAsVariable "css") (optCss opts) - >>= - maybe return (addStringAsVariable "title-prefix") - (optTitlePrefix opts) - >>= - maybe return (addStringAsVariable "epub-cover-image") - (optEpubCoverImage opts) - >>= - (\vars -> if format == "dzslides" - then do - dztempl <- UTF8.toString <$> readDataFile - ("dzslides" "template.html") - let dzline = "