#!/usr/bin/env stack
> --stack --install-ghc runghc

This is a command-line Pomodoro counter.

> module Pomodoro (session) where

> import Control.Concurrent (threadDelay)
> import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
> import Data.Time.Format (formatTime, defaultTimeLocale)
> import Display (display)
>
> data Pomodoro = First | Second | Third | Fourth
>     deriving (Pomodoro -> Pomodoro -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Pomodoro -> Pomodoro -> Bool
$c/= :: Pomodoro -> Pomodoro -> Bool
== :: Pomodoro -> Pomodoro -> Bool
$c== :: Pomodoro -> Pomodoro -> Bool
Eq, Eq Pomodoro
Pomodoro -> Pomodoro -> Bool
Pomodoro -> Pomodoro -> Ordering
Pomodoro -> Pomodoro -> Pomodoro
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Pomodoro -> Pomodoro -> Pomodoro
$cmin :: Pomodoro -> Pomodoro -> Pomodoro
max :: Pomodoro -> Pomodoro -> Pomodoro
$cmax :: Pomodoro -> Pomodoro -> Pomodoro
>= :: Pomodoro -> Pomodoro -> Bool
$c>= :: Pomodoro -> Pomodoro -> Bool
> :: Pomodoro -> Pomodoro -> Bool
$c> :: Pomodoro -> Pomodoro -> Bool
<= :: Pomodoro -> Pomodoro -> Bool
$c<= :: Pomodoro -> Pomodoro -> Bool
< :: Pomodoro -> Pomodoro -> Bool
$c< :: Pomodoro -> Pomodoro -> Bool
compare :: Pomodoro -> Pomodoro -> Ordering
$ccompare :: Pomodoro -> Pomodoro -> Ordering
Ord, Int -> Pomodoro -> ShowS
[Pomodoro] -> ShowS
Pomodoro -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Pomodoro] -> ShowS
$cshowList :: [Pomodoro] -> ShowS
show :: Pomodoro -> String
$cshow :: Pomodoro -> String
showsPrec :: Int -> Pomodoro -> ShowS
$cshowsPrec :: Int -> Pomodoro -> ShowS
Show, ReadPrec [Pomodoro]
ReadPrec Pomodoro
Int -> ReadS Pomodoro
ReadS [Pomodoro]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Pomodoro]
$creadListPrec :: ReadPrec [Pomodoro]
readPrec :: ReadPrec Pomodoro
$creadPrec :: ReadPrec Pomodoro
readList :: ReadS [Pomodoro]
$creadList :: ReadS [Pomodoro]
readsPrec :: Int -> ReadS Pomodoro
$creadsPrec :: Int -> ReadS Pomodoro
Read, Pomodoro
forall a. a -> a -> Bounded a
maxBound :: Pomodoro
$cmaxBound :: Pomodoro
minBound :: Pomodoro
$cminBound :: Pomodoro
Bounded, Int -> Pomodoro
Pomodoro -> Int
Pomodoro -> [Pomodoro]
Pomodoro -> Pomodoro
Pomodoro -> Pomodoro -> [Pomodoro]
Pomodoro -> Pomodoro -> Pomodoro -> [Pomodoro]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Pomodoro -> Pomodoro -> Pomodoro -> [Pomodoro]
$cenumFromThenTo :: Pomodoro -> Pomodoro -> Pomodoro -> [Pomodoro]
enumFromTo :: Pomodoro -> Pomodoro -> [Pomodoro]
$cenumFromTo :: Pomodoro -> Pomodoro -> [Pomodoro]
enumFromThen :: Pomodoro -> Pomodoro -> [Pomodoro]
$cenumFromThen :: Pomodoro -> Pomodoro -> [Pomodoro]
enumFrom :: Pomodoro -> [Pomodoro]
$cenumFrom :: Pomodoro -> [Pomodoro]
fromEnum :: Pomodoro -> Int
$cfromEnum :: Pomodoro -> Int
toEnum :: Int -> Pomodoro
$ctoEnum :: Int -> Pomodoro
pred :: Pomodoro -> Pomodoro
$cpred :: Pomodoro -> Pomodoro
succ :: Pomodoro -> Pomodoro
$csucc :: Pomodoro -> Pomodoro
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 :: Int -> String
secToTimestamp = forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
"%M:%S" forall b c a. (b -> c) -> (a -> b) -> a -> c
. POSIXTime -> UTCTime
posixSecondsToUTCTime forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral

