{-# LANGUAGE LambdaCase #-} module Hpack.Options where import System.FilePath import System.Directory data ParseResult = Help | PrintVersion | PrintNumericVersion | Run ParseOptions | ParseError deriving (Eq, Show) data Verbose = Verbose | NoVerbose deriving (Eq, Show) data Force = Force | NoForce deriving (Eq, Show) data ParseOptions = ParseOptions { parseOptionsVerbose :: Verbose , parseOptionsForce :: Force , parseOptionsToStdout :: Bool , parseOptionsTarget :: FilePath } deriving (Eq, Show) parseOptions :: FilePath -> [String] -> IO ParseResult parseOptions defaultTarget = \ case ["--version"] -> return PrintVersion ["--numeric-version"] -> return PrintNumericVersion ["--help"] -> return Help args -> case targets of Right (target, toStdout) -> do file <- expandTarget defaultTarget target let options | toStdout = ParseOptions NoVerbose Force toStdout file | otherwise = ParseOptions verbose force toStdout file return (Run options) Left err -> return err where silentFlag = "--silent" forceFlags = ["--force", "-f"] flags = silentFlag : forceFlags verbose = if silentFlag `elem` args then NoVerbose else Verbose force = if any (`elem` args) forceFlags then Force else NoForce ys = filter (`notElem` flags) args targets :: Either ParseResult (Maybe FilePath, Bool) targets = case ys of ["-"] -> Right (Nothing, True) ["-", "-"] -> Left ParseError [path] -> Right (Just path, False) [path, "-"] -> Right (Just path, True) [] -> Right (Nothing, False) _ -> Left ParseError expandTarget :: FilePath -> Maybe FilePath -> IO FilePath expandTarget defaultTarget = \ case Nothing -> return defaultTarget Just "" -> return defaultTarget Just target -> do isFile <- doesFileExist target isDirectory <- doesDirectoryExist target return $ case takeFileName target of _ | isFile -> target _ | isDirectory -> target defaultTarget "" -> target defaultTarget _ -> target