{- Copyright © 2012, Vincent Elisha Lee Frey. All rights reserved. - This is open source software distributed under a MIT license. - See the file 'LICENSE' for further information. -} module System.Console.CmdTheLine.Util ( -- * File path validation -- ** Existing path check fileExists, dirExists, pathExists -- ** Existing paths check , filesExist, dirsExist, pathsExist -- ** Valid path , validPath ) where import Control.Applicative import Text.PrettyPrint import System.Console.CmdTheLine.Common import System.Console.CmdTheLine.Err import System.Console.CmdTheLine.Term import Control.Monad.IO.Class ( liftIO ) import System.Directory ( doesFileExist, doesDirectoryExist ) import System.FilePath ( isValid ) doesFileOrDirExist :: String -> IO Bool doesFileOrDirExist = liftA2 (||) <$> doesFileExist <*> doesDirectoryExist check :: (String -> IO Bool) -> String -> String -> Err String check test errStr path = do isDir <- liftIO $ test path if isDir then return path else msgFail $ no errStr path validate :: (String -> IO Bool) -> String -> Term String -> Term String validate test errStr = ret . fmap (check test errStr) validates :: (String -> IO Bool) -> String -> Term [String] -> Term [String] validates test errStr = ret . fmap (mapM $ check test errStr) -- | 'fileExists' @term@ checks that 'String' in @term@ is a path to an existing -- /file/. If it is not, exit with an explanatory message for the user. fileExists :: Term String -> Term String fileExists = validate doesFileExist "file" -- | 'dirExists' @term@ checks that 'String' in @term@ is a path to an existing -- /directory/. If it is not, exit with an explanatory message for the user. dirExists :: Term String -> Term String dirExists = validate doesDirectoryExist "directory" -- | 'pathExists' @term@ checks that 'String' in @term@ is a path to an existing -- /file or directory/. If it is not, exit with an explanatory message for the -- user. pathExists :: Term String -> Term String pathExists = validate doesFileOrDirExist "file or directory" -- | 'filesExist' @term@ is as 'fileExists' but for a @term@ containing a list -- of file paths. filesExist :: Term [String] -> Term [String] filesExist = validates doesFileExist "file" -- | 'dirsExist' @term@ is as 'dirExists' but for a @term@ containing a list -- of directory paths. dirsExist :: Term [String] -> Term [String] dirsExist = validates doesDirectoryExist "directory" -- | 'pathsExist' @term@ is as 'pathExists' but for a @term@ containing a list -- of paths. pathsExist :: Term [String] -> Term [String] pathsExist = validates doesFileOrDirExist "file or directory" -- | 'validPath' @term@ checks that 'String' in @term@ is a valid path under -- the current operating system. If it is not, exit with an explanatory -- message for the user. validPath :: Term String -> Term String validPath = ret . fmap check where check str = if isValid str then return str else msgFail $ failDoc str failDoc str = quotes (text str) <+> text "is not a valid file path."