{-# LANGUAGE ApplicativeDo #-}

-- |
-- Module      : Slab.Command
-- Description : Command-line interface to Slab
--
-- @Slab.Command@ provides a command line interface for the Slab program.
--
-- Commands and options are defined by parsers written using the
-- @optparse-applicative@ library.
--
-- The implementation of each command can be found in the "Slab.Run" module.
module Slab.Command
  ( Command (..)
  , CommandWithPath (..)
  , RenderMode (..)
  , ParseMode (..)
  , RunMode (..)
  , parserInfo
  ) where

import Data.Text (Text)
import Options.Applicative ((<**>))
import Options.Applicative qualified as A

--------------------------------------------------------------------------------
data Command
  = Build FilePath RenderMode RunMode FilePath
  | Watch FilePath RenderMode RunMode FilePath
  | Serve FilePath FilePath
  | ReportPages FilePath
  | ReportHeadings FilePath
  | -- | Generate code. Only Haskell for now.
    Generate FilePath
  | CommandWithPath FilePath ParseMode CommandWithPath

-- | Commands operating on a path.
data CommandWithPath
  = Render RenderMode RunMode
  | -- | If True, simplify the evaluated AST.
    Execute Bool RunMode
  | -- | If True, simplify the evaluated AST.
    Evaluate Bool
  | Parse
  | -- | List the classes used in a template. TODO Later, we want to list (or create a tree) of extends/includes.
    Classes
  | -- | List the fragments used in a template. If a name is given, extract that definition.
    Fragments (Maybe Text)

data RenderMode = RenderNormal | RenderPretty

data ParseMode
  = -- | Don't process include statements.
    ParseShallow
  | -- | Process the include statements, creating a complete template.
    ParseDeep

data RunMode
  = -- | A failing external command fails the template.
    RunNormal
  | -- | A failing external command doesn't fail the template and its output is
    -- rendered in the template.
    RunPassthrough

--------------------------------------------------------------------------------
parserInfo :: A.ParserInfo Command
parserInfo :: ParserInfo Command
parserInfo =
  Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parser Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
    InfoMod Command
forall a. InfoMod a
A.fullDesc
      InfoMod Command -> InfoMod Command -> InfoMod Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.header FilePath
"slab - A programmable markup language to generate HTML"
      InfoMod Command -> InfoMod Command -> InfoMod Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
        FilePath
"Slab is a programmable markup language to generate HTML."

--------------------------------------------------------------------------------
parser :: A.Parser Command
parser :: Parser Command
parser =
  Mod CommandFields Command -> Parser Command
forall a. Mod CommandFields a -> Parser a
A.subparser
    ( FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
        FilePath
"build"
        ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserBuild Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
            FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
              FilePath
"Build a library of Slab templates to HTML"
        )
        Mod CommandFields Command
-> Mod CommandFields Command -> Mod CommandFields Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
          FilePath
"watch"
          ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserWatch Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
              FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
                FilePath
"Watch and build a library of Slab templates to HTML"
          )
        Mod CommandFields Command
-> Mod CommandFields Command -> Mod CommandFields Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
          FilePath
"serve"
          ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserServe Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
              FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
                FilePath
"Watch and serve a library of Slab templates"
          )
        Mod CommandFields Command
-> Mod CommandFields Command -> Mod CommandFields Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
          FilePath
"report"
          ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserReport Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
              FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
                FilePath
"Analyse a library of Slab templates"
          )
        Mod CommandFields Command
-> Mod CommandFields Command -> Mod CommandFields Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
          FilePath
"render"
          ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserRender Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
              FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
                FilePath
"Render a Slab template to HTML"
          )
        Mod CommandFields Command
-> Mod CommandFields Command -> Mod CommandFields Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
          FilePath
"run"
          ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserExectue Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
              FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
                FilePath
"Execute a Slab template"
          )
        Mod CommandFields Command
-> Mod CommandFields Command -> Mod CommandFields Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
          FilePath
"evaluate"
          ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserEvaluate Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
              FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
                FilePath
"Evaluate a Slab template"
          )
        Mod CommandFields Command
-> Mod CommandFields Command -> Mod CommandFields Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
          FilePath
"parse"
          ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserParse Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
              FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
                FilePath
"Parse a Slab template to AST"
          )
        Mod CommandFields Command
