content: {-# LANGUAGE DeriveDataTypeable #-}
  
  -- |  A module to deal with verbosity, how \'chatty\' a program should be.
  --    This module defines the 'Verbosity' data type, along with functions
  --    for manipulating a global verbosity value.
  module System.Console.CmdArgs.Verbosity(
      Verbosity(..), setVerbosity, getVerbosity,
      isNormal, isLoud,
      whenNormal, whenLoud
      ) where
  
  import Control.Monad
  import Data.Data
  import Data.IORef
  import System.IO.Unsafe
  
  
  -- | The verbosity data type
  data Verbosity
      = Quiet  -- ^ Only output essential messages (typically errors)
      | Normal -- ^ Output normal messages (typically errors and warnings)
      | Loud   -- ^ Output lots of messages (typically errors, warnings and status updates)
        deriving (Eq,Ord,Bounded,Enum,Show,Read,Data,Typeable)
  
  
  {-# NOINLINE ref #-}
  ref :: IORef Verbosity
  ref = unsafePerformIO $ newIORef Normal
  
  
  -- | Set the global verbosity.
  setVerbosity :: Verbosity -> IO ()
  setVerbosity = writeIORef ref
  
  -- | Get the global verbosity. Initially @Normal@ before any calls to 'setVerbosity'.
  getVerbosity :: IO Verbosity
  getVerbosity = readIORef ref
  
  -- | Used to test if warnings should be output to the user.
  --   @True@ if the verbosity is set to 'Normal' or 'Loud' (when @--quiet@ is /not/ specified).
  isNormal :: IO Bool
  isNormal = fmap (>=Normal) getVerbosity
  
  -- | Used to test if status updates should be output to the user.
  --   @True@ if the verbosity is set to 'Loud' (when @--verbose@ is specified).
  isLoud :: IO Bool
  isLoud = fmap (>=Loud) getVerbosity
  
  
  -- | An action to perform if the verbosity is normal or higher, based on 'isNormal'.
  whenNormal :: IO () -> IO ()
  whenNormal act = do
      b <- isNormal
      when b act
  
  -- | An action to perform if the verbosity is loud, based on 'isLoud'.
  whenLoud :: IO () -> IO ()
  whenLoud act = do
      b <- isLoud
      when b act
  