@@ -12,23 +12,23 @@ module Obelisk.CLI.Logging where
1212import Control.Concurrent (ThreadId, forkIO, killThread, threadDelay)
1313import Control.Concurrent.MVar (modifyMVar_, newMVar)
1414import Control.Monad (unless, void, when)
15−import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow, bracket, bracket_, catch, throwM)
15+import Control.Monad.Catch (MonadCatch, MonadMask, bracket, catch, throwM)
1616import Control.Monad.IO.Class (liftIO)
17+import Control.Monad.Log (Severity (..), WithSeverity (..), logMessage, runLoggingT)
1718import Control.Monad.Loops (iterateUntil)
1819import Control.Monad.Reader (MonadIO, ReaderT (..))
20+import Data.IORef (atomicModifyIORef', newIORef, readIORef, writeIORef)
1921import Data.Semigroup ((<>))
2022import Data.Text (Text)
2123import qualified Data.Text as T
2224import qualified Data.Text.IO as T
2325import System.Console.ANSI (Color (Red, White, Yellow), ColorIntensity (Vivid),
2426 ConsoleIntensity (FaintIntensity), ConsoleLayer (Foreground),
25− SGR (Reset, SetColor, SetConsoleIntensity), clearLine, setSGR)
27+ SGR (SetColor, SetConsoleIntensity), clearLine)
2628import System.Exit (ExitCode (..), exitWith)
2729import System.IO (BufferMode (NoBuffering), hFlush, hReady, hSetBuffering, stdin, stdout)
2830
29−import Control.Monad.Log (MonadLog, Severity (..), WithSeverity (..), logMessage, runLoggingT)
30−import Data.IORef (atomicModifyIORef', newIORef, readIORef, writeIORef)
31−
31+import qualified Obelisk.CLI.TerminalString as TS
3232import Obelisk.CLI.Types
3333
3434newCliConfig :: Severity -> Bool -> Bool -> IO CliConfig
@@ -89,12 +89,16 @@ handleLog' :: MonadIO m => Bool -> Output -> m Bool
8989handleLog' noColor output = do
9090 case output of
9191 Output_Log m -> liftIO $ do
92− writeLogWith T.putStrLn noColor m
92+ writeLog True noColor m
9393 Output_LogRaw m -> liftIO $ do
94− writeLogWith T.putStr noColor m
94+ writeLog False noColor m
9595 hFlush stdout -- Explicitly flush, as there is no newline
96− Output_Overwrite xs -> liftIO $ do
97− mapM_ putStr $ "\r" : xs
96+ Output_Write ts -> liftIO $ do
97+ T.putStrLn $ TS.render (not noColor) Nothing ts
98+ hFlush stdout
99+ Output_Overwrite ts -> liftIO $ do
100+ width <- TS.getTerminalWidth
101+ T.putStr $ "\r" <> (TS.render (not noColor) width ts)
98102 hFlush stdout
99103 Output_ClearLine -> liftIO $ do
100104 -- Go to the first column and clear the whole line
@@ -122,7 +126,7 @@ failWith s = do
122126-- | Intercept ExitFailure exceptions and log the given alert before exiting.
123127--
124128-- This is useful when you want to provide contextual information to a deeper failure.
125−withExitFailMessage :: (MonadIO m, MonadLog Output m, MonadCatch m, MonadThrow m) => Text -> m a -> m a
129+withExitFailMessage :: (Cli m, MonadCatch m) => Text -> m a -> m a
126130withExitFailMessage msg f = f `catch` \(e :: ExitCode) -> do
127131 case e of
128132 ExitFailure _ -> putLog Alert msg
@@ -130,17 +134,18 @@ withExitFailMessage msg f = f `catch` \(e :: ExitCode) -> do
130134 throwM e
131135
132136-- | Write log to stdout, with colors (unless `noColor`)
133−writeLogWith :: (MonadIO m, MonadMask m) => (Text -> IO ()) -> Bool -> WithSeverity Text -> m ()
134−writeLogWith f noColor (WithSeverity severity s)
135− | noColor && severity <= Warning = liftIO $ f $ T.pack (show severity) <> ": " <> s
136− | not noColor && severity <= Error = put [SetColor Foreground Vivid Red]
137− | not noColor && severity <= Warning = put [SetColor Foreground Vivid Yellow]
138− | not noColor && severity >= Debug = put [SetColor Foreground Vivid White, SetConsoleIntensity FaintIntensity]
139− | otherwise = liftIO $ f s
137+writeLog:: (MonadIO m, MonadMask m) => Bool -> Bool -> WithSeverity Text -> m ()
138+writeLog withNewLine noColor (WithSeverity severity s)
139+ | noColor && severity <= Warning = liftIO $ putFn $ T.pack (show severity) <> ": " <> s
140+ | not noColor && severity <= Error = TS.putStrWithSGR errorColors withNewLine s
141+ | not noColor && severity <= Warning = TS.putStrWithSGR warningColors withNewLine s
142+ | not noColor && severity >= Debug = TS.putStrWithSGR debugColors withNewLine s
143+ | otherwise = liftIO $ putFn s
140144 where
141− -- We must reset *before* outputting the newline (if any), otherwise the cursor won't be reset.
142− reset = setSGR [Reset] >> f ""
143− put sgr = liftIO $ bracket_ (setSGR sgr) reset $ T.putStr s
145+ putFn = if withNewLine then T.putStrLn else T.putStr
146+ errorColors = [SetColor Foreground Vivid Red]
147+ warningColors = [SetColor Foreground Vivid Yellow]
148+ debugColors = [SetColor Foreground Vivid White, SetConsoleIntensity FaintIntensity]
144149
145150-- | Allow the user to immediately switch to verbose logging upon pressing a particular key.
146151--