packages feed

descript-lang-0.2.0.0: app/Parse.hs

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