{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
module Distribution.Verbosity (
Verbosity,
silent, normal, verbose, deafening,
moreVerbose, lessVerbose, isVerboseQuiet,
intToVerbosity, flagToVerbosity,
showForCabal, showForGHC,
verboseNoFlags, verboseHasFlags,
modifyVerbosity,
verboseCallSite, verboseCallStack,
isVerboseCallSite, isVerboseCallStack,
verboseMarkOutput, isVerboseMarkOutput,
verboseUnmarkOutput,
verboseNoWrap, isVerboseNoWrap,
verboseTimestamp, isVerboseTimestamp,
verboseNoTimestamp,
) where
import Prelude ()
import Distribution.Compat.Prelude
import Distribution.ReadE
import Data.List (elemIndex)
import Distribution.Parsec
import Distribution.Verbosity.Internal
import qualified Data.Set as Set
import qualified Distribution.Compat.CharParsing as P
data Verbosity = Verbosity {
vLevel :: VerbosityLevel,
vFlags :: Set VerbosityFlag,
vQuiet :: Bool
} deriving (Generic, Show, Read, Typeable)
mkVerbosity :: VerbosityLevel -> Verbosity
mkVerbosity l = Verbosity { vLevel = l, vFlags = Set.empty, vQuiet = False }
instance Eq Verbosity where
x == y = vLevel x == vLevel y
instance Ord Verbosity where
compare x y = compare (vLevel x) (vLevel y)
instance Enum Verbosity where
toEnum = mkVerbosity . toEnum
fromEnum = fromEnum . vLevel
instance Bounded Verbosity where
minBound = mkVerbosity minBound
maxBound = mkVerbosity maxBound
instance Binary Verbosity
instance Structured Verbosity
silent :: Verbosity
silent = mkVerbosity Silent
normal :: Verbosity
normal = mkVerbosity Normal
verbose :: Verbosity
verbose = mkVerbosity Verbose
deafening :: Verbosity
deafening = mkVerbosity Deafening
moreVerbose :: Verbosity -> Verbosity
moreVerbose v =
case vLevel v of
Silent -> v
Normal -> v { vLevel = Verbose }
Verbose -> v { vLevel = Deafening }
Deafening -> v
lessVerbose :: Verbosity -> Verbosity
lessVerbose v =
verboseQuiet $
case vLevel v of
Deafening -> v
Verbose -> v { vLevel = Normal }
Normal -> v { vLevel = Silent }
Silent -> v
modifyVerbosity :: (Verbosity -> Verbosity) -> Verbosity -> Verbosity
modifyVerbosity f v = v { vLevel = vLevel (f v) }
intToVerbosity :: Int -> Maybe Verbosity
intToVerbosity 0 = Just (mkVerbosity Silent)
intToVerbosity 1 = Just (mkVerbosity Normal)
intToVerbosity 2 = Just (mkVerbosity Verbose)
intToVerbosity 3 = Just (mkVerbosity Deafening)
intToVerbosity _ = Nothing
parsecVerbosity :: CabalParsing m => m (Either Int Verbosity)
parsecVerbosity = parseIntVerbosity <|> parseStringVerbosity
where
parseIntVerbosity = fmap Left P.integral
parseStringVerbosity = fmap Right $ do
level <- parseVerbosityLevel
_ <- P.spaces
extras <- many (parseExtra <* P.spaces)
return (foldr (.) id extras (mkVerbosity level))
parseVerbosityLevel = P.choice
[ P.string "silent" >> return Silent
, P.string "normal" >> return Normal
, P.string "verbose" >> return Verbose
, P.string "debug" >> return Deafening
, P.string "deafening" >> return Deafening
]
parseExtra = P.char '+' >> P.choice
[ P.string "callsite" >> return verboseCallSite
, P.string "callstack" >> return verboseCallStack
, P.string "nowrap" >> return verboseNoWrap
, P.string "markoutput" >> return verboseMarkOutput
, P.string "timestamp" >> return verboseTimestamp
]
flagToVerbosity :: ReadE Verbosity
flagToVerbosity = parsecToReadE id $ do
e <- parsecVerbosity
case e of
Right v -> return v
Left i -> case intToVerbosity i of
Just v -> return v
Nothing -> fail $ "Bad verbosity: " ++ show i ++ ". Valid values are 0..3"
showForCabal, showForGHC :: Verbosity -> String
showForCabal v
| Set.null (vFlags v)
= maybe (error "unknown verbosity") show $
elemIndex v [silent,normal,verbose,deafening]
| otherwise
= unwords $ (case vLevel v of
Silent -> "silent"
Normal -> "normal"
Verbose -> "verbose"
Deafening -> "debug")
: concatMap showFlag (Set.toList (vFlags v))
where
showFlag VCallSite = ["+callsite"]
showFlag VCallStack = ["+callstack"]
showFlag VNoWrap = ["+nowrap"]
showFlag VMarkOutput = ["+markoutput"]
showFlag VTimestamp = ["+timestamp"]
showForGHC v = maybe (error "unknown verbosity") show $
elemIndex v [silent,normal,__,verbose,deafening]
where __ = silent
verboseCallSite :: Verbosity -> Verbosity
verboseCallSite = verboseFlag VCallSite
verboseCallStack :: Verbosity -> Verbosity
verboseCallStack = verboseFlag VCallStack
verboseMarkOutput :: Verbosity -> Verbosity
verboseMarkOutput = verboseFlag VMarkOutput
verboseUnmarkOutput :: Verbosity -> Verbosity
verboseUnmarkOutput = verboseNoFlag VMarkOutput
verboseNoWrap :: Verbosity -> Verbosity
verboseNoWrap = verboseFlag VNoWrap
verboseQuiet :: Verbosity -> Verbosity
verboseQuiet v = v { vQuiet = True }
verboseTimestamp :: Verbosity -> Verbosity
verboseTimestamp = verboseFlag VTimestamp
verboseNoTimestamp :: Verbosity -> Verbosity
verboseNoTimestamp = verboseNoFlag VTimestamp
verboseFlag :: VerbosityFlag -> (Verbosity -> Verbosity)
verboseFlag flag v = v { vFlags = Set.insert flag (vFlags v) }
verboseNoFlag :: VerbosityFlag -> (Verbosity -> Verbosity)
verboseNoFlag flag v = v { vFlags = Set.delete flag (vFlags v) }
verboseNoFlags :: Verbosity -> Verbosity
verboseNoFlags v = v { vFlags = Set.empty }
verboseHasFlags :: Verbosity -> Bool
verboseHasFlags = not . Set.null . vFlags
isVerboseCallSite :: Verbosity -> Bool
isVerboseCallSite = isVerboseFlag VCallSite
isVerboseCallStack :: Verbosity -> Bool
isVerboseCallStack = isVerboseFlag VCallStack
isVerboseMarkOutput :: Verbosity -> Bool
isVerboseMarkOutput = isVerboseFlag VMarkOutput
isVerboseNoWrap :: Verbosity -> Bool
isVerboseNoWrap = isVerboseFlag VNoWrap
isVerboseQuiet :: Verbosity -> Bool
isVerboseQuiet = vQuiet
isVerboseTimestamp :: Verbosity -> Bool
isVerboseTimestamp = isVerboseFlag VTimestamp
isVerboseFlag :: VerbosityFlag -> Verbosity -> Bool
isVerboseFlag flag = (Set.member flag) . vFlags