> -- | Manage Pomodoro sessions
> --
> -- Examples:
> --
> -- >>> putStrLn "Hello world!"
> -- Hello world!
> --
> -- >>> putStrLn "Test complete!"
> -- Test complete!

> -- | Replace a delay with no delay for testing purposes.
> no_del :: Int -> IO()
> no_del :: Int -> IO ()
no_del Int
_ = do
>     forall (m :: * -> *) a. Monad m => a -> m a
return ()
 
> pom :: Show a => IO () -> a -> IO ()
> pom :: forall a. Show a => IO () -> a -> IO ()
pom IO ()
delay a
m = do
>     let prefix :: String
prefix = forall a. Show a => a -> String
show a
m forall a. [a] -> [a] -> [a]
++ String
" pomodoro" forall a. [a] -> [a] -> [a]
++ String
" | "
>     IO () -> String -> Int -> IO ()
wait_seconds IO ()
delay String
prefix forall a b. (a -> b) -> a -> b
$ Int
25 forall a. Num a => a -> a -> a
* Int
60 forall a. Num a => a -> a -> a
+ Int
1
>     String -> IO ()
putStrLn String
"Finished, take a 5 minute rest."

> rest :: IO () -> Int -> IO ()
> rest :: IO () -> Int -> IO ()
rest IO ()
delay Int
minutes = do
>     let prefix :: String
prefix = String
"Rest time" forall a. [a] -> [a] -> [a]
++ String
" | "
>     IO () -> String -> Int -> IO ()
wait_seconds IO ()
delay String
prefix forall a b. (a -> b) -> a -> b
$ Int
minutes forall a. Num a => a -> a -> a
* Int
60 forall a. Num a => a -> a -> a
+ Int
1

> pomodoro :: IO () -> Pomodoro -> IO ()
> pomodoro :: IO () -> Pomodoro -> IO ()
pomodoro IO ()
delay Pomodoro
Fourth = do
>     forall a. Show a => IO () -> a -> IO ()
pom IO ()
delay Pomodoro
Fourth
>     String -> IO ()
putStrLn String
"Take a 30-minute rest now. You just completed 4 pomodoros."
>     String -> IO ()
putStrLn String
"Congratulations on 4 pomodoros finished in a row!"
> pomodoro IO ()
delay Pomodoro
m = do
>     forall a. Show a => IO () -> a -> IO ()
pom IO ()
delay Pomodoro
m
>     IO () -> Int -> IO ()
rest IO ()
delay Int
5
>     String -> IO ()
putStrLn String
"Get back to work." forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
delay
>     IO () -> Pomodoro -> IO ()
pomodoro IO ()
delay forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> a
succ Pomodoro
m
>
> wait_seconds :: IO () -> String -> Int -> IO()
> wait_seconds :: IO () -> String -> Int -> IO ()
wait_seconds IO ()
delay String
prefix Int
0 = String -> IO ()
display String
""
> wait_seconds IO ()
delay String
prefix Int
n = do
>     String -> IO ()
display forall a b. (a -> b) -> a -> b
$ String
prefix forall a. [a] -> [a] -> [a]
++ (Int -> String
secToTimestamp (Int
n forall a. Num a => a -> a -> a
- Int
1))
>     IO ()
delay
>     IO () -> String -> Int -> IO ()
wait_seconds IO ()
delay String
prefix forall a b. (a -> b) -> a -> b
$ Int
n forall a. Num a => a -> a -> a
- Int
1

> session :: IO() -> IO()
> session :: IO () -> IO ()
session IO ()
delay = IO () -> Pomodoro -> IO ()
pomodoro IO ()
delay Pomodoro
First