packages feed

Monadoro-0.2.6.3: app/Main.hs

module Main where

import Control.Monad      (void)
import Data.Char          (isDigit)
import Data.List          (intersect)
import Data.Version       (showVersion)
import System.Environment (getArgs)
import System.Exit        (ExitCode(ExitSuccess))
import System.Process     (system)

import CountdownLoop      (countdown)
import Pomodoro           (session)

import Paths_Monadoro     (getDataFileName, version)

main :: IO ()
main = monadoro

monadoro :: IO ()
monadoro = getArgs >>= parseArgs

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` ["--man", "-m"] = do
    man_file <- getDataFileName "man/monadoro.1"
    ExitSuccess <- system $ "man " ++ man_file
    return ()
  | otherwise = do
    warnAboutErrorsIfAny invalidIntervals
    runTimer validIntervals
    where (validIntervals, invalidIntervals) = checkInput xs

warnAboutErrorsIfAny :: [String] -> IO ()
warnAboutErrorsIfAny [] = return ()
warnAboutErrorsIfAny errors =
  putStrLn $ "Unable to parse as interval: " ++ show errors

{-| checkInput

Returns valid entries (first list) and invalid entries (second list).

>>> checkInput []
([],[])

>>> checkInput ["x"]
([],["x"])

>>> checkInput ["00:00"]
(["00:00"],[])

>>> checkInput ["00:00", "x"]
(["00:00"],["x"])

>>> checkInput ["00:00", "x"]
(["00:00"],["x"])

>>> checkInput ["00:00", "00:01", "x"]
(["00:00","00:01"],["x"])

-}

checkInput :: [String] -> ([String], [String])
checkInput [] = ([], [])
checkInput [x]
  | isValidTimeInterval x = ([x], [])
  | otherwise = ([], [x])
checkInput (x:xs) = (validEntries, invalidEntries)
  where
    validEntries =
      fst (checkInput [x]) ++ fst (checkInput xs)
    invalidEntries =
      snd (checkInput [x]) ++ snd (checkInput xs)

{-| isValidTimeInterval

>>> isValidTimeInterval "x"
False

>>> isValidTimeInterval "00:00"
True

-}

isValidTimeInterval :: String -> Bool
isValidTimeInterval (m1:m2:':':s1:[s2])
  | all isDigit [m1, m2, s1, s2] = True
isValidTimeInterval _ = False

containsEither :: (Eq a) => [a] -> [a] -> Bool
containsEither a = not . null . intersect a

usage :: String
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