#!/usr/bin/env stack > --stack --install-ghc runghc This is a command-line Pomodoro counter. > module Pomodoro (session, countdown) where > import Control.Concurrent (threadDelay) > import System.Console.ANSI (clearLine, > saveCursor, > restoreCursor) > import System.IO (hFlush, > stdout) > import Data.Time.Clock.POSIX (posixSecondsToUTCTime) > import Data.Time.Format (formatTime, defaultTimeLocale) > > data Pomodoro = First | Second | Third | Fourth > deriving (Eq, Ord, Show, Read, Bounded, Enum) > {-| Given an integer number of seconds, secToTimestamp > returns the corresponding time in MM:SS. > > >>> secToTimestamp 0 > "00:00" > >>> secToTimestamp 1500 > "25:00" > >>> secToTimestamp 3000 > "50:00" > -} > > secToTimestamp :: Int -> String > secToTimestamp = formatTime defaultTimeLocale "%M:%S" . posixSecondsToUTCTime . fromIntegral > -- | Manage Pomodoro sessions > -- > -- Examples: > -- > -- >>> putStrLn "Hello world!" > -- Hello world! > -- > -- >>> putStrLn "Test complete!" > -- Test complete! > countdown :: IO() > countdown = do > wait_seconds $ 25 * 60 + 1 > -- | Replace a delay with no delay for testing purposes. > no_del :: Int -> IO() > no_del _ = do > return () > pom :: Show a => a -> IO () > pom m = do > putStr $ show m ++ " pomodoro" ++ " | " > saveCursor > wait_seconds $ 25 * 60 + 1 > restoreCursor > putStrLn "Finished, take a 5 minute rest." > to_work :: IO () > to_work = do > saveCursor > putStr "Get back to work" > delay 2 > restoreCursor > clearLine > pomodoro :: Pomodoro -> IO () > pomodoro Fourth = do > pom Fourth > putStrLn "Take a 30-minute rest now. You just completed 4 pomodoros." > putStrLn "Congratulations on 4 pomodoros finished in a row!" > pomodoro m = do > pom m > delay $ 5 * 60 > to_work > pomodoro $ succ m > > wait_seconds :: Int -> IO() > wait_seconds 0 = putStr "" > wait_seconds n = do > saveCursor > putStr $ secToTimestamp $ n - 1 > hFlush stdout > restoreCursor > delay 1 > wait_seconds $ n - 1 > -- | delay: Pauses the thread for the given number of seconds. > -- > -- Example: > -- > -- >>> delay 0 > delay :: Int -> IO() > delay n = threadDelay $ n * 1000 * 1000 > session :: IO() > session = pomodoro First > main :: IO() > main = session