{-# LANGUAGE CPP #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE ScopedTypeVariables #-}
module XMonad.Prompt.OrgMode (
orgPrompt,
orgPromptPrimary,
ClipboardSupport (..),
OrgMode,
#ifdef TESTING
pInput,
Note (..),
Date (..),
Time (..),
TimeOfDay (..),
DayOfWeek (..),
#endif
) where
import XMonad.Prelude
import XMonad (X, io)
import XMonad.Prompt (XPConfig, XPrompt (showXPrompt), mkXPrompt)
import XMonad.Util.XSelection (getSelection)
import Data.Time (Day (ModifiedJulianDay), NominalDiffTime, UTCTime (utctDay), addUTCTime, defaultTimeLocale, formatTime, fromGregorian, getCurrentTime, iso8601DateFormat, nominalDay, toGregorian)
import System.Directory (getHomeDirectory)
import System.IO (IOMode (AppendMode), hPutStrLn, withFile)
import Text.ParserCombinators.ReadP (ReadP, munch, munch1, readP_to_S, skipSpaces, string, (<++))
data OrgMode = OrgMode
{ OrgMode -> ClipboardSupport
clpSupport :: ClipboardSupport
, :: String
, OrgMode -> String
orgFile :: FilePath
}
data ClipboardSupport
= PrimarySelection
| NoClpSupport
data Clp
= String
| Body String
instance XPrompt OrgMode where
showXPrompt :: OrgMode -> String
showXPrompt :: OrgMode -> String
showXPrompt OrgMode{ String
todoHeader :: String
todoHeader :: OrgMode -> String
todoHeader, String
orgFile :: String
orgFile :: OrgMode -> String
orgFile, ClipboardSupport
clpSupport :: ClipboardSupport
clpSupport :: OrgMode -> ClipboardSupport
clpSupport } =
[String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"Add ", String
todoHeader, String
clp, String
" to ", String
orgFile, String
": "]
where
String
clp :: String = case ClipboardSupport
clpSupport of
ClipboardSupport
NoClpSupport -> String
""
ClipboardSupport
PrimarySelection -> String
" + PS"
orgPrompt
:: XPConfig
-> String
-> FilePath
-> X ()
orgPrompt :: XPConfig -> String -> String -> X ()
orgPrompt XPConfig
xpc = XPConfig -> OrgMode -> X ()
mkOrgPrompt XPConfig
xpc (OrgMode -> X ())
-> (String -> String -> OrgMode) -> String -> String -> X ()
forall a b c d. (a -> b) -> (c -> d -> a) -> c -> d -> b
.: ClipboardSupport -> String -> String -> OrgMode
OrgMode ClipboardSupport
NoClpSupport
orgPromptPrimary :: XPConfig -> String -> FilePath -> X ()
orgPromptPrimary :: XPConfig -> String -> String -> X ()
orgPromptPrimary XPConfig
xpc = XPConfig -> OrgMode -> X ()
mkOrgPrompt XPConfig
xpc (OrgMode -> X ())
-> (String -> String -> OrgMode) -> String -> String -> X ()
forall a b c d. (a -> b) -> (c -> d -> a) -> c -> d -> b
.: ClipboardSupport -> String -> String -> OrgMode
OrgMode ClipboardSupport
PrimarySelection
mkOrgPrompt :: XPConfig -> OrgMode -> X ()
mkOrgPrompt :: XPConfig -> OrgMode -> X ()
mkOrgPrompt XPConfig
xpc oc :: OrgMode
oc@OrgMode{ String
todoHeader :: String
todoHeader :: OrgMode -> String
todoHeader, String
orgFile :: String
orgFile :: OrgMode -> String
orgFile, ClipboardSupport
clpSupport :: ClipboardSupport
clpSupport :: OrgMode -> ClipboardSupport
clpSupport } =
OrgMode -> XPConfig -> ComplFunction -> (String -> X ()) -> X ()
forall p.
XPrompt p =>
p -> XPConfig -> ComplFunction -> (String -> X ()) -> X ()
mkXPrompt OrgMode
oc XPConfig
xpc (IO [String] -> ComplFunction
forall a b. a -> b -> a
const ([String] -> IO [String]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [])) String -> X ()
appendNote
where
appendNote :: String -> X ()
appendNote :: String -> X ()
appendNote String
input = IO () -> X ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO () -> X ()) -> IO () -> X ()
forall a b. (a -> b) -> a -> b
$ do
Clp
clpStr <- case ClipboardSupport
clpSupport of
ClipboardSupport
NoClpSupport -> Clp -> IO Clp
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Clp -> IO Clp) -> Clp -> IO Clp
forall a b. (a -> b) -> a -> b
$ String -> Clp
Body String
""
ClipboardSupport
PrimarySelection -> do
String
sel <- IO String
forall (m :: * -> *). MonadIO m => m String
getSelection
Clp -> IO Clp
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Clp -> IO Clp) -> Clp -> IO Clp
forall a b. (a -> b) -> a -> b
$ if (String -> Bool) -> [String] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` String
sel) [String
"http://", String
"https://"]
then String -> Clp
Header String
sel
else String -> Clp
Body (String -> Clp) -> String -> Clp
forall a b. (a -> b) -> a -> b
$ String
"\n " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
sel
String
fp <- case String
orgFile of
Char
'/' : String
_ -> String -> IO String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
orgFile
Char
'~' : Char
'/' : String
_ -> IO String
getHomeDirectory IO String -> (String -> String) -> IO String
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
1 String
orgFile)
String
_ -> IO String
getHomeDirectory IO String -> (String -> String) -> IO String
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (String -> String -> String
forall a. Semigroup a => a -> a -> a
<> (Char
'/' Char -> String -> String
forall a. a -> [a] -> [a]
: String
orgFile))
String -> IOMode -> (Handle -> IO ()) -> IO ()
forall r. String -> IOMode -> (Handle -> IO r) -> IO r
withFile String
fp IOMode
AppendMode ((Handle -> IO ()) -> IO ())
-> (String -> Handle -> IO ()) -> String -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Handle -> String -> IO ()) -> String -> Handle -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Handle -> String -> IO ()
hPutStrLn
(String -> IO ()) -> (String -> IO String) -> String -> IO ()
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< IO String -> (Note -> IO String) -> Maybe Note -> IO String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> IO String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"") (Clp -> String -> Note -> IO String
ppNote Clp
clpStr String
todoHeader) (Maybe Note -> IO String)
-> (String -> Maybe Note) -> String -> IO String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe Note
pInput
(String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
input
data Time = Time
{ Time -> Date
date :: Date
, Time -> Maybe TimeOfDay
tod :: Maybe TimeOfDay
}
deriving (Time -> Time -> Bool
(Time -> Time -> Bool) -> (Time -> Time -> Bool) -> Eq Time
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Time -> Time -> Bool
$c/= :: Time -> Time -> Bool
== :: Time -> Time -> Bool
$c== :: Time -> Time -> Bool
Eq, Int -> Time -> String -> String
[Time] -> String -> String
Time -> String
(Int -> Time -> String -> String)
-> (Time -> String) -> ([Time] -> String -> String) -> Show Time
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Time] -> String -> String
$cshowList :: [Time] -> String -> String
show :: Time -> String
$cshow :: Time -> String
showsPrec :: Int -> Time -> String -> String
$cshowsPrec :: Int -> Time -> String -> String
Show)
data TimeOfDay = TimeOfDay Int Int
deriving (TimeOfDay -> TimeOfDay -> Bool
(TimeOfDay -> TimeOfDay -> Bool)
-> (TimeOfDay -> TimeOfDay -> Bool) -> Eq TimeOfDay
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TimeOfDay -> TimeOfDay -> Bool
$c/= :: TimeOfDay -> TimeOfDay -> Bool
== :: TimeOfDay -> TimeOfDay -> Bool
$c== :: TimeOfDay -> TimeOfDay -> Bool
Eq)
instance Show TimeOfDay where
show :: TimeOfDay -> String
show :: TimeOfDay -> String
show (TimeOfDay Int
h Int
m) = Int -> String
pad Int
h String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
":" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
pad Int
m
where
pad :: Int -> String
pad :: Int -> String
pad Int
n = (if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
9 then String
"0" else String
"") String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
n
data Date
= Today
| Tomorrow
| Next DayOfWeek
| Date (Int, Maybe Int, Maybe Integer)
deriving (Date -> Date -> Bool
(Date -> Date -> Bool) -> (Date -> Date -> Bool) -> Eq Date
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Date -> Date -> Bool
$c/= :: Date -> Date -> Bool
== :: Date -> Date -> Bool
$c== :: Date -> Date -> Bool
Eq, Eq Date
Eq Date
-> (Date -> Date -> Ordering)
-> (Date -> Date -> Bool)
-> (Date -> Date -> Bool)
-> (Date -> Date -> Bool)
-> (Date -> Date -> Bool)
-> (Date -> Date -> Date)
-> (Date -> Date -> Date)
-> Ord Date
Date -> Date -> Bool
Date -> Date -> Ordering
Date -> Date -> Date
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 :: Date -> Date -> Date
$cmin :: Date -> Date -> Date
max :: Date -> Date -> Date
$cmax :: Date -> Date -> Date
>= :: Date -> Date -> Bool
$c>= :: Date -> Date -> Bool
> :: Date -> Date -> Bool
$c> :: Date -> Date -> Bool
<= :: Date -> Date -> Bool
$c<= :: Date -> Date -> Bool
< :: Date -> Date -> Bool
$c< :: Date -> Date -> Bool
compare :: Date -> Date -> Ordering
$ccompare :: Date -> Date -> Ordering
$cp1Ord :: Eq Date
Ord, Int -> Date -> String -> String
[Date] -> String -> String
Date -> String
(Int -> Date -> String -> String)
-> (Date -> String) -> ([Date] -> String -> String) -> Show Date
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Date] -> String -> String
$cshowList :: [Date] -> String -> String
show :: Date -> String
$cshow :: Date -> String
showsPrec :: Int -> Date -> String -> String
$cshowsPrec :: Int -> Date -> String -> String
Show)
toOrgFmt :: Maybe TimeOfDay -> Day -> String
toOrgFmt :: Maybe TimeOfDay -> Day -> String
toOrgFmt Maybe TimeOfDay
tod Day
day =
[String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"<", String
isoDay, String
" ", Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
3 (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ DayOfWeek -> String
forall a. Show a => a -> String
show (Day -> DayOfWeek
dayOfWeek Day
day), String
time, String
">"]
where
String
time :: String = String -> (TimeOfDay -> String) -> Maybe TimeOfDay -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"" ((Char
' ' Char -> String -> String
forall a. a -> [a] -> [a]
:) (String -> String) -> (TimeOfDay -> String) -> TimeOfDay -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeOfDay -> String
forall a. Show a => a -> String
show) Maybe TimeOfDay
tod
String
isoDay :: String = TimeLocale -> String -> Day -> String
forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale (Maybe String -> String
iso8601DateFormat Maybe String
forall a. Maybe a
Nothing) Day
day
ppDate :: Time -> IO String
ppDate :: Time -> IO String
ppDate Time{ Date
date :: Date
date :: Time -> Date
date, Maybe TimeOfDay
tod :: Maybe TimeOfDay
tod :: Time -> Maybe TimeOfDay
tod } = do
UTCTime
curTime <- IO UTCTime
getCurrentTime
let curDay :: Day
curDay = UTCTime -> Day
utctDay UTCTime
curTime
(Integer
y, Int
m, Int
_) = Day -> (Integer, Int, Int)
toGregorian Day
curDay
diffToDay :: DayOfWeek -> NominalDiffTime
diffToDay DayOfWeek
d = DayOfWeek -> DayOfWeek -> NominalDiffTime
diffBetween DayOfWeek
d (Day -> DayOfWeek
dayOfWeek Day
curDay)
String -> IO String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> IO String) -> (Day -> String) -> Day -> IO String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe TimeOfDay -> Day -> String
toOrgFmt Maybe TimeOfDay
tod (Day -> IO String) -> Day -> IO String
forall a b. (a -> b) -> a -> b
$ case Date
date of
Date
Today -> Day
curDay
Date
Tomorrow -> UTCTime -> Day
utctDay (UTCTime -> Day) -> UTCTime -> Day
forall a b. (a -> b) -> a -> b
$ NominalDiffTime -> UTCTime -> UTCTime
addDays NominalDiffTime
1 UTCTime
curTime
Next DayOfWeek
wday -> UTCTime -> Day
utctDay (UTCTime -> Day) -> UTCTime -> Day
forall a b. (a -> b) -> a -> b
$ NominalDiffTime -> UTCTime -> UTCTime
addDays (DayOfWeek -> NominalDiffTime
diffToDay DayOfWeek
wday) UTCTime
curTime
Date (Int
d, Maybe Int
mbM, Maybe Integer
mbY) -> Integer -> Int -> Int -> Day
fromGregorian (Integer -> Maybe Integer -> Integer
forall a. a -> Maybe a -> a
fromMaybe Integer
y Maybe Integer
mbY) (Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
m Maybe Int
mbM) Int
d
where
NominalDiffTime -> UTCTime -> UTCTime
addDays :: NominalDiffTime -> UTCTime -> UTCTime
= NominalDiffTime -> UTCTime -> UTCTime
addUTCTime (NominalDiffTime -> UTCTime -> UTCTime)
-> (NominalDiffTime -> NominalDiffTime)
-> NominalDiffTime
-> UTCTime
-> UTCTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
* NominalDiffTime
nominalDay)
diffBetween :: DayOfWeek -> DayOfWeek -> NominalDiffTime
diffBetween :: DayOfWeek -> DayOfWeek -> NominalDiffTime
diffBetween DayOfWeek
d DayOfWeek
cur
| DayOfWeek
d DayOfWeek -> DayOfWeek -> Bool
forall a. Eq a => a -> a -> Bool
== DayOfWeek
cur = NominalDiffTime
7
| Bool
otherwise = Int -> NominalDiffTime
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> NominalDiffTime) -> (Int -> Int) -> Int -> NominalDiffTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int
forall a. Num a => a -> a
abs (Int -> NominalDiffTime) -> Int -> NominalDiffTime
forall a b. (a -> b) -> a -> b
$ (DayOfWeek -> Int
forall a. Enum a => a -> Int
fromEnum DayOfWeek
d Int -> Int -> Int
forall a. Num a => a -> a -> a
- DayOfWeek -> Int
forall a. Enum a => a -> Int
fromEnum DayOfWeek
cur) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
7
dayOfWeek :: Day -> DayOfWeek
dayOfWeek :: Day -> DayOfWeek
dayOfWeek (ModifiedJulianDay Integer
d) = Int -> DayOfWeek
forall a. Enum a => Int -> a
toEnum (Int -> DayOfWeek) -> Int -> DayOfWeek
forall a b. (a -> b) -> a -> b
$ Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Integer
d Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
3
data DayOfWeek
= Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday
deriving (DayOfWeek -> DayOfWeek -> Bool
(DayOfWeek -> DayOfWeek -> Bool)
-> (DayOfWeek -> DayOfWeek -> Bool) -> Eq DayOfWeek
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DayOfWeek -> DayOfWeek -> Bool
$c/= :: DayOfWeek -> DayOfWeek -> Bool
== :: DayOfWeek -> DayOfWeek -> Bool
$c== :: DayOfWeek -> DayOfWeek -> Bool
Eq, Eq DayOfWeek
Eq DayOfWeek
-> (DayOfWeek -> DayOfWeek -> Ordering)
-> (DayOfWeek -> DayOfWeek -> Bool)
-> (DayOfWeek -> DayOfWeek -> Bool)
-> (DayOfWeek -> DayOfWeek -> Bool)
-> (DayOfWeek -> DayOfWeek -> Bool)
-> (DayOfWeek -> DayOfWeek -> DayOfWeek)
-> (DayOfWeek -> DayOfWeek -> DayOfWeek)
-> Ord DayOfWeek
DayOfWeek -> DayOfWeek -> Bool
DayOfWeek -> DayOfWeek -> Ordering
DayOfWeek -> DayOfWeek -> DayOfWeek
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 :: DayOfWeek -> DayOfWeek -> DayOfWeek
$cmin :: DayOfWeek -> DayOfWeek -> DayOfWeek
max :: DayOfWeek -> DayOfWeek -> DayOfWeek
$cmax :: DayOfWeek -> DayOfWeek -> DayOfWeek
>= :: DayOfWeek -> DayOfWeek -> Bool
$c>= :: DayOfWeek -> DayOfWeek -> Bool
> :: DayOfWeek -> DayOfWeek -> Bool
$c> :: DayOfWeek -> DayOfWeek -> Bool
<= :: DayOfWeek -> DayOfWeek -> Bool
$c<= :: DayOfWeek -> DayOfWeek -> Bool
< :: DayOfWeek -> DayOfWeek -> Bool
$c< :: DayOfWeek -> DayOfWeek -> Bool
compare :: DayOfWeek -> DayOfWeek -> Ordering
$ccompare :: DayOfWeek -> DayOfWeek -> Ordering
$cp1Ord :: Eq DayOfWeek
Ord, Int -> DayOfWeek -> String -> String
[DayOfWeek] -> String -> String
DayOfWeek -> String
(Int -> DayOfWeek -> String -> String)
-> (DayOfWeek -> String)
-> ([DayOfWeek] -> String -> String)
-> Show DayOfWeek
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [DayOfWeek] -> String -> String
$cshowList :: [DayOfWeek] -> String -> String
show :: DayOfWeek -> String
$cshow :: DayOfWeek -> String
showsPrec :: Int -> DayOfWeek -> String -> String
$cshowsPrec :: Int -> DayOfWeek -> String -> String
Show)
instance Enum DayOfWeek where
toEnum :: Int -> DayOfWeek
toEnum :: Int -> DayOfWeek
toEnum Int
i = case Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod Int
i Int
7 of
Int
0 -> DayOfWeek
Sunday
Int
1 -> DayOfWeek
Monday
Int
2 -> DayOfWeek
Tuesday
Int
3 -> DayOfWeek
Wednesday
Int
4 -> DayOfWeek
Thursday
Int
5 -> DayOfWeek
Friday
Int
_ -> DayOfWeek
Saturday
fromEnum :: DayOfWeek -> Int
fromEnum :: DayOfWeek -> Int
fromEnum = \case
DayOfWeek
Monday -> Int
1
DayOfWeek
Tuesday -> Int
2
DayOfWeek
Wednesday -> Int
3
DayOfWeek
Thursday -> Int
4
DayOfWeek
Friday -> Int
5
DayOfWeek
Saturday -> Int
6
DayOfWeek
Sunday -> Int
7
data Note
= Scheduled String Time
| Deadline String Time
| NormalMsg String
deriving (Note -> Note -> Bool
(Note -> Note -> Bool) -> (Note -> Note -> Bool) -> Eq Note
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Note -> Note -> Bool
$c/= :: Note -> Note -> Bool
== :: Note -> Note -> Bool
$c== :: Note -> Note -> Bool
Eq, Int -> Note -> String -> String
[Note] -> String -> String
Note -> String
(Int -> Note -> String -> String)
-> (Note -> String) -> ([Note] -> String -> String) -> Show Note
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Note] -> String -> String
$cshowList :: [Note] -> String -> String
show :: Note -> String
$cshow :: Note -> String
showsPrec :: Int -> Note -> String -> String
$cshowsPrec :: Int -> Note -> String -> String
Show)
ppNote :: Clp -> String -> Note -> IO String
ppNote :: Clp -> String -> Note -> IO String
ppNote Clp
clp String
todo = \case
Scheduled String
str Time
time -> String -> String -> Maybe Time -> IO String
mkLine String
str String
"SCHEDULED: " (Time -> Maybe Time
forall a. a -> Maybe a
Just Time
time)
Deadline String
str Time
time -> String -> String -> Maybe Time -> IO String
mkLine String
str String
"DEADLINE: " (Time -> Maybe Time
forall a. a -> Maybe a
Just Time
time)
NormalMsg String
str -> String -> String -> Maybe Time -> IO String
mkLine String
str String
"" Maybe Time
forall a. Maybe a
Nothing
where
mkLine :: String -> String -> Maybe Time -> IO String
mkLine :: String -> String -> Maybe Time -> IO String
mkLine String
str String
sched Maybe Time
time = do
String
t <- case Maybe Time
time of
Maybe Time
Nothing -> String -> IO String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
""
Just Time
ti -> ((String
"\n " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
sched) String -> String -> String
forall a. Semigroup a => a -> a -> a
<>) (String -> String) -> IO String -> IO String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Time -> IO String
ppDate Time
ti
String -> IO String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> IO String) -> String -> IO String
forall a b. (a -> b) -> a -> b
$ case Clp
clp of
Body String
c -> [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"* ", String
todo, String
" ", String
str, String
t, String
c]
Header String
c -> [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"* ", String
todo, String
" [[", String
c, String
"][", String
str,String
"]]", String
t]
pInput :: String -> Maybe Note
pInput :: String -> Maybe Note
pInput String
inp = ((Note, String) -> Note) -> Maybe (Note, String) -> Maybe Note
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Note, String) -> Note
forall a b. (a, b) -> a
fst (Maybe (Note, String) -> Maybe Note)
-> ([ReadP Note] -> Maybe (Note, String))
-> [ReadP Note]
-> Maybe Note
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Note, String)] -> Maybe (Note, String)
forall a. [a] -> Maybe a
listToMaybe ([(Note, String)] -> Maybe (Note, String))
-> ([ReadP Note] -> [(Note, String)])
-> [ReadP Note]
-> Maybe (Note, String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ReadP Note -> ReadS Note
forall a. ReadP a -> ReadS a
`readP_to_S` String
inp) (ReadP Note -> [(Note, String)])
-> ([ReadP Note] -> ReadP Note) -> [ReadP Note] -> [(Note, String)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ReadP Note] -> ReadP Note
forall a. [ReadP a] -> ReadP a
lchoice ([ReadP Note] -> Maybe Note) -> [ReadP Note] -> Maybe Note
forall a b. (a -> b) -> a -> b
$
[ String -> Time -> Note
Scheduled (String -> Time -> Note) -> ReadP String -> ReadP (Time -> Note)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> ReadP String
getLast String
"+s" ReadP (Time -> Note) -> ReadP Time -> ReadP Note
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Date -> Maybe TimeOfDay -> Time
Time (Date -> Maybe TimeOfDay -> Time)
-> ReadP Date -> ReadP (Maybe TimeOfDay -> Time)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP Date
pDate ReadP (Maybe TimeOfDay -> Time)
-> ReadP (Maybe TimeOfDay) -> ReadP Time
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadP (Maybe TimeOfDay)
pTimeOfDay)
, String -> Time -> Note
Deadline (String -> Time -> Note) -> ReadP String -> ReadP (Time -> Note)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> ReadP String
getLast String
"+d" ReadP (Time -> Note) -> ReadP Time -> ReadP Note
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Date -> Maybe TimeOfDay -> Time
Time (Date -> Maybe TimeOfDay -> Time)
-> ReadP Date -> ReadP (Maybe TimeOfDay -> Time)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP Date
pDate ReadP (Maybe TimeOfDay -> Time)
-> ReadP (Maybe TimeOfDay) -> ReadP Time
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadP (Maybe TimeOfDay)
pTimeOfDay)
, String -> Note
NormalMsg (String -> Note) -> ReadP String -> ReadP Note
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> ReadP String
munch1 (Bool -> Char -> Bool
forall a b. a -> b -> a
const Bool
True)
]
where
getLast :: String -> ReadP String
getLast :: String -> ReadP String
getLast String
ptn = String -> String
forall a. [a] -> [a]
reverse
(String -> String) -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ')
(String -> String) -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String -> String
forall a. Int -> [a] -> [a]
drop (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
ptn)
(String -> String) -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
reverse
(String -> String) -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
([String] -> String) -> ReadP [String] -> ReadP String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP String -> ReadP String -> ReadP [String]
forall a sep. ReadP a -> ReadP sep -> ReadP [a]
endBy1 (String -> ReadP String
go String
"") (String -> ReadP String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
ptn)
where
go :: String -> ReadP String
go :: String -> ReadP String
go String
consumed = do
String
str <- (Char -> Bool) -> ReadP String
munch (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= String -> Char
forall a. [a] -> a
head String
ptn)
String
word <- (Char -> Bool) -> ReadP String
munch1 (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
' ')
(String -> ReadP String)
-> (String -> ReadP String) -> Bool -> String -> ReadP String
forall a. a -> a -> Bool -> a
bool String -> ReadP String
go String -> ReadP String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String
word String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
ptn) (String -> ReadP String) -> String -> ReadP String
forall a b. (a -> b) -> a -> b
$ String
consumed String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
str String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
word
pTimeOfDay :: ReadP (Maybe TimeOfDay)
pTimeOfDay :: ReadP (Maybe TimeOfDay)
pTimeOfDay = [ReadP (Maybe TimeOfDay)] -> ReadP (Maybe TimeOfDay)
forall a. [ReadP a] -> ReadP a
lchoice
[ TimeOfDay -> Maybe TimeOfDay
forall a. a -> Maybe a
Just (TimeOfDay -> Maybe TimeOfDay)
-> ReadP TimeOfDay -> ReadP (Maybe TimeOfDay)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int -> Int -> TimeOfDay
TimeOfDay (Int -> Int -> TimeOfDay) -> ReadP Int -> ReadP (Int -> TimeOfDay)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP Int
forall a. (Read a, Integral a) => ReadP a
pInt ReadP (Int -> TimeOfDay)
-> ReadP String -> ReadP (Int -> TimeOfDay)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* String -> ReadP String
string String
":" ReadP (Int -> TimeOfDay) -> ReadP Int -> ReadP TimeOfDay
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadP Int
forall a. (Read a, Integral a) => ReadP a
pInt )
, TimeOfDay -> Maybe TimeOfDay
forall a. a -> Maybe a
Just (TimeOfDay -> Maybe TimeOfDay)
-> ReadP TimeOfDay -> ReadP (Maybe TimeOfDay)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int -> Int -> TimeOfDay
TimeOfDay (Int -> Int -> TimeOfDay) -> ReadP Int -> ReadP (Int -> TimeOfDay)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP Int
forall a. (Read a, Integral a) => ReadP a
pInt ReadP (Int -> TimeOfDay) -> ReadP Int -> ReadP TimeOfDay
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> ReadP Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
0)
, Maybe TimeOfDay -> ReadP (Maybe TimeOfDay)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe TimeOfDay
forall a. Maybe a
Nothing
]
pDate :: ReadP Date
pDate :: ReadP Date
pDate = ReadP ()
skipSpaces ReadP () -> ReadP Date -> ReadP Date
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> [ReadP Date] -> ReadP Date
forall a. [ReadP a] -> ReadP a
lchoice
[ String -> String -> Date -> ReadP Date
forall a. String -> String -> a -> ReadP a
pString String
"tod" String
"ay" Date
Today
, String -> String -> Date -> ReadP Date
forall a. String -> String -> a -> ReadP a
pString String
"tom" String
"orrow" Date
Tomorrow
, DayOfWeek -> Date
Next (DayOfWeek -> Date) -> ReadP DayOfWeek -> ReadP Date
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP DayOfWeek
pNext
, (Int, Maybe Int, Maybe Integer) -> Date
Date ((Int, Maybe Int, Maybe Integer) -> Date)
-> ReadP (Int, Maybe Int, Maybe Integer) -> ReadP Date
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP (Int, Maybe Int, Maybe Integer)
pDate1 ReadP (Int, Maybe Int, Maybe Integer)
-> ReadP (Int, Maybe Int, Maybe Integer)
-> ReadP (Int, Maybe Int, Maybe Integer)
forall a. ReadP a -> ReadP a -> ReadP a
<++ ReadP (Int, Maybe Int, Maybe Integer)
pDate2 ReadP (Int, Maybe Int, Maybe Integer)
-> ReadP (Int, Maybe Int, Maybe Integer)
-> ReadP (Int, Maybe Int, Maybe Integer)
forall a. ReadP a -> ReadP a -> ReadP a
<++ ReadP (Int, Maybe Int, Maybe Integer)
pDate3
] ReadP Date -> ReadP () -> ReadP Date
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ReadP ()
skipSpaces
where
ReadP DayOfWeek
pNext :: ReadP DayOfWeek = [ReadP DayOfWeek] -> ReadP DayOfWeek
forall a. [ReadP a] -> ReadP a
lchoice
[ String -> String -> DayOfWeek -> ReadP DayOfWeek
forall a. String -> String -> a -> ReadP a
pString String
"m" String
"onday" DayOfWeek
Monday , String -> String -> DayOfWeek -> ReadP DayOfWeek
forall a. String -> String -> a -> ReadP a
pString String
"tu" String
"esday" DayOfWeek
Tuesday
, String -> String -> DayOfWeek -> ReadP DayOfWeek
forall a. String -> String -> a -> ReadP a
pString String
"w" String
"ednesday" DayOfWeek
Wednesday, String -> String -> DayOfWeek -> ReadP DayOfWeek
forall a. String -> String -> a -> ReadP a
pString String
"th" String
"ursday" DayOfWeek
Thursday
, String -> String -> DayOfWeek -> ReadP DayOfWeek
forall a. String -> String -> a -> ReadP a
pString String
"f" String
"riday" DayOfWeek
Friday , String -> String -> DayOfWeek -> ReadP DayOfWeek
forall a. String -> String -> a -> ReadP a
pString String
"sa" String
"turday" DayOfWeek
Saturday
, String -> String -> DayOfWeek -> ReadP DayOfWeek
forall a. String -> String -> a -> ReadP a
pString String
"su" String
"nday" DayOfWeek
Sunday
]
pDate1, pDate2, pDate3 :: ReadP (Int, Maybe Int, Maybe Integer)
pDate1 :: ReadP (Int, Maybe Int, Maybe Integer)
pDate1 = (ReadP Int -> ReadP (Maybe Int))
-> (ReadP Integer -> ReadP (Maybe Integer))
-> ReadP (Int, Maybe Int, Maybe Integer)
forall (f :: * -> *).
(ReadP Int -> ReadP (f Int))
-> (ReadP Integer -> ReadP (f Integer))
-> ReadP (Int, f Int, f Integer)
pDate' ((Int -> Maybe Int) -> ReadP Int -> ReadP (Maybe Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> Maybe Int
forall a. a -> Maybe a
Just) ((Integer -> Maybe Integer)
-> ReadP Integer -> ReadP (Maybe Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Integer -> Maybe Integer
forall a. a -> Maybe a
Just)
pDate2 :: ReadP (Int, Maybe Int, Maybe Integer)
pDate2 = (ReadP Int -> ReadP (Maybe Int))
-> (ReadP Integer -> ReadP (Maybe Integer))
-> ReadP (Int, Maybe Int, Maybe Integer)
forall (f :: * -> *).
(ReadP Int -> ReadP (f Int))
-> (ReadP Integer -> ReadP (f Integer))
-> ReadP (Int, f Int, f Integer)
pDate' ((Int -> Maybe Int) -> ReadP Int -> ReadP (Maybe Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> Maybe Int
forall a. a -> Maybe a
Just) (ReadP (Maybe Integer) -> ReadP Integer -> ReadP (Maybe Integer)
forall a b. a -> b -> a
const (Maybe Integer -> ReadP (Maybe Integer)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Integer
forall a. Maybe a
Nothing))
pDate3 :: ReadP (Int, Maybe Int, Maybe Integer)
pDate3 = (ReadP Int -> ReadP (Maybe Int))
-> (ReadP Integer -> ReadP (Maybe Integer))
-> ReadP (Int, Maybe Int, Maybe Integer)
forall (f :: * -> *).
(ReadP Int -> ReadP (f Int))
-> (ReadP Integer -> ReadP (f Integer))
-> ReadP (Int, f Int, f Integer)
pDate' (ReadP (Maybe Int) -> ReadP Int -> ReadP (Maybe Int)
forall a b. a -> b -> a
const (Maybe Int -> ReadP (Maybe Int)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Int
forall a. Maybe a
Nothing)) (ReadP (Maybe Integer) -> ReadP Integer -> ReadP (Maybe Integer)
forall a b. a -> b -> a
const (Maybe Integer -> ReadP (Maybe Integer)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Integer
forall a. Maybe a
Nothing))
pDate'
:: (ReadP Int -> ReadP (f Int ))
-> (ReadP Integer -> ReadP (f Integer))
-> ReadP (Int, f Int, f Integer)
pDate' :: (ReadP Int -> ReadP (f Int))
-> (ReadP Integer -> ReadP (f Integer))
-> ReadP (Int, f Int, f Integer)
pDate' ReadP Int -> ReadP (f Int)
p ReadP Integer -> ReadP (f Integer)
p' =
(,,) (Int -> f Int -> f Integer -> (Int, f Int, f Integer))
-> ReadP Int
-> ReadP (f Int -> f Integer -> (Int, f Int, f Integer))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP Int
forall a. (Read a, Integral a) => ReadP a
pInt
ReadP (f Int -> f Integer -> (Int, f Int, f Integer))
-> ReadP (f Int) -> ReadP (f Integer -> (Int, f Int, f Integer))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadP Int -> ReadP (f Int)
p (ReadP ()
skipSpaces ReadP () -> ReadP Int -> ReadP Int
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> [ReadP Int] -> ReadP Int
forall a. [ReadP a] -> ReadP a
lchoice
[ String -> String -> Int -> ReadP Int
forall a. String -> String -> a -> ReadP a
pString String
"ja" String
"nuary" Int
1 , String -> String -> Int -> ReadP Int
forall a. String -> String -> a -> ReadP a
pString String
"f" String
"ebruary" Int
2
, String -> String -> Int -> ReadP Int
forall a. String -> String -> a -> ReadP a
pString String
"mar" String
"ch" Int
3 , String -> String -> Int -> ReadP Int
forall a. String -> String -> a -> ReadP a
pString String
"ap" String
"ril" Int
4
, String -> String -> Int -> ReadP Int
forall a. String -> String -> a -> ReadP a
pString String
"may" String
"" Int
5 , String -> String -> Int -> ReadP Int
forall a. String -> String -> a -> ReadP a
pString String
"jun" String
"e" Int
6
, String -> String -> Int -> ReadP Int
forall a. String -> String -> a -> ReadP a
pString String
"jul" String
"y" Int
7 , String -> String -> Int -> ReadP Int
forall a. String -> String -> a -> ReadP a
pString String
"au" String
"gust" Int
8
, String -> String -> Int -> ReadP Int
forall a. String -> String -> a -> ReadP a
pString String
"s" String
"eptember" Int
9 , String -> String -> Int -> ReadP Int
forall a. String -> String -> a -> ReadP a
pString String
"o" String
"ctober" Int
10
, String -> String -> Int -> ReadP Int
forall a. String -> String -> a -> ReadP a
pString String
"n" String
"ovember" Int
11, String -> String -> Int -> ReadP Int
forall a. String -> String -> a -> ReadP a
pString String
"d" String
"ecember" Int
12
])
ReadP (f Integer -> (Int, f Int, f Integer))
-> ReadP (f Integer) -> ReadP (Int, f Int, f Integer)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadP Integer -> ReadP (f Integer)
p' (ReadP ()
skipSpaces ReadP () -> ReadP Integer -> ReadP Integer
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ReadP Integer
forall a. (Read a, Integral a) => ReadP a
pInt ReadP Integer -> (Integer -> ReadP Integer) -> ReadP Integer
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Integer
i -> Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
25) ReadP () -> Integer -> ReadP Integer
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Integer
i)
pString :: String -> String -> a -> ReadP a
pString :: String -> String -> a -> ReadP a
pString String
start String
leftover a
ret = do
ReadP String -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP String -> ReadP ()) -> ReadP String -> ReadP ()
forall a b. (a -> b) -> a -> b
$ String -> ReadP String
string String
start
String
l <- (Char -> Bool) -> ReadP String
munch (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
' ')
Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (String
l String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` String
leftover)
a -> ReadP a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
ret
pInt :: (Read a, Integral a) => ReadP a
pInt :: ReadP a
pInt = String -> a
forall a. Read a => String -> a
read (String -> a) -> ReadP String -> ReadP a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> ReadP String
munch1 Char -> Bool
isDigit
lchoice :: [ReadP a] -> ReadP a
lchoice :: [ReadP a] -> ReadP a
lchoice = (ReadP a -> ReadP a -> ReadP a) -> ReadP a -> [ReadP a] -> ReadP a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' ReadP a -> ReadP a -> ReadP a
forall a. ReadP a -> ReadP a -> ReadP a
(<++) ReadP a
forall (f :: * -> *) a. Alternative f => f a
empty
endBy1 :: ReadP a -> ReadP sep -> ReadP [a]
endBy1 :: ReadP a -> ReadP sep -> ReadP [a]
endBy1 ReadP a
parser ReadP sep
sep = ReadP a -> ReadP [a]
forall a. ReadP a -> ReadP [a]
many1 (ReadP a
parser ReadP a -> ReadP sep -> ReadP a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ReadP sep
sep)
where
many1 :: ReadP a -> ReadP [a]
many1 :: ReadP a -> ReadP [a]
many1 ReadP a
p = (:) (a -> [a] -> [a]) -> ReadP a -> ReadP ([a] -> [a])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP a
p ReadP ([a] -> [a]) -> ReadP [a] -> ReadP [a]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (ReadP a -> ReadP [a]
forall a. ReadP a -> ReadP [a]
many1 ReadP a
p ReadP [a] -> ReadP [a] -> ReadP [a]
forall a. ReadP a -> ReadP a -> ReadP a
<++ [a] -> ReadP [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [])