asciidiagram-1.2: exec-src/asciidiagram.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE CPP #-}
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative( (<$>), (<*>), pure )
#endif
import Control.Applicative( (<|>) )
import Control.Monad( when )
import Data.Monoid( (<>) )
import qualified Data.ByteString.Lazy as LB
import qualified Data.Text.IO as STIO
import System.Directory( getTemporaryDirectory )
import System.FilePath( (</>)
, replaceExtension
, takeExtension )
import Graphics.Rasterific.Svg( loadCreateFontCache )
import Graphics.Text.TrueType( FontCache )
import Codec.Picture( writePng )
import Options.Applicative( Parser
, ParserInfo
, argument
, execParser
, flag
, fullDesc
, header
, help
, helper
, info
, long
, metavar
, progDesc
, str
, switch
)
import Text.AsciiDiagram
data Options = Options
{ _inputFile :: !FilePath
, _outputFile :: !FilePath
, _verbose :: !Bool
, _format :: !(Maybe Format)
}
data Format = FormatSvg | FormatPng | FormatPdf
argParser :: Parser Options
argParser = Options
<$> ( argument str
(metavar "INPUTFILE"
<> help "Text file of the Ascii diagram to parse."))
<*> ( argument str
(metavar "OUTPUTFILE"
<> help ("Output file name, same as input with"
<> " different extension if unspecified."))
<|> pure "" )
<*> ( switch (long "verbose" <> help "Display more information") )
<*> ( flag Nothing (Just FormatSvg)
( long "svg"
<> help "Force the use of the SVG format (deduced from extension otherwise)")
<|> flag Nothing (Just FormatPng)
( long "png"
<> help "Force the use of the PNG format (deduced from extension otherwise) (by default)")
<|> flag Nothing (Just FormatPdf)
( long "pdf"
<> help "Force the use of the PDF format (deduced from extension otherwise)")
)
progOptions :: ParserInfo Options
progOptions = info (helper <*> argParser)
( fullDesc
<> progDesc "Convert INPUTFILE into a svg or png OUTPUTFILE"
<> header "asciidiagram - A pretty printer for ASCII art diagram to SVG." )
formatOfOuputFilename :: FilePath -> Format
formatOfOuputFilename f = case takeExtension f of
".png" -> FormatPng
".svg" -> FormatSvg
".pdf" -> FormatPdf
_ -> FormatPng
getFontCache :: Bool -> IO FontCache
getFontCache verbose = do
when verbose $ putStrLn "Loading/Building font cache (can be long)"
tempDir <- getTemporaryDirectory
loadCreateFontCache $ tempDir </> "asciidiagram-fonty-fontcache"
runConversion :: Options -> IO ()
runConversion opt = do
verbose . putStrLn $ "Loading file " ++ _inputFile opt
inputData <- STIO.readFile $ _inputFile opt
let diag = parseAsciiDiagram inputData
format = _format opt <|> (pure . formatOfOuputFilename $ _outputFile opt)
case format of
Nothing -> saveDoc diag
Just FormatSvg -> saveDoc diag
Just FormatPng -> savePng diag
Just FormatPdf -> savePdf diag
where
verbose = when $ _verbose opt
saveDoc diag = do
verbose . putStrLn $ "Writing SVG file " ++ _outputFile opt
saveAsciiDiagramAsSvg (savingPath "svg") diag
savingPath ext = case _outputFile opt of
"" -> replaceExtension (_inputFile opt) ext
p -> p
savePdf diag = do
cache <- getFontCache $ _verbose opt
verbose . putStrLn $ "Writing PDF file " ++ _outputFile opt
pdf <- pdfOfDiagram cache diag
LB.writeFile (savingPath "pdf") pdf
savePng diag = do
cache <- getFontCache $ _verbose opt
verbose . putStrLn $ "Writing PNG file " ++ _outputFile opt
img <- imageOfDiagram cache diag
writePng (savingPath "png") img
main :: IO ()
main = execParser progOptions >>= runConversion