-> Mod CommandFields Command -> Mod CommandFields Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
          FilePath
"generate"
          ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserGenerate Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
              FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
                FilePath
"Generate code corresponding to a Slab template"
          )
        Mod CommandFields Command
-> Mod CommandFields Command -> Mod CommandFields Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
          FilePath
"classes"
          ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserClasses Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
              FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
                FilePath
"Parse a Slab template and report its CSS classes"
          )
        Mod CommandFields Command
-> Mod CommandFields Command -> Mod CommandFields Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
          FilePath
"fragments"
          ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserFragments Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
              FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
                FilePath
"Parse a Slab template and report its fragments"
          )
    )

--------------------------------------------------------------------------------
parserBuild :: A.Parser Command
parserBuild :: Parser Command
parserBuild = do
  FilePath
srcDir <-
    ReadM FilePath -> Mod ArgumentFields FilePath -> Parser FilePath
forall a. ReadM a -> Mod ArgumentFields a -> Parser a
A.argument
      ReadM FilePath
forall s. IsString s => ReadM s
A.str
      (FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
A.metavar FilePath
"DIR" Mod ArgumentFields FilePath
-> Mod ArgumentFields FilePath -> Mod ArgumentFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasCompleter f => FilePath -> Mod f a
A.action FilePath
"file" Mod ArgumentFields FilePath
-> Mod ArgumentFields FilePath -> Mod ArgumentFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Directory of Slab templates to build.")
  RenderMode
mode <-
    RenderMode
-> RenderMode -> Mod FlagFields RenderMode -> Parser RenderMode
forall a. a -> a -> Mod FlagFields a -> Parser a
A.flag
      RenderMode
RenderNormal
      RenderMode
RenderPretty
      ( FilePath -> Mod FlagFields RenderMode
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
A.long FilePath
"pretty" Mod FlagFields RenderMode
-> Mod FlagFields RenderMode -> Mod FlagFields RenderMode
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod FlagFields RenderMode
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Use pretty-printing"
      )
  RunMode
passthrough <- Parser RunMode
parserPassthroughFlag
  FilePath
distDir <-
    Mod OptionFields FilePath -> Parser FilePath
forall s. IsString s => Mod OptionFields s -> Parser s
A.strOption
      ( FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
A.long FilePath
"dist"
          Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasValue f => a -> Mod f a
A.value FilePath
"./_site"
          Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
A.metavar FilePath
"DIR"
          Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. FilePath -> Mod f a
A.help
            FilePath
"A destination directory for the generated HTML files."
      )
  pure $ FilePath -> RenderMode -> RunMode -> FilePath -> Command
Build FilePath
srcDir RenderMode
mode RunMode
passthrough FilePath
distDir

parserServe :: A.Parser Command
parserServe :: Parser Command
parserServe = do
  FilePath
srcDir <-
    ReadM FilePath -> Mod ArgumentFields FilePath -> Parser FilePath
forall a. ReadM a -> Mod ArgumentFields a -> Parser a
A.argument
      ReadM FilePath
forall s. IsString s => ReadM s
A.str
      (FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
A.metavar FilePath
"DIR" Mod ArgumentFields FilePath
-> Mod ArgumentFields FilePath -> Mod ArgumentFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasCompleter f => FilePath -> Mod f a
A.action FilePath
"file" Mod ArgumentFields FilePath
-> Mod ArgumentFields FilePath -> Mod ArgumentFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Directory of Slab templates to build.")
  FilePath
distDir <-
    Mod OptionFields FilePath -> Parser FilePath
forall s. IsString s => Mod OptionFields s -> Parser s
A.strOption
      ( FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
A.long FilePath
"dist"
          Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasValue f => a -> Mod f a
A.value FilePath
"./_site"
          Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
A.metavar FilePath
"DIR"
          Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. FilePath -> Mod f a
A.help
            FilePath
"A directory with existing static files."
      )
  pure $ FilePath -> FilePath -> Command
Serve FilePath
srcDir FilePath
distDir

parserReport :: A.Parser Command
parserReport :: Parser Command
parserReport =
  Mod CommandFields Command -> Parser Command
forall a. Mod CommandFields a -> Parser a
A.subparser
    ( FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
        FilePath
"pages"
        ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserReportPages Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
            FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
              FilePath
"Report pages found in a directory"
        )
        Mod CommandFields Command
-> Mod CommandFields Command -> Mod CommandFields Command
forall a. Semigroup a => a -> a -> a
<> FilePath -> ParserInfo Command -> Mod CommandFields Command
forall a. FilePath -> ParserInfo a -> Mod CommandFields a
A.command
          FilePath
"headings"
          ( Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
A.info (Parser Command
parserReportHeadings Parser Command -> Parser (Command -> Command) -> Parser Command
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Command -> Command)
forall a. Parser (a -> a)
A.helper) (InfoMod Command -> ParserInfo Command)
-> InfoMod Command -> ParserInfo Command
forall a b. (a -> b) -> a -> b
$
              FilePath -> InfoMod Command
forall a. FilePath -> InfoMod a
A.progDesc
                FilePath
"Report the headings of a page"
          )
    )

