Monadoro 0.2.8.1 → 0.3.0.0
raw patch · 7 files changed
+104/−97 lines, 7 filesdep −ansi-terminalPVP ok
version bump matches the API change (PVP)
Dependencies removed: ansi-terminal
API changes (from Hackage documentation)
- Pomodoro: countdown :: IO ()
+ CountdownLoop: countdown_loop :: IO () -> String -> IO String
- Pomodoro: session :: IO ()
+ Pomodoro: session :: IO () -> IO ()
Files
- Monadoro.cabal +3/−6
- README.md +22/−18
- app/Main.hs +37/−7
- changelog +4/−0
- src/ConsoleDisplay.lhs +0/−3
- src/CountdownLoop.hs +5/−6
- src/Pomodoro.lhs +33/−57
Monadoro.cabal view
@@ -5,13 +5,13 @@ -- see: https://github.com/sol/hpack name: Monadoro-version: 0.2.8.1+version: 0.3.0.0 synopsis: A minimalistic CLI Pomodoro timer. description: A Pomodoro timer with two modes: single-pomodoro (default), and four-pomodoro (`--session`). category: Tools author: Patryk Kocielnik maintainer: patryk@kocielnik.pl-copyright: 2018-2021 Patryk Kocielnik+copyright: 2018-2022 Patryk Kocielnik license: MIT license-file: LICENSE build-type: Simple@@ -35,8 +35,7 @@ hs-source-dirs: src build-depends:- ansi-terminal >=0.8 && <1- , base >=4.7 && <5+ base >=4.7 && <5 , process >=1.6 && <2 , time >=1.8 && <2 default-language: Haskell2010@@ -50,7 +49,6 @@ ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends: Monadoro- , ansi-terminal >=0.8 && <1 , base >=4.7 && <5 , process >=1.6 && <2 , time >=1.8 && <2@@ -67,7 +65,6 @@ ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends: Monadoro- , ansi-terminal >=0.8 && <1 , base >=4.7 && <5 , doctest >=0.8 , hspec
README.md view
@@ -18,38 +18,42 @@ 2. Set the Pomodoro for 25 minutes, 3. Work on the task until the Pomodoro rings, 4. When the Pomodoro rings, put a checkmark on a paper,-5. If you have fewer than four checkmarks, take a short break (3-5 minutes), then go to step 2;-6. After four pomodoros, take a longer break (15-30 minutes), reset your checkmark count to zero, then go to step 1.+5. If you have fewer than four checkmarks, take a short break (3-5 minutes),+ then go to step 2;+6. After four pomodoros, take a longer break (15-30 minutes), reset your+ checkmark count to zero, then go to step 1. # Installing -## Install Stack--To install Stack on Ubuntu, you can use the command `sudo apt install-haskell-stack`.+## Fastest: With Nix already installed -## Installing Monadoro+`nix-shell -p haskellPackages.Monadoro --run monadoro` -Before installing, it is important to update the Stack index using `stack-update`.+## Using Stack -Having updated the Stack index, we can now run `stack install Monadoro`, paying-attention to capitalization of the first letter, which is important.+1. Ensure you have `stack` installed.+ - Vendor-recommended way: `curl -sSL https://get.haskellstack.org/ | sh`+ - Native install, on Ubuntu as an example: `apt install haskell-stack`+2. Install Monadoro+ 1. Update the Stack index: `stack update`+ 2. Install: `stack install Monadoro`. Note the capital "M" in the package+ name. ## Test suite dependencies -DocTest 0.16.1 Haskell library requires libtinfo to compile. On Ubuntu,-libtinfo can be installed using the command `apt install libtinfo-dev`.+DocTest 0.16.1 Haskell library requires libtinfo to compile (`libtinfo-dev` in+Apt on Ubuntu). # Credits -Initial draft of functionality by The Haskell Blog [^haskell_blog] author --GitHub user Elektroingenieur [^elektroingenieur].+Initial work: GitHub user Elektroingenieur [^elektroingenieur], author of The+Haskell Blog [^haskell_blog]. -Manpage generation from Markdown courtesy of Jérôme Belleman [^belleman] and-Pandoc [^pandoc] project contributors.+Manpage generation from Markdown: Jérôme Belleman [^belleman] and Pandoc+[^pandoc] project. -"Pomodoro Technique (illustration)" (CC BY 2.0) by [Michael Zero Mayer](https://www.flickr.com/photos/michael_mayer/6969282632/).+"Pomodoro Technique (illustration)" (CC BY 2.0) by [Michael Zero+Mayer](https://www.flickr.com/photos/michael_mayer/6969282632/). # References
app/Main.hs view
@@ -6,9 +6,10 @@ import Data.Version (showVersion) import System.Environment (getArgs) import System.Exit (ExitCode(ExitSuccess))+import Control.Concurrent (threadDelay) import System.Process (system) -import CountdownLoop (countdown)+import CountdownLoop (countdown_loop) import Pomodoro (session) import Paths_Monadoro (getDataFileName, version)@@ -19,20 +20,43 @@ monadoro :: IO () monadoro = getArgs >>= parseArgs +remove :: String -> [String] -> [String]+remove element list = filter (/=element) list+ parseArgs :: [String] -> IO () parseArgs xs | xs `containsEither` ["--help", "-h"] = putStrLn usage | xs `containsEither` ["--version", "-v"] = putStrLn . showVersion $ version- | xs `containsEither` ["--session", "-s"] = session+ | xs `containsEither` ["--session", "-s"] = session (getDelayIfNeeded xs) | xs `containsEither` ["--man", "-m"] = do man_file <- getDataFileName "man/monadoro.1" ExitSuccess <- system $ "man " ++ man_file return () | otherwise = do+ let filtered_params = filterParams xs+ runPomodoro (getDelayIfNeeded xs) filtered_params++filterParams :: [String] -> [String]+filterParams xs = (remove "-n" . remove "--nodelay") xs++runPomodoro :: IO () -> [String] -> IO ()+runPomodoro delay xs = do warnAboutErrorsIfAny invalidIntervals- runTimer validIntervals+ runTimer delay validIntervals where (validIntervals, invalidIntervals) = checkInput xs +with_delay :: IO()+with_delay = wait 1++-- Mocks a delay for test purposes.+no_delay :: IO()+no_delay = wait 0++getDelayIfNeeded :: [String] -> IO ()+getDelayIfNeeded xs+ | xs `containsEither` ["--nodelay", "-n"] = no_delay+ | otherwise = with_delay+ warnAboutErrorsIfAny :: [String] -> IO () warnAboutErrorsIfAny [] = return () warnAboutErrorsIfAny errors =@@ -96,7 +120,13 @@ usage = "Usage: monadoro [-h|--help] [-m|--man] [-v|--version] [--session]" ++ "[INTERVAL [...]]" -runTimer :: [String] -> IO ()-runTimer [] = void (countdown "25:00")-runTimer [t] = void (countdown t)-runTimer (t:ts) = parseArgs [t] >> parseArgs ts+milisec_per_second :: Int+milisec_per_second = 10 ^ (6 :: Int)++wait :: Int -> IO()+wait n = threadDelay (n * milisec_per_second)++runTimer :: IO () -> [String] -> IO ()+runTimer delayer [] = void (countdown_loop delayer "25:00")+runTimer delayer [t] = void (countdown_loop delayer t)+runTimer delayer (t:ts) = parseArgs [t] >> parseArgs ts
changelog view
@@ -1,3 +1,7 @@+monadoro (3.0.0)++ * Drop dependency on package ansi-terminal.+ monadoro (2.6.3) * Add a man page.
src/ConsoleDisplay.lhs view
@@ -6,9 +6,6 @@ > module ConsoleDisplay (display) where > > import Control.Concurrent (threadDelay)-> import System.Console.ANSI (clearLine,-> saveCursor,-> restoreCursor) > > display :: String -> IO () > display s = putStr $ "\r" ++ s
src/CountdownLoop.hs view
@@ -1,11 +1,9 @@ #!/usr/bin/env stack --stack --install-ghc runghc -module CountdownLoop (countdown) where+module CountdownLoop (countdown, countdown_loop) where import System.Environment (getArgs)-import System.Console.ANSI (saveCursor,- restoreCursor) import System.IO (hFlush, stdout) import Control.Concurrent (threadDelay)@@ -51,14 +49,15 @@ countdown :: String -> IO (String) countdown = countdown_loop with_delay +display :: String -> IO ()+display s = putStr $ s ++ " \r"+ countdown_loop :: IO() -> String -> IO (String) countdown_loop delayer "00:00" = putStrLn "00:00" >> return "00:00" countdown_loop delayer s = do- saveCursor- putStr s+ display s hFlush stdout delayer- restoreCursor (countdown_loop delayer . count_down_time) s parse :: [String] -> IO ()
src/Pomodoro.lhs view
@@ -3,23 +3,20 @@ This is a command-line Pomodoro counter. -> module Pomodoro (session, countdown) where+> module Pomodoro (session) 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@@ -27,12 +24,12 @@ > >>> secToTimestamp 3000 > "50:00" > -}-> +> > secToTimestamp :: Int -> String > secToTimestamp = formatTime defaultTimeLocale "%M:%S" . posixSecondsToUTCTime . fromIntegral > -- | Manage Pomodoro sessions-> -- +> -- > -- Examples: > -- > -- >>> putStrLn "Hello world!"@@ -41,64 +38,43 @@ > -- >>> 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+> pom :: Show a => IO () -> a -> IO ()+> pom delay m = do+> let prefix = show m ++ " pomodoro" ++ " | "+> wait_seconds delay prefix $ 25 * 60 + 1 > putStrLn "Finished, take a 5 minute rest." -> to_work :: IO ()-> to_work = do-> saveCursor-> putStr "Get back to work"-> delay 2-> restoreCursor-> clearLine+> rest :: IO () -> Int -> IO ()+> rest delay minutes = do+> let prefix = "Rest time" ++ " | "+> wait_seconds delay prefix $ minutes * 60 + 1 -> pomodoro :: Pomodoro -> IO ()-> pomodoro Fourth = do-> pom Fourth+> display :: String -> IO ()+> display s = putStr $ s ++ " \r"++> pomodoro :: IO () -> Pomodoro -> IO ()+> pomodoro delay Fourth = do+> pom delay 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+> pomodoro delay m = do+> pom delay m+> rest delay 5+> putStrLn "Get back to work." >> delay+> pomodoro delay $ succ m+>+> wait_seconds :: IO () -> String -> Int -> IO()+> wait_seconds delay prefix 0 = display ""+> wait_seconds delay prefix n = do+> display $ prefix ++ (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+> delay+> wait_seconds delay prefix $ n - 1 +> session :: IO() -> IO()+> session delay = pomodoro delay First