packages feed

haskell-debugger-0.9.0.0: hdb/Development/Debug/Options/Parser.hs

-- | Options parser using optparse-applicative for the debugger options in
-- 'Development.Debug.Options'
module Development.Debug.Options.Parser
  ( -- * Command line options parsing
    parseHdbOptions
  ) where

import Options.Applicative hiding (command)

import Data.Version
import qualified Options.Applicative
import qualified Paths_haskell_debugger as P

import GHC.Debugger.Logger
import Development.Debug.Options

--------------------------------------------------------------------------------
-- Options parser
--------------------------------------------------------------------------------

-- | Parser for 'HdbDAPServer' options
serverParser :: Parser HdbOptions
serverParser = HdbDAPServer
  <$> option auto
      ( long "port"
     <> short 'p'
     <> metavar "PORT"
     <> help "DAP server port" )
  <*> verbosityParser (Verbosity Debug)

-- | Parser for 'HdbCLI' options
cliParser :: Parser HdbOptions
cliParser = HdbCLI
  <$> strOption
      ( long "entry-point"
     <> short 'e'
     <> metavar "ENTRY_POINT"
     <> value "main"
     <> help "The name of the function that is called to start execution (default: main)" )
  <*> argument str
      ( metavar "ENTRY_FILE"
     <> help "The relative path from the project root to the file with the entry point for execution" )
  <*> many
        ( argument str
          ( metavar "ENTRY_ARGS..."
         <> help "The arguments passed to the entryPoint. If the entryPoint is main, these arguments are passed as environment arguments (as in getArgs) rather than direct function arguments."
          )
        )
  <*> option (words <$> str)
      ( long "extra-ghc-args"
     <> metavar "GHC_ARGS"
     <> value []
     <> help "Additional flags to pass to the ghc invocation that loads the program for debugging" )
  <*> verbosityParser (Verbosity Warning)

-- | Parser for 'HdbProxy' options
proxyParser :: Parser HdbOptions
proxyParser = HdbProxy
  <$> option auto
      ( long "port"
     <> short 'p'
     <> metavar "PORT"
     <> help "proxy port to which the debugger connects" )
  <*> verbosityParser (Verbosity Warning)

-- | Combined parser for HdbOptions
hdbOptionsParser :: Parser HdbOptions
hdbOptionsParser = hsubparser
  ( Options.Applicative.command "server"
    ( info serverParser
      ( progDesc "Start the Haskell debugger in DAP server mode" ) )
 <> Options.Applicative.command "cli"
    ( info cliParser
      ( progDesc "Debug a Haskell program in CLI mode" ) )
 <> Options.Applicative.command "proxy"
    ( info proxyParser
      ( progDesc "Internal mode used by the DAP server to proxy the stdin/stdout to the DAP client's terminal" ) )
  )
  <|> cliParser  -- Default to CLI mode if no subcommand

-- | Parser for --version flag
versioner :: Parser (a -> a)
versioner = simpleVersioner $ "Haskell Debugger, version " ++ showVersion P.version

-- | Parser for --verbosity 0
--
-- The default verbosity differs by mode (#86):
-- - DAP server mode: DEBUG
-- - CLI mode: WARNING
verbosityParser :: Verbosity -> Parser Verbosity
verbosityParser vdef = option verb
    ( long "verbosity"
   <> short 'v'
   <> metavar "VERBOSITY"
   <> value vdef
   <> help "Logger verbosity in [0..3] interval, where 0 is silent and 3 is debug"
    )
  where
    verb = Verbosity <$> (verbNum =<< auto)
    verbNum n = case n :: Int of
      0 -> pure Error
      1 -> pure Warning
      2 -> pure Info
      3 -> pure Debug
      _ -> readerAbort (ErrorMsg "Verbosity must be a value in [0..3]")

-- | Main parser info
hdbParserInfo :: ParserInfo HdbOptions
hdbParserInfo = info (hdbOptionsParser <**> versioner <**> helper)
  ( fullDesc
 <> header "Haskell debugger supporting both CLI and DAP modes" )

-- | Parse command line arguments
parseHdbOptions :: IO HdbOptions
parseHdbOptions = customExecParser
  defaultPrefs{prefShowHelpOnError = True, prefShowHelpOnEmpty = True}
  hdbParserInfo