{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE RecordWildCards #-} module Args ( Drive(..) , dryRunCmdArgs , withCmdArgs ) where import Paths_flight_igc (version) import Data.Version (showVersion) import System.Console.CmdArgs.Implicit ( Data , Typeable , Default(def) , summary , program , help , cmdArgs , (&=) ) import Control.Monad.Except (liftIO, throwError, when, unless) import Control.Monad.Trans.Except (runExceptT) import System.Directory (doesFileExist, doesDirectoryExist) import Text.RawString.QQ (r) import Options (DriveOptions(..)) description :: String description = intro where intro = [r| Parsing flight IGC files. |] data Drive = Drive { dir :: String , file :: String } deriving (Show, Data, Typeable) drive :: Drive drive = Drive { dir = def &= help "Over all the files in this directory" , file = def &= help "With this one file" } &= summary ("Flight IGC Parser " ++ showVersion version ++ description) &= program "flight-igc.exe" run :: IO Drive run = cmdArgs drive cmdArgsToDriveArgs :: Drive -> Maybe DriveOptions cmdArgsToDriveArgs Drive{ dir = d, file = f } = return DriveOptions { dir = d, file = f } -- SEE: http://stackoverflow.com/questions/2138819/in-haskell-is-there-a-way-to-do-io-in-a-function-guard checkedOptions :: DriveOptions -> IO (Either String DriveOptions) checkedOptions o@DriveOptions{..} = do x <- runExceptT $ do when (dir == "" && file == "") (throwError "No --dir or --file argument") dfe <- liftIO $ doesFileExist file dde <- liftIO $ doesDirectoryExist dir unless (dfe || dde) (throwError "The --dir argument is not a directory or the --file argument is not a file") case x of Left s -> return $ Left s Right _ -> return $ Right o dryRunCmdArgs :: IO () dryRunCmdArgs = print =<< run withCmdArgs :: (DriveOptions -> IO ()) -> IO () withCmdArgs f = do ca <- run print ca case cmdArgsToDriveArgs ca of Nothing -> putStrLn "Couldn't parse args." Just o -> do print o checked <- checkedOptions o case checked of Left s -> putStrLn s Right co -> f co