summaryrefslogtreecommitdiff
path: root/src/Text/Pandoc/Filter
diff options
context:
space:
mode:
authorLaurentRDC <>2019-04-08 23:10:00 (GMT)
committerhdiff <hdiff@hdiff.luite.com>2019-04-08 23:10:00 (GMT)
commit27a4ae7b3b04161800959901a17dec4481c06c09 (patch)
tree7793f17e75e03ca22fea3d32cdf354c7159228b2 /src/Text/Pandoc/Filter
parent30fea466d0dd6beb5e55a851e802ea7b470a35d0 (diff)
version 2.1.0.12.1.0.1
Diffstat (limited to 'src/Text/Pandoc/Filter')
-rw-r--r--src/Text/Pandoc/Filter/Pyplot.hs36
-rw-r--r--src/Text/Pandoc/Filter/Pyplot/Configuration.hs34
-rw-r--r--src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs60
-rw-r--r--src/Text/Pandoc/Filter/Pyplot/Internal.hs4
-rw-r--r--src/Text/Pandoc/Filter/Pyplot/Scripting.hs23
-rw-r--r--src/Text/Pandoc/Filter/Pyplot/Types.hs108
6 files changed, 157 insertions, 108 deletions
diff --git a/src/Text/Pandoc/Filter/Pyplot.hs b/src/Text/Pandoc/Filter/Pyplot.hs
index 6df85ae..83e2221 100644
--- a/src/Text/Pandoc/Filter/Pyplot.hs
+++ b/src/Text/Pandoc/Filter/Pyplot.hs
@@ -25,9 +25,9 @@ To trigger pandoc-pyplot, the following is __required__:
Here are the possible attributes what pandoc-pyplot understands:
- * @target=...@: Filepath where the resulting figure should be saved.
* @directory=...@ : Directory where to save the figure.
- * @caption="..."@: Specify a plot caption (or alternate text).
+ * @format=...@: Format of the generated figure. This can be an extension or an acronym, e.g. @format=png@.
+ * @caption="..."@: Specify a plot caption (or alternate text). Captions support Markdown formatting and LaTeX math (@$...$@).
* @dpi=...@: Specify a value for figure resolution, or dots-per-inch. Default is 80DPI.
* @include=...@: Path to a Python script to include before the code block. Ideal to avoid repetition over many figures.
@@ -43,6 +43,34 @@ plt.figure()
plt.plot([0,1,2,3,4], [1,2,3,4,5])
plt.title('This is an example figure')
```
+
+This is another paragraph
+
+```{.pyplot dpi=150 format=SVG}
+# This example was taken from the Matplotlib gallery
+# https://matplotlib.org/examples/pylab_examples/bar_stacked.html
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+N = 5
+menMeans = (20, 35, 30, 35, 27)
+womenMeans = (25, 32, 34, 20, 25)
+menStd = (2, 3, 4, 1, 2)
+womenStd = (3, 5, 2, 3, 3)
+ind = np.arange(N) # the x locations for the groups
+width = 0.35 # the width of the bars: can also be len(x) sequence
+
+p1 = plt.bar(ind, menMeans, width, color='#d62728', yerr=menStd)
+p2 = plt.bar(ind, womenMeans, width,
+ bottom=menMeans, yerr=womenStd)
+
+plt.ylabel('Scores')
+plt.title('Scores by group and gender')
+plt.xticks(ind, ('G1', 'G2', 'G3', 'G4', 'G5'))
+plt.yticks(np.arange(0, 81, 10))
+plt.legend((p1[0], p2[0]), ('Men', 'Women'))
+```
@
This filter was originally designed to be used with [Hakyll](https://jaspervdj.be/hakyll/).
@@ -64,6 +92,8 @@ makePlotPandocCompiler =
(unsafeCompiler . plotTransform)
@
+Custom configurations are possible via the @Configuration@ type and the filter
+functions @plotTransformWithConfig@ and @makePlotWithConfig@.
-}
module Text.Pandoc.Filter.Pyplot (
-- * Operating on single Pandoc blocks
@@ -75,6 +105,8 @@ module Text.Pandoc.Filter.Pyplot (
-- * For configuration purposes
, configuration
, Configuration (..)
+ , PythonScript
+ , SaveFormat (..)
-- * For testing and internal purposes only
, PandocPyplotError(..)
, makePlot'
diff --git a/src/Text/Pandoc/Filter/Pyplot/Configuration.hs b/src/Text/Pandoc/Filter/Pyplot/Configuration.hs
index 443afc0..8bfa877 100644
--- a/src/Text/Pandoc/Filter/Pyplot/Configuration.hs
+++ b/src/Text/Pandoc/Filter/Pyplot/Configuration.hs
@@ -11,8 +11,7 @@ Configuration for pandoc-pyplot
-}
module Text.Pandoc.Filter.Pyplot.Configuration (
- Configuration (..)
- , configuration
+ configuration
-- * For testing and internal purposes only
, inclusionKeys
, directoryKey
@@ -23,14 +22,13 @@ module Text.Pandoc.Filter.Pyplot.Configuration (
) where
import Data.Maybe (fromMaybe)
-import Data.Default.Class (Default, def)
+import Data.Default.Class (def)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Data.Yaml
import Data.Yaml.Config (loadYamlSettings, ignoreEnv)
-import Text.Pandoc.Filter.Pyplot.FigureSpec
-import Text.Pandoc.Filter.Pyplot.Scripting
+import Text.Pandoc.Filter.Pyplot.Types
-- | Keys that pandoc-pyplot will look for in code blocks. These are only exported for testing purposes.
directoryKey, captionKey, dpiKey, includePathKey, saveFormatKey :: String
@@ -49,32 +47,6 @@ inclusionKeys = [ directoryKey
, saveFormatKey
]
--- | Configuration of pandoc-pyplot, describing the default behavior
--- of the filter.
---
--- A Configuration is useful when dealing with lots of figures; it avoids
--- repeating the same values.sta
---
--- @since 2.1.0.0
-data Configuration
- = Configuration
- { defaultDirectory :: FilePath -- ^ The default directory where figures will be saved.
- , defaultIncludeScript :: PythonScript -- ^ The default script to run before other instructions.
- , defaultSaveFormat :: SaveFormat -- ^ The default save format of generated figures.
- , defaultDPI :: Int -- ^ The default dots-per-inch value for generated figures.
- , interpreter :: String -- ^ The name of the interpreter to use to render figures.
- }
- deriving (Eq, Show)
-
-instance Default Configuration where
- def = Configuration {
- defaultDirectory = "generated/"
- , defaultIncludeScript = mempty
- , defaultSaveFormat = PNG
- , defaultDPI = 80
- , interpreter = "python"
- }
-
-- A @Configuration@ cannot be directly created from a YAML file
-- for two reasons:
--
diff --git a/src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs b/src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs
index d8480ab..2bd2cd7 100644
--- a/src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs
+++ b/src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs
@@ -25,8 +25,7 @@ module Text.Pandoc.Filter.Pyplot.FigureSpec
import Control.Monad (join)
-import Data.Char (toLower)
-import Data.Hashable (Hashable, hash, hashWithSalt)
+import Data.Hashable (hash)
import Data.Maybe (fromMaybe)
import Data.Monoid ((<>))
import qualified Data.Text as T
@@ -42,7 +41,7 @@ import Text.Pandoc.Extensions (extensionsFromList, Extension(..)
import Text.Pandoc.Options (def, ReaderOptions(..))
import Text.Pandoc.Readers (readMarkdown)
-import Text.Pandoc.Filter.Pyplot.Scripting
+import Text.Pandoc.Filter.Pyplot.Types
readerOptions :: ReaderOptions
readerOptions = def
@@ -68,61 +67,6 @@ captionReader t = either (const Nothing) (Just . extractFromBlocks) $ runPure $
extractInlines (LineBlock multiinlines) = join multiinlines
extractInlines _ = []
--- | Generated figure file format supported by pandoc-pyplot.
-data SaveFormat
- = PNG
- | PDF
- | SVG
- | JPG
- | EPS
- | GIF
- | TIF
- deriving (Bounded, Enum, Eq, Show)
-
--- | Parse an image save format string
---
--- >>> saveFormatFromString ".png"
--- Just PNG
---
--- >>> saveFormatFromString "jpeg"
--- Just JPEG
---
--- >>> SaveFormatFromString "arbitrary"
--- Nothing
-saveFormatFromString :: String -> Maybe SaveFormat
-saveFormatFromString s
- | s `elem` ["png", "PNG", ".png"] = Just PNG
- | s `elem` ["pdf", "PDF", ".pdf"] = Just PDF
- | s `elem` ["svg", "SVG", ".svg"] = Just SVG
- | s `elem` ["eps", "EPS", ".eps"] = Just EPS
- | s `elem` ["gif", "GIF", ".gif"] = Just GIF
- | s `elem` ["jpg", "jpeg", "JPG", "JPEG", ".jpg", ".jpeg"] = Just JPG
- | s `elem` ["tif", "tiff", "TIF", "TIFF", ".tif", ".tiff"] = Just TIF
- | otherwise = Nothing
-
--- | Save format file extension
-extension :: SaveFormat -> String
-extension fmt = mconcat [".", fmap toLower . show $ fmt]
-
--- | Datatype containing all parameters required to run pandoc-pyplot
-data FigureSpec = FigureSpec
- { caption :: String -- ^ Figure caption.
- , script :: PythonScript -- ^ Source code for the figure.
- , saveFormat :: SaveFormat -- ^ Save format of the figure
- , directory :: FilePath -- ^ Directory where to save the file
- , dpi :: Int -- ^ Dots-per-inch of figure
- , blockAttrs :: Attr -- ^ Attributes not related to @pandoc-pyplot@ will be propagated.
- }
-
-instance Hashable FigureSpec where
- hashWithSalt salt spec =
- hashWithSalt salt ( caption spec
- , script spec
- , fromEnum . saveFormat $ spec
- , directory spec, dpi spec
- , blockAttrs spec
- )
-
-- | Convert a FigureSpec to a Pandoc block component
toImage :: FigureSpec -> Block
toImage spec = head . toList $ para $ imageWith attrs' target' "fig:" caption'
diff --git a/src/Text/Pandoc/Filter/Pyplot/Internal.hs b/src/Text/Pandoc/Filter/Pyplot/Internal.hs
index 5c8fee5..a3970c7 100644
--- a/src/Text/Pandoc/Filter/Pyplot/Internal.hs
+++ b/src/Text/Pandoc/Filter/Pyplot/Internal.hs
@@ -14,8 +14,10 @@ module Text.Pandoc.Filter.Pyplot.Internal (
module Text.Pandoc.Filter.Pyplot.Configuration
, module Text.Pandoc.Filter.Pyplot.FigureSpec
, module Text.Pandoc.Filter.Pyplot.Scripting
+ , module Text.Pandoc.Filter.Pyplot.Types
) where
import Text.Pandoc.Filter.Pyplot.Configuration
import Text.Pandoc.Filter.Pyplot.FigureSpec
-import Text.Pandoc.Filter.Pyplot.Scripting \ No newline at end of file
+import Text.Pandoc.Filter.Pyplot.Scripting
+import Text.Pandoc.Filter.Pyplot.Types \ No newline at end of file
diff --git a/src/Text/Pandoc/Filter/Pyplot/Scripting.hs b/src/Text/Pandoc/Filter/Pyplot/Scripting.hs
index ec90780..d867363 100644
--- a/src/Text/Pandoc/Filter/Pyplot/Scripting.hs
+++ b/src/Text/Pandoc/Filter/Pyplot/Scripting.hs
@@ -14,13 +14,10 @@ with running Python scripts.
module Text.Pandoc.Filter.Pyplot.Scripting
( runTempPythonScript
, hasBlockingShowCall
- , PythonScript
- , ScriptResult(..)
) where
import Data.Hashable (hash)
import Data.Monoid (Any(..))
-import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as T
@@ -29,40 +26,34 @@ import System.FilePath ((</>))
import System.IO.Temp (getCanonicalTemporaryDirectory)
import System.Process.Typed (runProcess, shell)
--- | String representation of a Python script
-type PythonScript = Text
-
--- | Possible result of running a Python script
-data ScriptResult
- = ScriptSuccess
- | ScriptFailure Int
+import Text.Pandoc.Filter.Pyplot.Types
-- | Take a python script in string form, write it in a temporary directory,
-- then execute it.
runTempPythonScript :: String -- ^ Interpreter (e.g. "python" or "python35")
-> PythonScript -- ^ Content of the script
-> IO ScriptResult -- ^ Result with exit code.
-runTempPythonScript interpreter script = do
+runTempPythonScript interpreter' script' = do
-- We involve the script hash as a temporary filename
-- so that there is never any collision
scriptPath <- (</> hashedPath) <$> getCanonicalTemporaryDirectory
- T.writeFile scriptPath script
+ T.writeFile scriptPath script'
- ec <- runProcess $ shell $ mconcat [interpreter, " ", show scriptPath]
+ ec <- runProcess $ shell $ mconcat [interpreter', " ", show scriptPath]
case ec of
ExitSuccess -> return ScriptSuccess
ExitFailure code -> return $ ScriptFailure code
where
- hashedPath = show . hash $ script
+ hashedPath = show . hash $ script'
-- | Detect the presence of a blocking show call, for example "plt.show()"
hasBlockingShowCall :: PythonScript -> Bool
-hasBlockingShowCall script =
+hasBlockingShowCall script' =
anyOf
[ "plt.show()" `elem` scriptLines
, "pyplot.show()" `elem` scriptLines
, "matplotlib.pyplot.show()" `elem` scriptLines
]
where
- scriptLines = T.lines script
+ scriptLines = T.lines script'
anyOf xs = getAny $ mconcat $ Any <$> xs \ No newline at end of file
diff --git a/src/Text/Pandoc/Filter/Pyplot/Types.hs b/src/Text/Pandoc/Filter/Pyplot/Types.hs
new file mode 100644
index 0000000..9021b78
--- /dev/null
+++ b/src/Text/Pandoc/Filter/Pyplot/Types.hs
@@ -0,0 +1,108 @@
+{-|
+Module : Text.Pandoc.Filter.Pyplot.Types
+Copyright : (c) Laurent P René de Cotret, 2019
+License : MIT
+Maintainer : laurent.decotret@outlook.com
+Stability : internal
+Portability : portable
+
+This module defines types in use in pandoc-pyplot
+-}
+
+module Text.Pandoc.Filter.Pyplot.Types where
+
+import Data.Char (toLower)
+import Data.Default.Class (Default, def)
+import Data.Hashable (Hashable, hashWithSalt)
+import Data.Text (Text)
+
+import Text.Pandoc.Definition (Attr)
+
+-- | String representation of a Python script
+type PythonScript = Text
+
+-- | Possible result of running a Python script
+data ScriptResult
+ = ScriptSuccess
+ | ScriptFailure Int
+
+-- | Generated figure file format supported by pandoc-pyplot.
+data SaveFormat
+ = PNG
+ | PDF
+ | SVG
+ | JPG
+ | EPS
+ | GIF
+ | TIF
+ deriving (Bounded, Enum, Eq, Show)
+
+-- | Parse an image save format string
+--
+-- >>> saveFormatFromString ".png"
+-- Just PNG
+--
+-- >>> saveFormatFromString "jpeg"
+-- Just JPEG
+--
+-- >>> SaveFormatFromString "arbitrary"
+-- Nothing
+saveFormatFromString :: String -> Maybe SaveFormat
+saveFormatFromString s
+ | s `elem` ["png", "PNG", ".png"] = Just PNG
+ | s `elem` ["pdf", "PDF", ".pdf"] = Just PDF
+ | s `elem` ["svg", "SVG", ".svg"] = Just SVG
+ | s `elem` ["eps", "EPS", ".eps"] = Just EPS
+ | s `elem` ["gif", "GIF", ".gif"] = Just GIF
+ | s `elem` ["jpg", "jpeg", "JPG", "JPEG", ".jpg", ".jpeg"] = Just JPG
+ | s `elem` ["tif", "tiff", "TIF", "TIFF", ".tif", ".tiff"] = Just TIF
+ | otherwise = Nothing
+
+-- | Save format file extension
+extension :: SaveFormat -> String
+extension fmt = mconcat [".", fmap toLower . show $ fmt]
+
+-- | Configuration of pandoc-pyplot, describing the default behavior
+-- of the filter.
+--
+-- A Configuration is useful when dealing with lots of figures; it avoids
+-- repeating the same values.sta
+--
+-- @since 2.1.0.0
+data Configuration
+ = Configuration
+ { defaultDirectory :: FilePath -- ^ The default directory where figures will be saved.
+ , defaultIncludeScript :: PythonScript -- ^ The default script to run before other instructions.
+ , defaultSaveFormat :: SaveFormat -- ^ The default save format of generated figures.
+ , defaultDPI :: Int -- ^ The default dots-per-inch value for generated figures.
+ , interpreter :: String -- ^ The name of the interpreter to use to render figures.
+ }
+ deriving (Eq, Show)
+
+instance Default Configuration where
+ def = Configuration {
+ defaultDirectory = "generated/"
+ , defaultIncludeScript = mempty
+ , defaultSaveFormat = PNG
+ , defaultDPI = 80
+ , interpreter = "python"
+ }
+
+-- | Datatype containing all parameters required to run pandoc-pyplot
+data FigureSpec = FigureSpec
+ { caption :: String -- ^ Figure caption.
+ , script :: PythonScript -- ^ Source code for the figure.
+ , saveFormat :: SaveFormat -- ^ Save format of the figure
+ , directory :: FilePath -- ^ Directory where to save the file
+ , dpi :: Int -- ^ Dots-per-inch of figure
+ , blockAttrs :: Attr -- ^ Attributes not related to @pandoc-pyplot@ will be propagated.
+ }
+
+instance Hashable FigureSpec where
+ hashWithSalt salt spec =
+ hashWithSalt salt ( caption spec
+ , script spec
+ , fromEnum . saveFormat $ spec
+ , directory spec, dpi spec
+ , blockAttrs spec
+ ) \ No newline at end of file