cmdtheline-0.2.0.0: src/System/Console/CmdTheLine/Util.hs
{- 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."