packages feed

dr-cabal-0.2.0.0: src/DrCabal/Cli.hs

{-# LANGUAGE ApplicativeDo #-}

{- |
Module                  : DrCabal.Cli
Copyright               : (c) 2022 Dmitrii Kovanikov
SPDX-License-Identifier : MPL-2.0
Maintainer              : Dmitrii Kovanikov <kovanikov@gmail.com>
Stability               : Experimental
Portability             : Portable

CLI parser for @dr-cabal@.
-}

module DrCabal.Cli
    ( Command (..)
    , readCommand

    , ProfileArgs (..)
    , FileMode (..)
    ) where

import DrCabal.Model (Style (..))

import qualified Options.Applicative as Opt

data Command
    = Profile ProfileArgs

data ProfileArgs = ProfileArgs
    { profileArgsStyle    :: Style
    , profileArgsFileMode :: FileMode
    }

data FileMode
    -- | Don't read from the file and don't store the results in the file
    = None

    -- | Store current results in the file
    | Output FilePath

    -- | Read previously saved results from the file
    | Input FilePath

readCommand :: IO Command
readCommand = Opt.execParser opts
  where
    opts = Opt.info (Opt.helper <*> commandP) $ mconcat
      [ Opt.fullDesc
      , Opt.progDesc "Profile cabal dependency build output"
      , Opt.header "dr-cabal - a CLI tool to treat cabal output"
      ]

-- | All possible commands.
commandP :: Opt.Parser Command
commandP = Opt.subparser $ mconcat
    [ Opt.command "profile"
        $ Opt.info (Opt.helper <*> profileP)
        $ Opt.progDesc "Build profiling report"
    ]

profileP :: Opt.Parser Command
profileP = do
    profileArgsStyle <- styleP
    profileArgsFileMode <- fileModeP

    pure $ Profile ProfileArgs{..}

styleP :: Opt.Parser Style
styleP = stackedP <|> pure Stacked
  where
    stackedP :: Opt.Parser Style
    stackedP = Opt.flag' Stacked $ mconcat
        [ Opt.long "stacked"
        , Opt.short 's'
        , Opt.help "Format as stacked"
        ]

fileModeP :: Opt.Parser FileMode
fileModeP = inputP <|> outputP <|> pure None
  where
    inputP :: Opt.Parser FileMode
    inputP = fmap Input $ Opt.strOption $ mconcat
        [ Opt.long "input"
        , Opt.short 'i'
        , Opt.metavar "FILE_PATH"
        , Opt.help "Read profile input from a JSON file, created by 'dr-cabal profile --output=<some-file>'"
        ]

    outputP :: Opt.Parser FileMode
    outputP = fmap Output $ Opt.strOption $ mconcat
        [ Opt.long "output"
        , Opt.short 'o'
        , Opt.metavar "FILE_PATH"
        , Opt.help "Save cabal output to a file in a JSON format"
        ]