serokell/importify

View on GitHub
app/Options.hs

Summary

Maintainability
Test Coverage
{-# LANGUAGE ApplicativeDo #-}

-- | Command line options for Importify

module Options
       ( ImportifyCliArgs  (..)
       , CommonOptions     (..)
       , Command (..)
       , CabalCacheOptions (..)
       , SingleFileOptions (..)

       , parseOptions
       ) where

import Universum

import Options.Applicative (Parser, ParserInfo, auto, command, execParser, flag', fullDesc, help,
                            helper, info, long, metavar, option, progDesc, short, showDefault,
                            strArgument, strOption, subparser, switch, value)
import System.Wlog (Severity (Info))

import Importify.Main (OutputOptions (..))

data ImportifyCliArgs = ImportifyCliArgs
    { icaCommon  :: !CommonOptions
    , icaCommand :: !Command
    } deriving (Show)

newtype CommonOptions = CommonOptions
    { coLoggingSeverity :: Severity -- ^ Severity for logger
    } deriving (Show)

data Command
    = SingleFile SingleFileOptions
    | CabalCache CabalCacheOptions
    deriving (Show)

data SingleFileOptions = SingleFileOptions
    { sfoFileName :: !FilePath      -- ^ File where all redundant imports should be removed
    , sfoOutput   :: !OutputOptions -- ^ Options for @importify file@ output
    } deriving (Show)

data CabalCacheOptions = CabalCacheOptions
    { ccoSaveSources  :: !Bool    -- ^ Don't delete downloaded package cache
    , ccoDependencies :: ![Text]  -- ^ Use specified dependencies overriding .cabal ones
    } deriving (Show)

cliArgumentsParser :: Parser ImportifyCliArgs
cliArgumentsParser = do
    icaCommon  <- commonArgsParser
    icaCommand <- commandParser
    pure ImportifyCliArgs{..}

commonArgsParser :: Parser CommonOptions
commonArgsParser = do
    coLoggingSeverity <- option auto $
        metavar "SEVERITY"
     <> long "logging-severity"
     <> short 'l'
     <> value Info
     <> showDefault
     <> help "Severity for logger"
    pure CommonOptions{..}

commandParser :: Parser Command
commandParser = subparser $
    command "file"
            (info (helper <*> fileParser)
                  (fullDesc <> progDesc "Importify a single file."))
 <> command "cache"
            (info (helper <*> cacheParser)
                  (fullDesc <> progDesc
                   "Search for .cabal file in current directory. If it's found then cache \
                   \all dependencies for every target and store them inside ./.importify folder."))

fileParser :: Parser Command
fileParser = do
    sfoFileName <- strArgument
      $ metavar "FILE"
     <> help "File to importify"
    sfoOutput <- outputOptionsParser
    pure (SingleFile SingleFileOptions{..})
  where
    outputOptionsParser :: Parser OutputOptions
    outputOptionsParser =
         flag' InPlace (  long "in-place"
                       <> short 'i'
                       <> help "Write changes directly to file")
     <|> ToFile <$> strOption (  long "to"
                              <> short 't'
                              <> help "Write to specified file")
     <|> pure ToConsole

cacheParser :: Parser Command
cacheParser = do
    ccoSaveSources <- switch
      $ long "preserve"
     <> short 'p'
     <> help "Don't remove downloaded package cache"
    ccoDependencies <- many $ strOption
      $ metavar "[STRING]"
     <> long "dependency"
     <> short 'd'
     <> help "List of manually specified dependencies that should be used \
             \for caching instead of libraries from .cabal file. This option \
             \overrides default behavior."
    pure (CabalCache CabalCacheOptions{..})

optsInfo :: ParserInfo ImportifyCliArgs
optsInfo = info
    (helper <*> cliArgumentsParser)
    (fullDesc <> progDesc "Importify - manage Haskell imports easily")

parseOptions :: IO ImportifyCliArgs
parseOptions = execParser optsInfo