{-# LANGUAGE ApplicativeDo #-}
module Slab.Command
( Command (..)
, CommandWithPath (..)
, RenderMode (..)
, ParseMode (..)
, RunMode (..)
, parserInfo
) where
import Data.Text (Text)
import Data.Version (showVersion)
import Options.Applicative ((<**>))
import Options.Applicative qualified as A
import Paths_slab (version)
data Command
= Build FilePath RenderMode RunMode FilePath
| Watch FilePath RenderMode RunMode FilePath
| Serve FilePath FilePath
| ReportPages FilePath
| ReportHeadings FilePath
|
ReportElement Text FilePath
|
Generate FilePath
| CommandWithPath FilePath ParseMode CommandWithPath
data CommandWithPath
= Render RenderMode RunMode
|
Execute Bool RunMode
|
Evaluate Bool
| Parse
| TODO
Classes
|
Fragments (Maybe Text)
data RenderMode = RenderNormal | RenderPretty
data ParseMode
=
ParseShallow
|
ParseDeep
data RunMode
=
RunNormal
|
RunPassthrough
parserInfo :: A.ParserInfo Command
parserInfo =
A.info (parser <**> simpleVersioner ("slab " <> version') <**> A.helper) $
A.fullDesc
<> A.header
("slab " <> version' <> " - A programmable markup language to generate HTML")
<> A.progDesc
"Slab is a programmable markup language to generate HTML."
where
version' = showVersion version
parser :: A.Parser Command
parser =
A.subparser
( A.command
"build"
( A.info (parserBuild <**> A.helper) $
A.progDesc
"Build a library of Slab templates to HTML"
)
<> A.command
"watch"
( A.info (parserWatch <**> A.helper) $
A.progDesc
"Watch and build a library of Slab templates to HTML"
)
<> A.command
"serve"
( A.info (parserServe <**> A.helper) $
A.progDesc
"Watch and serve a library of Slab templates"
)
<> A.command
"report"
( A.info (parserReport <**> A.helper) $
A.progDesc
"Analyse a library of Slab templates"
)
<> A.command
"render"
( A.info (parserRender <**> A.helper) $
A.progDesc
"Render a Slab template to HTML"
)
<> A.command
"run"
( A.info (parserExectue <**> A.helper) $
A.progDesc
"Execute a Slab template"
)
<> A.command
"evaluate"
( A.info (parserEvaluate <**> A.helper) $
A.progDesc
"Evaluate a Slab template"
)
<> A.command
"parse"
( A.info (parserParse <**> A.helper) $
A.progDesc
"Parse a Slab template to AST"
)
<> A.command
"generate"
( A.info (parserGenerate <**> A.helper) $
A.progDesc
"Generate code corresponding to a Slab template"
)
<> A.command
"classes"
( A.info (parserClasses <**> A.helper) $
A.progDesc
"Parse a Slab template and report its CSS classes"
)
<> A.command
"fragments"
( A.info (parserFragments <**> A.helper) $
A.progDesc
"Parse a Slab template and report its fragments"
)
)
parserBuild :: A.Parser Command
parserBuild = do
srcDir <-
A.argument
A.str
(A.metavar "DIR" <> A.action "file" <> A.help "Directory of Slab templates to build.")
mode <-
A.flag
RenderNormal
RenderPretty
( A.long "pretty" <> A.help "Use pretty-printing"
)
passthrough <- parserPassthroughFlag
distDir <-
A.strOption
( A.long "dist"
<> A.value "./_site"
<> A.metavar "DIR"
<> A.help
"A destination directory for the generated HTML files."
)
pure $ Build srcDir mode passthrough distDir
parserServe :: A.Parser Command
parserServe = do
srcDir <-
A.argument
A.str
(A.metavar "DIR" <> A.action "file" <> A.help "Directory of Slab templates to build.")
distDir <-
A.strOption
( A.long "dist"
<> A.value "./_site"
<> A.metavar "DIR"
<> A.help
"A directory with existing static files."
)
pure $ Serve srcDir distDir
parserReport :: A.Parser Command
parserReport =
A.subparser
( A.command
"pages"
( A.info (parserReportPages <**> A.helper) $
A.progDesc
"Report pages found in a directory"
)
<> A.command
"headings"
( A.info (parserReportHeadings <**> A.helper) $
A.progDesc
"Report the headings of a page"
)
<> A.command
"element"
( A.info (parserReportElement <**> A.helper) $
A.progDesc
"Return the content of element matching the provided ID"
)
)
parserReportPages :: A.Parser Command
parserReportPages = do
srcDir <-
A.argument
A.str
(A.metavar "DIR" <> A.action "file" <> A.help "Directory of Slab templates to analyse.")
pure $ ReportPages srcDir
parserReportHeadings :: A.Parser Command
parserReportHeadings = do
path <- parserTemplatePath
pure $ ReportHeadings path
parserReportElement :: A.Parser Command
parserReportElement = do
id_ <-
A.argument
A.str
(A.metavar "ID" <> A.help "Element ID to match.")
path <- parserTemplatePath
pure $ ReportElement id_ path
parserWatch :: A.Parser Command
parserWatch = do
srcDir <-
A.argument
A.str
(A.metavar "DIR" <> A.action "file" <> A.help "Directory of Slab templates to watch.")
mode <-
A.flag
RenderNormal
RenderPretty
( A.long "pretty" <> A.help "Use pretty-printing"
)
passthrough <- parserPassthroughFlag
distDir <-
A.strOption
( A.long "dist"
<> A.value "./_site"
<> A.metavar "DIR"
<> A.help
"A destination directory for the generated HTML files."
)
pure $ Watch srcDir mode passthrough distDir
parserExectue :: A.Parser Command
parserExectue = do
pathAndmode <- parserWithPath
simpl <-
A.switch
( A.long "simplify" <> A.help "Simplify the AST"
)
passthrough <- parserPassthroughFlag
pure $ uncurry CommandWithPath pathAndmode $ Execute simpl passthrough
parserRender :: A.Parser Command
parserRender = do
mode <-
A.flag
RenderNormal
RenderPretty
( A.long "pretty" <> A.help "Use pretty-printing"
)
pathAndmode <- parserWithPath
passthrough <- parserPassthroughFlag
pure $ uncurry CommandWithPath pathAndmode $ Render mode passthrough
parserEvaluate :: A.Parser Command
parserEvaluate = do
pathAndmode <- parserWithPath
simpl <-
A.switch
( A.long "simplify" <> A.help "Simplify the AST"
)
pure $ uncurry CommandWithPath pathAndmode $ Evaluate simpl
parserParse :: A.Parser Command
parserParse = do
pathAndmode <- parserWithPath
pure $ uncurry CommandWithPath pathAndmode Parse
parserGenerate :: A.Parser Command
parserGenerate = do
path <- parserTemplatePath
pure $ Generate path
parserClasses :: A.Parser Command
parserClasses = do
pathAndmode <- parserWithPath
pure $ uncurry CommandWithPath pathAndmode Classes
parserFragments :: A.Parser Command
parserFragments = do
pathAndmode <- parserWithPath
mname <-
A.optional $
A.argument
A.str
(A.metavar "NAME" <> A.help "Fragment name to extract.")
pure $ uncurry CommandWithPath pathAndmode $ Fragments mname
parserWithPath :: A.Parser (FilePath, ParseMode)
parserWithPath = (,) <$> parserTemplatePath <*> parserShallowFlag
parserTemplatePath :: A.Parser FilePath
parserTemplatePath =
A.argument
A.str
(A.metavar "FILE" <> A.action "file" <> A.help "Slab template to parse.")
parserShallowFlag :: A.Parser ParseMode
parserShallowFlag =
A.flag
ParseDeep
ParseShallow
( A.long "shallow" <> A.help "Don't parse recursively the included Slab files"
)
parserPassthroughFlag :: A.Parser RunMode
parserPassthroughFlag =
A.flag
RunNormal
RunPassthrough
( A.long "passthrough" <> A.help "Allow external command failures"
)
simpleVersioner
:: String
-> A.Parser (a -> a)
simpleVersioner version_ =
A.infoOption version_ $
mconcat
[ A.long "version"
, A.short 'v'
, A.help "Show version information"
, A.hidden
]