1 {-# LANGUAGE DeriveDataTypeable #-}
2 {-# LANGUAGE DeriveGeneric #-}
4 -----------------------------------------------------------------------------
6 -- Verbosity for Cabal functions.
9 -- Module : Distribution.Verbosity
10 -- Copyright : Ian Lynagh 2007
13 -- Maintainer : cabal-devel@haskell.org
14 -- Portability : portable
16 -- A 'Verbosity' type with associated utilities.
18 -- There are 4 standard verbosity levels from 'silent', 'normal',
19 -- 'verbose' up to 'deafening'. This is used for deciding what logging
22 -- Verbosity also is equipped with some internal settings which can be
23 -- used to control at a fine granularity the verbosity of specific
24 -- settings (e.g., so that you can trace only particular things you
25 -- are interested in.) It's important to note that the instances
26 -- for 'Verbosity' assume that this does not exist.
27 module Distribution
.Verbosity
75 import Distribution
.Compat
.Prelude
78 import Distribution
.ReadE
80 import Data
.List
(elemIndex)
81 import Distribution
.Parsec
82 import Distribution
.Pretty
83 import Distribution
.Utils
.Generic
(isAsciiAlpha
)
84 import Distribution
.Verbosity
.Internal
86 import qualified Data
.Set
as Set
87 import qualified Distribution
.Compat
.CharParsing
as P
88 import qualified Text
.PrettyPrint
as PP
90 data Verbosity
= Verbosity
91 { vLevel
:: VerbosityLevel
92 , vFlags
:: Set VerbosityFlag
95 deriving (Generic
, Show, Read, Typeable
)
97 mkVerbosity
:: VerbosityLevel
-> Verbosity
98 mkVerbosity l
= Verbosity
{vLevel
= l
, vFlags
= Set
.empty, vQuiet
= False}
100 instance Eq Verbosity
where
101 x
== y
= vLevel x
== vLevel y
103 instance Ord Verbosity
where
104 compare x y
= compare (vLevel x
) (vLevel y
)
106 instance Enum Verbosity
where
107 toEnum = mkVerbosity
. toEnum
108 fromEnum = fromEnum . vLevel
110 instance Bounded Verbosity
where
111 minBound = mkVerbosity
minBound
112 maxBound = mkVerbosity
maxBound
114 instance Binary Verbosity
115 instance Structured Verbosity
117 -- | In 'silent' mode, we should not print /anything/ unless an error occurs.
119 silent
= mkVerbosity Silent
121 -- | Print stuff we want to see by default.
123 normal
= mkVerbosity Normal
125 -- | Be more verbose about what's going on.
127 verbose
= mkVerbosity Verbose
129 -- | Not only are we verbose ourselves (perhaps even noisier than when
130 -- being 'verbose'), but we tell everything we run to be verbose too.
131 deafening
:: Verbosity
132 deafening
= mkVerbosity Deafening
134 -- | Increase verbosity level, but stay 'silent' if we are.
135 moreVerbose
:: Verbosity
-> Verbosity
138 Silent
-> v
-- silent should stay silent
139 Normal
-> v
{vLevel
= Verbose
}
140 Verbose
-> v
{vLevel
= Deafening
}
143 -- | Decrease verbosity level, but stay 'deafening' if we are.
144 lessVerbose
:: Verbosity
-> Verbosity
148 Deafening
-> v
-- deafening stays deafening
149 Verbose
-> v
{vLevel
= Normal
}
150 Normal
-> v
{vLevel
= Silent
}
153 -- | Combinator for transforming verbosity level while retaining the
154 -- original hidden state.
156 -- For instance, the following property holds
158 -- prop> isVerboseNoWrap (modifyVerbosity (max verbose) v) == isVerboseNoWrap v
160 -- __Note__: you can use @modifyVerbosity (const v1) v0@ to overwrite
161 -- @v1@'s flags with @v0@'s flags.
164 modifyVerbosity
:: (Verbosity
-> Verbosity
) -> Verbosity
-> Verbosity
165 modifyVerbosity f v
= v
{vLevel
= vLevel
(f v
)}
167 -- | Numeric verbosity level @0..3@: @0@ is 'silent', @3@ is 'deafening'.
168 intToVerbosity
:: Int -> Maybe Verbosity
169 intToVerbosity
0 = Just
(mkVerbosity Silent
)
170 intToVerbosity
1 = Just
(mkVerbosity Normal
)
171 intToVerbosity
2 = Just
(mkVerbosity Verbose
)
172 intToVerbosity
3 = Just
(mkVerbosity Deafening
)
173 intToVerbosity _
= Nothing
175 -- | Parser verbosity
177 -- >>> explicitEitherParsec parsecVerbosity "normal"
178 -- Right (Verbosity {vLevel = Normal, vFlags = fromList [], vQuiet = False})
180 -- >>> explicitEitherParsec parsecVerbosity "normal+nowrap "
181 -- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap], vQuiet = False})
183 -- >>> explicitEitherParsec parsecVerbosity "normal+nowrap +markoutput"
184 -- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False})
186 -- >>> explicitEitherParsec parsecVerbosity "normal +nowrap +markoutput"
187 -- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False})
189 -- >>> explicitEitherParsec parsecVerbosity "normal+nowrap+markoutput"
190 -- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False})
192 -- >>> explicitEitherParsec parsecVerbosity "deafening+nowrap+stdout+stderr+callsite+callstack"
193 -- Right (Verbosity {vLevel = Deafening, vFlags = fromList [VCallStack,VCallSite,VNoWrap,VStderr], vQuiet = False})
195 -- /Note:/ this parser will eat trailing spaces.
196 instance Parsec Verbosity
where
197 parsec
= parsecVerbosity
199 instance Pretty Verbosity
where
200 pretty
= PP
.text
. showForCabal
202 parsecVerbosity
:: CabalParsing m
=> m Verbosity
203 parsecVerbosity
= parseIntVerbosity
<|
> parseStringVerbosity
205 parseIntVerbosity
= do
207 case intToVerbosity i
of
209 Nothing
-> P
.unexpected
$ "Bad integral verbosity: " ++ show i
++ ". Valid values are 0..3"
211 parseStringVerbosity
= do
212 level
<- parseVerbosityLevel
214 flags
<- many
(parseFlag
<* P
.spaces
)
215 return $ foldl' (flip ($)) (mkVerbosity level
) flags
217 parseVerbosityLevel
= do
218 token
<- P
.munch1 isAsciiAlpha
220 "silent" -> return Silent
221 "normal" -> return Normal
222 "verbose" -> return Verbose
223 "debug" -> return Deafening
224 "deafening" -> return Deafening
225 _
-> P
.unexpected
$ "Bad verbosity level: " ++ token
228 token
<- P
.munch1 isAsciiAlpha
230 "callsite" -> return verboseCallSite
231 "callstack" -> return verboseCallStack
232 "nowrap" -> return verboseNoWrap
233 "markoutput" -> return verboseMarkOutput
234 "timestamp" -> return verboseTimestamp
235 "stderr" -> return verboseStderr
236 "stdout" -> return verboseNoStderr
237 "nowarn" -> return verboseNoWarn
238 _
-> P
.unexpected
$ "Bad verbosity flag: " ++ token
240 flagToVerbosity
:: ReadE Verbosity
241 flagToVerbosity
= parsecToReadE
id parsecVerbosity
243 showForCabal
:: Verbosity
-> String
245 | Set
.null (vFlags v
) =
246 maybe (error "unknown verbosity") show $
247 elemIndex v
[silent
, normal
, verbose
, deafening
]
251 : concatMap showFlag
(Set
.toList
(vFlags v
))
253 showLevel Silent
= "silent"
254 showLevel Normal
= "normal"
255 showLevel Verbose
= "verbose"
256 showLevel Deafening
= "debug"
258 showFlag VCallSite
= ["+callsite"]
259 showFlag VCallStack
= ["+callstack"]
260 showFlag VNoWrap
= ["+nowrap"]
261 showFlag VMarkOutput
= ["+markoutput"]
262 showFlag VTimestamp
= ["+timestamp"]
263 showFlag VStderr
= ["+stderr"]
264 showFlag VNoWarn
= ["+nowarn"]
266 showForGHC
:: Verbosity
-> String
268 maybe (error "unknown verbosity") show $
269 elemIndex v
[silent
, normal
, __
, verbose
, deafening
]
271 __
= silent
-- this will be always ignored by elemIndex
273 -- | Turn on verbose call-site printing when we log.
274 verboseCallSite
:: Verbosity
-> Verbosity
275 verboseCallSite
= verboseFlag VCallSite
277 -- | Turn on verbose call-stack printing when we log.
278 verboseCallStack
:: Verbosity
-> Verbosity
279 verboseCallStack
= verboseFlag VCallStack
281 -- | Turn on @-----BEGIN CABAL OUTPUT-----@ markers for output
282 -- from Cabal (as opposed to GHC, or system dependent).
283 verboseMarkOutput
:: Verbosity
-> Verbosity
284 verboseMarkOutput
= verboseFlag VMarkOutput
286 -- | Turn off marking; useful for suppressing nondeterministic output.
287 verboseUnmarkOutput
:: Verbosity
-> Verbosity
288 verboseUnmarkOutput
= verboseNoFlag VMarkOutput
290 -- | Disable line-wrapping for log messages.
291 verboseNoWrap
:: Verbosity
-> Verbosity
292 verboseNoWrap
= verboseFlag VNoWrap
294 -- | Mark the verbosity as quiet.
295 verboseQuiet
:: Verbosity
-> Verbosity
296 verboseQuiet v
= v
{vQuiet
= True}
298 -- | Turn on timestamps for log messages.
299 verboseTimestamp
:: Verbosity
-> Verbosity
300 verboseTimestamp
= verboseFlag VTimestamp
302 -- | Turn off timestamps for log messages.
303 verboseNoTimestamp
:: Verbosity
-> Verbosity
304 verboseNoTimestamp
= verboseNoFlag VTimestamp
306 -- | Switch logging to 'stderr'.
309 verboseStderr
:: Verbosity
-> Verbosity
310 verboseStderr
= verboseFlag VStderr
312 -- | Switch logging to 'stdout'.
315 verboseNoStderr
:: Verbosity
-> Verbosity
316 verboseNoStderr
= verboseNoFlag VStderr
318 -- | Turn off warnings for log messages.
319 verboseNoWarn
:: Verbosity
-> Verbosity
320 verboseNoWarn
= verboseFlag VNoWarn
322 -- | Helper function for flag enabling functions.
323 verboseFlag
:: VerbosityFlag
-> (Verbosity
-> Verbosity
)
324 verboseFlag flag v
= v
{vFlags
= Set
.insert flag
(vFlags v
)}
326 -- | Helper function for flag disabling functions.
327 verboseNoFlag
:: VerbosityFlag
-> (Verbosity
-> Verbosity
)
328 verboseNoFlag flag v
= v
{vFlags
= Set
.delete flag
(vFlags v
)}
330 -- | Turn off all flags.
331 verboseNoFlags
:: Verbosity
-> Verbosity
332 verboseNoFlags v
= v
{vFlags
= Set
.empty}
334 verboseHasFlags
:: Verbosity
-> Bool
335 verboseHasFlags
= not . Set
.null . vFlags
337 -- | Test if we should output call sites when we log.
338 isVerboseCallSite
:: Verbosity
-> Bool
339 isVerboseCallSite
= isVerboseFlag VCallSite
341 -- | Test if we should output call stacks when we log.
342 isVerboseCallStack
:: Verbosity
-> Bool
343 isVerboseCallStack
= isVerboseFlag VCallStack
345 -- | Test if we should output markets.
346 isVerboseMarkOutput
:: Verbosity
-> Bool
347 isVerboseMarkOutput
= isVerboseFlag VMarkOutput
349 -- | Test if line-wrapping is disabled for log messages.
350 isVerboseNoWrap
:: Verbosity
-> Bool
351 isVerboseNoWrap
= isVerboseFlag VNoWrap
353 -- | Test if we had called 'lessVerbose' on the verbosity.
354 isVerboseQuiet
:: Verbosity
-> Bool
355 isVerboseQuiet
= vQuiet
357 -- | Test if we should output timestamps when we log.
358 isVerboseTimestamp
:: Verbosity
-> Bool
359 isVerboseTimestamp
= isVerboseFlag VTimestamp
361 -- | Test if we should output to 'stderr' when we log.
364 isVerboseStderr
:: Verbosity
-> Bool
365 isVerboseStderr
= isVerboseFlag VStderr
367 -- | Test if we should output warnings when we log.
368 isVerboseNoWarn
:: Verbosity
-> Bool
369 isVerboseNoWarn
= isVerboseFlag VNoWarn
371 -- | Helper function for flag testing functions.
372 isVerboseFlag
:: VerbosityFlag
-> Verbosity
-> Bool
373 isVerboseFlag flag
= (Set
.member flag
) . vFlags
376 -- >>> import Test.QuickCheck (Arbitrary (..), arbitraryBoundedEnum)
377 -- >>> instance Arbitrary VerbosityLevel where arbitrary = arbitraryBoundedEnum
378 -- >>> instance Arbitrary Verbosity where arbitrary = fmap mkVerbosity arbitrary