packages feed

valiant-cli-0.1.0.0: src/Valiant/CLI/Output.hs

module Valiant.CLI.Output
  ( printHeader
  , printProgress
  , printOk
  , printFailed
  , printStale
  , printMissing
  , printSummary
  , printLn
  ) where

import Data.Text (Text)
import Data.Text qualified as T
import Data.Text.IO qualified as TIO
import System.Console.ANSI
  ( Color (..)
  , ColorIntensity (..)
  , ConsoleLayer (..)
  , SGR (..)
  , hSupportsANSIColor
  , setSGRCode
  )
import System.IO (stdout)

-- | Print a section header.
printHeader :: Text -> IO ()
printHeader hdr = TIO.putStrLn $ "valiant: " <> hdr

-- | Print progress line without trailing newline.
--
-- @printProgress 3 10 "sql/users/find_by_id.sql"@ produces:
--
-- >  [3/10] sql/users/find_by_id.sql ...
printProgress :: Int -> Int -> FilePath -> IO ()
printProgress n total path = do
  let pad = length (show total)
      idx = leftPad pad (show n)
  putStr $ "  [" <> idx <> "/" <> show total <> "] " <> path <> " ... "

-- | Print green "ok" with newline.
printOk :: IO ()
printOk = withColor Green $ TIO.putStrLn "ok"

-- | Print red "FAILED" with detail on the next line.
printFailed :: Text -> IO ()
printFailed detail = do
  withColor Red $ TIO.putStrLn "FAILED"
  TIO.putStrLn $ "    " <> detail

-- | Print yellow "STALE" with newline.
printStale :: IO ()
printStale = withColor Yellow $ TIO.putStrLn "STALE"

-- | Print yellow "MISSING" with newline.
printMissing :: IO ()
printMissing = withColor Yellow $ TIO.putStrLn "MISSING"

-- | Print a summary line.
printSummary :: Int -> Int -> IO ()
printSummary ok total
  | ok == total = do
      printLn ""
      withColor Green . TIO.putStrLn $
        "  All " <> T.pack (show total) <> " queries valid."
  | otherwise = do
      printLn ""
      withColor Red . TIO.putStrLn $
        "  "
          <> T.pack (show ok)
          <> " of "
          <> T.pack (show total)
          <> " queries valid. "
          <> T.pack (show (total - ok))
          <> " failed."

-- | Print a line of text.
printLn :: Text -> IO ()
printLn = TIO.putStrLn

-- Helpers -----------------------------------------------------------------

leftPad :: Int -> String -> String
leftPad n s = replicate (n - length s) ' ' <> s

withColor :: Color -> IO () -> IO ()
withColor color action = do
  supportsColor <- hSupportsANSIColor stdout
  if supportsColor
    then do
      putStr (setSGRCode [SetColor Foreground Vivid color])
      action
      putStr (setSGRCode [Reset])
    else action