{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Text.Pandoc.Filter.Plot.Types (
Toolkit(..)
, PlotM
, PlotEnv(..)
, Configuration(..)
, Script
, CheckResult(..)
, InclusionKey(..)
, FigureSpec(..)
, SaveFormat(..)
, figureContentHash
, cls
, extension
, toolkits
, inclusionKeys
, isWindows
) where
import Control.Monad.Reader
import Data.Char (toLower)
import Data.Default.Class (Default, def)
import Data.Hashable (hash)
import Data.List (intersperse)
import Data.Semigroup (Semigroup (..))
import Data.String (IsString (..))
import Data.Text (Text)
import Data.Yaml
import GHC.Generics (Generic)
import System.Info (os)
import Text.Pandoc.Definition (Attr, Format(..))
toolkits :: [Toolkit]
toolkits = enumFromTo minBound maxBound
data Toolkit
= Matplotlib
| Matlab
| PlotlyPython
| PlotlyR
| Mathematica
| Octave
| GGPlot2
| GNUPlot
| Graphviz
deriving (Bounded, Eq, Enum, Generic)
instance Show Toolkit where
show Matplotlib = "Python/Matplotlib"
show Matlab = "MATLAB"
show PlotlyPython = "Python/Plotly"
show PlotlyR = "R/Plotly"
show Mathematica = "Mathematica"
show Octave = "GNU Octave"
show GGPlot2 = "ggplot2"
show GNUPlot = "gnuplot"
show Graphviz = "graphviz"
cls :: Toolkit -> Text
cls Matplotlib = "matplotlib"
cls Matlab = "matlabplot"
cls PlotlyPython = "plotly_python"
cls PlotlyR = "plotly_r"
cls Mathematica = "mathplot"
cls Octave = "octaveplot"
cls GGPlot2 = "ggplot2"
cls GNUPlot = "gnuplot"
cls Graphviz = "graphviz"
type PlotM a = ReaderT PlotEnv IO a
data PlotEnv
= PlotEnv { toolkit :: !Toolkit
, config :: !Configuration
}
data Configuration = Configuration
{ defaultDirectory :: !FilePath
, defaultWithSource :: !Bool
, defaultDPI :: !Int
, defaultSaveFormat :: !SaveFormat
, captionFormat :: !Format
, matplotlibPreamble :: !Script
, plotlyPythonPreamble :: !Script
, plotlyRPreamble :: !Script
, matlabPreamble :: !Script
, mathematicaPreamble :: !Script
, octavePreamble :: !Script
, ggplot2Preamble :: !Script
, gnuplotPreamble :: !Script
, graphvizPreamble :: !Script
, matplotlibExe :: !FilePath
, matlabExe :: !FilePath
, plotlyPythonExe :: !FilePath
, plotlyRExe :: !FilePath
, mathematicaExe :: !FilePath
, octaveExe :: !FilePath
, ggplot2Exe :: !FilePath
, gnuplotExe :: !FilePath
, graphvizExe :: !FilePath
, matplotlibTightBBox :: !Bool
, matplotlibTransparent :: !Bool
} deriving (Eq, Show)
instance Default Configuration where
def = Configuration
{ defaultDirectory = "plots/"
, defaultWithSource = False
, defaultDPI = 80
, defaultSaveFormat = PNG
, captionFormat = Format "markdown+tex_math_dollars"
, matplotlibPreamble = mempty
, plotlyPythonPreamble= mempty
, plotlyRPreamble = mempty
, matlabPreamble = mempty
, mathematicaPreamble = mempty
, octavePreamble = mempty
, ggplot2Preamble = mempty
, gnuplotPreamble = mempty
, graphvizPreamble = mempty
, matplotlibExe = if isWindows then "python" else "python3"
, matlabExe = "matlab"
, plotlyPythonExe = if isWindows then "python" else "python3"
, plotlyRExe = "Rscript"
, mathematicaExe = "math"
, octaveExe = "octave"
, ggplot2Exe = "Rscript"
, gnuplotExe = "gnuplot"
, graphvizExe = "dot"
, matplotlibTightBBox = False
, matplotlibTransparent = False
}
type Script = Text
data CheckResult
= CheckPassed
| CheckFailed String
deriving (Eq)
instance Semigroup CheckResult where
(<>) CheckPassed a = a
(<>) a CheckPassed = a
(<>) (CheckFailed msg1) (CheckFailed msg2) = CheckFailed (msg1 <> msg2)
instance Monoid CheckResult where
mempty = CheckPassed
data InclusionKey
= DirectoryK
| CaptionK
| SaveFormatK
| WithSourceK
| CaptionFormatK
| PreambleK
| DpiK
| ExecutableK
| MatplotlibTightBBoxK
| MatplotlibTransparentK
deriving (Bounded, Eq, Enum)
instance Show InclusionKey where
show DirectoryK = "directory"
show CaptionK = "caption"
show SaveFormatK = "format"
show WithSourceK = "source"
show CaptionFormatK = "caption_format"
show PreambleK = "preamble"
show DpiK = "dpi"
show ExecutableK = "executable"
show MatplotlibTightBBoxK = "tight_bbox"
show MatplotlibTransparentK = "transparent"
inclusionKeys :: [InclusionKey]
inclusionKeys = enumFromTo (minBound::InclusionKey) maxBound
data FigureSpec = FigureSpec
{ caption :: !Text
, withSource :: !Bool
, script :: !Script
, saveFormat :: !SaveFormat
, directory :: !FilePath
, dpi :: !Int
, extraAttrs :: ![(Text, Text)]
, blockAttrs :: !Attr
}
figureContentHash :: FigureSpec -> Int
figureContentHash FigureSpec{..} =
hash (script, fromEnum saveFormat, directory, dpi, extraAttrs)
data SaveFormat
= PNG
| PDF
| SVG
| JPG
| EPS
| GIF
| TIF
| WEBP
deriving (Bounded, Enum, Eq, Show, Generic)
instance IsString SaveFormat where
fromString s
| s `elem` ["png", "PNG", ".png"] = PNG
| s `elem` ["pdf", "PDF", ".pdf"] = PDF
| s `elem` ["svg", "SVG", ".svg"] = SVG
| s `elem` ["eps", "EPS", ".eps"] = EPS
| s `elem` ["gif", "GIF", ".gif"] = GIF
| s `elem` ["jpg", "jpeg", "JPG", "JPEG", ".jpg", ".jpeg"] = JPG
| s `elem` ["tif", "tiff", "TIF", "TIFF", ".tif", ".tiff"] = TIF
| s `elem` ["webp", "WEBP", ".webp"] = WEBP
| otherwise = error $
mconcat [ s
, " is not one of valid save format : "
, mconcat $ intersperse ", " $ show <$> saveFormats
]
where
saveFormats = (enumFromTo minBound maxBound) :: [SaveFormat]
instance FromJSON SaveFormat
instance ToJSON SaveFormat where
toJSON = toJSON . extension
extension :: SaveFormat -> String
extension fmt = mconcat [".", fmap toLower . show $ fmt]
isWindows :: Bool
isWindows = os `elem` ["mingw32", "win32", "cygwin32"]