parserReportPages :: A.Parser Command
parserReportPages :: Parser Command
parserReportPages = do
  FilePath
srcDir <-
    ReadM FilePath -> Mod ArgumentFields FilePath -> Parser FilePath
forall a. ReadM a -> Mod ArgumentFields a -> Parser a
A.argument
      ReadM FilePath
forall s. IsString s => ReadM s
A.str
      (FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
A.metavar FilePath
"DIR" Mod ArgumentFields FilePath
-> Mod ArgumentFields FilePath -> Mod ArgumentFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasCompleter f => FilePath -> Mod f a
A.action FilePath
"file" Mod ArgumentFields FilePath
-> Mod ArgumentFields FilePath -> Mod ArgumentFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Directory of Slab templates to analyse.")
  pure $ FilePath -> Command
ReportPages FilePath
srcDir

parserReportHeadings :: A.Parser Command
parserReportHeadings :: Parser Command
parserReportHeadings = do
  FilePath
path <- Parser FilePath
parserTemplatePath
  pure $ FilePath -> Command
ReportHeadings FilePath
path

parserWatch :: A.Parser Command
parserWatch :: Parser Command
parserWatch = do
  FilePath
srcDir <-
    ReadM FilePath -> Mod ArgumentFields FilePath -> Parser FilePath
forall a. ReadM a -> Mod ArgumentFields a -> Parser a
A.argument
      ReadM FilePath
forall s. IsString s => ReadM s
A.str
      (FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
A.metavar FilePath
"DIR" Mod ArgumentFields FilePath
-> Mod ArgumentFields FilePath -> Mod ArgumentFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasCompleter f => FilePath -> Mod f a
A.action FilePath
"file" Mod ArgumentFields FilePath
-> Mod ArgumentFields FilePath -> Mod ArgumentFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Directory of Slab templates to watch.")
  RenderMode
mode <-
    RenderMode
-> RenderMode -> Mod FlagFields RenderMode -> Parser RenderMode
forall a. a -> a -> Mod FlagFields a -> Parser a
A.flag
      RenderMode
RenderNormal
      RenderMode
RenderPretty
      ( FilePath -> Mod FlagFields RenderMode
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
A.long FilePath
"pretty" Mod FlagFields RenderMode
-> Mod FlagFields RenderMode -> Mod FlagFields RenderMode
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod FlagFields RenderMode
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Use pretty-printing"
      )
  RunMode
passthrough <- Parser RunMode
parserPassthroughFlag
  FilePath
distDir <-
    Mod OptionFields FilePath -> Parser FilePath
forall s. IsString s => Mod OptionFields s -> Parser s
A.strOption
      ( FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
A.long FilePath
"dist"
          Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasValue f => a -> Mod f a
A.value FilePath
"./_site"
          Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
A.metavar FilePath
"DIR"
          Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. FilePath -> Mod f a
A.help
            FilePath
"A destination directory for the generated HTML files."
      )
  pure $ FilePath -> RenderMode -> RunMode -> FilePath -> Command
Watch FilePath
srcDir RenderMode
mode RunMode
passthrough FilePath
distDir

parserExectue :: A.Parser Command
parserExectue :: Parser Command
parserExectue = do
  (FilePath, ParseMode)
pathAndmode <- Parser (FilePath, ParseMode)
parserWithPath
  Bool
simpl <-
    Mod FlagFields Bool -> Parser Bool
A.switch
      ( FilePath -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
A.long FilePath
"simplify" Mod FlagFields Bool -> Mod FlagFields Bool -> Mod FlagFields Bool
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod FlagFields Bool
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Simplify the AST"
      )
  RunMode
passthrough <- Parser RunMode
parserPassthroughFlag
  pure $ (FilePath -> ParseMode -> CommandWithPath -> Command)
-> (FilePath, ParseMode) -> CommandWithPath -> Command
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry FilePath -> ParseMode -> CommandWithPath -> Command
CommandWithPath (FilePath, ParseMode)
pathAndmode (CommandWithPath -> Command) -> CommandWithPath -> Command
forall a b. (a -> b) -> a -> b
$ Bool -> RunMode -> CommandWithPath
Execute Bool
simpl RunMode
passthrough

parserRender :: A.Parser Command
parserRender :: Parser Command
parserRender = do
  RenderMode
mode <-
    RenderMode
-> RenderMode -> Mod FlagFields RenderMode -> Parser RenderMode
forall a. a -> a -> Mod FlagFields a -> Parser a
A.flag
      RenderMode
RenderNormal
      RenderMode
RenderPretty
      ( FilePath -> Mod FlagFields RenderMode
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
A.long FilePath
"pretty" Mod FlagFields RenderMode
-> Mod FlagFields RenderMode -> Mod FlagFields RenderMode
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod FlagFields RenderMode
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Use pretty-printing"
      )
  (FilePath, ParseMode)
pathAndmode <- Parser (FilePath, ParseMode)
parserWithPath
  RunMode
passthrough <- Parser RunMode
parserPassthroughFlag
  pure $ (FilePath -> ParseMode -> CommandWithPath -> Command)
-> (FilePath, ParseMode) -> CommandWithPath -> Command
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry FilePath -> ParseMode -> CommandWithPath -> Command
CommandWithPath (FilePath, ParseMode)
pathAndmode (CommandWithPath -> Command) -> CommandWithPath -> Command
forall a b. (a -> b) -> a -> b
$ RenderMode -> RunMode -> CommandWithPath
Render RenderMode
mode RunMode
passthrough

parserEvaluate :: A.Parser Command
parserEvaluate :: Parser Command
parserEvaluate = do
  (FilePath, ParseMode)
pathAndmode <- Parser (FilePath, ParseMode)
parserWithPath
  Bool
simpl <-
    Mod FlagFields Bool -> Parser Bool
A.switch
      ( FilePath -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
A.long FilePath
"simplify" Mod FlagFields Bool -> Mod FlagFields Bool -> Mod FlagFields Bool
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod FlagFields Bool
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Simplify the AST"
      )
  pure $ (FilePath -> ParseMode -> CommandWithPath -> Command)
-> (FilePath, ParseMode) -> CommandWithPath -> Command
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry FilePath -> ParseMode -> CommandWithPath -> Command
CommandWithPath (FilePath, ParseMode)
pathAndmode (CommandWithPath -> Command) -> CommandWithPath -> Command
forall a b. (a -> b) -> a -> b
$ Bool -> CommandWithPath
Evaluate Bool
simpl

parserParse :: A.Parser Command
parserParse :: Parser Command
parserParse = do
  (FilePath, ParseMode)
pathAndmode <- Parser (FilePath, ParseMode)
parserWithPath
  pure $ (FilePath -> ParseMode -> CommandWithPath -> Command)
-> (FilePath, ParseMode) -> CommandWithPath -> Command
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry FilePath -> ParseMode -> CommandWithPath -> Command
CommandWithPath (FilePath, ParseMode)
pathAndmode CommandWithPath
Parse

parserGenerate :: A.Parser Command
parserGenerate :: Parser Command
parserGenerate = do
  FilePath
path <- Parser FilePath
parserTemplatePath
  pure $ FilePath -> Command
Generate FilePath
path

parserClasses :: A.Parser Command
parserClasses :: Parser Command
parserClasses = do
  (FilePath, ParseMode)
pathAndmode <- Parser (FilePath, ParseMode)
parserWithPath
  pure $ (FilePath -> ParseMode -> CommandWithPath -> Command)
-> (FilePath, ParseMode) -> CommandWithPath -> Command
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry FilePath -> ParseMode -> CommandWithPath -> Command
CommandWithPath (FilePath, ParseMode)
pathAndmode CommandWithPath
Classes

parserFragments :: A.Parser Command
parserFragments :: Parser Command
parserFragments = do
  (FilePath, ParseMode)
pathAndmode <- Parser (FilePath, ParseMode)
parserWithPath
  Maybe Text
mname <-
    Parser Text -> Parser (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
A.optional (Parser Text -> Parser (Maybe Text))
-> Parser Text -> Parser (Maybe Text)
forall a b. (a -> b) -> a -> b
$
      ReadM Text -> Mod ArgumentFields Text -> Parser Text
forall a. ReadM a -> Mod ArgumentFields a -> Parser a
A.argument
        ReadM Text
forall s. IsString s => ReadM s
A.str
        (FilePath -> Mod ArgumentFields Text
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
A.metavar FilePath
"NAME" Mod ArgumentFields Text
-> Mod ArgumentFields Text -> Mod ArgumentFields Text
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields Text
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Fragment name to extract.")
  pure $ (FilePath -> ParseMode -> CommandWithPath -> Command)
-> (FilePath, ParseMode) -> CommandWithPath -> Command
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry FilePath -> ParseMode -> CommandWithPath -> Command
CommandWithPath (FilePath, ParseMode)
pathAndmode (CommandWithPath -> Command) -> CommandWithPath -> Command
forall a b. (a -> b) -> a -> b
$ Maybe Text -> CommandWithPath
Fragments Maybe Text
mname

--------------------------------------------------------------------------------
parserWithPath :: A.Parser (FilePath, ParseMode)
parserWithPath :: Parser (FilePath, ParseMode)
parserWithPath = (,) (FilePath -> ParseMode -> (FilePath, ParseMode))
-> Parser FilePath -> Parser (ParseMode -> (FilePath, ParseMode))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser FilePath
parserTemplatePath Parser (ParseMode -> (FilePath, ParseMode))
-> Parser ParseMode -> Parser (FilePath, ParseMode)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser ParseMode
parserShallowFlag

parserTemplatePath :: A.Parser FilePath
parserTemplatePath :: Parser FilePath
parserTemplatePath =
  ReadM FilePath -> Mod ArgumentFields FilePath -> Parser FilePath
forall a. ReadM a -> Mod ArgumentFields a -> Parser a
A.argument
    ReadM FilePath
forall s. IsString s => ReadM s
A.str
    (FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
A.metavar FilePath
"FILE" Mod ArgumentFields FilePath
-> Mod ArgumentFields FilePath -> Mod ArgumentFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasCompleter f => FilePath -> Mod f a
A.action FilePath
"file" Mod ArgumentFields FilePath
-> Mod ArgumentFields FilePath -> Mod ArgumentFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Slab template to parse.")

parserShallowFlag :: A.Parser ParseMode
parserShallowFlag :: Parser ParseMode
parserShallowFlag =
  ParseMode
-> ParseMode -> Mod FlagFields ParseMode -> Parser ParseMode
forall a. a -> a -> Mod FlagFields a -> Parser a
A.flag
    ParseMode
ParseDeep
    ParseMode
ParseShallow
    ( FilePath -> Mod FlagFields ParseMode
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
A.long FilePath
"shallow" Mod FlagFields ParseMode
-> Mod FlagFields ParseMode -> Mod FlagFields ParseMode
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod FlagFields ParseMode
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Don't parse recursively the included Slab files"
    )

--------------------------------------------------------------------------------
parserPassthroughFlag :: A.Parser RunMode
parserPassthroughFlag :: Parser RunMode
parserPassthroughFlag =
  RunMode -> RunMode -> Mod FlagFields RunMode -> Parser RunMode
forall a. a -> a -> Mod FlagFields a -> Parser a
A.flag
    RunMode
RunNormal
    RunMode
RunPassthrough
    ( FilePath -> Mod FlagFields RunMode
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
A.long FilePath
"passthrough" Mod FlagFields RunMode
-> Mod FlagFields RunMode -> Mod FlagFields RunMode
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod FlagFields RunMode
forall (f :: * -> *) a. FilePath -> Mod f a
A.help FilePath
"Allow external command failures"
    )