Skip to content
4 changes: 2 additions & 2 deletions simplex.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,5 @@ Executable simplex
, mtl >= 2.0.1
, time >= 1.4
, random >= 1.0


, text >= 1.0
, MissingH >= 1.5.0
20 changes: 19 additions & 1 deletion src/Simplex/CmdLineOpts.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import Data.Maybe
data Flag = Help | Verbose | Print | NoClean
| Pdflatex String | Pdfcrop String
| Graphviz String | Gnuplot String
| Ditaa String | PlantUML String
| Mermaid String | Java String
| Watch Int | DryRun | Type String
| Density Int | Quality Int | Crop
| Convert String | Force | Version
Expand All @@ -38,7 +40,11 @@ data Opts = Opts {
optPdflatex :: String,
optPdfcrop :: String,
optGraphviz :: String,
optJava :: String,
optGnuplot :: String,
optDitaa :: String,
optPlantUML :: String,
optMermaid :: String,
optConvert :: String
}

Expand All @@ -62,6 +68,10 @@ defOpts = Opts {
optPdfcrop = "pdfcrop",
optGraphviz = "dot",
optGnuplot = "gnuplot",
optJava = "java",
optDitaa = "ditaa.jar",
optPlantUML = "plantuml.jar",
optMermaid = "mmdc",
optConvert = "convert"
}

