-- | Parses actions from the command line.
module Parse
( prompt
) where
import Action
import Options.Applicative hiding (Success, Failure, action)
import Data.Semigroup ((<>))
prompt :: IO Action
prompt = execParser actionP
actionP :: ParserInfo Action
actionP = info (helper <*> actionP_) actionInfo
serveP :: ParserInfo ()
serveP = info (helper <*> serveP_) serveInfo
augCompileP :: ParserInfo (Watcher Compile)
augCompileP = info (helper <*> watchP_ compileP_) compileInfo
augEvalP :: ParserInfo (Watcher Eval)
augEvalP = info (helper <*> watchP_ evalP_) evalInfo
augRefactorP :: ParserInfo (Watcher Refactor)
augRefactorP = info (helper <*> watchP_ refactorP_) refactorInfo
serveP_ :: Parser ()
serveP_ = pure ()
actionP_ :: Parser Action
actionP_ = subparser $ mconcat actionCommands
actionCommands :: [Mod CommandFields Action]
actionCommands =
[ command "serve" $ ActionServe <$ serveP
, commandGroup "Individual Comamnds:"
, command "compile" $ ActionIndiv . fmap ActionCompile <$> augCompileP
, command "eval" $ ActionIndiv . fmap ActionEval <$> augEvalP
, command "refactor" $ ActionIndiv . fmap ActionRefactor <$> augRefactorP
]
watchP_ :: Parser a -> Parser (Watcher a)
watchP_ subP_ = flip Watcher <$> subP_ <*> doWatch
where doWatch
= switch
$ long "watch"
<> short 'w'
<> help "Makes the source (SRC) a directory instead of a file. \
\Every time a file in this directory (or subdirectory) changes, \
\the action will be run on that specific file."
compileP_ :: Parser Compile
compileP_ = mkCompile <$> src <*> optional out
where src
= strArgument
$ metavar "SRC"
<> help "Path to the source code"
out
= strOption
$ metavar "OUT"
<> long "output"
<> short 'o'
<> help "Directory where the compiled package will be saved. \
\Defaults to the same directory as the source"
evalP_ :: Parser Eval
evalP_ = Eval <$> src
where src
= strArgument
$ metavar "SRC"
<> help "Path to the source code"
refactorP_ :: Parser Refactor
refactorP_ = mkRefactor <$> action <*> many arg <*> inPath <*> optional outPath
where action
= strArgument
$ metavar "ACTION"
<> help "The refactor action to run. --list for a full list"
arg
= strArgument
$ metavar "ARG"
<> help "Argument to the action. --list for a full list"
inPath
= strOption
$ metavar "SRC"
<> long "input"
<> short 'i'
<> help "Path to the source code"
outPath
= strOption
$ metavar "OUT"
<> long "output"
<> short 'o'
<> help "File where the refactored code will be saved. \
\Defaults to the original path, so the original source is overwritten"
actionInfo :: InfoMod a
actionInfo
= fullDesc
<> progDesc "Command-line interface for the Descript programming language"
<> header "descript-cli - command-line interface for the Descript programming language"
<> footer "This is the interface for the Descript programming language.\n\
\It includes commands for simple actions, such as compiling individual files or doing basic refactors.\n\
\It also includes a language server ('descript serve'), which adds Descript support to editors like VSCode."
serveInfo :: InfoMod a
serveInfo
= fullDesc
<> progDesc "Start the language server"
<> header "descript-cli serve - start the language server"
<> footer "Only need one server per system, even if there are multiple workspaces and clients.\n\
\This command should be called by language clients, such as the 'descript-lang' VSCode plugin,\n\
\once they want to edit Descript files."
compileInfo :: InfoMod a
compileInfo
= fullDesc
<> progDesc "Compile a Descript program"
<> header "descript-cli compile - compile a Descript program"
<> footer "Parses and interprets the program. \
\Expects it's query to reduce into a compiled datatype (a primitive or 'Code' record). \
\Generates a new file or directory with the output, \
\in the same directory as the source. \
\If you don't want to compile the query, \
\you just want to see what it reduces to, \
\use 'descript eval' instead."
evalInfo :: InfoMod a
evalInfo
= fullDesc
<> progDesc "Evaluate a Descript program"
<> header "descript-cli eval - evaluate a Descript program"
<> footer "Parses and interprets the program. Then reprints its query. \
\Useful for just experimenting with Descript. \
\Also useful for debugging bad programs, e.g. ones which don't compile."
refactorInfo :: InfoMod a
refactorInfo
= fullDesc
<> progDesc "Refactor a Descript source"
<> header "descript-cli refactor - refactor a Descript source"
<> footer "Modify a Descript source - for instance, rename a record"