{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE ViewPatterns #-}
module Life.Message
( beautyPrint
, boldText
, prompt
, promptNonEmpty
, errorMessage
, warningMessage
, successMessage
, infoMessage
, skipMessage
, abortCmd
, choose
, chooseYesNo
) where
import System.Console.ANSI (Color (..), ColorIntensity (Vivid), ConsoleIntensity (BoldIntensity),
ConsoleLayer (Foreground), SGR (..), setSGR)
import System.IO (hFlush)
import qualified Data.Text as T
import qualified Relude.Unsafe as Unsafe
putStrFlush :: Text -> IO ()
putStrFlush msg = do
putText msg
hFlush stdout
setColor :: Color -> IO ()
setColor color = setSGR [SetColor Foreground Vivid color]
bold :: IO ()
bold = setSGR [SetConsoleIntensity BoldIntensity]
reset :: IO ()
reset = do
setSGR [Reset]
hFlush stdout
beautyPrint :: [IO ()] -> Text -> IO ()
beautyPrint formats msg = do
sequence_ formats
putText msg
reset
prompt :: IO Text
prompt = do
setColor Blue
putStrFlush " ⟳ "
reset
getLine
promptNonEmpty :: IO Text
promptNonEmpty = do
res <- T.strip <$> prompt
if T.null res
then warningMessage "The answer shouldn't be empty" >> promptNonEmpty
else pure res
boldText :: Text -> IO ()
boldText message = bold >> putStrFlush message >> reset
boldDefault :: Text -> IO ()
boldDefault message = boldText (" [" <> message <> "]")
colorMessage :: Color -> Text -> IO ()
colorMessage color message = do
setColor color
putTextLn $ " " <> message
reset
errorMessage, warningMessage, successMessage, infoMessage, skipMessage :: Text -> IO ()
errorMessage = colorMessage Red
warningMessage = colorMessage Yellow
successMessage = colorMessage Green
infoMessage = colorMessage Blue
skipMessage = colorMessage Cyan
abortCmd :: Text -> Text -> IO ()
abortCmd cmd msg = do
warningMessage msg
errorMessage $ "Aborting 'life " <> cmd <> "' command."
exitFailure
printQuestion :: Text -> [Text] -> IO ()
printQuestion question (def:rest) = do
let restSlash = T.intercalate "/" rest
putStrFlush question
boldDefault def
putTextLn $ "/" <> restSlash
printQuestion question [] = putTextLn question
choose :: Text -> [Text] -> IO Text
choose question choices = do
printQuestion question choices
answer <- prompt
if | T.null answer -> pure (Unsafe.head choices)
| T.toLower answer `elem` choices -> pure answer
| otherwise -> do
errorMessage "This wasn't a valid choice."
choose question choices
data Answer = Y | N
yesOrNo :: Text -> Maybe Answer
yesOrNo (T.toLower -> answer )
| T.null answer = Just Y
| answer `elem` ["yes", "y", "ys"] = Just Y
| answer `elem` ["no", "n"] = Just N
| otherwise = Nothing
chooseYesNo :: Text -> IO Bool
chooseYesNo q = do
printQuestion q ["y", "n"]
answer <- yesOrNo <$> prompt
case answer of
Nothing -> do
errorMessage "This wasn't a valid choice."
chooseYesNo q
Just Y -> pure True
Just N -> pure False