diagrams-pdf-0.2.0: src/Diagrams/Backend/Pdf/CmdLine.hs
{-# LANGUAGE DeriveDataTypeable, NoMonomorphismRestriction #-}
-----------------------------------------------------------------------------
-- |
-- Module : Diagrams.Backend.Pdf.CmdLine
-- Copyright : (c) 2013 alpheccar.org (see LICENSE)
-- License : BSD-style (see LICENSE)
--
-- Convenient creation of command-line-driven executables for
-- rendering diagrams using the Pdf backend.
--
-- * 'defaultMain' creates an executable which can render a single
-- diagram at various options.
--
-----------------------------------------------------------------------------
module Diagrams.Backend.Pdf.CmdLine
( defaultMain
, multipleMain
, Pdf
) where
import Diagrams.Prelude hiding (width, height, interval)
import Diagrams.Backend.Pdf
import System.Console.CmdArgs.Implicit hiding (args)
import Prelude
import Data.List.Split
import System.Environment (getProgName)
import qualified Graphics.PDF as P
data DiagramOpts = DiagramOpts
{ width :: Maybe Int
, height :: Maybe Int
, output :: FilePath
, compressed :: Maybe Bool
, author :: Maybe String
}
deriving (Show, Data, Typeable)
diagramOpts :: String -> DiagramOpts
diagramOpts prog = DiagramOpts
{ width = def
&= typ "INT"
&= help "Desired width of the output image (default 400)"
, height = def
&= typ "INT"
&= help "Desired height of the output image (default 400)"
, output = def
&= typFile
&= help "Output file"
, compressed = def
&= typ "BOOL"
&= help "Compressed PDF file"
, author = def
&= typ "STRING"
&= help "Author of the document"
}
&= summary "Command-line diagram generation."
&= program prog
-- | This is the simplest way to render diagrams, and is intended to
-- be used like so:
--
-- > ... other definitions ...
-- > myDiagram = ...
-- >
-- > main = defaultMain myDiagram
--
-- Compiling a source file like the above example will result in an
-- executable which takes command-line options for setting the size,
-- output file, and so on, and renders @myDiagram@ with the
-- specified options.
--
-- Pass @--help@ to the generated executable to see all available
-- options. Currently it looks something like
--
-- @
-- Command-line diagram generation.
--
-- Foo [OPTIONS]
--
-- Common flags:
-- -w --width=INT Desired width of the output image (default 400)
-- -h --height=INT Desired height of the output image (default 400)
-- -o --output=FILE Output file
-- -c --compressed Compressed PDF file
-- -? --help Display help message
-- -V --version Print version information
-- @
--
-- For example, a couple common scenarios include
--
-- @
-- $ ghc --make MyDiagram
--
-- # output image.eps with a width of 400pt (and auto-determined height)
-- $ ./MyDiagram --compressed -o image.pdf -w 400
-- @
defaultMain :: Diagram Pdf R2 -> IO ()
defaultMain d = do
prog <- getProgName
opts <- cmdArgs (diagramOpts prog)
let sizeSpec = case (width opts, height opts) of
(Nothing, Nothing) -> Absolute
(Just wi, Nothing) -> Width (fromIntegral wi)
(Nothing, Just he) -> Height (fromIntegral he)
(Just wi, Just he) -> Dims (fromIntegral wi)
(fromIntegral he)
(w,h) = sizeFromSpec sizeSpec
theAuthor = maybe "diagrams-pdf" id (author opts)
compression = maybe False id (compressed opts)
docRect = P.PDFRect 0 0 (floor w) (floor h)
pdfOpts = PdfOptions sizeSpec
ifCanRender opts $ do
P.runPdf (output opts)
(P.standardDocInfo { P.author=P.toPDFString theAuthor, P.compressed = compression}) docRect $ do
page1 <- P.addPage Nothing
P.drawWithPage page1 $ renderDia Pdf pdfOpts d
-- | Generate a multipage PDF document from several diagrams.
-- Each diagram is scaled to the page size
multipleMain :: [Diagram Pdf R2] -> IO ()
multipleMain d = do
prog <- getProgName
opts <- cmdArgs (diagramOpts prog)
let sizeSpec = case (width opts, height opts) of
(Nothing, Nothing) -> Absolute
(Just wi, Nothing) -> Width (fromIntegral wi)
(Nothing, Just he) -> Height (fromIntegral he)
(Just wi, Just he) -> Dims (fromIntegral wi)
(fromIntegral he)
(w,h) = sizeFromSpec sizeSpec
theAuthor = maybe "diagrams-pdf" id (author opts)
compression = maybe False id (compressed opts)
docRect = P.PDFRect 0 0 (floor w) (floor h)
pdfOpts = PdfOptions sizeSpec
createPage aDiag = do
page1 <- P.addPage Nothing
P.drawWithPage page1 $ renderDia Pdf pdfOpts aDiag
ifCanRender opts $ do
P.runPdf (output opts)
(P.standardDocInfo { P.author=P.toPDFString theAuthor, P.compressed = compression}) docRect $ do
mapM_ createPage d
ifCanRender :: DiagramOpts -> IO () -> IO ()
ifCanRender opts action =
case splitOn "." (output opts) of
[""] -> putStrLn "No output file given."
ps | last ps `elem` ["pdf"] -> action
| otherwise -> putStrLn $ "Unknown file type: " ++ last ps