1-- | Main Pandoc program. Parses command-line options and calls the
2-- appropriate readers and writers.
4import Text.Pandoc.UTF8 ( decodeUTF8, encodeUTF8 )
5import Text.Pandoc.Readers.Markdown ( readMarkdown )
6import Text.Pandoc.Readers.HTML ( readHtml )
7import Text.Pandoc.Writers.S5 ( s5CSS, s5Javascript, writeS5 )
8import Text.Pandoc.Writers.RST ( writeRST )
9import Text.Pandoc.Readers.RST ( readRST )
10import Text.Pandoc.ASCIIMathML ( asciiMathMLScript )
11import Text.Pandoc.Writers.HTML ( writeHtml )
12import Text.Pandoc.Writers.LaTeX ( writeLaTeX )
13import Text.Pandoc.Readers.LaTeX ( readLaTeX )
14import Text.Pandoc.Writers.RTF ( writeRTF )
15import Text.Pandoc.Writers.Markdown ( writeMarkdown )
16import Text.Pandoc.Writers.DefaultHeaders ( defaultHtmlHeader, defaultRTFHeader, defaultS5Header, defaultLaTeXHeader )
17import Text.Pandoc.Definition
18import Text.Pandoc.Shared
19import System ( exitWith, getArgs, getProgName )
21import System.Console.GetOpt
22import IO ( stdout, stderr, hPutStrLn )
23import Data.Maybe ( fromMaybe )
24import Data.List ( isPrefixOf )
25import Char ( toLower )
26import Control.Monad ( (>>=) )
31-- | Association list of formats and readers.
32readers :: [(String, ParserState -> String -> Pandoc)]
33readers = [("native" , readPandoc)
34 ,("markdown" , readMarkdown)
37 ,("latex" , readLaTeX)
40-- | Reader for native Pandoc format.
41readPandoc :: ParserState -> String -> Pandoc
42readPandoc state input = read input
44-- | Association list of formats and pairs of writers and default headers.
45writers :: [ ( String, ( WriterOptions -> Pandoc -> String, String ) ) ]
46writers = [("native" , (writeDoc, ""))
47 ,("html" , (writeHtml, defaultHtmlHeader))
48 ,("s5" , (writeS5, defaultS5Header))
49 ,("latex" , (writeLaTeX, defaultLaTeXHeader))
50 ,("markdown" , (writeMarkdown, ""))
51 ,("rst" , (writeRST, ""))
52 ,("rtf" , (writeRTF, defaultRTFHeader))
55-- | Writer for Pandoc native format.
56writeDoc :: WriterOptions -> Pandoc -> String
57writeDoc options = prettyPandoc
59-- | Data structure for command line options.
61 { optPreserveTabs :: Bool -- ^ If @False@, convert tabs to spaces
62 , optTabStop :: Int -- ^ Number of spaces per tab
63 , optStandalone :: Bool -- ^ If @True@, include header and footer
64 , optReader :: ParserState -> String -> Pandoc -- ^ Reader to use
65 , optWriter :: WriterOptions -> Pandoc -> String -- ^ Writer to use
66 , optParseRaw :: Bool -- ^ If @True@, parse unconvertable HTML and TeX
67 , optCSS :: String -- ^ CSS file to link to
68 , optIncludeInHeader :: String -- ^ File to include in header
69 , optIncludeBeforeBody :: String -- ^ File to include at beginning of body
70 , optIncludeAfterBody :: String -- ^ File to include at end of body
71 , optCustomHeader :: String -- ^ Custom header to use, or "DEFAULT"
72 , optDefaultHeader :: String -- ^ Default header
73 , optTitlePrefix :: String -- ^ Optional prefix for HTML title
74 , optNumberSections :: Bool -- ^ If @True@, number sections in LaTeX
75 , optIncremental :: Bool -- ^ If @True@, show lists incrementally in S5
76 , optSmartypants :: Bool -- ^ If @True@, use smart quotes, dashes, ...
77 , optASCIIMathML :: Bool -- ^ If @True@, use ASCIIMathML in HTML or S5
80-- | Defaults for command-line options.
83 { optPreserveTabs = False
85 , optStandalone = False
86 , optReader = readMarkdown
87 , optWriter = writeHtml
90 , optIncludeInHeader = ""
91 , optIncludeBeforeBody = ""
92 , optIncludeAfterBody = ""
93 , optCustomHeader = "DEFAULT"
94 , optDefaultHeader = defaultHtmlHeader
96 , optNumberSections = False
97 , optIncremental = False
98 , optSmartypants = False
99 , optASCIIMathML = False
102-- | A list of functions, each transforming the options data structure in response
103-- to a command-line option.
104options :: [OptDescr (Opt -> IO Opt)]
106 [ Option "v" ["version"]
109 hPutStrLn stderr ("Version " ++ version)
110 exitWith ExitSuccess))
113 , Option "h" ["help"]
117 hPutStrLn stderr (usageInfo (prg ++ " [OPTIONS] [FILES] - convert FILES from one markup format to another\nIf no OPTIONS specified, converts from markdown to html.\nIf no FILES specified, input is read from STDIN.\nOptions:") options)
118 exitWith ExitSuccess))
121 , Option "fr" ["from","read"]
123 (\arg opt -> case (lookup (map toLower arg) readers) of
124 Just reader -> return opt { optReader = reader }
125 Nothing -> error ("Unknown reader: " ++ arg) )
127 ("Source format (" ++ (concatMap (\(name, fn) -> " " ++ name) readers) ++ " )")
129 , Option "tw" ["to","write"]
131 (\arg opt -> case (lookup (map toLower arg) writers) of
132 Just (writer, defaultHeader) ->
133 return opt { optWriter = writer,
134 optDefaultHeader = defaultHeader }
135 Nothing -> error ("Unknown writer: " ++ arg) )
137 ("Output format (" ++ (concatMap (\(name, fn) -> " " ++ name) writers) ++ " )")
139 , Option "s" ["standalone"]
141 (\opt -> return opt { optStandalone = True }))
142 "Include needed header and footer on output"
144 , Option "p" ["preserve-tabs"]
146 (\opt -> return opt { optPreserveTabs = True }))
147 "Preserve tabs instead of converting to spaces"
149 , Option "" ["tab-stop"]
151 (\arg opt -> return opt { optTabStop = (read arg) } )
153 "Tab stop (default 4)"
155 , Option "R" ["parse-raw"]
157 (\opt -> return opt { optParseRaw = True }))
158 "Parse untranslatable HTML codes and LaTeX environments as raw"
160 , Option "S" ["smartypants"]
162 (\opt -> return opt { optSmartypants = True }))
163 "Use smartypants for html output"
165 , Option "m" ["asciimathml"]
167 (\opt -> return opt { optASCIIMathML = True, optStandalone = True }))
168 "Use ASCIIMathML script in html output"
170 , Option "i" ["incremental"]
172 (\opt -> return opt { optIncremental = True }))
173 "Make list items display incrementally in S5"
175 , Option "N" ["number-sections"]
177 (\opt -> return opt { optNumberSections = True }))
178 "Number sections in LaTeX"
182 (\arg opt -> return opt { optCSS = arg, optStandalone = True })
184 "Link to CSS style sheet"
186 , Option "H" ["include-in-header"]
190 return opt { optIncludeInHeader = text, optStandalone = True })
192 "File to include at end of header (implies -s)"
194 , Option "B" ["include-before-body"]
198 return opt { optIncludeBeforeBody = text })
200 "File to include before document body"
202 , Option "A" ["include-after-body"]
206 return opt { optIncludeAfterBody = text })
208 "File to include after document body"
210 , Option "" ["custom-header"]
214 return opt { optCustomHeader = text, optStandalone = True })
216 "File to use for custom header (implies -s)"
218 , Option "T" ["title-prefix"]
220 (\arg opt -> return opt { optTitlePrefix = arg, optStandalone = True })
222 "String to prefix to HTML window title"
224 , Option "D" ["print-default-header"]
227 let header = case (lookup arg writers) of
228 Just (writer, head) -> head
229 Nothing -> error ("Unknown reader: " ++ arg)
230 hPutStrLn stdout header
231 exitWith ExitSuccess)
233 "Print default header for FORMAT"
238 let (actions, sources, errors) = getOpt RequireOrder options args
240 -- thread option data structure through all supplied option actions
241 opts <- foldl (>>=) (return startOpt) actions
243 let Opt { optPreserveTabs = preserveTabs
244 , optTabStop = tabStop
245 , optStandalone = standalone
248 , optParseRaw = parseRaw
250 , optIncludeInHeader = includeHeader
251 , optIncludeBeforeBody = includeBefore
252 , optIncludeAfterBody = includeAfter
253 , optCustomHeader = customHeader
254 , optDefaultHeader = defaultHeader
255 , optTitlePrefix = titlePrefix
256 , optNumberSections = numberSections
257 , optIncremental = incremental
258 , optSmartypants = smartypants
259 , optASCIIMathML = asciiMathML
262 let writingS5 = (defaultHeader == defaultS5Header)
263 let tabFilter = if preserveTabs then id else (tabsToSpaces tabStop)
264 let addBlank str = str ++ "\n\n"
265 let removeCRs str = filter (/= '\r') str -- remove DOS-style line endings
266 let filter = tabFilter . addBlank . removeCRs
267 let startParserState = defaultParserState { stateParseRaw = parseRaw,
268 stateTabStop = tabStop,
269 stateStandalone = standalone }
270 let csslink = if (css == "") then
273 "<link rel=\"stylesheet\" href=\"" ++ css ++
274 "\" type=\"text/css\" media=\"all\" />\n"
275 let asciiMathMLLink = if asciiMathML then asciiMathMLScript else ""
276 let header = (if (customHeader == "DEFAULT") then defaultHeader else customHeader) ++
277 csslink ++ asciiMathMLLink ++ includeHeader
278 let writerOptions = WriterOptions { writerStandalone = standalone,
279 writerHeader = header,
280 writerTitlePrefix = titlePrefix,
281 writerSmartypants = smartypants,
282 writerTabStop = tabStop,
283 writerS5 = writingS5,
284 writerIncremental = incremental,
285 writerNumberSections = numberSections,
286 writerIncludeBefore = includeBefore,
287 writerIncludeAfter = includeAfter }
289 (readSources sources) >>= (putStrLn . encodeUTF8 . (writer writerOptions) .
290 (reader startParserState) . filter .
291 decodeUTF8 . (joinWithSep "\n"))
294 readSources [] = mapM readSource ["-"]
295 readSources sources = mapM readSource sources
296 readSource "-" = getContents
297 readSource source = readFile source
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list