summaryrefslogtreecommitdiff
path: root/executable/Main.hs
blob: 3f850064c82c3870b17fe51837f0d640fd2c6c53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
{-# LANGUAGE ApplicativeDo   #-}
{-# LANGUAGE LambdaCase      #-}
{-# LANGUAGE TemplateHaskell #-}

module Main where

import           Control.Applicative              ((<|>))
import           Control.Monad                    (join)

import           Data.Default.Class               (def)
import           Data.List                        (intersperse, (\\))
import           Data.Monoid                      ((<>))
import qualified Data.Text                        as T
import qualified Data.Text.IO                     as T

import           Options.Applicative
import qualified Options.Applicative.Help.Pretty  as P

import           System.Directory                 (doesFileExist)
import           System.IO.Temp                   (writeSystemTempFile)

import           Text.Pandoc.Filter.Plot          (availableToolkits,
                                                   plotTransform)
import           Text.Pandoc.Filter.Plot.Internal (Toolkit (..), cls, Configuration(..),
                                                   supportedSaveFormats, 
                                                   configuration, toolkits)

import           Text.Pandoc.JSON                 (toJSONFilter)

import           Web.Browser                      (openBrowser)

import qualified Data.Version                     as V
import           Paths_pandoc_plot                (version)

import           ManPage                          (embedManualHtml)
import           ExampleConfig                    (embedExampleConfig)

main :: IO ()
main = join $ execParser opts
    where
        opts = info (run <**> helper)
            (fullDesc
            <> progDesc "This pandoc filter generates plots from code blocks using a multitude of possible renderers. This allows to keep documentation and figures in perfect synchronicity."
            <> header "pandoc-plot - generate figures directly in documents using your plotting toolkit of choice."
            <> footerDoc (Just footer')
            )


toJSONFilterWithConfig :: IO ()
toJSONFilterWithConfig = do
    c <- config
    toJSONFilter (plotTransform c)


config :: IO Configuration
config = do 
    configExists <- doesFileExist ".pandoc-plot.yml"
    if configExists
        then configuration ".pandoc-plot.yml" 
        else return def


data Flag = Version
          | Manual
          | Toolkits
          | Config
    deriving (Eq)


run :: Parser (IO ())
run = do
    versionP <- flag Nothing (Just Version) (mconcat
        [ long "version"
        , short 'v'
        , help "Show version number and exit."
        ])

    manualP  <- flag Nothing (Just Manual) (mconcat
        [ long "manual"
        , short 'm'
        , help "Open the manual page in the default web browser and exit."
        ])

    toolkitsP <- flag Nothing (Just Toolkits) (mconcat
        [ long "toolkits"
        , short 't'
        , help "Show information on toolkits and exit. Executables from the configuration \
               \file will be used, if a '.pandoc-plot.yml' file is in the current directory."
        ])
    
    configP <- flag Nothing (Just Config) (mconcat
        [ long "write-example-config"
        , help "Write an example configuration in '.pandoc-plot.yml', \
               \which you can subsequently customize, and exit. If '.pandoc-plot.yml' \
               \already exists, an error will be thrown. "])

    input    <- optional $ strArgument (metavar "AST")
    return $ go (versionP <|> manualP <|> toolkitsP <|> configP) input
    where
        go :: Maybe Flag -> Maybe String -> IO ()
        go (Just Version)  _ = putStrLn (V.showVersion version)
        go (Just Manual)   _ = writeSystemTempFile "pandoc-plot-manual.html" (T.unpack manualHtml)
                                >>= \fp -> openBrowser ("file:///" <> fp)
                                >> return ()
        go (Just Toolkits) _ = do
            c <- config
            putStrLn "\nAVAILABLE TOOLKITS\n"
            available <- availableToolkits c
            return available >>= mapM_ toolkitInfo
            putStrLn "\nUNAVAILABLE TOOLKITS\n"
            -- We don't use unavailableToolkits because this would force
            -- more IO actions
            let unavailable = toolkits \\ available
            return unavailable >>= mapM_ toolkitInfo
        go (Just Config)   _ = T.writeFile ".example-pandoc-plot.yml" exampleConfig

        go Nothing         _ = toJSONFilterWithConfig


manualHtml :: T.Text
manualHtml = T.pack $(embedManualHtml)


exampleConfig :: T.Text
exampleConfig = T.pack $(embedExampleConfig)


toolkitInfo :: Toolkit -> IO ()
toolkitInfo tk = do
    putStrLn $ "Toolkit: " <> show tk
    putStrLn $ "    Code block trigger: " <> (T.unpack . cls $ tk)
    putStrLn $ "    Supported save formats: " <> (mconcat . intersperse ", " . fmap show $ supportedSaveFormats tk)
    putStrLn mempty


-- | Use Doc type directly because of newline formatting
footer' :: P.Doc
footer' = mconcat [
        P.text "Example usage with pandoc:"
    , P.line, P.line
    , P.indent 4 $ P.string "> pandoc --filter pandoc-plot input.md --output output.html"
    , P.line, P.line
    , P.text "If you use pandoc-plot in combination with other filters, you probably want to run pandoc-plot first. Here is an example with pandoc-crossref:"
    , P.line, P.line
    , P.indent 4 $ P.string "> pandoc --filter pandoc-plot --filter pandoc-crossref -i input.md -o output.pdf"
    , P.line, P.line
    , P.text "More information can be found via the manual (pandoc-plot --manual) or the repository README, located at"
    , P.line
    , P.indent 4 $ P.text "https://github.com/LaurentRDC/pandoc-plot"
    , P.line
    ]