Expand All @@ -74,12 +84,16 @@ cmdOpts = [
Option "p" ["print"] (NoArg Print) "Print processed tex to stdout.",
Option "c" ["crop"] (NoArg Crop) "Crops the document so that no margins are left.",
Option "f" ["force"] (NoArg Force) "Forces the creation of output files.",
Option "tT" ["type"] (ReqArg Type "") "Specify type of output (pdf, png, tex)",
Option "tT" ["type"] (ReqArg Type "") "Specify type of output (pdf, png, tex, html)",
Option "x" ["pdflatex"] (ReqArg Pdflatex "") "Path to `pdflatex' executable",
Option "k" ["pdfcrop"] (ReqArg Pdfcrop "") "Path to `pdfcrop'",
Option "z" ["graphviz"] (ReqArg Graphviz "") "Path to `dot' (graphviz)",
Option "g" ["gnuplot"] (ReqArg Gnuplot "") "Path to `gnuplot'",
Option "m" ["convert"] (ReqArg Convert "") "Path to `convert' (ImageMagick)",
Option "" ["java"] (ReqArg Java "") "Path to `java'",
Option "" ["mmdc"] (ReqArg Mermaid "") "Path to `mmdc'",
Option "" ["ditaa"] (ReqArg Ditaa "") "Path to ditaai.jar",
Option "" ["plantuml"] (ReqArg PlantUML "") "Path to plantuml.jar",
Option "w" ["watch"] (OptArg (Watch . read . fromMaybe "2000") "") "Watch files or folder (optionally amount of time in ms)",
Option "3" ["three-times"] (NoArg ThreeTimes) "Execute `pdflatex' three times instead of the default two times.",
Option "s" ["symbols"] (OptArg (ListSymbols . fromMaybe "\\%s\n") "") "Show a list of symboles known to simplex.",
Expand Down Expand Up @@ -115,6 +129,10 @@ parseArgs = do
Pdflatex c -> opts { optPdflatex = c }
Pdfcrop c -> opts { optPdfcrop = c }
Graphviz c -> opts { optGraphviz = c }
Java c -> opts { optJava = c }
Mermaid c -> opts { optMermaid = c }
Ditaa c -> opts { optDitaa = c }
PlantUML c -> opts { optPlantUML = c }
Gnuplot c -> opts { optGnuplot = c }
Convert c -> opts { optConvert = c }
parseOpts opts _ = opts
Expand Down
20 changes: 15 additions & 5 deletions src/Simplex/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ data State = SStart | SNewline | SControl | SControlAfter | SSymbol | SSpace | S
isBlock (TBlock _) = True
isBlock _ = False

convertAlias :: String -> String
convertAlias s =
case s of
".chapter" -> "!!"
".part" -> "!!!"
".section" -> "="
".subsection" -> "=="
".subsubsection" -> "==="
_ -> s

parse :: [Token] -> Document
parse = parse' $ Document [] []

Expand Down Expand Up @@ -314,7 +324,7 @@ lex' l c m SStart s@(x:xs)
| otherwise = lex' l (c+1) [x] SControl xs

lex' l c m SNewline s@(x:xs)
| x == '\n' = mkBlock m : lex' (l+1) 0 m SStart xs
| x == '\n' = mkBlock m : lex' (l+1) 0 [] SStart xs
| x == ' ' = lex' l (c+1) m SSpace xs
| x == '\t' = lex' l (c+1) ('\n':m) SSymbol xs
| isAlpha x = mkBlock m : lex' l (c+1) [x] SCommand xs
Expand All @@ -327,10 +337,10 @@ lex' l c m SCommand s@(x:xs)
| otherwise = lex' l (c+1) (x:m) SCommand xs

lex' l c m SControl s@(x:xs)
| x == ' ' && c < 4 = TControl (reverse m) : lex' l (c+1) [] SControlAfter xs
| x == ' ' = TControl (reverse m) : lex' l (c+1) [] SSymbol xs
| x == '\t' = TControl (reverse m) : lex' l (c+1) [] SSymbol xs
| x == '\n' = TControl (reverse m) : lex' (l+1) 0 [] SNewline xs
| x == ' ' && c < 4 = TControl (convertAlias (reverse m)) : lex' l (c+1) [] SControlAfter xs
| x == ' ' = TControl (convertAlias (reverse m)) : lex' l (c+1) [] SSymbol xs
| x == '\t' = TControl (convertAlias (reverse m)) : lex' l (c+1) [] SSymbol xs
| x == '\n' = TControl (convertAlias (reverse m)) : lex' (l+1) 0 [] SNewline xs
| otherwise = lex' l (c+1) (x:m) SControl xs

lex' l c m SControlAfter s@(x:xs)
Expand Down
110 changes: 94 additions & 16 deletions src/Simplex/Specials.hs
Original file line number Diff line number Diff line change
Expand Up @@ -35,32 +35,60 @@ processSpecials o s (Document b m) = do
processSpecials' :: Opts -> Spec -> [Block] -> IO (Spec, [Block])

processSpecials' opts spec (BVerbatim "digraph" b : xs) = do
(spec', pdf) <- mkGraph "dot" "digraph" opts spec b
(spec', g) <- mkGraph "dot" "digraph" opts spec b
(spec'', rest) <- processSpecials' opts spec' xs
return (spec'', (if null pdf
return (spec'', (if null g
then BVerbatim "error" "Graphviz .digraph failed"
else BCommand "image" [pdf]) : rest)
else BCommand "image" [g]) : rest)

processSpecials' opts spec (BVerbatim "graph" b : xs) = do
(spec', pdf) <- mkGraph "neato" "graph" opts spec b
(spec', g) <- mkGraph "neato" "graph" opts spec b
(spec'', rest) <- processSpecials' opts spec' xs
return (spec'', (if null pdf
return (spec'', (if null g
then BVerbatim "error" "Graphviz .graph failed"
else BCommand "image" [pdf]) : rest)
else BCommand "image" [g]) : rest)

processSpecials' opts spec (BVerbatim "neato" b : xs) = do
(spec', pdf) <- mkGraph "neato" "" opts spec b
(spec', g) <- mkGraph "neato" "" opts spec b
(spec'', rest) <- processSpecials' opts spec' xs
return (spec'', (if null pdf
return (spec'', (if null g
then BVerbatim "error" "Graphviz .neato failed"
else BCommand "image" [pdf]) : rest)
else BCommand "image" [g]) : rest)

processSpecials' opts spec (BVerbatim "dot" b : xs) = do
(spec', pdf) <- mkGraph "dot" "" opts spec b
(spec', g) <- mkGraph "dot" "" opts spec b
(spec'', rest) <- processSpecials' opts spec' xs
return (spec'', (if null pdf
return (spec'', (if null g
then BVerbatim "error" "Graphviz .dot failed"
else BCommand "image" [pdf]) : rest)
else BCommand "image" [g]) : rest)

processSpecials' opts spec (BVerbatim "gnuplot" b : xs) = do
(spec', g) <- mkGraph "gnuplot" "" opts spec b
(spec'', rest) <- processSpecials' opts spec' xs
return (spec'', (if null g
then BVerbatim "error" "Gnuplot .gp failed"
else BCommand "image" [g]) : rest)

processSpecials' opts spec (BVerbatim "mermaid" b : xs) = do
(spec', g) <- mkGraph "mermaid" "" opts spec b
(spec'', rest) <- processSpecials' opts spec' xs
return (spec'', (if null g
then BVerbatim "error" "Mermaid .mmd failed"
else BCommand "image" [g]) : rest )

processSpecials' opts spec (BVerbatim "ditaa" b : xs) = do
(spec', png) <- mkGraph "ditaa" "" opts spec b
(spec'', rest) <- processSpecials' opts spec' xs
return (spec'', (if null png
then BVerbatim "error" "ditaa .ditaa failed"
else BCommand "image" [png]) : rest )

processSpecials' opts spec (BVerbatim "plantuml" b : xs) = do
(spec', g) <- mkGraph "plantuml" "" opts spec b
(spec'', rest) <- processSpecials' opts spec' xs
return (spec'', (if null g
then BVerbatim "error" "plantuml .plantuml failed"
else BCommand "image" [g]) : rest )

processSpecials' opts spec (x : xs) = do
(spec', rest) <- processSpecials' opts spec xs
Expand All @@ -78,10 +106,60 @@ randomString n = do

mkGraph e g opts spec c = do
file <- randomString 10

let spec' = spec { sRemoveFiles = (file ++ ".pdf") : (file ++ ".dot") : sRemoveFiles spec }
case e of
"dot" -> mkGraphDot e file g opts spec c
"neato" -> mkGraphDot e file g opts spec c
"gnuplot" -> mkGraphGnuPlot e file g opts spec c
"mermaid" -> mkGraphMermaid e file g opts spec c
"ditaa" -> mkGraphDitaa e file g opts spec c
"plantuml" -> mkGraphPlantUML e file g opts spec c
_ -> return (spec, [])


mkGraphDot e file g opts spec c = do
let spec' = if (optType opts == "html")
then spec { sRemoveFiles = (file ++ ".dot") : sRemoveFiles spec }
else spec { sRemoveFiles = (file ++ ".jpeg") : (file ++ ".dot") : sRemoveFiles spec}
writeFile (file ++ ".dot") (if null g then c else g ++ " G {\n" ++ c ++ "\n}\n")

r <- exec (optVerbose opts) (optGraphviz opts) ["-Tpdf", "-K" ++ e, file ++ ".dot", "-o" ++ file ++ ".pdf"]
return (spec', (either (const "") (const $ file ++ ".pdf") r))
r <- exec (optVerbose opts) (optGraphviz opts) ["-Tjpeg", "-K" ++ e, file ++ ".dot", "-o" ++ file ++ ".jpeg"]
return (spec', (either (const "") (const $ file ++ ".jpeg") r))

mkGraphGnuPlot e file g opts spec c = do
let spec' = if (optType opts == "html" )
then spec { sRemoveFiles = (file ++ ".gp") : sRemoveFiles spec }
else spec { sRemoveFiles = (file ++ ".jpeg") : (file ++ ".gp") : sRemoveFiles spec }
writeFile (file ++ ".gp") ("set terminal jpeg\n" ++ "set output \"" ++ file ++ ".jpeg" ++ "\"\n" ++c ++ "\n")

r <- exec (optVerbose opts) (optGnuplot opts) [file ++ ".gp"]
return (spec', (either (const "") (const $ file ++ ".jpeg") r))

mkGraphMermaid e file g opts spec c = do
let spec' = if (optType opts == "html")
then spec { sRemoveFiles = (file ++ ".mmd") : sRemoveFiles spec}
else spec { sRemoveFiles = (file ++ ".png") : (file ++ ".mmd") : sRemoveFiles spec}
writeFile (file ++ ".mmd") (c ++ "\n")

r <- exec (optVerbose opts) (optMermaid opts) ["-i", file ++ ".mmd" , "-o", file ++ ".png"]

return (spec', (either (const "") (const $ file ++ ".png") r))

mkGraphDitaa e file g opts spec c = do
let spec' = if (optType opts == "html")
then spec { sRemoveFiles = (file ++ ".ditaa") : sRemoveFiles spec}
else spec { sRemoveFiles = (file ++ ".png") : (file ++ ".ditaa") : sRemoveFiles spec}
writeFile (file ++ ".ditaa") (c ++ "\n")

r <- exec (optVerbose opts) (optJava opts) ["-jar", (optDitaa opts),file ++ ".ditaa", file ++ ".png"]

return (spec', (either (const "") (const $ file ++ ".png") r))

mkGraphPlantUML e file g opts spec c = do
let spec' = if (optType opts == "html")
then spec { sRemoveFiles = (file ++ ".plantuml") : sRemoveFiles spec }
else spec { sRemoveFiles = (file ++ ".png") : (file ++ ".plantuml") : sRemoveFiles spec }
writeFile (file ++ ".plantuml") ("@startuml\n" ++ c ++ "\n@enduml\n")

r <- exec (optVerbose opts) (optJava opts) ["-jar", (optPlantUML opts), file ++ ".plantuml"]

return (spec', (either (const "") (const $ file ++ ".png") r))
57 changes: 48 additions & 9 deletions src/Simplex/ToTeX.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{-# LANGUAGE Haskell2010 #-}

module Simplex.ToTeX (toTeX) where
module Simplex.ToTeX (toTeX, docProps) where

import Simplex.Parser
import Simplex.Config
Expand Down Expand Up @@ -115,13 +115,45 @@ packages = [("inputenc", "\\usepackage[utf8]{inputenc}\n"),

]

docProps doc@(Document blocks props) = props

toTeX cfg doc@(Document blocks props) = concat $ preamble $ toTeX' cfg' $ blocks
where
cfg' = config cfg doc
preamble xs =
documentClass cfg' props

: "\\usepackage{iftex}\n"
: "\\ifPDFTeX"
: "\\usepackage{lmodern} % pdflatex or dvi latex\n"
: "\\usepackage[T1]{fontenc}\n"
: "\\usepackage[utf8]{inputenc}\n"
: "\\else\n"
: "\\usepackage{fontspec} % XeLaTeX or LuaLaTeX\n"
: "\\fi\n"
: maybe
""
(\x -> "\\usepackage[heading = true ]{ctex}\n")
(lookup "cjk" props)
: "\\usepackage[\n"
: "latexmk\n"
: "]{lwarp}\n"
: maybe
""
(\x -> "\\setcounter{FileDepth}{" ++ x ++ "}\n")
(lookup "filedepth" props)
: maybe
""
(\x -> "\\setcounter{SideTOCDepth}{" ++ x ++ "}\n")
(lookup "sidetocdepth" props)
: maybe
""
(\x -> "\\boolfalse{FileSectionNames}\n")
(lookup "nofilesectionnames" props)
: maybe
""
(\x -> "\\CSSFilename{" ++ x ++ "}\n")
(lookup "css" props)
: maybe
""
(\x -> "\\usepackage[" ++ x ++ "]{babel}\n")
Expand All @@ -130,28 +162,31 @@ toTeX cfg doc@(Document blocks props) = concat $ preamble $ toTeX' cfg' $ blocks
: "\\usepackage{fancyhdr}\n"
: "\\usepackage{tabularx}\n"

: "\\usepackage{eurosym}\n"
: "\\DeclareUnicodeCharacter{20AC}{\\euro{}}\n"
: "%% \\usepackage{eurosym}\n"
: maybe
"%% \\DeclareUnicodeCharacter{20AC}{\\euro{}}\n"
(\x -> "")
(lookup "cjk" props)

: "\\usepackage{amsmath}\n"
: "\\usepackage{amsfonts}\n"
: "\\usepackage{amssymb}\n"

: "\\usepackage{stmaryrd}\n"
: "\\usepackage{wasysym}\n"
: "%% \\usepackage{wasysym}\n"

: "\\let\\EUR\\undefined\n"
: "\\usepackage{marvosym}\n"
: "%% \\let\\EUR\\undefined\n"
: "%% \\usepackage{marvosym}\n"

: "\\usepackage{verbatim}\n"
: "\\usepackage{listings}\n"
: "\\usepackage{multicol}\n"

: "\\usepackage[usenames,dvipsnames]{color}\n"
: "\\usepackage[table]{xcolor}\n"
: "\\usepackage{multirow}\n"
: "%% \\usepackage[table]{xcolor}\n"
: "%% \\usepackage{multirow}\n"

: "\\usepackage{lastpage}\n"
: "%% \\usepackage{lastpage}\n"
: "\\usepackage{graphicx}\n"
: maybe
"\\usepackage[section]{placeins}\n"
Expand Down Expand Up @@ -251,6 +286,10 @@ toTeX cfg doc@(Document blocks props) = concat $ preamble $ toTeX' cfg' $ blocks
(\x -> "\\setcounter{tocdepth}{" ++ x ++ "}\n")
(lookup "tocdepth" props)

: maybe
"\\newcommand{\\setkomavar}[2]{} %% FIXME: later\n"
(\x -> "")
(lookup "letter" props)
: maybe
""
(\x -> "\\setkomavar{fromaddress}{" ++ escapeTeX' "}\n" x)
Expand Down
1 change: 1 addition & 0 deletions src/Simplex/Util.hs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ skipOneSpace s = s

removeIfExists :: String -> IO ()
removeIfExists file = do
print $ "removing file " ++ file
exists <- doesFileExist file
when exists (removeFile file)

Expand Down
Loading