hlint-1.0.0.0: src/CmdLine.hs
module CmdLine(Mode(..), getMode) where
import Control.Monad
import Data.List
import Data.Maybe
import System.Console.GetOpt
import System.Directory
import System.Environment
import System.Exit
import System.FilePath
import Util
import Paths_hlint
import Data.Version
data Mode = Mode
{modeHints :: [FilePath] -- ^ which hint files to use
,modeFiles :: [FilePath] -- ^ which files to run it on
,modeTest :: Bool -- ^ run in test mode?
,modeReports :: [FilePath] -- ^ where to generate reports
,modeIgnoreFiles :: [FilePath] -- ^ where the ignore files are
,modeIgnore :: [String] -- ^ the ignore commands on the command line
}
data Opts = Help | HintFile FilePath | Test | Report FilePath | Ignore String | IgnoreFile FilePath
deriving Eq
opts = [Option "?" ["help"] (NoArg Help) "Display help message"
,Option "h" ["hint"] (ReqArg HintFile "file") "Hint file to use"
,Option "t" ["test"] (NoArg Test) "Run in test mode"
,Option "r" ["report"] (OptArg (Report . fromMaybe "report.html") "file") "Generate a report in HTML"
,Option "i" ["ignore"] (ReqArg Ignore "message") "Ignore a particular hint"
,Option "I" ["ignore-file"] (ReqArg IgnoreFile "file") "A file of things to ignore"
]
-- | Exit out if you need to display help info
getMode :: IO Mode
getMode = do
args <- getArgs
let (opt,files,err) = getOpt Permute opts args
let test = Test `elem` opt
when (not $ null err) $
error $ unlines $ "Unrecognised arguments:" : err
when (Help `elem` opt || (null files && not test)) $ do
putStr $ unlines ["HLint v" ++ showVersion version ++ ", (C) Neil Mitchell 2006-2008, University of York"
,""
," hlint [files] [options]"
,usageInfo "" opts
,"HLint makes hints on how to improve some Haskell code."]
exitWith ExitSuccess
hints <- return [x | HintFile x <- opt]
hints <- if null hints then getFile "Hints.hs" else return hints
files <- liftM concat $ mapM getFile files
dat <- getDataDir
let stdIgnoreFile = dat </> "hlint_ignore.txt"
hasIgnoreFile <- doesFileExist stdIgnoreFile
return Mode{modeHints=hints, modeFiles=files, modeTest=test
,modeReports=[x | Report x <- opt]
,modeIgnore=[x | Ignore x <- opt]
,modeIgnoreFiles=[stdIgnoreFile | hasIgnoreFile] ++ [x | IgnoreFile x <- opt]
}
ifNull :: [a] -> [a] -> [a]
ifNull x y = if null x then y else x
getFile :: FilePath -> IO [FilePath]
getFile file = do
b <- doesDirectoryExist file
if b then f file else do
b <- doesFileExist file
if b then return [file] else do
dat <- getDataDir
let s = dat </> file
b <- doesFileExist s
if b then return [s] else error $ "Couldn't find file: " ++ file
where
f file | takeExtension file `elem` [".hs",".lhs"] = return [file]
f file = do
b <- doesDirectoryExist file
if not b then return [] else do
s <- getDirectoryContents file
liftM concat $ mapM (f . (</>) file) $ filter (not . isBadDir) s
isBadDir :: FilePath -> Bool
isBadDir x = "." `isPrefixOf` x || "_" `isPrefixOf` x