{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
module Text.Pandoc.Filter.Plot.Renderers.Matplotlib (
matplotlibSupportedSaveFormats
, matplotlibCommand
, matplotlibCapture
, matplotlibExtraAttrs
, matplotlibAvailable
, matplotlibCheckIfShow
) where
import Text.Pandoc.Filter.Plot.Renderers.Prelude
import qualified Data.Map.Strict as M
import Data.Monoid (Any(..))
import qualified Data.Text as T
matplotlibSupportedSaveFormats :: [SaveFormat]
matplotlibSupportedSaveFormats = [PNG, PDF, SVG, JPG, EPS, GIF, TIF]
matplotlibCommand :: OutputSpec -> Text -> Text
matplotlibCommand OutputSpec{..} exe = [st|#{exe} "#{oScriptPath}"|]
matplotlibCapture :: FigureSpec -> FilePath -> Script
matplotlibCapture = appendCapture matplotlibCaptureFragment
matplotlibCaptureFragment :: FigureSpec -> FilePath -> Script
matplotlibCaptureFragment FigureSpec{..} fname = [st|
import matplotlib.pyplot as plt
plt.savefig(r"#{fname}", dpi=#{dpi}, transparent=#{transparent}, bbox_inches=#{tightBox})
|]
where attrs = M.fromList extraAttrs
tight_ = readBool $ M.findWithDefault "False" "tight" attrs
transparent_ = readBool $ M.findWithDefault "False" "transparent" attrs
tightBox = if tight_ then ("'tight'"::Text) else ("None"::Text)
transparent = if transparent_ then ("True"::Text) else ("False"::Text)
matplotlibExtraAttrs :: M.Map Text Text -> (M.Map Text Text)
matplotlibExtraAttrs kv = M.filterWithKey (\k _ -> k `elem` ["tight_bbox", "transparent"]) kv
matplotlibAvailable :: PlotM Bool
matplotlibAvailable = do
mexe <- executable Matplotlib
case mexe of
Nothing -> return False
Just (Executable dir exe) ->
commandSuccess dir [st|#{exe} -c "import matplotlib"|]
matplotlibCheckIfShow :: Script -> CheckResult
matplotlibCheckIfShow s =
if getAny $ mconcat showPresent
then CheckFailed "encountered a call to `matplotlib.pyplot.show`."
else CheckPassed
where
showPresent = (\n -> Any (T.isInfixOf n s)) <$> [
"matplotlib.pyplot.show()"
, "pyplot.show()"
, "plt.show()"
]
readBool :: Text -> Bool
readBool s | s `elem` ["True", "true", "'True'", "'true'", "1"] = True
| s `elem` ["False", "false", "'False'", "'false'", "0"] = False
| otherwise = errorWithoutStackTrace $ unpack $ mconcat ["Could not parse '", s, "' into a boolean. Please use 'True' or 'False'"]