fuzzytime 0.5 → 0.6
raw patch · 2 files changed
+161/−110 lines, 2 filesdep +haskell98
Dependencies added: haskell98
Files
- fuzzytime.cabal +4/−4
- fuzzytime.hs +157/−106
fuzzytime.cabal view
@@ -1,7 +1,7 @@ Name: fuzzytime-Version: 0.5-Description: A clock which tells the time in a more familiar way-Synopsis: A clock which tells the time in a more familiar way+Version: 0.6+Description: A clock and timer that tell the time in a more human way+Synopsis: A clock and timer that tell the time in a more human way Category: Utils License: GPL License-file: LICENSE@@ -12,4 +12,4 @@ Executable fuzzytime Main-is: fuzzytime.hs- Build-Depends: base >= 4 && < 5, cmdargs, old-time+ Build-Depends: base >= 4 && < 5, cmdargs, haskell98, old-time
fuzzytime.hs view
@@ -1,3 +1,5 @@+-- fuzzytime timer (no END) when timer is set+ -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ---- | ---- Module : Fuzzytime@@ -6,9 +8,11 @@ ---- Maintainer : Kamil Stachowski <kamil.stachowski@gmail.com> ---- Stability : unstable ---- Portability : unportable----- A clock that ells the time in a more familiar way (the \"ten past six\"-style).+---- A clock that ells the time in a more human way (the \"ten past six\"-style). -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +{-# LANGUAGE DeriveDataTypeable #-}+ module Main ( -- * Description -- $description@@ -18,55 +22,32 @@ import Data.Char (isDigit) import Data.List (intercalate)+import System.Directory (removeFile) import System.Console.CmdArgs-import System.Time+import System.Environment (getEnv)+import System.Time (getClockTime) import FuzzyTime -- $description--- A small utility to tell the current time in a more familiar way (the \"ten past six\"-style).+-- fuzzytime is a small utility which tells what time it is or how much time there is left to something, in a more familiar way such as "ten to six" rather than 17:51 (telling the time), or "in five minutes" (telling the left time). ----- The whole thing works like this: the current time is read and turned into CalendarTime. This is fuzzified (i.e. the precision is reduced) and at the same time changed into FuzzyTime. FuzzyTime holds the time as two Ints (hour and min), the target language, the desired clock (12 vs. 24) and an information on whether it is am or pm (needed for the 12-hour clock). Custom functions show FuzzyTime as the \"ten past six\"-style String.+-- There are two modes: telling the time / the time left till some event, and setting the timer. See main below. --+-- The intended use is in an environment which does not provide a status bar with a built-in clock. It is expected to be piper to a status bar and run every minute or so in the clock mode.+-- The timer can be set via the timer-setting mode. When the timer is set, the clock mode will show how much time there is left till some event. To get back to showing the actual time, timer has to be unset.+--+-- Example use:+-- Say you have fuzzytime piped to your status bar and it serves as a usual clock applet. Then you got an e-mail saying that you're going to have a meeting at one o'clock. You set the timer to 13:00 and instead of the current time, fuzzytime begins to show you how much time you have left till the meeting. After you come back, you unset the timer and have fuzzytime display the current time again.+-- -- Depends on N. Mitchell's System.Console.CmdArds 0.6.4-1+. -- -- To add a new language, two things need to be done: -- -- (1) The new language needs to be added to confAvailLangs (in fuzzytime.hs) and to instance Show FuzzyTime (in FuzzyTime.hs). ----- (2) A module FuzzyTime.NewLanguge needs to be created and added to the list of imported modules in FuzzyTime.hs.----- CHANGELOG--- TODO--- exit codes--- answers for Greek (:35, midnight, εντεκάμιση)--- check Danish: midnight + noon, halves--- 0.5 2011.01.17--- added halves as base (de, nl and pl)--- added Greek (thanks Gbak), Dutch (thanks litemotiv) and Turkish--- some corrections (thanks Daniel Fischer from beginners@haskell.org again)--- 0.4.1 2011.01.15--- fixed nextFTHour--- 0.4 2011.01.15--- added --time (thanks Daniel Fischer and Brent Yorgey from beginners@haskell.org!)--- added --style--- added Danish (by M_ller with my modifications)--- removed "południe" from pl--- sorted out the representation of midnight and noon--- added a man page--- 0.3 2011.01.14--- added midnight and noon--- added checking cli options--- fixed the "quarter past quarter" bug--- 0.2 2011.01.12--- added French and German--- added 12 vs. 24-hour clock--- 0.1.1 2010.12.06--- added cabal--- 0.1 2010.12.05--- initial release: two languages (en and pl), 1 < precision < 60+-- (2) A module FuzzyTime.NewLanguge needs to be created and added to the list of imports in FuzzyTime.hs. -- config =========================================================================================================================================================================@@ -74,119 +55,189 @@ -- available ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- | \[config] Available languages.+-- | \[config] Languages available. confAvailLangs :: [String]-confAvailLangs = ["da", "de", "el", "en", "fr", "nl", "pl", "tr"]---- | Print nicely what languages are available.-showAvailLangs :: String -> String-showAvailLangs i = case length confAvailLangs of- 0 -> "none"- 1 -> head confAvailLangs- otherwise -> intercalate ", " (init confAvailLangs) ++ " " ++ i ++ " " ++ last confAvailLangs+confAvailLangs = ["da", "de", "el", "en", "es", "fr", "nl", "pl", "tr"] -- defaults ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- | \[config] The default clock (12 vs. 24-hour).-confDefClock :: Int-confDefClock = 12- -- | \[config] The default language. confDefLang :: String confDefLang = "en" --- | \[config] The default precision (should be in [1..60]).-confDefPrec :: Int-confDefPrec = 5+-- | \[config] The default clock (12 vs. 24-hour) for the clock mode.+confDefClockClock :: Int+confDefClockClock = 12 --- | \[config] The default style (see man).-confDefStyle :: Int-confDefStyle = 1+-- | \[config] The default precision (should be in [1..60]) for the clock mode.+confDefClockPrec :: Int+confDefClockPrec = 5 --- | \[config] The default time (current).-confSetCurrTime :: FuzzyTimeConf -> IO FuzzyTimeConf-confSetCurrTime ft = do+-- | \[config] The default style for the clock mode (see the man page).+confDefClockStyle :: Int+confDefClockStyle = 1+++-- | \[config] Get the default config for showing the time.+getDefClockConf :: IO FuzzyTimeConf+getDefClockConf = do nowClock <- getClockTime+ let nowString = take 5. drop 11 $ show nowClock+ return $ ClockConf {+ clock = confDefClockClock &= help confHelpClockClock+ , lang = confDefLang &= help confHelpClockLang+ , prec = confDefClockPrec &= help confHelpClockPrec+ , time = nowString &= help confHelpClockTime+ , style = confDefClockStyle &= help confHelpClockStyle+ } &= name "clock" &= help confHelpClock++-- | \[config] Get the default config for either showing the time or setting the timer.+getDefTimerConf :: IO FuzzyTimeConf+getDefTimerConf = do+ nowClock <- getClockTime let nowString = take 5 . drop 11 $ show nowClock- return $ ft { time = nowString &= help confHelpTime }+ endFile <- (readFile =<< confTimerFileLoc) `catch` (\_ -> return "empty")+ let endString = take 5 endFile+ return $ TimerConf {+ end = endString &= args &= typ "END"+ , lang = confDefLang &= ignore+ , now = nowString &= ignore+ } &= name "timer" &= help confHelpTimer --- | \[config] Get the default config. Note that time is set to "" and can only be filled later with confSetCurrTime. This is due to getClockTime being in IO.-getDefConf :: FuzzyTimeConf-getDefConf = FuzzyTimeConf {- clock = confDefClock &= help confHelpClock- , lang = confDefLang &= help confHelpLang- , prec = confDefPrec &= help confHelpPrec- , time = ""- , style = confDefStyle &= help confHelpStyle- }- &= program confHelpProgram- &= summary confHelpSummary+-- internal ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- | \[config] The default location for the timer file.+confTimerFileLoc :: IO String+confTimerFileLoc = do+ home <- getEnv "HOME"+ return $ home ++ "/.fuzzytimer"+++-- | Print nicely what languages are available.+showAvailLangs :: String -> String+showAvailLangs i = case length confAvailLangs of+ 0 -> "none"+ 1 -> head confAvailLangs+ _ -> intercalate ", " (init confAvailLangs) ++ " " ++ i ++ " " ++ last confAvailLangs++ -- help --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- | \[config] Help message for clock+-- | \[config] Help message for the clock (showing) mode. confHelpClock :: String-confHelpClock = "12 or 24-hour clock; default " ++ show confDefClock ++ "-hour."+confHelpClock = "Print fuzzy time if timer is not set, and countdown if it is." --- | \[config] Help message for lang-confHelpLang :: String-confHelpLang = "Language (currently " ++ showAvailLangs "and" ++ "); default " ++ confDefLang ++ "."+-- | \[config] Help message for --clock.+confHelpClockClock :: String+confHelpClockClock = "12 or 24-hour clock; default " ++ show confDefClockClock ++ "-hour." --- | \[config] Help message for prec-confHelpPrec :: String-confHelpPrec = "Precision (1 <= prec <= 60 [minutes]); default " ++ show confDefPrec ++ "."+-- | \[config] Help message for --lang.+confHelpClockLang :: String+confHelpClockLang = "Language (currently " ++ showAvailLangs "and" ++ "); default " ++ confDefLang ++ "." --- | \[config] Help message for time-confHelpTime :: String-confHelpTime = "Time to fuzzify as HH:MM; default current time." +-- | \[config] Help message for --prec.+confHelpClockPrec :: String+confHelpClockPrec = "Precision (1 <= prec <= 60 [minutes]); default " ++ show confDefClockPrec ++ "." --- | \[config] Help message for style-confHelpStyle :: String-confHelpStyle = "How the time is told (seem the man page); default " ++ show confDefStyle ++ "."+-- | \[config] Help message for --time.+confHelpClockTime :: String+confHelpClockTime = "Time to fuzzify as HH:MM; default current time." +-- | \[config] Help message for --style.+confHelpClockStyle :: String+confHelpClockStyle = "How the time is told (seem the man page); default " ++ show confDefClockStyle ++ "."+++-- | \[config] Help message for the timer (setting) mode.+confHelpTimer :: String+confHelpTimer = "Set timer to END as HH:MM or \"unset\". (Disables printing time.)"++-- | \[config] Help message for END.+confHelpTimerEnd :: String+confHelpTimerEnd = "Set the timer to countdown to END as HH:MM; obligatory."++ -- | \[config] Help message for program confHelpProgram :: String confHelpProgram = "fuzzytime" -- | \[config] Help message for summary confHelpSummary :: String-confHelpSummary = "A clock that tells the time in a more familiar way.\nv0.5, 2011.01.17, kamil.stachowski@gmail.com, GPL3+"+confHelpSummary = "A clock and timer that tell the time in a more human way.\nv0.6, 2011.01.21, kamil.stachowski@gmail.com, GPL3+" -- check -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- | \[config] Check that arguments given at cli are correct.+-- | \[config] Check that arguments given at cli or read from the timer file are correct. checkFTConf :: FuzzyTimeConf -> Either String FuzzyTimeConf-checkFTConf ftc@(FuzzyTimeConf clock lang prec time style)- | clock `notElem` [12, 24] = Left "--clock must be either 12 or 24."- | lang `notElem` confAvailLangs = Left ("--lang must be " ++ showAvailLangs "or" ++ ".")- | prec < 1 || prec > 60 = Left "--prec must be 1 < prec < 60."- | not checkTimeOk = Left "--time must be given as HH:MM, where HH is in [0..23] and MM is in [0..59]"- | style `notElem` [1, 2] = Left "--style must be either 1 or 2 (see the man page)."- | otherwise = Right ftc- where- checkTimeOk :: Bool- checkTimeOk = case break (== ':') time of- (hh, _:mm) -> not (null hh || null mm)- && all isDigit hh && all isDigit mm- && (let h = read hh; m = read mm- in 0 <= h && h < 24 && 0 <= m && m < 60)- _ -> False +checkFTConf c@(ClockConf clock lang prec time style)+ | clock `notElem` [12, 24] = Left "--clock must be either 12 or 24."+ | lang `notElem` confAvailLangs = Left ("--lang must be " ++ showAvailLangs "or" ++ ".")+ | prec < 1 || prec > 60 = Left "--prec must be 1 < prec < 60."+ | not (checkTimeOk time) = Left "--time must be given as HH:MM, where HH is in [0..23] and MM is in [0..59]."+ | style `notElem` [1, 2] = Left "--style must be either 1 or 2 (see the man page)."+ | otherwise = Right c +checkFTConf t@(TimerConf end lang now)+ | not (checkTimeOk end)+ && end /= "unset" = Left "END must be given and in the same format as --time."+ | not (checkTimeOk now) = Left "--time must be given as HH:MM, where HH is in [0..23] and MM is in [0..59]."+ | otherwise = Right t+++-- | \[config] Check that a string is a properly formatted time (HH:MM).+checkTimeOk :: String -> Bool+checkTimeOk time = case break (== ':') time of+ (hh, _:mm) -> not (null hh || null mm)+ && all isDigit hh && all isDigit mm+ && (let h = read hh; m = read mm+ in 0 <= h && h < 24 && 0 <= m && m < 60)+ _ -> False++ -- main =========================================================================================================================================================================== --- | The main part. Only reads the command line args and the current time, fuzzifies and prints it.+-- | There are two modes: telling the time, and setting the timer.+-- Telling the time happens when invoked as "fuzzytime clock". If the timer is set (if ~/.fuzzytimer exists), the countdown is shown. Otherwise, time is shown.+-- Setting the timer happens when invoked as "fuzzytime timer END", where END can be either the time to countdown to (as HH:MM), or "unset" to disable the timer.+-- Note that they are different from the two modes of FuzzyTime: telling the time can invoke both FuzzyTime's ClockConf and TimerConf, and setting the timer only happens here. main :: IO () main = do- c <- cmdArgs =<< confSetCurrTime getDefConf -- ^ confSetCurrTime required to avoid unsafePerformIO- case checkFTConf c of- Left msg -> putStrLn msg- Right conf -> print $ toFuzzyTime conf+ clockConf <- getDefClockConf+ timerConf <- getDefTimerConf+ conf <- cmdArgs (modes [clockConf, timerConf] &= program confHelpProgram &= summary confHelpSummary)+ case conf of+ -- Showing the time mode.+ cc@(ClockConf _ _ _ _ _)+ -> do+ let realConf = if end timerConf == "empty" then+ conf+ else+ timerConf {+ lang = lang conf+ , now = time conf+ }+ case checkFTConf realConf of+ Left e -> putStrLn e+ Right c -> print $ toFuzzyTime c+ -- Setting the timer mode.+ tc@(TimerConf end _ _)+ -> do+ path <- confTimerFileLoc+ case checkFTConf tc of+ Left e -> putStrLn e+ Right c -> do+ removeFile path `catch` (\_ -> putStrLn "Timer is not set.")+ if end == "unset" then+ putStrLn "Timer has been unset."+ else do+ writeFile path end+ putStrLn $ "Timer has been set to " ++ end ++ "."