-- | 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"